From 3777e3f36a61a05da19d5c6575fdd59288848948 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 17 Jan 2024 15:19:53 +0100 Subject: [PATCH 001/383] cmake: Recommend native CMake commands in README Resolves one item in #1235. Closes #1294. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4013e6a9..6e88eb4e 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,9 @@ To maintain a pristine source tree, CMake encourages to perform an out-of-source $ mkdir build && cd build $ cmake .. - $ make - $ make check # run the test suite - $ sudo make install # optional + $ cmake --build . + $ ctest # run the test suite + $ sudo cmake --build . --target install # optional To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake .. -LH` to see the full list of available flags. From 51df2d9ab3a61dafee2c12b39e651d93a6b5be76 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 17 Jan 2024 16:54:04 +0100 Subject: [PATCH 002/383] tests: Drop redundant _scalar_check_overflow calls Redundant since d23da6d55714271c720fee58fbff5e5ef2fe193f. --- src/tests.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tests.c b/src/tests.c index 32946439..e653aeea 100644 --- a/src/tests.c +++ b/src/tests.c @@ -2927,18 +2927,14 @@ static void run_scalar_tests(void) { secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); CHECK(!overflow); secp256k1_scalar_mul(&z, &x, &y); - CHECK(!secp256k1_scalar_check_overflow(&z)); CHECK(secp256k1_scalar_eq(&r1, &z)); if (!secp256k1_scalar_is_zero(&y)) { secp256k1_scalar_inverse(&zz, &y); - CHECK(!secp256k1_scalar_check_overflow(&zz)); secp256k1_scalar_inverse_var(&zzv, &y); CHECK(secp256k1_scalar_eq(&zzv, &zz)); secp256k1_scalar_mul(&z, &z, &zz); - CHECK(!secp256k1_scalar_check_overflow(&z)); CHECK(secp256k1_scalar_eq(&x, &z)); secp256k1_scalar_mul(&zz, &zz, &y); - CHECK(!secp256k1_scalar_check_overflow(&zz)); CHECK(secp256k1_scalar_eq(&secp256k1_scalar_one, &zz)); } secp256k1_scalar_mul(&z, &x, &x); From 94a14d5290e6ca805f23b1a7baca197d15e55f84 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:09:47 +0000 Subject: [PATCH 003/383] ci: Update cache action This change fixes deprecation warnings for Node.js 16 actions in the GHA CI. See: - https://github.com/marketplace/actions/cache - https://github.com/actions/cache/releases/tag/v4.0.0 --- .github/actions/install-homebrew-valgrind/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/install-homebrew-valgrind/action.yml b/.github/actions/install-homebrew-valgrind/action.yml index 094ff891..ce10eb26 100644 --- a/.github/actions/install-homebrew-valgrind/action.yml +++ b/.github/actions/install-homebrew-valgrind/action.yml @@ -16,7 +16,7 @@ runs: cat valgrind_fingerprint shell: bash - - uses: actions/cache@v3 + - uses: actions/cache@v4 id: cache with: path: ${{ env.CI_HOMEBREW_CELLAR_VALGRIND }} From 218f0cc93bd77eae926f4c4e259951b92bf00aec Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 31 Jan 2024 20:50:33 +0000 Subject: [PATCH 004/383] ci: Add native macOS arm64 job --- .github/workflows/ci.yml | 62 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ad905af..c230dc4a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -585,10 +585,10 @@ jobs: run: env if: ${{ always() }} - macos-native: - name: "x86_64: macOS Monterey" + x86_64-macos-native: + name: "x86_64: macOS Monterey, Valgrind" # See: https://github.com/actions/runner-images#available-images. - runs-on: macos-12 # Use M1 once available https://github.com/github/roadmap/issues/528 + runs-on: macos-12 env: CC: 'clang' @@ -644,6 +644,62 @@ jobs: run: env if: ${{ always() }} + arm64-macos-native: + name: "ARM64: macOS Sonoma" + # See: https://github.com/actions/runner-images#available-images. + runs-on: macos-14 + + env: + CC: 'clang' + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + WITH_VALGRIND: 'no' + CTIMETESTS: 'no' + + strategy: + fail-fast: false + matrix: + env_vars: + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } + - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } + - BUILD: 'distcheck' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Homebrew packages + run: | + brew install automake libtool gcc + ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc + + - name: CI script + env: ${{ matrix.env_vars }} + run: ./ci/ci.sh + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + win64-native: name: ${{ matrix.configuration.job_name }} # See: https://github.com/actions/runner-images#available-images. From 00111c9c563367cf5163cda1ce6b9c6f032cea43 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 1 Feb 2024 00:47:12 +0100 Subject: [PATCH 005/383] tests: add missing fe comparison checks for inverse field test cases `check_fe_equal` is a wrapper around `secp256k1_fe_equal` that takes care of normalization. Since it doesn't check anything itself, the CHECK macro is needed at the call-sites to actually ensure equality. --- src/tests.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests.c b/src/tests.c index e653aeea..a64c3073 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3618,9 +3618,9 @@ static void run_inverse_tests(void) for (i = 0; (size_t)i < sizeof(fe_cases)/sizeof(fe_cases[0]); ++i) { for (var = 0; var <= 1; ++var) { test_inverse_field(&x_fe, &fe_cases[i][0], var); - check_fe_equal(&x_fe, &fe_cases[i][1]); + CHECK(check_fe_equal(&x_fe, &fe_cases[i][1])); test_inverse_field(&x_fe, &fe_cases[i][1], var); - check_fe_equal(&x_fe, &fe_cases[i][0]); + CHECK(check_fe_equal(&x_fe, &fe_cases[i][0])); } } for (i = 0; (size_t)i < sizeof(scalar_cases)/sizeof(scalar_cases[0]); ++i) { From e7bdddd9c9c4b9f4f44420f3c7eeaef44f0c82ff Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 1 Feb 2024 15:33:02 +0100 Subject: [PATCH 006/383] refactor: rename `check_fe_equal` -> `fe_equal` As this function doesn't do any checking, it's better to rename it, so that it's less likely to miss the needed `CHECK`. --- src/modules/ellswift/tests_impl.h | 8 ++++---- src/tests.c | 28 ++++++++++++++-------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 7d1efbc4..f96e3a12 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -188,9 +188,9 @@ void run_ellswift_tests(void) { CHECK(ret == ((testcase->enc_bitmap >> c) & 1)); if (ret) { secp256k1_fe x2; - CHECK(check_fe_equal(&t, &testcase->encs[c])); + CHECK(fe_equal(&t, &testcase->encs[c])); secp256k1_ellswift_xswiftec_var(&x2, &testcase->u, &testcase->encs[c]); - CHECK(check_fe_equal(&testcase->x, &x2)); + CHECK(fe_equal(&testcase->x, &x2)); } } } @@ -203,7 +203,7 @@ void run_ellswift_tests(void) { CHECK(ret); ret = secp256k1_pubkey_load(CTX, &ge, &pubkey); CHECK(ret); - CHECK(check_fe_equal(&testcase->x, &ge.x)); + CHECK(fe_equal(&testcase->x, &ge.x)); CHECK(secp256k1_fe_is_odd(&ge.y) == testcase->odd_y); } for (i = 0; (unsigned)i < sizeof(ellswift_xdh_tests_bip324) / sizeof(ellswift_xdh_tests_bip324[0]); ++i) { @@ -290,7 +290,7 @@ void run_ellswift_tests(void) { secp256k1_ecmult(&resj, &decj, &sec, NULL); secp256k1_ge_set_gej(&res, &resj); /* Compare. */ - CHECK(check_fe_equal(&res.x, &share_x)); + CHECK(fe_equal(&res.x, &share_x)); } /* Verify the joint behavior of secp256k1_ellswift_xdh */ for (i = 0; i < 200 * COUNT; i++) { diff --git a/src/tests.c b/src/tests.c index a64c3073..1caee85e 100644 --- a/src/tests.c +++ b/src/tests.c @@ -2953,7 +2953,7 @@ static void random_fe_non_square(secp256k1_fe *ns) { } } -static int check_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { +static int fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe an = *a; secp256k1_fe bn = *b; secp256k1_fe_normalize_weak(&an); @@ -3090,7 +3090,7 @@ static void run_field_half(void) { #endif secp256k1_fe_normalize_weak(&u); secp256k1_fe_add(&u, &u); - CHECK(check_fe_equal(&t, &u)); + CHECK(fe_equal(&t, &u)); /* Check worst-case input: ensure the LSB is 1 so that P will be added, * which will also cause all carries to be 1, since all limbs that can @@ -3109,7 +3109,7 @@ static void run_field_half(void) { #endif secp256k1_fe_normalize_weak(&u); secp256k1_fe_add(&u, &u); - CHECK(check_fe_equal(&t, &u)); + CHECK(fe_equal(&t, &u)); } } @@ -3136,7 +3136,7 @@ static void run_field_misc(void) { secp256k1_fe_add(&z, &q); /* z = x+v */ q = x; /* q = x */ secp256k1_fe_add_int(&q, v); /* q = x+v */ - CHECK(check_fe_equal(&q, &z)); + CHECK(fe_equal(&q, &z)); /* Test the fe equality and comparison operations. */ CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); CHECK(secp256k1_fe_equal(&x, &x)); @@ -3196,27 +3196,27 @@ static void run_field_misc(void) { secp256k1_fe_add(&y, &x); z = x; secp256k1_fe_mul_int(&z, 3); - CHECK(check_fe_equal(&y, &z)); + CHECK(fe_equal(&y, &z)); secp256k1_fe_add(&y, &x); secp256k1_fe_add(&z, &x); - CHECK(check_fe_equal(&z, &y)); + CHECK(fe_equal(&z, &y)); z = x; secp256k1_fe_mul_int(&z, 5); secp256k1_fe_mul(&q, &x, &fe5); - CHECK(check_fe_equal(&z, &q)); + CHECK(fe_equal(&z, &q)); secp256k1_fe_negate(&x, &x, 1); secp256k1_fe_add(&z, &x); secp256k1_fe_add(&q, &x); - CHECK(check_fe_equal(&y, &z)); - CHECK(check_fe_equal(&q, &y)); + CHECK(fe_equal(&y, &z)); + CHECK(fe_equal(&q, &y)); /* Check secp256k1_fe_half. */ z = x; secp256k1_fe_half(&z); secp256k1_fe_add(&z, &z); - CHECK(check_fe_equal(&x, &z)); + CHECK(fe_equal(&x, &z)); secp256k1_fe_add(&z, &z); secp256k1_fe_half(&z); - CHECK(check_fe_equal(&x, &z)); + CHECK(fe_equal(&x, &z)); } } @@ -3618,9 +3618,9 @@ static void run_inverse_tests(void) for (i = 0; (size_t)i < sizeof(fe_cases)/sizeof(fe_cases[0]); ++i) { for (var = 0; var <= 1; ++var) { test_inverse_field(&x_fe, &fe_cases[i][0], var); - CHECK(check_fe_equal(&x_fe, &fe_cases[i][1])); + CHECK(fe_equal(&x_fe, &fe_cases[i][1])); test_inverse_field(&x_fe, &fe_cases[i][1], var); - CHECK(check_fe_equal(&x_fe, &fe_cases[i][0])); + CHECK(fe_equal(&x_fe, &fe_cases[i][0])); } } for (i = 0; (size_t)i < sizeof(scalar_cases)/sizeof(scalar_cases[0]); ++i) { @@ -4556,7 +4556,7 @@ static void ecmult_const_mult_xonly(void) { /* Check that resj's X coordinate corresponds with resx. */ secp256k1_fe_sqr(&v, &resj.z); secp256k1_fe_mul(&v, &v, &resx); - CHECK(check_fe_equal(&v, &resj.x)); + CHECK(fe_equal(&v, &resj.x)); } /* Test that secp256k1_ecmult_const_xonly correctly rejects X coordinates not on curve. */ From e7ea32e30a9f628855c4ddc7533ebd5d2013dc40 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Thu, 22 Feb 2024 20:11:51 +0000 Subject: [PATCH 007/383] msan: Add SECP256K1_CHECKMEM_MSAN_DEFINE which applies to memory sanitizer and not valgrind --- src/checkmem.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/checkmem.h b/src/checkmem.h index f2169dec..7e333ce5 100644 --- a/src/checkmem.h +++ b/src/checkmem.h @@ -30,6 +30,8 @@ * - SECP256K1_CHECKMEM_DEFINE(p, len): * - marks the len-byte memory pointed to by p as defined data (public data, in the * context of constant-time checking). + * - SECP256K1_CHECKMEM_MSAN_DEFINE(p, len): + * - Like SECP256K1_CHECKMEM_DEFINE, but applies only to memory_sanitizer. * */ @@ -48,11 +50,16 @@ # define SECP256K1_CHECKMEM_ENABLED 1 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) # define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) +# define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) __msan_unpoison((p), (len)) # define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) # define SECP256K1_CHECKMEM_RUNNING() (1) # endif #endif +#if !defined SECP256K1_CHECKMEM_MSAN_DEFINE +# define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) SECP256K1_CHECKMEM_NOOP((p), (len)) +#endif + /* If valgrind integration is desired (through the VALGRIND define), implement the * SECP256K1_CHECKMEM_* macros using valgrind. */ #if !defined SECP256K1_CHECKMEM_ENABLED From 31ba40494428dcbf2eb5eb6f2328eca91b0b0746 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 21 Feb 2024 16:16:16 +0000 Subject: [PATCH 008/383] msan: notate variable assignments from assembly code msan isn't smart enough to see that these are set without some help. --- src/scalar_4x64_impl.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 7b9c542f..ede31a06 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -462,6 +462,14 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) : "S"(l), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m0, sizeof(m0)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m1, sizeof(m1)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m2, sizeof(m2)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m3, sizeof(m3)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m4, sizeof(m4)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m5, sizeof(m5)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&m6, sizeof(m6)); + /* Reduce 385 bits into 258. */ __asm__ __volatile__( /* Preload */ @@ -541,6 +549,12 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); + SECP256K1_CHECKMEM_MSAN_DEFINE(&p0, sizeof(p0)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&p1, sizeof(p1)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&p2, sizeof(p2)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&p3, sizeof(p3)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&p4, sizeof(p4)); + /* Reduce 258 bits into 256. */ __asm__ __volatile__( /* Preload */ @@ -586,6 +600,10 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) : "=g"(c) : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1) : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); + + SECP256K1_CHECKMEM_MSAN_DEFINE(r, sizeof(*r)); + SECP256K1_CHECKMEM_MSAN_DEFINE(&c, sizeof(c)); + #else secp256k1_uint128 c128; uint64_t c, c0, c1, c2; From 11420a7a2836114393b70f4d10bb81921403a360 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 1 Feb 2024 00:28:45 +0100 Subject: [PATCH 009/383] tests: improve fe_sqr test Currently the `run_sqr` test doesn't do anything with the result of the `fe_sqr` call. Improve that by checking that the equation `(x+y)*(x-y) = x^2 - y^2` holds for some random values y, as suggested in issue #1471 by real-or-random. The existing loop for generating the x values is kept as-is. --- src/tests.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/tests.c b/src/tests.c index 1caee85e..85b48812 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3285,18 +3285,31 @@ static void run_fe_mul(void) { } static void run_sqr(void) { - secp256k1_fe x, s; + int i; + secp256k1_fe x, y, lhs, rhs, tmp; - { - int i; - secp256k1_fe_set_int(&x, 1); - secp256k1_fe_negate(&x, &x, 1); + secp256k1_fe_set_int(&x, 1); + secp256k1_fe_negate(&x, &x, 1); - for (i = 1; i <= 512; ++i) { - secp256k1_fe_mul_int(&x, 2); - secp256k1_fe_normalize(&x); - secp256k1_fe_sqr(&s, &x); - } + for (i = 1; i <= 512; ++i) { + secp256k1_fe_mul_int(&x, 2); + secp256k1_fe_normalize(&x); + + /* Check that (x+y)*(x-y) = x^2 - y*2 for some random values y */ + random_fe_test(&y); + + lhs = x; + secp256k1_fe_add(&lhs, &y); /* lhs = x+y */ + secp256k1_fe_negate(&tmp, &y, 1); /* tmp = -y */ + secp256k1_fe_add(&tmp, &x); /* tmp = x-y */ + secp256k1_fe_mul(&lhs, &lhs, &tmp); /* lhs = (x+y)*(x-y) */ + + secp256k1_fe_sqr(&rhs, &x); /* rhs = x^2 */ + secp256k1_fe_sqr(&tmp, &y); /* tmp = y^2 */ + secp256k1_fe_negate(&tmp, &tmp, 1); /* tmp = -y^2 */ + secp256k1_fe_add(&rhs, &tmp); /* rhs = x^2 - y^2 */ + + CHECK(fe_equal(&lhs, &rhs)); } } From 2028069df2e16a05b332ae24c7ae63791f461063 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 1 Feb 2024 14:46:31 +0100 Subject: [PATCH 010/383] doc: clarify input requirements for secp256k1_fe_mul "... neither can be equal to b." could suggest that the values are not allowed to be identical, but what is meant here is that the mentioned inputs shouldn't point to the same object. --- src/field.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field.h b/src/field.h index bd589bf8..8c65a3af 100644 --- a/src/field.h +++ b/src/field.h @@ -255,8 +255,8 @@ static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); /** Multiply two field elements. * * On input, a and b must be valid field elements; r does not need to be initialized. - * r and a may point to the same object, but neither can be equal to b. The magnitudes - * of a and b must not exceed 8. + * r and a may point to the same object, but neither may point to the object pointed + * to by b. The magnitudes of a and b must not exceed 8. * Performs {r = a * b} * On output, r will have magnitude 1, but won't be normalized. */ From 84a93de4d2ba1063aa3d67d592db8ae0bb4a307e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 19 Mar 2024 17:15:14 +0100 Subject: [PATCH 011/383] ci: Add workaround for ASLR bug in sanitizers Fixes #1506. --- .github/actions/run-in-docker-action/action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index dbfaa4fe..126abc2d 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -36,6 +36,10 @@ runs: load: true cache-from: type=gha + - # Workaround for https://github.com/google/sanitizers/issues/1614 . + run: sudo sysctl -w vm.mmap_rnd_bits=28 + shell: bash + - # Tell Docker to pass environment variables in `env` into the container. run: > docker run \ From a5e8ab248447864873eae9b00f94175594477d66 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 19 Mar 2024 17:17:13 +0100 Subject: [PATCH 012/383] ci: Add sanitizer env variables to debug output --- ci/ci.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/ci.sh b/ci/ci.sh index 9cc71595..3999af4f 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -17,7 +17,8 @@ print_environment() { SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ EXAMPLES \ HOST WRAPPER_CMD \ - CC CFLAGS CPPFLAGS AR NM + CC CFLAGS CPPFLAGS AR NM \ + UBSAN_OPTIONS ASAN_OPTIONS LSAN_OPTIONS do eval "isset=\${$var+x}" if [ -n "$isset" ]; then From a61339149f1faae3c5d8e9ba533d96ff1ca2c32d Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Fri, 29 Mar 2024 15:04:39 +0000 Subject: [PATCH 013/383] change inconsistent array param to pointer The behavior is identical, but the former syntax suggests guarantees that don't actually exist. --- src/scalar_4x64_impl.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index ede31a06..835b7fa6 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -681,7 +681,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); } -static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { +static void secp256k1_scalar_mul_512(uint64_t *l8, const secp256k1_scalar *a, const secp256k1_scalar *b) { #ifdef USE_ASM_X86_64 const uint64_t *pb = b->d; __asm__ __volatile__( @@ -696,7 +696,7 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c /* (rax,rdx) = a0 * b0 */ "movq %%r15, %%rax\n" "mulq %%r11\n" - /* Extract l0 */ + /* Extract l8[0] */ "movq %%rax, 0(%%rsi)\n" /* (r8,r9,r10) = (rdx) */ "movq %%rdx, %%r8\n" @@ -714,7 +714,7 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" - /* Extract l1 */ + /* Extract l8[1] */ "movq %%r8, 8(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += a0 * b2 */ @@ -735,7 +735,7 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" - /* Extract l2 */ + /* Extract l8[2] */ "movq %%r9, 16(%%rsi)\n" "xorq %%r9, %%r9\n" /* (r10,r8,r9) += a0 * b3 */ @@ -764,7 +764,7 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" - /* Extract l3 */ + /* Extract l8[3] */ "movq %%r10, 24(%%rsi)\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += a1 * b3 */ @@ -785,7 +785,7 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" - /* Extract l4 */ + /* Extract l8[4] */ "movq %%r8, 32(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += a2 * b3 */ @@ -800,51 +800,51 @@ static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, c "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" - /* Extract l5 */ + /* Extract l8[5] */ "movq %%r9, 40(%%rsi)\n" /* (r10,r8) += a3 * b3 */ "movq %%r15, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" - /* Extract l6 */ + /* Extract l8[6] */ "movq %%r10, 48(%%rsi)\n" - /* Extract l7 */ + /* Extract l8[7] */ "movq %%r8, 56(%%rsi)\n" : "+d"(pb) - : "S"(l), "D"(a->d) + : "S"(l8), "D"(a->d) : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); #else /* 160 bit accumulator. */ uint64_t c0 = 0, c1 = 0; uint32_t c2 = 0; - /* l[0..7] = a[0..3] * b[0..3]. */ + /* l8[0..7] = a[0..3] * b[0..3]. */ muladd_fast(a->d[0], b->d[0]); - extract_fast(l[0]); + extract_fast(l8[0]); muladd(a->d[0], b->d[1]); muladd(a->d[1], b->d[0]); - extract(l[1]); + extract(l8[1]); muladd(a->d[0], b->d[2]); muladd(a->d[1], b->d[1]); muladd(a->d[2], b->d[0]); - extract(l[2]); + extract(l8[2]); muladd(a->d[0], b->d[3]); muladd(a->d[1], b->d[2]); muladd(a->d[2], b->d[1]); muladd(a->d[3], b->d[0]); - extract(l[3]); + extract(l8[3]); muladd(a->d[1], b->d[3]); muladd(a->d[2], b->d[2]); muladd(a->d[3], b->d[1]); - extract(l[4]); + extract(l8[4]); muladd(a->d[2], b->d[3]); muladd(a->d[3], b->d[2]); - extract(l[5]); + extract(l8[5]); muladd_fast(a->d[3], b->d[3]); - extract_fast(l[6]); + extract_fast(l8[6]); VERIFY_CHECK(c1 == 0); - l[7] = c0; + l8[7] = c0; #endif } From f7f0184ba1358cb8659607d2d0105628cb130e4f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 27 Mar 2024 15:18:57 +0000 Subject: [PATCH 014/383] msan: notate more variable assignments from assembly code This was missed in 31ba40494428dcbf2eb5eb6f2328eca91b0b0746 because older versions of clang did not complain about it. But clang-17, at least, does. --- src/scalar_4x64_impl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 835b7fa6..82cd957f 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -814,6 +814,9 @@ static void secp256k1_scalar_mul_512(uint64_t *l8, const secp256k1_scalar *a, co : "+d"(pb) : "S"(l8), "D"(a->d) : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); + + SECP256K1_CHECKMEM_MSAN_DEFINE(l8, sizeof(*l8) * 8); + #else /* 160 bit accumulator. */ uint64_t c0 = 0, c1 = 0; From a85e2233e701c3e3dd1673d187d7d8806de387ff Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 4 Apr 2024 11:40:19 +0200 Subject: [PATCH 015/383] ci: Note affected clangs in comment on ASLR quirk Resolves #1506. --- .github/actions/run-in-docker-action/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index 126abc2d..74933686 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -37,6 +37,7 @@ runs: cache-from: type=gha - # Workaround for https://github.com/google/sanitizers/issues/1614 . + # The underlying issue has been fixed in clang 18.1.3. run: sudo sysctl -w vm.mmap_rnd_bits=28 shell: bash From aa00a6b8924a7095e9bf650fcda4e69551af69b2 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 12 Apr 2024 17:24:29 +0200 Subject: [PATCH 016/383] Introduce CEIL_DIV macro and use it --- src/ecmult_impl.h | 6 +++--- src/util.h | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 6d14c7ac..2cf38399 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -42,7 +42,7 @@ #endif #define WNAF_BITS 128 -#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w)) +#define WNAF_SIZE_BITS(bits, w) CEIL_DIV(bits, w) #define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w) /* The number of objects allocated on the scratch space for ecmult_multi algorithms */ @@ -808,8 +808,8 @@ static int secp256k1_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n return 1; } /* Compute ceil(n/max_n_batch_points) and ceil(n/n_batches) */ - *n_batches = 1 + (n - 1) / max_n_batch_points; - *n_batch_points = 1 + (n - 1) / *n_batches; + *n_batches = CEIL_DIV(n, max_n_batch_points); + *n_batch_points = CEIL_DIV(n, *n_batches); return 1; } diff --git a/src/util.h b/src/util.h index 154d9ebc..b04a239d 100644 --- a/src/util.h +++ b/src/util.h @@ -170,7 +170,10 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ #define ALIGNMENT 16 #endif -#define ROUND_TO_ALIGN(size) ((((size) + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT) +/* ceil(x/y) for integers x > 0 and y > 0. Here, / denotes rational division. */ +#define CEIL_DIV(x, y) (1 + ((x) - 1) / (y)) + +#define ROUND_TO_ALIGN(size) (CEIL_DIV(size, ALIGNMENT) * ALIGNMENT) /* Macro for restrict, when available and not in a VERIFY build. */ #if defined(SECP256K1_BUILD) && defined(VERIFY) From ab45c3e0892ec6cffed714d89fb146bee694fcb2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Dec 2021 18:21:57 -0500 Subject: [PATCH 017/383] Initial gej blinding -> final ge blinding Instead of having the starting point of the ecmult_gen computation be offset, do it with the final point. This enables reasoning over the set of points reachable in intermediary computations, which can be leveraged by potential future optimization. Because the final point is in affine coordinates, its projective blinding is no longer possible. It will be reintroduced again in a different way, in a later commit. Also introduce some more comments and more descriptive names. --- src/ecmult_gen.h | 6 ++--- src/ecmult_gen_impl.h | 51 +++++++++++++++++++++++-------------------- src/tests.c | 25 +++++++++++---------- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index a430e8d5..23d94aba 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -32,9 +32,9 @@ typedef struct { /* Whether the context has been built. */ int built; - /* Blinding values used when computing (n-b)G + bG. */ - secp256k1_scalar blind; /* -b */ - secp256k1_gej initial; /* bG */ + /* Blinding values used when computing nG as (n-b)G + bG. */ + secp256k1_scalar scalar_offset; /* -b */ + secp256k1_ge ge_offset; /* bG */ } secp256k1_ecmult_gen_context; static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index af412173..d9ef58ce 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -25,8 +25,8 @@ static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_cont static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { ctx->built = 0; - secp256k1_scalar_clear(&ctx->blind); - secp256k1_gej_clear(&ctx->initial); + secp256k1_scalar_clear(&ctx->scalar_offset); + secp256k1_ge_clear(&ctx->ge_offset); } /* For accelerating the computation of a*G: @@ -51,12 +51,13 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_ge_storage adds; secp256k1_scalar gnb; int i, j, n_i; - + memset(&adds, 0, sizeof(adds)); - *r = ctx->initial; - /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ - secp256k1_scalar_add(&gnb, gn, &ctx->blind); - add.infinity = 0; + secp256k1_gej_set_infinity(r); + + /* Blind scalar/point multiplication by computing (gn-b)*G + b*G instead of gn*G. */ + secp256k1_scalar_add(&gnb, gn, &ctx->scalar_offset); + for (i = 0; i < n; i++) { n_i = secp256k1_scalar_get_bits(&gnb, i * bits, bits); for (j = 0; j < g; j++) { @@ -76,6 +77,11 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_gej_add_ge(r, r, &add); } n_i = 0; + + /* Correct for the scalar_offset added at the start (ge_offset = b*G, while b was + * subtracted from the input scalar gn). */ + secp256k1_gej_add_ge(r, r, &ctx->ge_offset); + secp256k1_ge_clear(&add); secp256k1_scalar_clear(&gnb); } @@ -84,19 +90,17 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { secp256k1_scalar b; secp256k1_gej gb; - secp256k1_fe s; unsigned char nonce32[32]; secp256k1_rfc6979_hmac_sha256 rng; unsigned char keydata[64]; if (seed32 == NULL) { - /* When seed is NULL, reset the initial point and blinding value. */ - secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); - secp256k1_gej_neg(&ctx->initial, &ctx->initial); - secp256k1_scalar_set_int(&ctx->blind, 1); + /* When seed is NULL, reset the final point and blinding value. */ + secp256k1_ge_neg(&ctx->ge_offset, &secp256k1_ge_const_g); + ctx->scalar_offset = secp256k1_scalar_one; return; } /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ - secp256k1_scalar_get_b32(keydata, &ctx->blind); + secp256k1_scalar_get_b32(keydata, &ctx->scalar_offset); /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, * and guards against weak or adversarial seeds. This is a simpler and safer interface than * asking the caller for blinding values directly and expecting them to retry on failure. @@ -105,24 +109,23 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const memcpy(keydata + 32, seed32, 32); secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); memset(keydata, 0, sizeof(keydata)); - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - secp256k1_fe_set_b32_mod(&s, nonce32); - secp256k1_fe_cmov(&s, &secp256k1_fe_one, secp256k1_fe_normalizes_to_zero(&s)); - /* Randomize the projection to defend against multiplier sidechannels. - Do this before our own call to secp256k1_ecmult_gen below. */ - secp256k1_gej_rescale(&ctx->initial, &s); - secp256k1_fe_clear(&s); + + /* TODO: reintroduce projective blinding. */ + + /* For a random blinding value b, set ctx->scalar_offset=-b, ctx->ge_offset=bG. */ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); secp256k1_scalar_set_b32(&b, nonce32, NULL); - /* A blinding value of 0 works, but would undermine the projection hardening. */ + /* The blinding value cannot be zero, as that would mean ge_offset = infinity, + * which secp256k1_gej_add_ge cannot handle. */ secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b)); secp256k1_rfc6979_hmac_sha256_finalize(&rng); memset(nonce32, 0, 32); - /* The random projection in ctx->initial ensures that gb will have a random projection. */ secp256k1_ecmult_gen(ctx, &gb, &b); secp256k1_scalar_negate(&b, &b); - ctx->blind = b; - ctx->initial = gb; + ctx->scalar_offset = b; + secp256k1_ge_set_gej(&ctx->ge_offset, &gb); + + /* Clean up. */ secp256k1_scalar_clear(&b); secp256k1_gej_clear(&gb); } diff --git a/src/tests.c b/src/tests.c index 85b48812..e8b22a63 100644 --- a/src/tests.c +++ b/src/tests.c @@ -248,8 +248,8 @@ static void run_selftest_tests(void) { static int ecmult_gen_context_eq(const secp256k1_ecmult_gen_context *a, const secp256k1_ecmult_gen_context *b) { return a->built == b->built - && secp256k1_scalar_eq(&a->blind, &b->blind) - && secp256k1_gej_eq_var(&a->initial, &b->initial); + && secp256k1_scalar_eq(&a->scalar_offset, &b->scalar_offset) + && secp256k1_ge_eq_var(&a->ge_offset, &b->ge_offset); } static int context_eq(const secp256k1_context *a, const secp256k1_context *b) { @@ -5570,18 +5570,18 @@ static void test_ecmult_gen_blind(void) { unsigned char seed32[32]; secp256k1_gej pgej; secp256k1_gej pgej2; - secp256k1_gej i; + secp256k1_ge p; secp256k1_ge pge; random_scalar_order_test(&key); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); secp256k1_testrand256(seed32); - b = CTX->ecmult_gen_ctx.blind; - i = CTX->ecmult_gen_ctx.initial; + b = CTX->ecmult_gen_ctx.scalar_offset; + p = CTX->ecmult_gen_ctx.ge_offset; secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, seed32); - CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.blind)); + CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej2, &key); CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); - CHECK(!gej_xyz_equals_gej(&i, &CTX->ecmult_gen_ctx.initial)); + CHECK(!secp256k1_ge_eq_var(&p, &CTX->ecmult_gen_ctx.ge_offset)); secp256k1_ge_set_gej(&pge, &pgej); CHECK(secp256k1_gej_eq_ge_var(&pgej2, &pge)); } @@ -5589,13 +5589,14 @@ static void test_ecmult_gen_blind(void) { static void test_ecmult_gen_blind_reset(void) { /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ secp256k1_scalar b; - secp256k1_gej initial; + secp256k1_ge p1, p2; secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); - b = CTX->ecmult_gen_ctx.blind; - initial = CTX->ecmult_gen_ctx.initial; + b = CTX->ecmult_gen_ctx.scalar_offset; + p1 = CTX->ecmult_gen_ctx.ge_offset; secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); - CHECK(secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.blind)); - CHECK(gej_xyz_equals_gej(&initial, &CTX->ecmult_gen_ctx.initial)); + CHECK(secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); + p2 = CTX->ecmult_gen_ctx.ge_offset; + CHECK(secp256k1_ge_eq_var(&p1, &p2)); } static void run_ecmult_gen_blind(void) { From 486518b35026715bd286bf1595ab0f51968c4b6f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 30 Dec 2021 12:22:58 -0500 Subject: [PATCH 018/383] Make exhaustive tests's scalar_inverse(&x,&x) work The old code overwrote the input at the start of the function, making a call like secp256k1_scalar_inverse(&x,&x) always fail. --- src/scalar_low_impl.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 0895db6a..7f53e626 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -169,17 +169,22 @@ static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const se static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { int i; - *r = 0; + uint32_t res = 0; SECP256K1_SCALAR_VERIFY(x); - for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) - if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) - *r = i; + for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { + if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) { + res = i; + break; + } + } - SECP256K1_SCALAR_VERIFY(r); /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus * have a composite group order; fix it in exhaustive_tests.c). */ - VERIFY_CHECK(*r != 0); + VERIFY_CHECK(res != 0); + *r = res; + + SECP256K1_SCALAR_VERIFY(r); } static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { From fde1dfcd8d0a2a6444491b235d9ae2926f4ad7f4 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 26 Dec 2021 18:09:27 -0500 Subject: [PATCH 019/383] Signed-digit multi-comb ecmult_gen algorithm This introduces the signed-digit multi-comb multiplication algorithm for constant-time G multiplications (ecmult_gen). It is based on section 3.3 of "Fast and compact elliptic-curve cryptography" by Mike Hamburg (see https://eprint.iacr.org/2012/309). Original implementation by Peter Dettman, with changes by Pieter Wuille to use scalars for recoding, and additional comments. --- src/ecmult_gen.h | 106 +- src/ecmult_gen_compute_table.h | 4 +- src/ecmult_gen_compute_table_impl.h | 146 +- src/ecmult_gen_impl.h | 216 +- src/precompute_ecmult_gen.c | 69 +- src/precomputed_ecmult_gen.c | 10091 +------------------------- src/precomputed_ecmult_gen.h | 4 +- src/tests_exhaustive.c | 2 +- 8 files changed, 762 insertions(+), 9876 deletions(-) diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 23d94aba..edac5a8b 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -1,5 +1,5 @@ /*********************************************************************** - * Copyright (c) 2013, 2014 Pieter Wuille * + * Copyright (c) Pieter Wuille, Peter Dettman * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ @@ -10,31 +10,105 @@ #include "scalar.h" #include "group.h" -#ifndef ECMULT_GEN_PREC_BITS -# define ECMULT_GEN_PREC_BITS 4 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("ECMULT_GEN_PREC_BITS undefined, assuming default value") + +/* Configuration parameters for the signed-digit multi-comb algorithm: + * + * - COMB_BLOCKS is the number of blocks the input is split into. Each + * has a corresponding table. + * - COMB_TEETH is the number of bits simultaneously covered by one table. + * + * The comb's spacing (COMB_SPACING), or the distance between the teeth, + * is defined as ceil(256 / (COMB_BLOCKS * COMB_TEETH)). Each block covers + * COMB_SPACING * COMB_TEETH consecutive bits in the input. + * + * The size of the precomputed table is COMB_BLOCKS * (1 << (COMB_TEETH - 1)) + * secp256k1_ge_storages. + * + * The number of point additions equals COMB_BLOCKS * COMB_SPACING. Each point + * addition involves a cmov from (1 << (COMB_TEETH - 1)) table entries and a + * conditional negation. + * + * The number of point doublings is COMB_SPACING - 1. */ + +#if defined(EXHAUSTIVE_TEST_ORDER) +/* We need to control these values for exhaustive tests because + * the table cannot have infinities in them (secp256k1_ge_storage + * doesn't support infinities) */ +# undef COMB_BLOCKS +# undef COMB_TEETH +# if EXHAUSTIVE_TEST_ORDER > 32 +# define COMB_BLOCKS 52 +# define COMB_TEETH 5 +# elif EXHAUSTIVE_TEST_ORDER > 16 +# define COMB_BLOCKS 64 +# define COMB_TEETH 4 +# elif EXHAUSTIVE_TEST_ORDER > 8 +# define COMB_BLOCKS 86 +# define COMB_TEETH 3 +# elif EXHAUSTIVE_TEST_ORDER > 4 +# define COMB_BLOCKS 128 +# define COMB_TEETH 2 +# else +# define COMB_BLOCKS 256 +# define COMB_TEETH 1 # endif +#else /* !defined(EXHAUSTIVE_TEST_ORDER) */ +/* Use (11, 6) as default configuration, which results in a 22 kB table. */ +# ifndef COMB_BLOCKS +# define COMB_BLOCKS 11 +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") +# endif +# endif +# ifndef COMB_TEETH +# define COMB_TEETH 6 +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") +# endif +# endif +#endif /* defined(EXHAUSTIVE_TEST_ORDER) */ + +/* Range checks on the parameters. */ +#if !(1 <= COMB_BLOCKS && COMB_BLOCKS <= 256) +# error "COMB_BLOCKS must be in the range [1, 256]" +#endif +#if !(1 <= COMB_TEETH && COMB_TEETH <= 8) +# error "COMB_TEETH must be in the range [1, 8]" +#endif + +/* The remaining COMB_* parameters are derived values, don't modify these. */ +/* - The distance between the teeth of each comb. */ +#define COMB_SPACING CEIL_DIV(256, COMB_BLOCKS * COMB_TEETH) +/* - The number of bits covered by all the blocks; must be at least 256. */ +#define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) +/* - The number of entries per table. */ +#define COMB_POINTS (1 << (COMB_TEETH - 1)) + +/* Additional sanity checks. */ +#if (COMB_BLOCKS - 1) * COMB_TEETH * COMB_SPACING >= 256 +# error "COMB_BLOCKS can be reduced" +#endif +#if COMB_BLOCKS * (COMB_TEETH - 1) * COMB_SPACING >= 256 +# error "COMB_TEETH can be reduced" #endif #ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_DEF(ECMULT_GEN_PREC_BITS) +# pragma message DEBUG_CONFIG_DEF(COMB_BLOCKS) +# pragma message DEBUG_CONFIG_DEF(COMB_TEETH) #endif -#if ECMULT_GEN_PREC_BITS != 2 && ECMULT_GEN_PREC_BITS != 4 && ECMULT_GEN_PREC_BITS != 8 -# error "Set ECMULT_GEN_PREC_BITS to 2, 4 or 8." -#endif - -#define ECMULT_GEN_PREC_G(bits) (1 << bits) -#define ECMULT_GEN_PREC_N(bits) (256 / bits) - typedef struct { /* Whether the context has been built. */ int built; - /* Blinding values used when computing nG as (n-b)G + bG. */ - secp256k1_scalar scalar_offset; /* -b */ - secp256k1_ge ge_offset; /* bG */ + /* Values chosen such that + * + * n*G == comb(n + (2^COMB_BITS-1)/2 + scalar_offset, G/2) + ge_offset. + * + * This expression lets us use scalar blinding and optimize the comb precomputation. See + * ecmult_gen_impl.h for more details. */ + secp256k1_scalar scalar_offset; + secp256k1_ge ge_offset; } secp256k1_ecmult_gen_context; static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); diff --git a/src/ecmult_gen_compute_table.h b/src/ecmult_gen_compute_table.h index e577158d..cd4f9233 100644 --- a/src/ecmult_gen_compute_table.h +++ b/src/ecmult_gen_compute_table.h @@ -1,5 +1,5 @@ /*********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Copyright (c) Pieter Wuille, Gregory Maxwell * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ @@ -9,6 +9,6 @@ #include "ecmult_gen.h" -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits); +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth); #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ diff --git a/src/ecmult_gen_compute_table_impl.h b/src/ecmult_gen_compute_table_impl.h index dfbacdbf..5ad0b0b3 100644 --- a/src/ecmult_gen_compute_table_impl.h +++ b/src/ecmult_gen_compute_table_impl.h @@ -1,5 +1,5 @@ /*********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Copyright (c) Pieter Wuille, Gregory Maxwell, Peter Dettman * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ @@ -10,74 +10,96 @@ #include "ecmult_gen_compute_table.h" #include "group_impl.h" #include "field_impl.h" +#include "scalar_impl.h" #include "ecmult_gen.h" #include "util.h" -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int bits) { - int g = ECMULT_GEN_PREC_G(bits); - int n = ECMULT_GEN_PREC_N(bits); +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth) { + size_t points = ((size_t)1) << (teeth - 1); + size_t points_total = points * blocks; + int spacing = (256 + blocks * teeth - 1) / (blocks * teeth); + secp256k1_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); + secp256k1_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); + secp256k1_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); + secp256k1_gej u; + size_t vs_pos = 0; + secp256k1_scalar half; + int block, i; - secp256k1_ge* prec = checked_malloc(&default_error_callback, n * g * sizeof(*prec)); - secp256k1_gej gj; - secp256k1_gej nums_gej; - int i, j; + VERIFY_CHECK(points_total > 0); - VERIFY_CHECK(g > 0); - VERIFY_CHECK(n > 0); - - /* get the generator */ - secp256k1_gej_set_ge(&gj, gen); - - /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ - { - static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; - secp256k1_fe nums_x; - secp256k1_ge nums_ge; - int r; - r = secp256k1_fe_set_b32_limit(&nums_x, nums_b32); - (void)r; - VERIFY_CHECK(r); - r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); - (void)r; - VERIFY_CHECK(r); - secp256k1_gej_set_ge(&nums_gej, &nums_ge); - /* Add G to make the bits in x uniformly distributed. */ - secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, gen, NULL); - } - - /* compute prec. */ - { - secp256k1_gej gbase; - secp256k1_gej numsbase; - secp256k1_gej* precj = checked_malloc(&default_error_callback, n * g * sizeof(*precj)); /* Jacobian versions of prec. */ - gbase = gj; /* PREC_G^j * G */ - numsbase = nums_gej; /* 2^j * nums. */ - for (j = 0; j < n; j++) { - /* Set precj[j*PREC_G .. j*PREC_G+(PREC_G-1)] to (numsbase, numsbase + gbase, ..., numsbase + (PREC_G-1)*gbase). */ - precj[j*g] = numsbase; - for (i = 1; i < g; i++) { - secp256k1_gej_add_var(&precj[j*g + i], &precj[j*g + i - 1], &gbase, NULL); - } - /* Multiply gbase by PREC_G. */ - for (i = 0; i < bits; i++) { - secp256k1_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - secp256k1_gej_double_var(&numsbase, &numsbase, NULL); - if (j == n - 2) { - /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ - secp256k1_gej_neg(&numsbase, &numsbase); - secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); - } - } - secp256k1_ge_set_all_gej_var(prec, precj, n * g); - free(precj); - } - for (j = 0; j < n; j++) { - for (i = 0; i < g; i++) { - secp256k1_ge_to_storage(&table[j*g + i], &prec[j*g + i]); + /* u is the running power of two times gen we're working with, initially gen/2. */ + secp256k1_scalar_half(&half, &secp256k1_scalar_one); + secp256k1_gej_set_infinity(&u); + for (i = 255; i >= 0; --i) { + /* Use a very simple multiplication ladder to avoid dependency on ecmult. */ + secp256k1_gej_double_var(&u, &u, NULL); + if (secp256k1_scalar_get_bits(&half, i, 1)) { + secp256k1_gej_add_ge_var(&u, &u, gen, NULL); } } +#ifdef VERIFY + { + /* Verify that u*2 = gen. */ + secp256k1_gej double_u; + secp256k1_gej_double_var(&double_u, &u, NULL); + VERIFY_CHECK(secp256k1_gej_eq_ge_var(&double_u, gen)); + } +#endif + + for (block = 0; block < blocks; ++block) { + int tooth; + /* Here u = 2^(block*teeth*spacing) * gen/2. */ + secp256k1_gej sum; + secp256k1_gej_set_infinity(&sum); + for (tooth = 0; tooth < teeth; ++tooth) { + /* Here u = 2^((block*teeth + tooth)*spacing) * gen/2. */ + int bit_off; + /* Make sum = sum(2^((block*teeth + t)*spacing), t=0..tooth) * gen/2. */ + secp256k1_gej_add_var(&sum, &sum, &u, NULL); + /* Make u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ + secp256k1_gej_double_var(&u, &u, NULL); + /* Make ds[tooth] = u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ + ds[tooth] = u; + /* Make u = 2^((block*teeth + tooth + 1)*spacing) * gen/2. */ + for (bit_off = 1; bit_off < spacing; ++bit_off) { + secp256k1_gej_double_var(&u, &u, NULL); + } + } + /* Now u = 2^((block*teeth + teeth)*spacing) * gen/2 + * = 2^((block+1)*teeth*spacing) * gen/2 */ + + /* Next, compute the table entries for block number block in Jacobian coordinates. + * The entries will occupy vs[block*points + i] for i=0..points-1. + * We start by computing the first (i=0) value corresponding to all summed + * powers of two times G being negative. */ + secp256k1_gej_neg(&vs[vs_pos++], &sum); + /* And then teeth-1 times "double" the range of i values for which the table + * is computed: in each iteration, double the table by taking an existing + * table entry and adding ds[tooth]. */ + for (tooth = 0; tooth < teeth - 1; ++tooth) { + size_t stride = ((size_t)1) << tooth; + size_t index; + for (index = 0; index < stride; ++index, ++vs_pos) { + secp256k1_gej_add_var(&vs[vs_pos], &vs[vs_pos - stride], &ds[tooth], NULL); + } + } + } + VERIFY_CHECK(vs_pos == points_total); + + /* Convert all points simultaneously from secp256k1_gej to secp256k1_ge. */ + secp256k1_ge_set_all_gej_var(prec, vs, points_total); + /* Convert all points from secp256k1_ge to secp256k1_ge_storage output. */ + for (block = 0; block < blocks; ++block) { + size_t index; + for (index = 0; index < points; ++index) { + secp256k1_ge_to_storage(&table[block * points + index], &prec[block * points + index]); + } + } + + /* Free memory. */ + free(vs); + free(ds); free(prec); } diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index d9ef58ce..b8b40038 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -1,5 +1,5 @@ /*********************************************************************** - * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Copyright (c) Pieter Wuille, Gregory Maxwell, Peter Dettman * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ @@ -29,38 +29,180 @@ static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx secp256k1_ge_clear(&ctx->ge_offset); } -/* For accelerating the computation of a*G: - * To harden against timing attacks, use the following mechanism: - * * Break up the multiplicand into groups of PREC_BITS bits, called n_0, n_1, n_2, ..., n_(PREC_N-1). - * * Compute sum(n_i * (PREC_G)^i * G + U_i, i=0 ... PREC_N-1), where: - * * U_i = U * 2^i, for i=0 ... PREC_N-2 - * * U_i = U * (1-2^(PREC_N-1)), for i=PREC_N-1 - * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0 ... PREC_N-1) = 0. - * For each i, and each of the PREC_G possible values of n_i, (n_i * (PREC_G)^i * G + U_i) is - * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0 ... PREC_N-1). - * None of the resulting prec group elements have a known scalar, and neither do any of - * the intermediate sums while computing a*G. - * The prec values are stored in secp256k1_ecmult_gen_prec_table[i][n_i] = n_i * (PREC_G)^i * G + U_i. - */ -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { - int bits = ECMULT_GEN_PREC_BITS; - int g = ECMULT_GEN_PREC_G(bits); - int n = ECMULT_GEN_PREC_N(bits); +/* Compute the scalar (2^COMB_BITS - 1) / 2, the difference between the gn argument to + * secp256k1_ecmult_gen, and the scalar whose encoding the table lookup bits are drawn + * from (before applying blinding). */ +static void secp256k1_ecmult_gen_scalar_diff(secp256k1_scalar* diff) { + int i; + /* Compute scalar -1/2. */ + secp256k1_scalar neghalf; + secp256k1_scalar_half(&neghalf, &secp256k1_scalar_one); + secp256k1_scalar_negate(&neghalf, &neghalf); + + /* Compute offset = 2^(COMB_BITS - 1). */ + *diff = secp256k1_scalar_one; + for (i = 0; i < COMB_BITS - 1; ++i) { + secp256k1_scalar_add(diff, diff, diff); + } + + /* The result is the sum 2^(COMB_BITS - 1) + (-1/2). */ + secp256k1_scalar_add(diff, diff, &neghalf); +} + +static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { + uint32_t comb_off; secp256k1_ge add; + secp256k1_fe neg; secp256k1_ge_storage adds; - secp256k1_scalar gnb; - int i, j, n_i; + secp256k1_scalar d; memset(&adds, 0, sizeof(adds)); + + /* We want to compute R = gn*G. + * + * To blind the scalar used in the computation, we rewrite this to be + * R = (gn - b)*G + b*G, with a blinding value b determined by the context. + * + * The multiplication (gn-b)*G will be performed using a signed-digit multi-comb (see Section + * 3.3 of "Fast and compact elliptic-curve cryptography" by Mike Hamburg, + * https://eprint.iacr.org/2012/309). + * + * Let comb(s, P) = sum((2*s[i]-1)*2^i*P for i=0..COMB_BITS-1), where s[i] is the i'th bit of + * the binary representation of scalar s. So the s[i] values determine whether -2^i*P (s[i]=0) + * or +2^i*P (s[i]=1) are added together. COMB_BITS is at least 256, so all bits of s are + * covered. By manipulating: + * + * comb(s, P) = sum((2*s[i]-1)*2^i*P for i=0..COMB_BITS-1) + * <=> comb(s, P) = sum((2*s[i]-1)*2^i for i=0..COMB_BITS-1) * P + * <=> comb(s, P) = (2*sum(s[i]*2^i for i=0..COMB_BITS-1) - sum(2^i for i=0..COMB_BITS-1)) * P + * <=> comb(s, P) = (2*s - (2^COMB_BITS - 1)) * P + * + * If we wanted to compute (gn-b)*G as comb(s, G), it would need to hold that + * + * (gn - b) * G = (2*s - (2^COMB_BITS - 1)) * G + * <=> s = (gn - b + (2^COMB_BITS - 1))/2 (mod order) + * + * We use an alternative here that avoids the modular division by two: instead we compute + * (gn-b)*G as comb(d, G/2). For that to hold it must be the case that + * + * (gn - b) * G = (2*d - (2^COMB_BITS - 1)) * (G/2) + * <=> d = gn - b + (2^COMB_BITS - 1)/2 (mod order) + * + * Adding precomputation, our final equations become: + * + * ctx->scalar_offset = -b + * ctx->ge_offset = b*G + * d = gn + ctx->scalar_offset + (2^COMB_BITS - 1)/2 (mod order) + * R = comb(d, G/2) + ctx->ge_offset + * + * comb(d, G/2) function is then computed by summing + or - 2^(i-1)*G, for i=0..COMB_BITS-1, + * depending on the value of the bits d[i] of the binary representation of scalar d. + */ + + /* Compute the scalar d = (gn + ctx->scalar_offset + (2^COMB_BITS - 1)/2). */ + secp256k1_ecmult_gen_scalar_diff(&d); + secp256k1_scalar_add(&d, &d, &ctx->scalar_offset); + secp256k1_scalar_add(&d, &d, gn); + + /* In secp256k1_ecmult_gen_prec_table we have precomputed sums of the + * (2*d[i]-1) * 2^(i-1) * G points, for various combinations of i positions. + * We rewrite our equation in terms of these table entries. + * + * Let mask(b) = sum(2^((b*COMB_TEETH + t)*COMB_SPACING) for t=0..COMB_TEETH-1), + * with b ranging from 0 to COMB_BLOCKS-1. So for example with COMB_BLOCKS=11, + * COMB_TEETH=6, COMB_SPACING=4, we would have: + * mask(0) = 2^0 + 2^4 + 2^8 + 2^12 + 2^16 + 2^20, + * mask(1) = 2^24 + 2^28 + 2^32 + 2^36 + 2^40 + 2^44, + * mask(2) = 2^48 + 2^52 + 2^56 + 2^60 + 2^64 + 2^68, + * ... + * mask(10) = 2^240 + 2^244 + 2^248 + 2^252 + 2^256 + 2^260 + * + * We will split up the bits d[i] using these masks. Specifically, each mask is + * used COMB_SPACING times, with different shifts: + * + * d = (d & mask(0)<<0) + (d & mask(1)<<0) + ... + (d & mask(COMB_BLOCKS-1)<<0) + + * (d & mask(0)<<1) + (d & mask(1)<<1) + ... + (d & mask(COMB_BLOCKS-1)<<1) + + * ... + * (d & mask(0)<<(COMB_SPACING-1)) + ... + * + * Now define table(b, m) = (m - mask(b)/2) * G, and we will precompute these values for + * b=0..COMB_BLOCKS-1, and for all values m which (d & mask(b)) can take (so m can take on + * 2^COMB_TEETH distinct values). + * + * If m=(d & mask(b)), then table(b, m) is the sum of 2^i * (2*d[i]-1) * G/2, with i + * iterating over the set bits in mask(b). In our example, table(2, 2^48 + 2^56 + 2^68) + * would equal (2^48 - 2^52 + 2^56 - 2^60 - 2^64 + 2^68) * G/2. + * + * With that, we can rewrite comb(d, G/2) as: + * + * 2^0 * (table(0, d>>0 & mask(0)) + ... + table(COMB_BLOCKS-1, d>>0 & mask(COMP_BLOCKS-1))) + * + 2^1 * (table(0, d>>1 & mask(0)) + ... + table(COMB_BLOCKS-1, d>>1 & mask(COMP_BLOCKS-1))) + * + 2^2 * (table(0, d>>2 & mask(0)) + ... + table(COMB_BLOCKS-1, d>>2 & mask(COMP_BLOCKS-1))) + * + ... + * + 2^(COMB_SPACING-1) * (table(0, d>>(COMB_SPACING-1) & mask(0)) + ...) + * + * Or more generically as + * + * sum(2^i * sum(table(b, d>>i & mask(b)), b=0..COMB_BLOCKS-1), i=0..COMB_SPACING-1) + * + * This is implemented using an outer loop that runs in reverse order over the lines of this + * equation, which in each iteration runs an inner loop that adds the terms of that line and + * then doubles the result before proceeding to the next line. + * + * In pseudocode: + * c = infinity + * for comb_off in range(COMB_SPACING - 1, -1, -1): + * for block in range(COMB_BLOCKS): + * c += table(block, (d >> comb_off) & mask(block)) + * if comb_off > 0: + * c = 2*c + * return c + * + * This computes c = comb(d, G/2), and thus finally R = c + ctx->ge_offset. Note that it would + * be possible to apply an initial offset instead of a final offset (moving ge_offset to take + * the place of infinity above), but the chosen approach allows using (in a future improvement) + * an incomplete addition formula for most of the multiplication. + * + * The last question is how to implement the table(b, m) function. For any value of b, + * m=(d & mask(b)) can only take on at most 2^COMB_TEETH possible values (the last one may have + * fewer as there mask(b) may exceed the curve order). So we could create COMB_BLOCK tables + * which contain a value for each such m value. + * + * Now note that if m=(d & mask(b)), then flipping the relevant bits of m results in negating + * the result of table(b, m). This is because table(b,m XOR mask(b)) = table(b, mask(b) - m) = + * (mask(b) - m - mask(b)/2)*G = (-m + mask(b)/2)*G = -(m - mask(b)/2)*G = -table(b, m). + * Because of this it suffices to only store the first half of the m values for every b. If an + * entry from the second half is needed, we look up its bit-flipped version instead, and negate + * it. + * + * secp256k1_ecmult_gen_prec_table[b][index] stores the table(b, m) entries. Index + * is the relevant mask(b) bits of m packed together without gaps. */ + secp256k1_gej_set_infinity(r); + /* Outer loop: iterate over comb_off from COMB_SPACING - 1 down to 0. */ + comb_off = COMB_SPACING - 1; + while (1) { + uint32_t block; + uint32_t bit_pos = comb_off; + /* Inner loop: for each block, add table entries to the result. */ + for (block = 0; block < COMB_BLOCKS; ++block) { + /* Gather the mask(block)-selected bits of d into bits. They're packed: + * bits[tooth] = d[(block*COMB_TEETH + tooth)*COMB_SPACING + comb_off]. */ + uint32_t bits = 0, sign, abs, index, tooth; + for (tooth = 0; tooth < COMB_TEETH && bit_pos < 256; ++tooth) { + uint32_t bit = secp256k1_scalar_get_bits(&d, bit_pos, 1); + bits |= bit << tooth; + bit_pos += COMB_SPACING; + } - /* Blind scalar/point multiplication by computing (gn-b)*G + b*G instead of gn*G. */ - secp256k1_scalar_add(&gnb, gn, &ctx->scalar_offset); + /* If the top bit of bits is 1, flip them all (corresponding to looking up + * the negated table value), and remember to negate the result in sign. */ + sign = (bits >> (COMB_TEETH - 1)) & 1; + abs = (bits ^ -sign) & (COMB_POINTS - 1); + VERIFY_CHECK(sign == 0 || sign == 1); + VERIFY_CHECK(abs < COMB_POINTS); - for (i = 0; i < n; i++) { - n_i = secp256k1_scalar_get_bits(&gnb, i * bits, bits); - for (j = 0; j < g; j++) { /** This uses a conditional move to avoid any secret data in array indexes. * _Any_ use of secret indexes has been demonstrated to result in timing * sidechannels, even when the cache-line access patterns are uniform. @@ -71,19 +213,33 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 * by Dag Arne Osvik, Adi Shamir, and Eran Tromer * (https://www.tau.ac.il/~tromer/papers/cache.pdf) */ - secp256k1_ge_storage_cmov(&adds, &secp256k1_ecmult_gen_prec_table[i][j], j == n_i); + for (index = 0; index < COMB_POINTS; ++index) { + secp256k1_ge_storage_cmov(&adds, &secp256k1_ecmult_gen_prec_table[block][index], index == abs); + } + + /* Set add=adds or add=-adds, in constant time, based on sign. */ + secp256k1_ge_from_storage(&add, &adds); + secp256k1_fe_negate(&neg, &add.y, 1); + secp256k1_fe_cmov(&add.y, &neg, sign); + + /* Add the looked up and conditionally negated value to r. */ + secp256k1_gej_add_ge(r, r, &add); } - secp256k1_ge_from_storage(&add, &adds); - secp256k1_gej_add_ge(r, r, &add); + + /* Double the result, except in the last iteration. */ + if (comb_off-- == 0) break; + secp256k1_gej_double(r, r); } - n_i = 0; /* Correct for the scalar_offset added at the start (ge_offset = b*G, while b was * subtracted from the input scalar gn). */ secp256k1_gej_add_ge(r, r, &ctx->ge_offset); + /* Cleanup. */ + secp256k1_fe_clear(&neg); secp256k1_ge_clear(&add); - secp256k1_scalar_clear(&gnb); + memset(&adds, 0, sizeof(adds)); + secp256k1_scalar_clear(&d); } /* Setup blinding values for secp256k1_ecmult_gen. */ diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index ce648cb9..11ab8ba0 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -17,10 +17,42 @@ #include "ecmult_gen.h" #include "ecmult_gen_compute_table_impl.h" +static const int CONFIGS[1][2] = { + {11, 6} +}; + +static void print_table(FILE* fp, int blocks, int teeth) { + size_t points = ((size_t)1) << (teeth - 1); + int outer; + size_t inner; + + secp256k1_ge_storage* table = checked_malloc(&default_error_callback, blocks * points * sizeof(secp256k1_ge_storage)); + secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth); + + fprintf(fp, "#elif (COMB_BLOCKS == %d) && (COMB_TEETH == %d)\n", blocks, teeth); + for (outer = 0; outer != blocks; outer++) { + fprintf(fp,"{"); + for (inner = 0; inner != points; inner++) { + fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 + ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")", + SECP256K1_GE_STORAGE_CONST_GET(table[outer * points + inner])); + if (inner != points - 1) { + fprintf(fp,",\n"); + } + } + if (outer != blocks - 1) { + fprintf(fp,"},\n"); + } else { + fprintf(fp,"}\n"); + } + } + free(table); +} + int main(int argc, char **argv) { const char outfile[] = "src/precomputed_ecmult_gen.c"; FILE* fp; - int bits; + size_t config; (void)argc; (void)argv; @@ -40,36 +72,15 @@ int main(int argc, char **argv) { fprintf(fp, "# error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode\n"); fprintf(fp, "#endif /* EXHAUSTIVE_TEST_ORDER */\n"); fprintf(fp, "#define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u)\n"); - fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = {\n"); - for (bits = 2; bits <= 8; bits *= 2) { - int g = ECMULT_GEN_PREC_G(bits); - int n = ECMULT_GEN_PREC_N(bits); - int inner, outer; - - secp256k1_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(secp256k1_ge_storage)); - secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, bits); - - fprintf(fp, "#if ECMULT_GEN_PREC_BITS == %d\n", bits); - for(outer = 0; outer != n; outer++) { - fprintf(fp,"{"); - for(inner = 0; inner != g; inner++) { - fprintf(fp, "S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 - ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")", - SECP256K1_GE_STORAGE_CONST_GET(table[outer * g + inner])); - if (inner != g - 1) { - fprintf(fp,",\n"); - } - } - if (outer != n - 1) { - fprintf(fp,"},\n"); - } else { - fprintf(fp,"}\n"); - } - } - fprintf(fp, "#endif\n"); - free(table); + fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = {\n"); + fprintf(fp, "#if 0\n"); + for (config = 0; config < sizeof(CONFIGS) / sizeof(*CONFIGS); ++config) { + print_table(fp, CONFIGS[config][0], CONFIGS[config][1]); } + fprintf(fp, "#else\n"); + fprintf(fp, "# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build.\n"); + fprintf(fp, "#endif\n"); fprintf(fp, "};\n"); fprintf(fp, "#undef S\n"); diff --git a/src/precomputed_ecmult_gen.c b/src/precomputed_ecmult_gen.c index 75ec59c2..25519d31 100644 --- a/src/precomputed_ecmult_gen.c +++ b/src/precomputed_ecmult_gen.c @@ -7,9740 +7,363 @@ # error Cannot compile precomputed_ecmult_gen.c in exhaustive test mode #endif /* EXHAUSTIVE_TEST_ORDER */ #define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) -const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)] = { -#if ECMULT_GEN_PREC_BITS == 2 -{S(3a9ed373,6eed3eec,9aeb5ac0,21b54652,56817b1f,8de6cd0,fbcee548,ba044bb5,7bcc5928,bdc9c023,dfc663b8,9e4f6969,ab751798,8e600ec1,d242010c,45c7974a), -S(e44d7675,c3cb2857,4e133c01,a74f4afc,5ce684f8,4a789711,603f7c4f,50abef58,25bcb62f,fe2e2ce2,196ad86c,a006e20,8c64d21b,b25320a3,b5574b9c,1e1bfb4b), -S(6ada98a4,8118166f,e7082591,d6cda51e,914b60b1,49696270,3350249b,ee8d4770,c234dfad,f3847877,a0a7bcda,112dba85,1cdddf00,84d0c07,df1d1a,a3ec3aeb), -S(a94ae8,63264dfb,b910ea95,4ce9ca7e,4f86f92d,9f3a95d1,ed61552a,7a3f5743,7f53f7f1,6ad2d08f,15e73314,6d80467,41557acf,19556c0f,ed7117ce,37040823)}, -{S(1b8462eb,1ccdf7b2,b8372f2f,cec1f479,ab07c09f,cb26d6c3,965ec73,4d654f81,62f6755,b4a7891d,55de6427,fbc37d33,e4eea418,a2c04392,a3d11807,ccc9025), -S(c3b55f99,9cd9113c,fcb4f29,be00c785,cc70d1c1,f1cfd0ed,593abe8d,260bd2bb,8945790b,5696225a,1c6a1f45,1d6b085e,cde2f332,df068271,f6279877,6d1015aa), -S(a4b41b41,1a255142,ee62144d,96ccfdc,a3cdf5a6,af32bdd8,d1c3d26b,d6aab0b9,3ade7f6a,299ee56c,299fcaad,72a146d2,62db1dcd,2ea1a355,d6e00294,ee34c3), -S(d4af67c6,75f97f30,4a621fe5,343dfa5b,e432d9f1,43758d4d,62df1e09,b79abfe8,d0fea700,2a851a85,33929e5f,1f41d4a9,68b9e520,6c19f3b0,35ce96a5,12b61921)}, -{S(6ae991de,18418b49,160194f,a735eb72,c299b987,1981a4f9,aa717ad2,bcdcf13,7ee8011a,40f384f2,e50add2d,97005173,2787cc7c,89dafb66,301bc94d,24b913f), -S(c28203a6,e0f93259,778bddca,10f994be,67cec8a3,109d0001,d830a8e7,b452794b,18df3a42,ec24b713,2ac4b6ec,dd7605e4,169aa07a,41d7559e,bde808d9,bbfbcb14), -S(4848adb6,b0350cd7,b745b603,cff69deb,8be10519,cc02881c,4b980157,5635aa37,7a814076,187ed7b9,84d0be65,b2f83b90,325441cf,54325183,beb01136,d626ca5c), -S(515d497f,f274da3d,9bb9e4f7,e1b77e8a,af859d52,be7c7e93,f197267,d73ce5ae,da648754,a5ed476,3fad55e1,e93f9687,2d1fe961,b448b9bf,2c42c885,b44678f0)}, -{S(64850a04,76870a44,2cfa57e0,4e4707f7,eccc5e99,12dbcb07,3b457317,717f5686,7c5facd2,91a6defb,a1837cb9,3bcbd0f5,bc37572e,68ccb2a0,c062a155,46656fcc), -S(c3ae412c,a3e5f22b,44863ab1,b5e64719,99078ac0,d5844d9,6a37899f,3e064475,e491d89e,b38b0443,50d96e01,7baceb35,fa0e247,8c982d25,5a2a332c,239e0a54), -S(e72c3804,a774f3db,42348883,297b5035,c9dd3970,7e3bc60d,1e51e41,d7d8e395,e3cb5abb,c3c259ab,2c9e5,fa059c10,fe6f633b,4f99da29,61b9117e,61fbb457), -S(6a7b9de1,8d16a0e2,1b30cb61,3586ebc6,78b60618,e2b45e2d,8c94ad09,36227f74,ac1fb735,266d34,eb995f8f,91cbc339,f63b6e6,bd4c89f0,d7607908,75a4918f)}, -{S(92133195,a4fd0c59,7e0cf65e,8ce1d939,e333f7a8,441523aa,31e339e1,2ae51e8d,556a388,7a7d579e,87de7f49,8c54bf24,2ca4b8a2,8b959e21,ceec4555,b8fabccf), -S(1b3ee78b,df5cbab,a7649125,40852351,602bb558,e4bea533,dbb08eb0,299ae994,9a0c2165,5512777f,fac5ed54,b8e5b4ce,d7a6b17d,643f8c3d,d0173a96,3a4c7aa), -S(6be3de2d,1ceb66ac,1ecd3435,3f241a89,cdaf48f4,a8d5522a,1d6f0083,3c4b2a39,88e10da0,e53b8f5a,ada0db7e,e1ce75c2,8898d5e,156e777f,7acc3ba0,9fee727f), -S(b38c82e4,3e0559db,6732e87a,7cb1e6e6,6164f6f2,258ce060,6d239836,5af9ec0d,9e0f87f4,9d240b33,dc325bd0,49e9fac5,6b7a64e8,57f27ab9,ad765604,2fe47653)}, -{S(ae5fb021,e9256cc0,6236d667,b76b9bdf,304a4683,d2916ffe,489cf019,6b4c5683,e768366b,5c8d36b6,18e45550,d57493e2,41fed17d,12627e37,b29b4b74,d3603696), -S(e4f916f1,a96dc6dd,8867a619,fef6cf67,14ec2642,12d7ba2b,14b5fbda,b584f339,b44855e3,3ddf19b4,31f109b1,daeea11c,340a9ad8,c17b78ea,c9979ecb,791c31fd), -S(4baca037,647377c6,f3146dcc,d732b21d,32449773,f55766d4,de5b239b,2ef89e6a,50b4b046,b9e3cab5,dffdefa,fa305051,7bdb2deb,9bd9fb,9d3cfca0,34a72228), -S(867d7d44,734389e9,71363522,9d4f2c3b,bfc66e57,44a5f01d,1c93c201,9dd3f363,e9b94307,b39ceb65,653f2206,ffc8c858,37654fb5,90eb8d1f,24a9c82e,d8b4d210)}, -{S(782d5c9a,d970322e,deff2e7b,57844184,c589a4da,c042fcf3,86c1a9f8,26c1babb,27bba565,405cb392,64762d97,cbaff552,1bc38b20,56afe313,556542d3,f200eb06), -S(d07eb76,bb6694dd,4d6160e7,4d4a397d,963ea132,f74d0b9,e9f35c06,830940,2b7f902,62c67203,d6f3fc8c,2d435309,7f8e80fa,c2a732a5,dfdf6dee,ab47f017), -S(36afeed4,b7507388,285fc481,beb1de1,bc8e143c,ce7b8e46,7c1e22c0,395fef48,5318e7c9,686171a8,ceefff55,3fc98e41,d9e0d789,a2e880fd,6487c2f5,54816a97), -S(cfc25614,fc96d911,24b3b74,7aed144d,8656693b,a2844934,d2ee61ab,ab794160,fa9e529b,be133fe2,835ec397,b130ff27,187aefdd,df524ed0,9fdd0486,5cf6c014)}, -{S(ebc119d3,8e794efa,85fcbd,5affac35,f73c7428,590ede0f,6365f1ea,87c65b4b,183a9992,3911b1b1,cd9b0fea,3667b6e1,52af7499,8d32beb3,d2ecb91d,af6e8a06), -S(456dfac3,c239290c,336d1b46,e9638bd2,592484bc,f76d011d,104cea57,dd0e5167,62264555,8de68f49,170a8aa4,121aa307,378984a1,76b8affc,241419e6,95500049), -S(71108a04,a50b30f8,29f1420f,b9994ba,384c2ff0,8a581672,e3464bb2,93f0f756,ff6a402c,eb50bb4f,7ae17680,458f53fe,d627b0b,dca24cb1,b033feda,f27cbff4), -S(f8261d8e,ea970b26,fb13ed01,cec553b0,a374b03e,c14763ec,13e68ff9,b219f39,3cee77fb,6e684798,68499e40,fd33fd61,e43ab21d,96a6bf78,35dad6c8,2fea2407)}, -{S(bc4bb9a6,292aa09f,5c66dc9b,667c4642,6b08211f,a9a80f5e,f3f17b,21f275de,5d0e0492,39a862ec,b9649572,6f11bc09,cebd9f29,d9407ab3,1603054d,d9b76b07), -S(ccf3d9af,434d96b9,fd9e12ee,45ea3858,5060b000,896f1de7,a73a12a1,3f635c73,7efe7415,8a3893af,d408b0c,fcd992d9,cff412f0,f77d6a9c,5d5a9235,d14f5e21), -S(18ade473,1ee3019f,ad5621f0,cfc0d6ee,ba69ab38,fdca04ae,fedddf1d,f9cad1ab,1ea6e4d3,63f1cbfb,e9d11c54,c2ab43a4,49e9610f,24b6adf4,446454c9,c3bdccf0), -S(8bc05563,1b13b451,5a99eebd,837e67e9,e80ab8d3,58ee840e,3140ac8e,131cc214,cede3aba,b11b6a91,4ef1ef36,30c12127,bb818ec9,b4d3ad38,a9e68641,a7b799a)}, -{S(c8e595d2,666f4913,1f375b67,81b9113a,d0760e5,9477ca17,8863828b,307488f0,a82cf2a9,d823af13,5c23a04b,bc12dd81,2c352a48,27e19030,8e089d9d,9c316596), -S(d194c03b,ff719a14,6bba239,fc3e1255,7637c9b1,30609ff9,1501942d,348930ee,5e9387d6,4bbc72de,39ca8141,c6c6d526,530e82,47b43161,72717b68,28d1c1c1), -S(cfe58760,54b85d2b,e1220cbc,28ba55f4,51cb3c4b,1ef1d39e,b82e8c25,7538b631,a7616b4a,f3564048,b5cdc6bd,b0250abb,ab1bdd33,a7a15857,31119d26,94ff4bea), -S(190a763e,58315639,578def37,53f4610e,5a802af9,e4873d3e,8c3186c0,e424ac42,b156da85,b8462fa6,83f85c7e,5f718ed7,34a159c2,5b18d092,185ff467,8b8840ed)}, -{S(49e7429b,e0d97bf9,3f17e9a8,53fedb6a,a9bc6edd,8e85f44b,9d2f1469,b2d3b178,ff9e5dfc,2746679e,9826039d,578bac31,c08fbaac,a075214c,73c50f,74568fff), -S(2beda894,682676e6,11bf6a,78cae329,c26b47c6,237d0e52,61a70b9c,36796207,103a18d9,a6785ad0,2129ca1b,96834d9f,f185d49c,edd1c053,96a8c9f4,dd16be16), -S(9602058a,fce0160a,70bd2a32,6cd3eb1b,e5ffbaa8,e05bc2db,fbb9c303,7b449ceb,1fa171c,682393c8,2b237910,2ba5ca8,7efa0543,b8cd65af,de324f14,cc53945b), -S(118d0b52,f418dcd2,b6864967,a49f9d88,809f2468,8bbb6c47,c68f2eb7,bbe7ab31,30ebfb30,ba0bac02,57bf568d,479b7bed,2b1512f9,33aaa040,4966b6fd,5e1678)}, -{S(9a1db7bf,53241ed1,df8d3ea0,f70c0b26,76b43ebc,bcb4622a,9704b0a,3067400a,e3638ad2,95740505,455b2e1e,d495c57a,54ed8e8f,c647a6b9,c69b7dd0,715cef52), -S(b5c353a5,c86b2d4a,9b00804e,f0439259,335d0bde,91dd2bac,a567cd5e,284be39a,5bba9f1e,877d5e0d,21e384d,52de73eb,9aefcaa5,132117d1,2dd984c9,4a0562e1), -S(337a0242,62b9fd60,28f5fcdb,c2305543,385010d6,98fb258a,d5c25b1c,4a765fed,e179c1fb,d671e158,36050d89,48fac97c,57abcae6,79e3be7f,16ed8b98,84dcb013), -S(ecc024ca,640ec936,f7e2320b,58147466,686528ed,579865d0,f61672e8,3e6b0f18,a1335b77,ddb11959,24d40e4c,81270679,270f87e4,158a745c,8d2d810c,ee7024eb)}, -{S(50cd2e16,997d7d45,98bb2d9b,61aceaff,5ad5f38c,8286a0e1,d08055ad,726c7800,dd19c3b,c08b8d97,88f9de1,5941f5fa,6402bbbb,5fdc708b,cfc08844,eb23733b), -S(34d6a7b6,733bf5e9,ae6aad06,5ee0793b,4f5e1ba9,97de99f9,8771ca57,81fb2382,22f8c6f6,dc7203a8,53e64cf1,dbf26d6d,e255f0bf,bddd9508,a759db8f,2c55cbd9), -S(8458b56c,982ccb85,8731c149,e2f38880,3958d6b7,55f38582,b9f4d95b,85d22ee3,b5b8fc5d,2da56779,a5b06b85,b5d07349,9b04cfb1,2d7b26b2,d9a4bf44,3f00cb05), -S(cdbf1327,3388dd49,c163ce36,8d451e3b,51bc7924,173efc08,376cac4d,6f73a84a,d2854757,18fa95a7,1978bb04,5e81095c,f1423d45,e533ba6e,ad91f40f,a6961d2a)}, -{S(4bd266bd,4a730879,cb06d8dc,bd8e5854,c50b6221,d83e0a10,3afcb2a9,a64cca67,a4654a1d,835a51f0,5a877200,1768c549,909212e5,78e3b1d1,df935959,93650863), -S(6666f098,c04d51a2,609c9eb6,596dc668,16735175,1458cd51,59f5bc1e,2c86722c,4ce5faca,45027cb6,85aad7de,e926be69,95b22719,d8d8fb61,260fc9d7,62a9e47b), -S(87b459b0,6e3e2750,31087f45,79e53818,fc200703,59d28147,ad79e39a,488c79ab,2656b94d,d33c0721,b90e981c,b47dda60,166839c0,1c5ca2ee,76979133,824d2488), -S(830acf28,c0a99fcd,f1d3409,ca3066fa,ef8d267a,7ae6ba4,55fceb5,7f76f83c,aa4ec098,51361d43,a339f418,a28de217,a9f464dc,26ceea5a,ae74b4f3,193a58a7)}, -{S(217de5b,a47e8de,cb9d8dc3,dc8fcfd8,203c514b,b9d7bb5e,fb03584b,aa1baaff,c77bddc0,3af15e63,912e51c7,19bd8186,67f999ed,9bd801b8,11bc289b,f12864ed), -S(e5abf144,9c4770fe,b6772067,b18dce01,efab139e,f0a4d73a,eeff868e,6425a7a4,ba62fc47,597dea8d,4bcd1a08,77730314,81ea6990,796a29b5,94bd06d7,d5330188), -S(699e20cd,3b320b24,878b6a98,4c3338d7,45f93ae1,a7aaf363,e20b18e1,8b6d0f56,6602370d,65efc133,83ee1c45,baae4a65,efce9bf8,acb0c3,cfedb5c2,94f36d2), -S(6cf56e78,d6f58bec,32184506,9f26cdbd,7f6ae28,ed310203,dfe410a4,b83449dc,4c24cc91,f78d5c14,690ae276,89a56531,34f89a09,c17e229b,3ab7379c,6da021c8)}, -{S(761cab41,3916a1f5,e131f337,e9023519,6199f789,87ef390b,3f2d8bfa,b0e9bbc6,f10272df,f7e91c40,3565da85,17fd3011,bde7b797,526d3c3,f00fb28e,f26dbd91), -S(ec45cef2,3211527f,220dd3c5,2e4b88be,8f0b0191,d9e73d7d,679fd75d,ae9dc2ae,ac07402f,c7cf8884,8f00e396,42b5e306,7749e10a,441c18b2,646b2fcf,3f76309e), -S(70234e32,61f2e099,a1525a81,9ab7c926,bd672805,ed3562,55369cec,85615e9b,785a6c93,f2673a8f,ccf3b332,35922f9,208dcaee,6932c27c,b8e40b0e,c9b06360), -S(a7c9a0cd,c3692f9a,48ba8307,de80b5d9,80593eef,9e236bf2,49c9693b,c2bb46b,d44258b3,790b9ca2,9636694,6e9ec845,3e3eacf1,a9253092,a7bc92d7,62a03d3c)}, -{S(60b01067,25cf781d,e78ba725,40508697,3f2ff6ec,1511515,6e19384,1fddda7a,624ccf87,f0ec21b9,82efbc4,6d4db878,5d20fb8e,dfe663fc,46660bb7,98c96eb), -S(5d24589d,5ebf326c,9419d539,f06b2291,42c02d0e,44556a3c,772f484,6cb78938,2fb6e6bb,759dbfb7,57257d21,43064225,beeeaf42,4c99b426,aa27d969,d459a5a0), -S(43d4db79,797f6415,93248363,38980bb4,3c90400f,a698ab3a,ba38a4a0,9bb13701,e2bacfbf,b84517da,efb0e137,678ee0b7,bbeefd64,7256628d,7edf46f8,38c65ffd), -S(eb0e5c31,d95f3325,78596f3c,8a027e48,453b5c24,4d0627f3,cffbd413,f8c53db2,29386000,7c3c97da,cc0b5a30,1a7c7c6c,8a1dbfe1,5358c72c,5fa30912,634d4a0b)}, -{S(a707efc4,89165c75,7edcea3c,ce729b44,91f04142,3fc6ea9a,704f52df,c8a0650,f2e7657c,6c618494,c01c5a90,d06b625b,c9416d63,f7b8f809,dda5076f,74fa2c92), -S(b930b8c,a68df36d,80b589ba,72dda82b,502bcee2,cb98a9e9,95c3235b,457ad4c6,7b8fff37,9970f1b4,1a12baae,f7628868,fd3f1003,bd6ea442,46559b40,3a1e8bf6), -S(a6d3233,f7e1001c,eea237bc,d4484744,aa0888b7,a2b44b82,59a542a6,c0d6b552,d2f5772,1c2cbc0,7179d252,3cc0d0e6,94551842,afbb51e4,31a6efb3,9206a70c), -S(c1dd7db5,e5dc3f50,2b08a177,98bb1cfa,afd02252,1bdec7e5,f4653e7b,3303cbaa,558676c3,e25db8,c46bd903,2e9dd122,a981fc50,cbb9e807,157ef35b,5619d3bc)}, -{S(6efd8760,aed4f239,bd97a00,63794c4,ef14acc9,f5b94862,4c7f8b51,3ff35278,74acac29,694c5307,aa221b37,f2ea068a,a269fcd3,c6d85aaf,a8c8eac1,17d7f997), -S(cdd67435,c9fd1182,88f703b1,1fb4e848,9aa2b752,3237a279,ca30a11e,d05de955,149e113c,49db4e2d,bd50dffd,bd53dcf1,a5876825,da059718,e0575d3d,f39476f3), -S(b0fdcf78,9c509ff9,8bb36db8,dbbad047,36bce756,e350373d,ba4d452,8410280d,7c8a7550,91b2cac5,ab71d820,84b335e9,b630cee7,2a277e12,dcb04605,21747c9e), -S(b5ca53ad,77f1569d,ae1c26bf,84ab8e71,98e305fe,e21545e6,f3b2c734,aaa161f2,ec96edd,82ed1d41,cc8423d3,bba6d50,4659de8c,ae5730a9,a0b54fe1,25acdb34)}, -{S(2def7e67,7906cf3f,3677e7b6,1b0a8f8,985fbd9b,23265ea7,18a5c16e,139f0a8,650a89bb,df8c8326,d364fae7,558de827,a529780c,9b7bf8f1,c6925632,7c59c74c), -S(847cecc2,f30f30d3,40ff0276,9167e2db,97b07103,821eecfe,640fe4a1,b3f5a08b,e59c450,3ea1f4db,c4b00c6,e5b912f6,7dafd112,59773c66,d478781,bb343d40), -S(4157664b,4baa043b,9cb959d6,96aa1501,5635bfc8,a20ba704,b6477aaf,a9af9ea5,3e44d11,432b4e5b,97428706,4a787681,522ffe,28eab2f1,15e5bcd6,d42f69ea), -S(675389b6,32431381,bbc0d5eb,20f356aa,31418409,ea9150b,aa7f9c83,41b1124a,999645d2,7a169a1c,de866f4b,ae713070,b9b37c9c,a393567d,8ecd04c5,85b8059d)}, -{S(9705d56f,f75c7d2c,bacc47a4,a6cf8b10,300c688c,fdbd1b1,528f41b9,652d49fa,c53f7f11,896f2edb,fc957dd7,2cc90856,c5df9d86,43e42489,70182843,84201b98), -S(ed362790,55151b78,4e6f5088,e99b7079,d2409203,c08a8791,7644a639,7a8b6199,84affa8c,62a0109c,b003196c,25296d8d,5d3e1904,c1cd10c2,1e73fad1,3a46caa1), -S(21227229,b8deca6f,c30351e1,7607ef99,23cc3f8,9aaaa48,9661487c,7b3bd0e3,a054a47,fcab568b,f8bd4234,a5d7fbec,b11d96e1,aa3ad5b4,88fbb405,a7437f21), -S(59f2227c,32afa124,999ad653,8393e47d,d64c4331,773e09ed,f0517651,3090f07d,1348ffdf,d8adad12,4370f188,cfb47fde,a8297e6f,ea00967,7061bf66,e03b0472)}, -{S(5b27aec1,c644f0a9,ba7f6486,9a960ea6,28343ab,da3feab2,4a2d6add,754866a2,3d1f365c,2aee6c1e,ab2f1879,429b6275,5d1bac85,2998ef25,8a914bfc,ca280b43), -S(27f03daf,a370763a,e2b44480,7b9e6779,9361efcf,cdd7be23,6c493392,f19253fc,eeedf887,cd8f3df0,9d1748c5,62723c56,31956880,cceb0f1f,c118052f,8c44b5ff), -S(d301d8c2,8d7413cf,3298cf95,1f7d6c3a,2e8d86ee,c5e3fbd5,e80e5358,4855e04b,6856d7f1,5e94773a,465cb69c,8b7f8961,a2988f50,fdc179d7,63a92ab5,d94b22a5), -S(8b88670b,72fd02c8,5f973403,5299ad19,484c1367,c8296c73,122d80c7,9bce8407,c98b5a2c,3b0d5c44,32975c0d,32c90794,63ade4fe,92cd4c44,4e8e64ae,7a05c5d4)}, -{S(53512a21,4a659914,82cc157f,da02880f,7c4ff9e6,47a93136,c1e55725,9ce7132f,3ccac75b,13cc40fa,5ab2e017,80f55f2e,b8e6a7e7,22b2e6b1,13a28316,b3c99d3), -S(2a1e20e6,8cfbb77a,ec1f5666,dfc1c85c,c4a07dda,4ead1722,8d7f3633,6771be47,b1f5752b,3f6650ff,261898a7,a8c61f71,48e8f54f,a39e2f4f,8e94ea2f,b332a08a), -S(560d86db,354e5f8e,e8522056,aa9d0f5f,6329fca8,2bf11ba9,fc29505f,7974662d,bfd52860,f42f9d8d,84892fda,b78aa79,9143eee7,26fbc95,b5e17856,53b13878), -S(24c3c40b,df047994,d0416339,e64d6195,276e3779,68869b66,3ecdf186,4703207d,643b0918,c8dce682,50aa3abb,db68f9cf,f8ac64a2,2c7cb77,ef8fd252,36cdf29c)}, -{S(534e9d8,bea140bb,4970b516,c42f2677,dc413f42,9b7c56de,e261f60d,ec68f9d8,e55aff90,1098b0a9,ea377acd,b62dc479,da109514,2654107a,28c68e9f,73b1cba), -S(28ecf7fd,a122550,8301ad75,6028e29e,13da7586,d8b2aaeb,f061e927,dd030db3,bc3e08d3,df4218b,88279f3d,cf75dca7,4a9f567b,75ad0a86,f9379c6e,37661962), -S(851aa3bf,37ee83d0,8318527a,5f4366ee,8ae98d29,de2254d6,2e4428fb,cb5e0f21,423393e3,937816e7,ada1df1c,ebdda887,5e114ab4,23059a35,96668a80,7820754), -S(7e6cf455,9d674d6f,a6263ffa,69cef00e,f69f50e5,4a5d6603,5efb7732,b1aec817,3c6d0cdb,c7ac0623,1c47c044,e28bba2f,105a1730,7cdce1a9,ced324c8,f770cea2)}, -{S(dd7503a2,a3e15e7,39eb9b1f,856d6e33,be4890b2,f40cfea8,1bdf516c,b942731,ca9cd04e,c3789ab4,5088b819,953e08a0,b8adb8b,b2b6f7c8,661a2d3b,83a54c77), -S(9850c031,33d251c2,9f0d64a,f7941f4c,475c6099,e6ba606,9d396ce2,772a5e53,acad3120,b2b5aff9,209bdfce,34d6e5a0,899c9de9,15083064,b84fe57f,2e1c1adb), -S(14194578,53638284,4574721,cb83660,bedd3cff,b68c7023,3f3e6a8e,1d78d797,94d7a10,f4e52fca,c855fbc0,7c977386,b11e179b,db6e6488,67ff3957,28ef2556), -S(c35a90c9,d1f6e5f0,265b7f79,ec47025f,75eda795,27a80f3d,297eb2de,9a85c603,94336bed,d5187e4,5faa0993,875e2421,b7e02eb1,c4dd9e94,b4aab892,3f63f838)}, -{S(c8116b60,1f8d72c6,24957215,46b844f6,bf6bae0b,7575a77,f1f6c6c2,5524fa2b,b7477ca6,de2004df,34882c65,3a46821b,53372f13,ed822cbf,40c20bd9,ddd1d6bd), -S(100f81d7,3b016931,1291696c,c08236f3,6100d4e,10737bd9,2b583d74,1b1903dc,80740c37,a67af622,bcfad64c,38be6968,7e780ad7,318163fe,5d2373a5,b6c90976), -S(17d3e5c8,8a7c9ec5,8a600c2b,c5d0574,491d3c19,6cca5de5,1f812975,e6fd3152,6676bbb0,9ef082b5,f8ebe69b,22c57949,43df3335,2d329621,3238f39,36bc0b9a), -S(f7ccb6af,6dd503e9,a694d721,7e0444a9,6428f277,2cf0e511,cc73bf08,590a5475,817daf4f,3a7106,f23aa303,772a35a4,92d49ce,1d4cf9b5,fde4653d,28ac6cf8)}, -{S(e7ff8d5c,83bd5846,5c967b5,37ac0f36,b9ffe9d2,fc7531e,ef183cb1,7369c066,9a9c3c4b,e482031b,f6dc69fa,843ea90e,de165479,26ba201b,5f05b00a,dbcc30a8), -S(da3b16c5,dd1f95f7,6e54297a,d6be133a,ef0df2f,45f14a55,de978a02,6b8b5fda,6712c26a,cd07740a,70573f13,f42e2b10,edbe32ab,fdb517fa,7a61af6e,aa1c6132), -S(18e515af,fe6c7273,e2acc85b,6dc345c8,f0dce23b,219abd3a,d295f686,4e02ff15,339f848e,f0b1bc1d,fa748290,f25e381e,68cebff2,f3e47caf,ff654909,63fcd515), -S(66bdebee,8c0935ef,32735526,c077cadf,bbc14003,8cbe910e,66107308,8c2edf8b,91ca5bbf,3911b59e,d6c6fe5,2fdd9a94,5ed49883,275b8cac,7fe4c63b,530c7a50)}, -{S(d8f08d18,ece61855,5b06a3b5,ac8e7cf,a6375446,cbc7c8db,ad924f78,69e7f00e,46a91d23,910957eb,db830624,73839954,2cea0570,2f67a09d,d7d19217,646606e), -S(3af65e2b,b700e873,edcf50c7,913e6fb5,534e314f,a2eda897,29fad58f,c7a49b54,dafee0e8,7d70e7b6,fb159def,92a6e5d6,cfd6b8f3,68fdec20,7719e085,94bb8e28), -S(10db17f1,8b009000,660f7dc4,d1a48fba,13926ba,67b71c34,51d2557f,a6f141ca,2f5bcc34,51445a41,d5f574e0,278845d4,805f82ab,ec84bf1c,a39b4bc8,9abdac4c), -S(ab18b6c1,55cb972d,9152c11a,36877a3a,86df3379,181c712f,7242bddf,9fd8f099,b8b8f41b,dcfc9ac0,fc112dbb,63e4cf,72906ad5,1ddaf95c,2a8ecbe5,bae0e229)}, -{S(ca3c008e,cf9efd5f,75cc1035,f9edaa7c,46b17d25,9895b0e3,b3523b6e,eee9daaf,a676aea9,3ce9bb,128ffc34,deb96b0f,72179d28,77406d04,6d0c8b5c,3572f4d2), -S(cf03f3c4,11bf7fe1,46abf004,ecc3583a,25116d55,6c6fff00,71464810,8470f0aa,aa0c0197,d57d72d7,bf336ab3,5527f42e,c7472b8f,8113a9f0,c99f129,4b39e7bf), -S(5d78371e,cb875987,c9e65356,d35240b6,c51e3897,6f884d73,c80dc0d0,839e8b26,76451b48,5c9d7468,77017dd7,412e06b6,2ccfd59d,a1800765,31bae6a5,b2a0bf73), -S(c1df0be6,6001ba2f,2a4ac3a9,466eb526,f37432e0,43688623,8fddcfd1,c1a2bacc,a8b676d5,2b3ecf46,e5849f4c,7c7c46a7,33beff28,d59285a,755509cf,5c629060)}, -{S(8a4e9691,3533875d,b8559500,65c90785,a78233ac,ef24113c,f6ed543a,e6a40024,57d9444,8d091df9,602e6c7f,c3f88934,d45a7c76,18da574b,4d4c15a6,6925bcf4), -S(2afd690,bb940709,ed1a4f85,41658f4d,254edbdb,7a64fff7,c06c904c,47d0cc7,d2177070,3bcdc50c,bc219ac4,62a6fab3,5897b550,d057f9ef,837ac04a,f6233c2f), -S(aad6646,8406b84d,38782e5a,669bddfd,c2279bd7,df486dd7,93e15f82,47bb9cfa,5c0a68b6,2065ebad,f38595e9,5f7a44fe,2bfd7ca8,4ecbaa82,ad39fbd7,b5a1afe5), -S(4a7d2720,1b508d35,a89b6406,68e99cdf,5a400d1c,cb21732b,e51fb44d,61c4cbb,d714cc9,9d59036c,4d82b668,e852cd52,d4d09ba4,f4007346,c7c1bb97,232b0fbd)}, -{S(458f8dbf,9cef8cbc,5d2046c7,42ca6297,e8fc76a,ad22fd3,af4f9a8e,2173d857,57074c8f,14a36b5f,6924517,6e3dc7b6,4d12a08d,8d00565,e70e0ca1,56f29820), -S(970222f4,b79b7b44,bc10c23,1dd6ed2b,2d3412d9,a225fb31,53e8d633,57f2c9a4,5151094a,f28c4b19,6653a42a,dd1f2270,50f0bced,e5e9339a,cea08b7f,e44f9357), -S(5efd117f,645a903,dd4d3f60,72a1f9e0,3c5a91d5,c8042267,1f791747,df32cfa0,770add6c,9b44ecc6,6b7a5fd3,3801ffc3,112bee8a,af0c02c3,fc646347,fb8483f3), -S(ffe6a8da,2abb5280,2d5b9e43,d2d0505f,f564db87,57179c55,30238353,c51c5365,4f1a00f5,4171e1,65d40719,8b913be5,fa84f018,50c40123,9aaa98dd,b303cb71)}, -{S(d2fff4de,9ecfdbd2,dd99ebae,d038415b,19b6c44c,9717926c,9e9a668,3fdfd377,a7e8ef8b,89877e3c,cca566cc,7b7dd537,d157cab,121d1623,b6880567,ac66fa8b), -S(5aaf3141,4ec3d722,75d928a1,c6a528d1,c94ce228,19eb8932,b0da11c,9e4a4574,5d496edf,c3b054ed,5b7fd57c,e731e41b,a538089e,19c11232,2e844b49,918da76b), -S(5798970,da3ee2e,d65e087e,81d9ce60,fb7ee1d4,145af16b,42a4889b,31b68258,8a8fba47,b0b2d716,6324f55b,143b3b14,9af089b0,dc9b9557,40c5df93,3067841d), -S(b482e028,f9cfe926,6d7d4072,c01d30ea,28dfaf9e,268f979d,faaf0b11,4f420d45,eddfa10b,7cba2273,4fa22208,51fc47ba,82721443,19a60d40,624d4e7d,454aff71)}, -{S(b3b5422f,1361ce5c,bf7cc061,3c78aa88,a02683ee,cddeaaf3,f5516cb,291632e0,1790cb50,cc2c760a,c7c2e97c,c44aff29,86c73be5,59a88180,8d036e7a,94347156), -S(34359647,5f3bb33f,eaac445b,5574c7b0,d2fcecf1,50a098d2,445748bd,482b5e0b,7caef8f2,4aa39495,6a36abc7,6704f7f,f7be9b22,6e3a1004,bc3dccc8,3a58cfa5), -S(5000310b,6e81394c,4f91677b,a03c5ca2,5e5c2581,bdaeb320,573febcc,4bd638fa,1c238674,6752ef6,25526d5d,1c80e106,c45a7b83,9ffd9160,bbe6bbe2,8056b532), -S(be843ac0,1b9efaac,adb5c047,49c5990,7441afda,8f33b1ad,20f6335a,5bea9c02,1d14d074,baf0a79,6c165a23,fa9ac432,c46f6576,838625ca,1d73c7f5,327808b0)}, -{S(2e01d33a,c10caa03,ab514f75,46226f67,69a08f01,56017b64,a2436a34,447bfdbe,f5bd77a1,2c61f2ef,60a8c937,cf29e1e6,882b12c0,3e7a7763,f1ea498e,9207836), -S(c8104402,70594c5b,f4e36d2f,ed9e6fb4,2d362b49,5eab7a11,2b1e1c26,aaa20cec,939741b4,db55bca3,53879f72,6362518f,98538a95,77249283,e62b98b6,b3c65c34), -S(408038a2,a79bc8cc,f1fe98f7,d7ddc784,28fd3c71,ed6be435,d76f1390,ed4e3ec0,2dbc7345,f4a358c6,f9690213,1f0418ba,2db1fd01,7e47d8a7,583d30c8,e74027ba), -S(8f0e6b51,50d752a4,86f0edad,a8c21b14,1f7a73c7,2d797233,6a45fc96,8c857683,3cd1fe18,21f1291,7d86b629,ad5aa2ea,46243c8c,398be570,f1959d4a,47b5c3cd)}, -{S(934807e3,60b79e08,d1e28924,2478db59,331c171,6366f421,eda4417b,c0699286,f7f83c26,50e7a77e,2f760e68,7f475858,b2c2d770,195c199d,33a84324,e23f02ef), -S(73c23592,7ae07afa,1cfc030f,a8c874c1,e6d876a4,7414894e,dfd993d1,208ff29d,c2158086,e6dcb078,3a602887,d5d780bc,6e620946,91260289,5244ddc2,f98bb1f5), -S(e588d73a,6eb03f3c,4700380f,17f4c36a,41415cf6,43bd12b3,7e5eedd5,13612e84,3a1cc3ed,22df4c92,96dfa9e3,3faf5035,d084a6f4,fd06c27b,e9bdfefe,bcf1753), -S(7fe24906,485a5638,42ae477b,de90b8a3,1984bf42,7f43660a,f120370d,cf6a3d3d,16bf27da,45038c52,a6051298,26039376,a6fbf802,583ee59a,9752dd09,f30a7ed5)}, -{S(accea070,aa6709bf,efd88be4,bef1d485,a0da83e7,ac9a1eb0,eda8387e,b9fe666b,93fc1c9d,fed8fff9,60ef750e,94dd2342,5fa08c3d,8eda3eee,7f51381,196080e3), -S(412c82e9,f90a302d,f404bf6f,c3581516,b23519aa,2ec26f20,9c80fca3,1f4d0698,31b2bbb8,493e0c15,796d93bb,59cf70d2,7f9c65b4,b3a74969,8612f72e,a42e572b), -S(c0ce0313,52b119b9,795635d8,5e2f5153,a3514d6c,190e2a0c,f9effdf9,bcbdd6ff,b4ef69bd,d4671af5,2be6a4be,1ab4460,71485a7f,6fde10f3,65db8bb0,91eeceb2), -S(b7a23510,abe3c77b,3720006a,9e29c6c,180e40aa,889ea103,ea2387c1,1667aa9a,863f8837,faef7267,d7e36595,a15dd7a4,b2012733,c7347dff,501017f,188ce8b1)}, -{S(a488f83,2bf3e57b,5225f748,754ba2b5,cd9657c7,175198ae,122c3d1c,ee336ef2,4e326d40,648cf269,2db42532,55391fca,5c2b48d7,44a9e39f,bd1293dc,827e9021), -S(bf6227e2,a75c717f,fb3d8d62,361b9212,45bf64e,b19554ed,11040b32,521b9e52,209826fd,41f88c85,f90b4c4b,f90caba0,9cba91aa,687cc502,23bc71cb,7f5459a3), -S(c0ecca8e,90d6979b,54b9e9aa,5a804c8e,106b8b41,a609b85d,1824d079,e2b95f70,1ce95138,2b6eff47,9660cc00,8ed77229,b11158ef,15d97809,a6253439,b88cc4ff), -S(3d4861e1,6069f0f,ddacdb17,595e59df,54a07376,4237b29c,102eba03,230dcb3a,435fa321,90e459cb,137046d7,d316fcff,6fd6c954,a8e2476f,3d38d9e8,263deb51)}, -{S(a473de46,a554667a,368fd573,168dea23,3f81153d,e1b35b26,90da8863,71e6c131,4ba0b462,92aed936,7a2bf9e9,de48a08a,874fd681,aef86a15,58b49e4f,13dbbcec), -S(435ae44e,4f062fae,72ec122d,b7cd5d5a,719c5889,a76ee171,be0e5c61,c5c2d148,d4a6c494,1fafd583,39b59229,b384a5bb,85140ed9,b8cc99b6,38f995b4,2044f380), -S(c170e94b,8fbff40c,159b8fda,ab69093,49e7ce91,1658aa2,896049cc,56b4ee31,19b45604,e602baaa,7085e27a,69d8317f,26ecb345,a558a3e1,5456c1a6,5d89e992), -S(2a043b61,f5e22943,19a38b67,b3bf2f8c,89be156e,641159ad,c94144c9,971af395,17d7c7e1,6c097256,be0cfb11,d9a3cdd7,8bca6a1a,c9514e37,3f59aa5b,c48eeb9c)}, -{S(476d7ba4,35177a71,299267f4,14ef275d,48b434e1,380c1afd,9fac4606,f8e02be0,7f1255fa,57a60447,c14d6574,1d7774b9,695e6d25,1b46912d,d33c77f3,f756edc2), -S(ac4bc955,aae3fa7c,a4ac46a3,84cc2f7f,3cf71f73,b15dd3bc,30513ca2,7da2808a,694ee4e8,6ff945c4,4a5ffd3a,19965ae5,2e15cca9,b51d4795,855eaad7,fc959809), -S(43b4f6e4,25ce5fd6,2c5d6d5,ce33c6c2,df453c6a,9fcb3b15,83faba41,69fee22d,dfda0e64,572ee74f,1fbcc406,7879fbbc,b3896243,70d4bc7a,677eedc0,a3432e4c), -S(e2c0dd25,96da70ee,2569cd83,cea9281e,e37c731c,d0112018,7966da7e,75a9cadd,f87becf8,ed20a606,f8be39ec,2baff52f,60543859,fbbf2b9d,2f8c9933,838b6507)}, -{S(4f62ab4c,b7fb0d13,12620121,9841e932,b0de312d,674cd002,315594e9,81dfb3a1,1145fdd8,c5d16653,a9129b0c,39fcbbd9,5968d22c,ff2127bf,91e89847,35e2834f), -S(ca2ca59e,ad140068,e488658a,836090a8,eba824f0,3c6a81f8,fed13956,865f1be9,f8e286f9,8e9c9003,e4701dfe,83b79be0,d475e320,8cc6fda1,84095f5c,9d0d70b3), -S(eae775d0,8d013499,5ffcba75,33a6dd91,2a07ef45,5a20f49b,8e7b7ed2,75d3c54b,aa4ba756,dd0bd16b,32e86c7e,a520ce1a,bc224d2f,822059e,3df2cd7f,d8d1f855), -S(db566c14,bcae1071,e0bd82a,7a965a72,101d4b5c,29cd7aad,c91e5e99,f4648978,78569150,59ba0432,3afd6a3b,ae5eb503,f920318f,25fc8c45,d1b0fe35,fcbab0e1)}, -{S(110f05a7,489138c6,51e48771,d505c7ce,68bd6e61,67cf4c3,3933441f,a236f263,761652d,178d0d5c,f6189501,d02d7078,2f10f835,27894d79,4f93dff6,e90a3b16), -S(7e0419aa,c31953f4,73ac26a6,80fa9996,7e8f0af6,18ba8a64,de8be81,33f48b6f,b6ef4bd6,5b82a94d,e774eb86,63ad7144,f025fc3e,d8a229cc,af59a816,5c38638f), -S(ec0cc26c,6044567d,609cf31c,c874d9a1,844f61db,37ac4e04,10497e05,c7accec8,20004878,3f7d270e,81144d48,ec839dc1,d1ecdac7,75910eec,b2942619,c8baba8e), -S(942bb265,6d6cf90a,44b1701,76fa9b2b,e366ddbe,fce1a83c,cb3ecb4c,555626cc,e07e2e36,2a835d8e,31601417,fb185a06,14aa4598,6896880b,f1df90e9,aa5c40a7)}, -{S(81f4223,6a39a14e,d2764665,22edb719,f2fb72b2,c571ed67,343e2c57,4fb60e5b,34f10ee5,6c1d5e02,51e8ba8c,9f129391,521f0601,2ebb4549,7377967a,d8347e4b), -S(f983c256,b5c49a86,6bf19c43,50083f4a,7e9cfba8,723d4740,f6909434,3b422fb0,11dd2c7f,16c588c7,d675ddd2,be80e785,50f63fb9,1f1bc016,bc29891b,f5bbd8d5), -S(37fc1499,95a90668,a871c28d,8ed84092,b928fc95,2c459c6d,cde783,28c936ed,e0b07cfb,6fc2442e,4459036d,bcd0117f,c36760ef,2f1046de,17673726,a41316df), -S(4ffc822e,916594f3,fa007cd2,682f0c5d,91b835ac,dbda2ad6,3ac3b73e,5094a175,3ff732fb,57aee90d,ad86ede4,5afa2e18,c95a0a77,d6cd008b,11c95bfc,dc927843)}, -{S(2dc8f27b,b3bdcaa9,2feace80,f2f6212f,8209477e,531e74cb,f497372e,9a2f2263,7feb63a7,96b55bee,ffa180ba,fef47776,fc4fabd4,2ccdcd97,64b4bab3,10350790), -S(c395d4c4,d877c2c8,268621d9,5fbf4f3a,bf839512,c68dc89f,82d6e757,d3938cf7,b37a444,a4e73223,204799c3,df859859,892eae5a,73844d09,9d33eac6,37779a7a), -S(d31454b8,b44e2a30,395674f8,abdc4fb4,6ac242b1,68f0fcd9,c59cbe1d,c8d2b47e,c5a4cbe4,6f8775cd,9482de12,4bcf447a,14e75b52,74f04a5f,c7912457,e31a4d82), -S(c133b76c,a0e74084,b279a464,dd7d5ab5,829e8304,ad8bd982,b2e112a2,9f452272,3bc44411,65b0b601,93bbef51,641b2569,a57aa5c9,6150ffb3,936f00c6,b6434b80)}, -{S(118d5053,fa3ef05c,810cf906,3a410f53,38a9e6bf,513b9a7f,5259112f,f84ad7e4,a371fc9b,c9182528,27d6c842,32e4e44a,9d32eafa,84f1a02d,a86039d1,6309e92), -S(29f11f0d,1457c9ef,7660a6f7,efc42e79,f58ad31c,1df3ee82,33856c30,185a4152,60cc2ceb,5a506326,657219fb,5a8bfcc8,d290f5b,1e05f73a,5f410c10,6ad99bf0), -S(ab757a3a,7af4069e,23493c2f,3978b8af,67d735ea,92382381,727ca6a0,df3082d5,335e418d,1ac2ac71,81a96a7b,7d15c55f,f8c6e342,83aa7f9d,8ae130e,dbe0fd41), -S(37e90fb6,b197550,14d0ea75,1ef33c24,a00d8cf2,5ecd8476,8adabba4,477260f7,90ce4d73,7613beaf,3e884036,5071f104,b88a58a,94c80b4a,1325694,722abbae)}, -{S(568b3e2a,2db4792e,4ef4ee66,14e201f8,a847fdca,38bb003b,adb06d74,1e4f999b,7334b395,61cbcce4,49d83eed,205a4c40,d91d2751,938ba7d0,6ed9e5a5,e1ffea7c), -S(8e37181d,e892fa67,3f26c69c,f6940204,c8f5e5b4,7a027489,ba6f02ac,b87a40ff,9c1a3ad0,bf418dd3,876388af,d45c6ab6,dfa7f7f6,94e991e3,ef0895e,7d7a51c9), -S(cf2e6330,134713f0,cfb27276,9e65e4ae,83d7a3b,84900aaa,3d32d401,55a19673,b8a0a5ca,ebbb17c3,923448a,767804ef,43bb056b,724471f2,5b089b3,ec77e453), -S(ac0df937,d2d65ab2,e6bd28ac,76551b78,bcb1f38d,81f988e9,3fe2b8ed,740ab0b9,f546faf2,120b2e92,6c4f0f18,49cc01eb,834e1406,b5ab4d54,bf3abd22,2b40ec25)}, -{S(7c32fcd7,13305cc7,44fc4ff5,2d315e2d,d4cdf7c0,31b41a64,db6ecbf9,fd4edcbb,7f002bf7,b8e1b8f4,a4a4f2b,1922983e,fb901e13,59cbe934,8a31d91b,7bc86bf4), -S(c72e640,f0401cde,93d85764,224730de,8d46477b,538528b2,53361873,c9f39dfb,571700b2,b5768244,63541839,a1a890bc,dc823e39,a7d137f,9e31e849,583b8fbe), -S(3bf6cfec,83091c9e,1c1deab8,6271526d,9d9afce3,1f052a3a,c8ebd1a9,49005470,35fbff47,bc7d13bb,197e6d7d,50596617,79a06b,e956bfca,667cf070,b80b45de), -S(3416d9d3,6c2c2c6b,77a5d647,500b145c,926cb3e7,1aeb7e83,101dc410,a72bf818,c785a0c4,7408b8b0,30b386cf,9e39f1ef,7bbc4358,f66ddc20,22b1b781,8ca175cc)}, -{S(29d70da5,92094c96,e293c115,42b9dbab,b30df8db,ac98416b,65b0b75b,b3ca446e,a8a5aa3c,c3269596,dd8a9d98,87a3b772,efa1c668,3f8a947f,ff80c662,31c70799), -S(bcaf0322,1e406be9,5df0e9d8,79d82851,2a71aa7a,7a84d8c2,ceb0a6,9d33d827,7a9ecf5c,efb0adf0,c0a2af5b,dc6c2537,b1fdbe0d,be399bf5,6e9d3612,a94f4239), -S(7a24f37d,d6a8c278,cdae5cd1,70be20e5,b9c9c028,ffd3c9fe,4dd3fc18,45a339b2,705f933a,d0dc7a14,7838c060,abba9bc1,7012ccbe,83633551,536e8aba,c8b5ee1b), -S(c35ffef3,aa4a3e9d,93dcaa91,a972172b,785d997e,dee6cf34,e181d217,a3c83d97,122638e5,b7bd05a9,1c5ad0d9,bda96767,6281434,dd0f8a92,561df9bd,96779571)}, -{S(7885bb79,25196ae6,f45b6658,f3c04f5,a3b76cb6,1d60eaf2,45cb35c2,2552267a,9839aae2,b4d9de01,1a119d3a,d269a821,dd88d287,2f031910,a2f3cc22,2e8555a7), -S(b425f805,2659b55e,4b46894e,3498c273,e1869ffb,880e9c50,20bef244,ad471ea7,b0bde647,f6422b6,a8f8fd07,a6f8c73,5b5a17bd,9d6eb57b,34142a18,93825a7e), -S(ccdc5e4c,7593b182,a70c2f97,c358db89,f5b09cf9,de3c5bdf,2a44808e,a84023df,8004b543,df7a516e,faebadfd,c2121101,1ab99b4f,c7a8cdf1,43a56afc,8aa72854), -S(d55f41a9,331ead98,db392478,aea2ce68,ae5c9f84,179caed1,aba5d60f,246f576d,43eed529,61c8bc39,8da97200,92f66f18,69be7dc2,d644f291,98be290d,adabc6a3)}, -{S(422f029,1f51c4df,af233322,7015e4c1,ec8175b1,a8ab6b2f,60a9e291,7242d940,51ae32b0,ed5d39d,e1d61437,d363d59,181a68b6,4e052bc5,9d132da0,9c1f422e), -S(3287920f,f0fc9643,9b0aff00,d6944422,297d3f52,7539f579,98fe3d29,80cc58c4,eaab3473,d562fe1,6cb86453,52228f69,f34efede,6934a587,ce62760d,5fb7869a), -S(a9ce3776,2c703adf,e36d3f6c,7a2b04b9,288bd09e,59bf6fd8,25cb0ac,84bbc641,1e9e8e03,ade9a185,d0680f80,9a9a0468,2338a1bb,4fdc129d,f6a86377,2f9da89), -S(a7480262,bab701d4,11642b23,50934791,8e393f5f,3d55ca2d,fcdf1957,f20c4e04,460875e0,a7afbd6b,ee8491df,d1e80b58,9cba5bd3,a6e4d74e,a4f5bc6c,567460d4)}, -{S(43cf2273,e372157c,2180640,594c144c,93f64fa1,75f28cd2,5e7efebb,14028a93,1f8b092d,4cabc600,33782374,10eafd04,37d6436f,6064932,6f8de6d,94059d4e), -S(e327e5fe,3d20effd,89532c73,eae90c0a,36358e5e,65cff655,b25bd325,8339599f,311932aa,8e4c3f38,cf6ba972,d9872585,14d376,460a1185,6b3a8bbb,ef050996), -S(5fe08c73,62e99994,ea0416e7,d29e1f8e,56e66baa,ef9f3cd8,47732960,c6e545ba,f9373f76,5a340816,cde0db8f,486d6453,531c0ec7,4ddea72e,280d7f42,2fd7ad80), -S(5c32f5a4,74b7f6f0,c019f7d0,a2df5c77,4017dc1a,f93b5c00,bd531eac,32488609,94ca08eb,3d86eb5d,b8f31b4d,9455a6c6,1525a0cf,b388b698,4fb286c7,188d3193)}, -{S(9f10aba7,5a7b9fa0,233bf53c,d819ba2d,919f8acf,9a5e6717,2c93229d,547a40bd,85485295,254a4456,87b065aa,dad21f32,b31735e1,96333fb8,11117a00,d0bf2361), -S(b56da700,114ee476,21540199,e77ba271,e8d578a4,5be263c6,cee2e8ad,fb3a3e48,23ec87c4,236c1299,96ba8d3f,b8cc8af0,b099042c,6623deaf,2abc10cb,c17536fd), -S(a9d94ff7,a5be0ab7,5a8563d6,b061a8a0,7e12690,4870fe3e,39c4ce98,93e96b09,8d1b1b28,a0366d25,a61b617d,9fc10194,72fb3e5e,ff5ce43c,9e1bf1ec,708be6be), -S(fb9fa3f5,381ed2f8,b8f407b2,9991fa07,a6d7a265,4dd2b3b0,cffa3814,10efe8ec,8e9b9167,bf42b7f0,6bb22bb2,3fb40e01,bfbac1a0,dac536ba,b17e7970,803ed9f4)}, -{S(b365ce49,d21ca341,c173b6d7,2238c56b,f080d218,a89e57c6,ce1664f6,5c290a44,e77935dd,75d26531,d4045f72,3b4b5dc4,6608f8b,60f58989,d2ac4002,c304cf04), -S(f512da13,dec07111,2b2cdffe,f72b2b20,aab81bc4,8c3514d2,f6f1360e,ea17e855,3934b35b,87269072,77bb171b,fa2bf260,244b1f6a,13bdba7e,a3e43b8,d86d8abe), -S(3e000708,badfe5fd,d7f708ca,92bd5784,80d0164f,d76bb0bb,4dfaf9eb,e54335a6,713915c9,7c1b1d3a,7111ea47,6c232b85,527ed32b,1e6c4584,cf36e9d8,5abb9d80), -S(c6e97208,17f00aef,4988ea97,8f7a0240,efe4a0ce,203ff10f,4dc77e2b,eb49934,d47cc2d7,f0e499b4,985048fd,fd5f14,83d1f90d,a1abc2ff,340993cb,e7ae03d4)}, -{S(38186a1d,6092b158,554f3f6d,c6de049a,2037577b,2da8db39,163fde30,b19dbf2a,a8cf045,9c7ea28a,415d01f4,47566d54,f986cab5,eb272326,442f32ef,cb6c43c8), -S(ac911a57,1f58a283,517f1ae7,7b2ec8ce,1bbb2d17,3e2dd021,bbaf352e,edca57ad,c9e985f3,f278463b,66851c70,d2a2192,299a3bb1,7ac40661,bff10ea9,29734b3a), -S(9a691204,2f6e8cf2,7189de67,f04d15c5,b80df68e,daa7dc7b,74d08053,e32d4516,a60a7abd,6448fc26,3d49e9fc,32b51f05,1578a8c6,74827059,ddfb9f93,f4621acb), -S(8e6ecfe4,e5b519fc,be7bfc37,5b0738b4,618e5586,dea95ce1,8b870424,55b8d1da,4d459953,53cf5ec3,43b38aed,c3d6bf27,83230fbb,9fc0e147,5cc5ca9,6a341ef8)}, -{S(d8e5f3ba,c152215a,8cf8ca08,40aaad6c,7d001aa0,140bb0b4,dcac726,229ee272,e59390a8,21e8608b,e53fb258,a426dfb6,ca762fd0,9d574f7c,5555cb8d,7174b381), -S(281c15f2,ff06b872,5d0b9a22,2583cbe1,f29c6bd9,7d63db8f,426bbbb7,f36dfd57,ca452a00,fd4afd88,f5369ec0,5b3a99a8,7ebc60cc,db297d6e,ad1479ce,a8c87bf1), -S(69c61933,b91a122a,36087b61,1fb86372,3cfaec6a,5e51b4de,9db83fb5,cc5a1e5c,18b17e6d,74d632da,90946919,2ea6700a,ddfb34f1,f537e5ff,581e04c1,97437d78), -S(e97b38d0,9bc65cb3,421a6ba7,9efeb127,16fc82fd,b539f94c,1c068699,2aab5eb8,43244371,2d899972,a9ebfdab,4ab8a5d3,b7b14b0e,64d82d52,50b9875d,bfc9e1a8)}, -{S(f41bd2b0,e0f49133,747e831c,af4c7a0c,22d2b55f,1cd4ca53,1115d81b,b47754b0,869485d7,26d4687b,c57a9eb6,e90e93a7,bce3b523,998d16c1,297c996a,b68c4fa3), -S(b6161665,b95062e3,aefcc0b5,1220e1d4,dc6945ec,3f73ca4c,47449592,ca977cf9,edea5f23,e6dd49be,7d718fbc,d0368be2,ab3b556c,e1c1de15,1d811c81,44bfd39e), -S(efa245d4,3743d3cd,863a6144,cae9db8a,c7b80e58,4bb31a66,1b670b3e,a17a63b1,ccb90bd2,806117e3,3781f7fd,7ec24d22,b6174aa7,1c8b0f35,bd22e95b,7f5fd96b), -S(ff59688a,fc00c3ce,15e0b2fd,d829725d,28b9d07f,9fb13e7,61ea7f8c,c271914,9779dd1f,aa487c2d,b4c4bb48,3877a848,c329fe68,52c05a8c,7c8d1c51,95a905c6)}, -{S(67c452cb,e71c61c5,8aaf68cc,b1f6208d,5646432b,86774f8f,60081179,6d5337c9,d5f859de,a125aee2,11dcc7cb,b50b4fa3,ef4f9767,7eb94f65,b6a181df,9b938c0a), -S(247c1e17,4a3fcde8,580214e6,b791ad00,59a992d9,84a80f32,640e25ea,3841b18e,1a9f638a,74228a49,e083b3c,c233022f,6943ce4,457199ca,30f230d3,42fb15c4), -S(d36e3977,66121dd6,af8676ea,155f4898,c04ad6f9,d682841a,6811c4c7,2d0a498c,61c0712d,24db9d98,dd6dcdcb,e0a57878,b5cc5a88,d42c50c7,d5f144ce,a937ebf1), -S(b0a52f1f,2cad54b6,658a07a0,dd64c7df,e227aa3f,a32329bd,cf0dba1d,b33de23,c760832f,9be22f9d,c7d17a21,46255338,25ed8afd,1468d03d,d6ae5593,71bfad31)}, -{S(56d09714,cde8f0c,f1956cf,a56bb0aa,b73507c8,bc0399f8,c0fd17de,19e48e9b,d62e1f31,b40ca6ba,71de9059,8a9fb911,6c5f0007,df0c33eb,f50db688,ef0ab90f), -S(a070b352,ecfb2a06,d450cfbf,6800d7ab,6ecd58c4,a5d66c38,a330feb7,739c7dd0,226e8d14,8b074b35,db600e7f,4bbf40f5,c957e5d2,10b757de,3796f2db,1fa4e89f), -S(acf26ed4,9c8d49fc,69d83f06,168a7ead,77a0e16b,89fcd5b9,65da0d65,5dcb7d3f,54894631,5bfd024f,cfff92f2,df2e2ce8,987c385e,6147d783,612a91bb,5411126d), -S(33b944e9,fbcac6bb,4a0a2c95,168180de,fb88eb50,7cbe354,884af02e,dbf5e0c1,a0de73f,8c3646b2,dfeb126b,100a8e6,f5adfd54,2e26b225,d096d760,90f87c62)}, -{S(31095045,658b8c85,ec0c4ddc,7cbce691,d060181d,ffa08855,f3f36722,4c026225,9a8cc527,1c231ce7,aeb6e73b,9acbc16f,4b331b01,4bd457b8,799bad40,547c210c), -S(48472fcc,ddf9b0b3,99ca4d48,254695ba,4beb02da,849833ca,fe68454e,284998c9,a08a0346,83e54fda,d2a1fe63,20b67fb1,b58a4671,b4d08172,b1b6ffc3,c3852499), -S(22cbc8e8,e2d632e7,bbff1662,4b6b971b,ae0b1c12,14c342d6,61fccc2a,af196054,1fae61c2,9843ca1c,6ec5a163,f11c5c7a,1ec4637,4406f32,67a47c4,c111ef3d), -S(5024b68f,89c9eb0,fe4e1517,726f2cef,d270ecf8,182dd81d,20d65a67,8dc81c32,952869d4,4a76c942,ac9c0516,fc16b1d7,a0de7bc7,3fb1a18d,a7253d0b,cbd9019c)}, -{S(da34375c,e38127dc,cc88a823,55d763a7,2dd5d733,d9bac216,7c3e621b,ede529df,13426579,db1353d2,8095e1f2,a007904d,5c04a725,2c621ce4,41157aef,d2e28cf2), -S(ca76f69,937d5d84,659fce11,e1dce556,f450874,5c0e003c,5e474b84,515a7ef5,d2e10042,a71e3e65,d1290d8d,7b5389ea,4156528a,2633ba15,bfe900fa,c5464939), -S(8d7a5378,92f98107,3dcfea0c,9750e22d,e42066a7,ce3b4d16,8b1e56fd,c8a9b93b,ca32aad9,b5d0b83,8eeebde1,8eb7b526,8169b0ae,912539f9,49a1981,d6065703), -S(d58ca70a,51085dee,3d1c06a6,13a5a46d,22d1ba6f,6077df3e,f67b33b9,614869c7,bd212d56,451c1609,93ab9ffe,9371c3b0,76a2c702,d7c12823,ee66a084,ee82fbdb)}, -{S(a80dd274,9cb3c40d,af91b91f,6e8b0850,27fae17,96e416fb,8a172c27,d39e8789,466161e1,e9519ac5,e1b03652,cd1ce6cd,1d7dc696,aa59ab5c,565d822f,af427896), -S(e2313561,865ab364,7118595,e7a10279,4a94ff32,48b7247f,a21d2a3c,906cfc7d,9af6a874,d22254c,f148b479,7d70947d,3065d907,e01f35f2,6f14811c,bb1b36ca), -S(db567947,4a29e5aa,b6cd6cd9,9e92ef97,21eb61db,37b0d0ef,2807624a,e50f1b30,1132a05b,f945f3b4,3bb70fb2,1ef08fe6,c2d4f18,ef2fd356,73f3c430,6ee73ce3), -S(3b4569ea,9feb4458,1c89625,5f39f4d8,3f590d39,c50f3df9,1f061019,c8094e53,97fabe3a,cf3f72b6,c1f01688,690cdac1,c92afe2f,9b1a9138,b9951f97,ddbcdd8f)}, -{S(b3dee3f6,cc08c0ba,5b7ba3b8,50469647,34f7dca1,630e806e,f84157e8,2992c765,d523bf3c,6b004cbd,59db62b2,58395f63,d487d6ce,31799ee1,59ddf96e,d9bae2e8), -S(93c41e9d,ef80a2f6,93cbea0b,c5c111ae,11fd8a86,3940097c,b8753970,e3123733,83a51bb5,849464b3,ee5be4b6,5c5215ed,55e5f157,db8b64bf,aaed7099,497fee0a), -S(6ac20b8b,6c5314e1,72a39c51,a30fdd47,db16215f,e7ed2283,76f74eb3,718ce734,73b0cfa7,ca3836f8,15ef0ddb,d74ca28a,b83093b3,4ae41a94,e92ddfe0,89af26f3), -S(7536c8f8,dc949d7d,c43910a0,8007d6dd,8398f8e3,28ece93d,93b95171,7d2a6479,43e214ad,2c36155b,187973d1,bcdcbbd0,58448490,a1a835ae,2f661084,d8370a10)}, -{S(df9c2e20,68e1e333,f6acc6c3,ba9928eb,e761d4b0,27eaa1de,dae18079,29705021,491f455b,6e937f91,35fe9060,a8c5b6c1,60de5af9,ba90aba4,c060145a,da1b032d), -S(db3f1233,c95cafc0,a5ec4224,2a62e08,745dc259,28b9a938,e6940809,9376dee,94903b4b,2908cd49,95f0883f,1a11d65,880673c4,ef07aa9b,5416de42,8e4ed716), -S(a4eda54e,c923719f,8c4b217e,2c20690c,5986c871,fad99156,8a1f6614,4d48e91a,87736a5f,e71db939,3a673e7a,9bc89091,2ee0c459,5150b88c,792fc2a1,bad3a6b9), -S(ea2475a,ac3db1d8,60263b16,aaff75d5,3c68bd1b,da9123ac,951a8015,30961202,2e723212,716c3573,e58765d7,459070af,45a48555,c176af74,fbf212ab,ff29033e)}, -{S(afdfa934,6f7bcc74,ec473e17,f5048650,11c5251b,bd6c0c70,c25cb561,4b004da8,b16eec26,d575cec6,b8720f94,4ccdddd,78a5c446,a0cf286,fd933f6a,999a4a39), -S(e529f606,84edf5b9,5cd3aba7,233959e9,65639ebd,13c58d6b,c8824fde,3f6e94df,93354f65,e5299a8e,210a94ac,8a871f2a,a7a0a6d7,558fafe0,f67f7c5d,ab304610), -S(83438a3b,47df9b79,baabaeb8,40ea82f4,e7b6aa6c,49802c24,d380fdfa,2f453d0f,25fd4329,e2ac037c,46025db2,16d1d18f,395797ce,613c8c54,beffabd7,eb17eb73), -S(30b3d04f,76e7f7ca,9ddccff1,f904b937,dd972f39,11092f75,9070dd4f,f67cff48,b70176a2,30e72a7e,645c2122,4b9194f0,3c38f18,7020ebed,120df9af,588dbf4f)}, -{S(c8e9e9c6,55d9d7e3,16a16971,f7b7ed06,fa5a2ddb,56288169,ea96c439,6a53e01e,3bf36e6e,8cb2f52d,8a7a155d,1b3e4a17,e06ae0cb,b1dec52a,9b5fbb2,9f0b8a1f), -S(b6b755d8,3e6f1b3,e19a079b,daf2cfe7,22dceea0,2791b200,52ce09a4,d066f196,350f105c,6e52d1b6,da090848,1e338375,7f78a1b3,da3d64f9,eec159cc,ee2c425), -S(713368a8,f3fe29d9,cb8dbff8,6b74b41e,bf2fa4d8,11aced57,47cd800b,afa434cd,2a99e4fc,a4fa0758,8c6ff4ad,968323d,b753d9c4,42b81496,fb0cf028,e9c79173), -S(9e8a9fd0,23b165fc,8d95e7e1,39804c07,aad352cc,18b803d5,b7bf8ae5,5f2fb3,dd7ead28,6afc6105,89e1f4a6,386798e5,97e92401,397f8d50,2ad9802,71a1e81e)}, -{S(9d687619,c1c2c42e,3e466fd0,1ad5a0b8,b459ab12,642d80dc,1081ae1c,a8009f58,34fa7382,687f04f5,1fb15740,c31df8e3,145a0908,ac699527,983a712,23414391), -S(aff756a6,6ea7ea7d,85ba28df,fb25a543,f317f806,f18a4b62,5469ecc9,7e5468aa,b344ad2e,b5cbf601,805017e6,3f8a3d76,99ecfd82,28a9d2be,a7f34436,9e1563d9), -S(d7f37592,cd207f26,80c3e659,ab26a9f3,86270623,bcfd6737,fba2839a,a2ff3f7f,46a52a06,fec906ae,79a81333,39659e09,7ad928d2,4b9495eb,98e89062,d87b0d3e), -S(7fa626bb,98c9f1a,84db146d,584aa1a,3ae75f01,1a86800f,21c2ad77,eb1df5ec,c8a92713,ee8edcdd,3954b267,cd1aed45,929599a3,3d10ab09,5a1703c2,447bc9ef)}, -{S(bede42c9,3086c85,d6793a53,5fcedc15,6202042d,35051eac,a86ee941,aa961d84,e0e7ae8b,a657730c,2fc631ce,82b58bca,1dcd52bf,6f071eb0,cb7b9f7b,24bdeb5b), -S(dbc001ae,137b542,ec96adfa,367531f5,a88b124e,8dda4600,1b14433d,acb50db0,e49c3c9e,abd1e5c3,c5fa8df9,46d7705,e54f594e,d31a5b81,bbc9cf68,d15fd7fa), -S(e199e2ef,a5120572,b844d1bd,76b2b66d,e7f5d2ad,283d4b87,3dda2597,f739733,9926c3f3,88af1ded,eee14bc5,bbf3310,4be655ff,c3ad4798,5b8e4f13,48f3f5c2), -S(19df4eaf,d8bea6e8,edef3a83,415a7a15,a2c3a8a8,95d19651,6c0b0f1,1628f9d9,6e36af6e,9f01cd77,dfa50cc4,a647b222,d6503c57,b4b6cccb,7b9f96bb,d68fb968)}, -{S(998c1a4f,52aa78a,8ab3a94e,66d787b7,145fdaa6,4701c0bc,8bab6933,3ca18ec7,a069228d,355e75be,f50b4682,b210b776,95b997ab,12d87b3a,29e87b1d,289de833), -S(6388dbf6,171559be,2d7e02fa,2bebd597,c373c97f,95d7c4cb,614db1a,9c19a82e,b1d06e7c,83dd9880,a7e1582b,27b3be98,e2953cda,505ecf6e,3ee88bec,713e6035), -S(66f24649,523c8820,798f6e34,a3c0cac1,ebaf194b,c4c32c84,a8ec5a2d,2dedd188,ec6d60de,74e50469,64ab846,1d09335,ae9f657,bb8b6f7a,85e02867,11390425), -S(43784439,5667fc87,d1b4486b,f798d397,e6aa598d,be9f6b21,63fd8218,ea7c8490,dcf33b4c,5738904e,6a4a67b9,a6360ff1,e603fc6c,617a7b6b,17095d56,e6eb2989)}, -{S(8c422f9c,4e2aa24a,6513390,fbcd3531,50b28c5d,40ee8add,8c9d5591,6440cf99,21809c0,2c3f1879,f677997,919d0deb,fd8b2d00,5f249de0,e3df9b4e,8df20524), -S(46f4b7e6,6fc006d3,84e202ce,e1658299,cee653b3,db8672e2,a2e26506,8bfa8b73,d09d2a58,d6c88882,2b2ef6e9,3cd26cc2,4c20f338,50d05e7f,6c937a9c,f8670e7a), -S(a19360c0,66d42f02,541dffe7,fa9aac94,26a4de5a,8a756643,cb812e66,9be21d42,3dd23994,8e869afc,5ca5ca6a,f51fd836,7c612022,d9b78aa2,4a78b8bf,d48a7958), -S(53f1c8b6,f62e094c,3a814741,e2c31259,95fb285c,d8e12d1f,9130c9ce,b1eeb63f,9129139d,42e3c44e,f124685c,fdddddd5,ba9bf1ff,5a61534a,d48503c,b48568b5)}, -{S(3cd27c1f,ece87bf8,10e9c382,a0d7939a,de6f757d,9d0178a4,ea486e2e,241d1216,806192c8,1852c43b,d2439452,b42152e,b0f8a728,50f3af8b,be9670f,fc919897), -S(e00029c9,85a513c0,9eb33ad3,5d0b712f,30bed96a,48eda85c,fc2509b5,99f7b3c0,bc83f8eb,c1bbfb39,981c89f5,7c23912e,780e6cb4,e3a97599,28e51430,a7a205c3), -S(85282c5d,fe004218,1af469d8,8949c331,545e94c2,3a7782a6,4b5b2afd,7e2bc98a,88f0b05d,4032c6d2,8b4140dd,482fdf9a,724181a3,a1ed22a0,ba4b83c,fbd6a61c), -S(8e26c183,26188725,d12e7726,9eb3afcd,121c2b17,6d7678a0,93a496e0,9c4f65ea,a574d95,7e9eb080,5f83e417,f145a708,971e2153,a8ab8462,99d52583,8472e368)}, -{S(7e562c7f,87ba4090,c3147469,78bcb59,722627af,75555e0,ded87772,f67a5ef,433effc5,1a6da4b4,14f793fb,58961db1,fc6681da,2e367f06,331eae98,4c1f31d4), -S(b273ce89,62c52be5,cb23cae,d2b98015,78c7dae3,d10af405,461b4101,c0ff1c43,4ebad439,72b99896,f7f41019,57766925,f145d0ce,59424c8a,6c5cbacc,a3979f16), -S(dc301ce9,26e82026,38b1fe94,7d166507,642a89a1,509fe1c6,5c13af35,9fc34c11,a7230a1,52c96952,a6e5bf42,c4fb504f,12d2577b,40e8b947,53db719b,52ca6b53), -S(4a9fd32c,a97ed57e,83e5c712,5b7a2af7,3fa9ea4e,d96ed369,6aa9f0e3,cbfafda0,4659c8a8,b9d5c6c,cbfcaa9e,eb2cc24a,225de909,faba88c2,132ecf8a,da456ffd)}, -{S(9189ba51,a650f218,5b0e78b2,4fc81b3f,95896526,65bb6ec3,506eff71,71399ad4,981c7770,b6d9fe5e,f55f55b4,4dcd4b29,57ee7078,5cd95d84,d59bbf8,6049a067), -S(8043092c,79a5aa9,c85468f,3e95665b,f7742d3c,78e46529,9fa55525,df768f,5d4df375,eda914f2,49b3755f,365412e8,1f587da9,b444cad0,d3ff87e0,4a7d5f55), -S(c4ceb96c,c733f959,70fc29e1,6abc8ce6,61edb654,6ecda22d,854552ba,3ddca54c,6c1a710a,f15c503e,b2e4ce7b,341256b5,ab3f5a0d,bf1ae1ae,f47d12d4,9c6e3b4a), -S(ef2ffdd3,54249e01,63e49632,c12f236,f71dca92,536ac805,70792598,a46f784f,b121fddc,795491b6,97a1cd12,9964803e,68f60f13,55cee300,5d64f761,3fa1e3d9)}, -{S(b381f721,8381bcba,39ce4649,ded8aeed,43d5548a,b1b09981,a704856a,9b2af576,fd401803,9e993bc,1396a459,8270d4b3,f26f47f1,8babbdc,bfcc30b3,671302bd), -S(9b88c66e,8abab5ea,b4b0e3b8,10bcf0a0,d3987e1c,c53b04cf,9e445f2b,a50b1744,f2f8df3,6fdcb9a8,abe5778e,33fb1912,20b55224,85286f25,3914d175,cf5b85bd), -S(3da8ba80,a6744737,eb75edb4,3bdce32e,f6f1b74b,bc0f7f36,3cc2f342,209a4e52,d61d3a19,bdb8d194,1ee3e2a4,50d7e87,bd00652b,4a52c415,825185b4,a2ad1467), -S(a23779f1,b3716be7,82d4bbb4,3d81677e,d78ed041,c2786f33,49d56666,8bfcec02,33b57d01,c3f38b53,d96ebc7b,2aca2c08,66de0c9d,9764dcb8,dce0c27e,f4217963)}, -{S(e2937985,7de31ced,bca13b56,16a2b853,c1f6c915,8ba5b999,405603bf,eda41ce3,bfff0870,88508486,361a6388,b70638f6,7eacd5fc,a1a1e187,93b2c282,d4d90ec3), -S(42e86050,d6101847,d9aa35b6,45ec7a23,2fd77d5d,c60ad7cd,a10e531c,876187d7,e0a1140,b5e0ab81,79c4a1d9,4e67f6da,ff166fdb,48dd3dd9,4e110519,fdec0563), -S(236ce23b,a13fb252,ee19f08e,9a3948cc,f3edf6b8,9802175b,67d34e91,b82ca1f2,3b569c1b,5c8aae64,b154565,70d7335b,e9f4085a,a2c7e522,96094b93,f9642667), -S(aecaf4d5,282956a7,5831cc6a,a2c09b93,655ab061,1556fba0,8b81bcd,9d9284e5,efdd1e5f,f6c357f0,21d1fe01,d8c6f2fe,c2d0e85e,12b7fab3,6920e684,df21e93a)}, -{S(9eb2f66f,e59abee,bd7c1bd8,dc102027,e94890d6,d24cefe0,e0e3185a,d84567da,123480a6,b2109616,2f5c8bba,4c71ad28,b1ef6d3c,c6b864ab,eec3bfd5,15069b19), -S(e178a416,f501623e,5fb17e46,9d7ae900,1b508178,91f25b5a,83adc565,7556ed18,e0712be6,e78d1a97,452c35a,c19e0459,dd6762a6,9b5ec073,ad1d6ed5,8ba3b369), -S(99243b08,6c3ba8cc,f44cf61e,c7a4ec89,541019e8,65a04ecb,da7e4683,16b5e883,9fb51a9f,4cab9214,d5247350,10a557ca,403fa1c3,b55d722,19557d8b,df2de0c2), -S(c33c61e2,5ceeeb1f,2fa47e22,a93f16ca,123235c2,b7cf9af5,e712e88f,808fb372,a72ded7f,3a362df8,a0992be1,6ab23f52,996f200d,b4981d5c,9cb76712,f0a88274)}, -{S(46481a2d,9c09cf4f,e869ece0,3f065938,e144393b,125191de,a52975d6,f6e0f3f3,74245935,50f81ff0,412a2ccd,f0ec2149,a66a61d0,d63cfd19,74a672f2,ba3dc512), -S(b5d5fb4a,ff2752fb,114a8b1a,c285ad44,5dbcf4aa,fe8f75cb,31bc43a,4298d86f,6f2e10cb,b36e3f26,ca280661,3ac0c052,1fb0781b,214e404,92574c09,8d87e519), -S(308bac42,a25bafbf,93a6ae26,cf99cbc5,1a643215,2cfd927d,7250a964,bc459289,ab38c54b,5725609,3d83bd6c,1dcd4242,e13bd844,c2b7b6c3,b1fdc8e,f7c1abc4), -S(b3c63fe1,67804d24,bf0b00f4,1c4a0175,4886e9c6,a9047439,adf365d6,bca491a7,d0a1a577,da95a3e3,6e2657b9,f9804c8e,93b5e635,6e5fa540,4fe8e3c5,5cf89b2e)}, -{S(5111fd06,525fbe47,3fbd604,6faad331,e715cc48,d2851a8d,70b34c5e,35db531,96ffe690,ff3d3901,d9505f1f,a13c446d,4065ce5e,fabd4ced,59c4f8ca,440d1515), -S(bc12f2be,3b0f27e1,92c9d446,59bec78a,4a592f0e,997be28c,313d93ac,4769fb4a,143f1a68,1f6d69f,66f49543,b131a1f6,c8e3b933,271dd57a,3be9db9d,1f9c31b7), -S(edc09cf5,6730b640,689c052b,989bf0fd,de56d4e4,8079000a,b4e8eff2,23ab61b3,57f21a98,eadedef2,8ff6063d,53bf158b,c38e1c1f,6df2d6e0,5ff7ad18,47c91bea), -S(4ba6c933,962ee6dd,7b7a80fd,4102ead5,d94a224a,4236234a,72afef90,3537c70f,f84264af,c8424c8d,77b4cdc0,37f4fdfc,3b1c7dec,f0fd3da6,f696beb0,98b2840b)}, -{S(6d3b19f9,79986500,2f0fe9f7,67efdd28,73839d01,3b7f4cc0,842b0a85,c1934182,b261bd9c,c90bf00c,3ac67bf3,728ef44e,2aa1b660,6cfd4c41,20d1bab3,aa05efc), -S(b9e6fbd6,bacca67c,d2977ad7,458d006,bea2288f,598904af,6794cd1,dc819231,bfd5bcf,2aeca281,d596798d,482ab975,73b15bfa,db7df642,abdc727e,cf664f1e), -S(f2e3c13c,8e1da25a,3b05272c,fa653ef5,487ea653,6d55bed6,c9ee0e77,85325f90,7bcae36c,67ec60cc,108a8794,cb24a3,b70c5f0d,2d58c813,77dfbd7c,10972256), -S(1317a41e,f4f09481,db342808,63d49b1b,dfb2a11a,f843ddba,29499f1c,69cba337,28aa8ec0,ba9021f,c49e90f5,65c61254,3b2e6e0f,57370374,93fe349e,11ea5eed)}, -{S(5a9ce5ce,5b6c4aeb,88f47c4f,680002a3,d898da92,603c0513,d72ae0c0,239f10ca,c1d25370,ef453f49,7982bdc5,d7062098,1a0dcfe7,d07a0339,eadfc5bc,dd0d7874), -S(575eaa03,caf5e2bd,eea82550,f961b06b,e8c8a25d,a13f912c,856776a9,2c3cd783,732a2a82,da6c4d7c,79f5bef3,9b39831f,f8f79233,f9700346,fabff503,50624616), -S(b70091c1,99c77e1b,756625fc,de51262f,93e236ca,f48d6f79,d5ad6d2c,1c4eddff,d301345f,3d600128,503f3b0a,7ecb44de,f623c9d6,b3ed8cae,d676cabe,695cd53d), -S(338ea0d3,6d5d98fd,b95db010,633555de,c9cae973,720ac4e7,bfddc91b,176103f2,bd9e4e53,e18e541e,8ddb1d24,ffbf38d5,d2529ad3,3c043c07,1fe78847,63be57fb)}, -{S(cf850614,851d0868,16a329fc,f5c1afc,6dfdbbb0,ed9278f1,22de3890,cb693837,b768ddcf,f8dbe818,fcda1d41,1133a9d8,5ba6fa7c,9dc85b1f,23b3174d,69e3f33), -S(e3195ebc,5ee69554,73a626ea,14332378,1da933b0,fb5a1484,da2363d,65cadc7e,d0acda43,e7ff4df9,dd1f46bb,93e8bb3e,ff73644a,e024b5ca,8996a750,91928bd6), -S(5741cbec,60c5375f,6dc383c1,9b0dd4db,1a6a8aed,5658e87b,fef33a14,2e281580,66e9e972,2a6df27b,24500496,ded7638c,a19152d5,7c7adb04,74125ff5,1be6cb5b), -S(7e64bc9b,ea4c6460,b9b1ef71,95a4f4e2,5601d616,11ae689e,cb05b0b1,ade57298,bf43d8b2,65094986,324842b3,23fcb1f6,5d0896ef,1537630f,e42b669b,42758a62)}, -{S(17631e86,523e4d18,51417204,dde16c6a,bb7ded2f,2504bce,6683159,63e9b492,cc3a083e,e4622c59,4d934ecf,2471143f,4af9c4e,481866b4,637104ac,d815c97), -S(69d98c81,2dd5cd4,229eee2d,d82f75a4,986e514d,cd8dd1aa,1bed8447,e5f46fb,7d72fd27,40e91bbc,64a3ca20,243eb038,9cdc46d7,eab75343,8103f4b2,43e9de06), -S(76f7c0d1,c661944,5f0f5beb,568cdeb4,9cd483d,e5bcb737,2de66e73,cab23c2c,540422cd,994b4411,6ed2d068,5dc78193,fb5b5fd6,28e3f432,ee2d221f,8783ef7a), -S(6938d574,f67039b5,eb87fbdb,b759fcdf,4fc2c341,ac5817d6,8ea8277c,d4297574,5a2679bc,83685ca8,d3961d51,1a5ea081,8ae917c9,4606d552,620093eb,f399de53)}, -{S(60ad1b2,a075a3f5,fcf72668,cb48703a,f44c3442,23566340,b0fd682c,ae829ddb,534bb9d8,46bd457d,3574e528,87787f61,743b8cc8,e7b9032c,587992fa,c0ca2818), -S(1d66875f,42d8e75d,5651a635,1db1a820,725a29cf,74e0577d,833bf841,94e9a2d6,803ed33d,2188877a,c2e3d4e6,d78aae19,8d2eeb5e,a9e2c3cc,29cd5214,c20a78be), -S(cf400141,4811b30,70345420,e23ff7fc,bb800b9f,ea2e18cd,84b1b637,7b59ea39,2b8ca9bc,722dee2e,29996865,93178cdf,16503531,e3885322,d42b0ff4,dd091927), -S(ff2612ac,2f9925cb,cd76b975,b23aff70,428062f5,8f64a507,28b3021c,6548495c,e3bc502d,6046782f,8d2cd0f3,f5bd7ea,f661e4d8,5eebb56f,cf2e9d78,535994b3)}, -{S(4839ed9d,4a5e9c82,4c6ab373,b9cce0ee,6d8f19e4,2185c791,89b52aa3,52533187,a1663ed9,7007472,8367faff,33ba90f3,620b6b18,a816ff71,7fe8e97,20304323), -S(ea4b17,5edef6e2,46f8eb69,5bdd5b86,f06231d2,38303d94,c89399b4,af9a4531,aaf021e2,555632b4,da731da2,fb3fa644,2e8c34f7,9ed5a701,d9ff6be6,c3d3e7c7), -S(62def07d,3b90500b,548c2126,5d65f122,edf17b97,9defab64,3e702276,774ba43b,1caa772b,bd3ecd64,c83d903f,ae57a9de,49649abb,5aa7a21,2dc2a904,e97f9ad0), -S(b8cab6cc,e7898d3f,ffabaa1f,8bf0fcb6,fb00239c,27f33ca0,dd893d98,b2784eb0,96841107,cdcc5d3b,5c1c9c7f,39b92ff1,5831e400,73762437,7d062af3,4b0a1db0)}, -{S(63b931af,dd8dd850,d9b2f2fd,480e109,14365299,254ae0a7,b04cbc2a,def6a5a8,dddb17fd,8100129c,27b1122,34587e41,e6b47b01,9ed91775,b217a10b,3030288d), -S(a2a4d3f4,40c5500d,a0cca022,21cea8d5,89410fdd,7782d574,85112d8f,e6ffdd61,adbc7f46,db8b0f29,31dec8a,bdfcf396,96f158be,f6f28d4b,d88e14f5,5ecd7bd7), -S(242766db,7d3aa77a,6daafe42,1fc02bc2,d78bb495,771264fe,4f9ae1d7,837106cd,f9d7f63,7f83f5a0,6dc4cd42,af1aa54c,821f1711,66bb9c02,58ff6448,de3da6ac), -S(c089b764,f873e53f,9fb390b1,d802c7cf,e68f8dab,6f2ba524,4e309027,8ea60dda,7f83e920,b2fb47d1,c7b9aa13,eca044b1,7ab67d0c,94767d39,80aff8a3,1d9effaa)}, -{S(ee609aa5,cfe0de2c,45d1df32,707e4e8,d8c4c572,3acabf20,c95e8d12,9f237cdf,27a1804f,d2ecbe1c,9eb1958,d8b7898e,968c6e5,e798b2b,b86b7a55,f0b00695), -S(16c7fca9,8bc28613,af1133ca,6c3ed5fd,5792858a,73a87773,17c004d9,c88a81b7,7d6d7f8c,4ed838f,7f96a060,32d20e01,b792a729,57d502ef,575e68a6,c55c8b1b), -S(c2c5cfc2,4e16cf88,af21c30a,2e37461f,230a1401,2a970057,f20e87f1,de517cec,6a6c834c,bf6d682f,b1b4779f,1629b1b7,3feac678,38e34a08,74d335d4,9245c37e), -S(1c948040,7673a271,23dd0fd2,85de249a,49c94348,75ec6660,3d0afdb8,9edd4642,2122d99,6781bee8,628b27bc,cdc00293,43e3627a,f14e8e23,4a144b59,3ed887b5)}, -{S(a336ba43,9d7ddf1b,91b05a4f,72083cf5,1f8ff83c,15ac69df,7bcd2d30,c645cead,a99919fc,a5854c02,e7246315,477a6cca,e29005dd,e950c35e,7aef7d4,7e4cacd), -S(211e7055,6cf61cc9,9db2576,20048424,9a5cc104,e818857c,2bcfd86b,35f09d24,f69df2c7,d480cc49,8b605364,e4f64998,a7d26b26,f354dc7d,1780f0a3,324f4bb), -S(781b8f44,86276947,6dc1b3c3,f0935984,6e827615,b22cc0d1,4e92eb46,4420089f,c49a50ef,3ecceb1e,cc6081c3,7acd7449,73b8c2e1,9bdb9802,f55626d9,129bbe09), -S(62161d16,921adaa6,5aa8a7c,b3dd1dab,1e32f9c2,e4ddd119,e5d8a321,3e0f262b,eaae5b60,49d51781,ab479eb8,32153328,fce9b678,3778a06e,581fc028,e5352d8b)}, -{S(9bd360f1,9a65f3d3,757a6d30,74e793fc,8a972315,9dda6f9f,f84bafa9,8b70cfd0,d16b8dd1,5937851d,6382b0e7,f6f858f,862021cf,857f4576,2fce65fe,ef5081ac), -S(820f3f6d,f4747a54,563f4a2c,b1f9a2a3,4454d1ef,c28c4f87,2fa123e2,89a65fea,27a82421,216b7b0f,2cedbe3e,d45d4b1b,c70e47c7,cda3929a,f46d05e6,5b51124b), -S(37e88e66,33965cc1,c313ba45,6762548f,147eb369,debf6661,c8c63749,afca6d30,c2573a88,f797bf94,cb42d82c,c7e1dd5f,67b29517,f41c8950,cd27f77c,f4c4885f), -S(39d0df0e,22fa1770,3ebce0cf,753134bc,5ba82a82,b50886af,ddb4afa3,c67a2df7,3a05b6d7,3fef259d,f900ad7e,23ba9ca3,fa0e8c22,75a98ea7,d60d3ef8,5116bb2b)}, -{S(47686db4,ef418446,4955455b,8aa0cb42,9903b2df,9872087f,74923a43,6a5fa06d,997c2258,ba1958bf,6801fa6c,56a1eeaf,2f4d4f6f,16ee1ec9,389569e3,6abee360), -S(ef85e550,7edfc88c,697e9396,e700cdc9,70a0c65a,cded23ec,97e8fac3,637ff492,7edffbeb,c39d7ff7,90fc479c,704b5717,231b6c17,8a89a032,35b64361,c8f37bed), -S(4790f35d,c4cfc648,cc011693,d4de07b8,341a068d,b89bbdea,b5dc26e2,49673db,52b2c399,97870c54,98427e7c,3a1b1e6b,58151033,ce11d5e2,a07950b4,c0d6a228), -S(b4fe974d,2de71dcd,b6000352,1f2920c3,9c898c81,cbe9953e,41db3462,f298446c,f2f7921e,28e06841,1b7da1e6,81442a6f,e5df27bf,307fc5ad,90268199,eb8dae9d)}, -{S(17d69e5a,f192e0f2,693926e2,adbccce0,8aee8656,5b1838,54cb05f2,d8563ee0,ff0c4e1,bf955a39,f8d14bfc,68094b97,6f1f5429,e04b21eb,9a86e4df,d2e11507), -S(e275d881,a266b218,77523b34,6bd25e69,5ef771a6,b60bc0f9,44b9be13,fcb937f4,50917dec,bfb8c492,97254e5b,32635da0,e16f8a1c,cae44508,546e024d,b91710d9), -S(594e43dc,498fed,9206ecb,8cba88a8,789f34a6,c17700fe,b0b99533,3e18010b,100741ca,9d03b5ca,a094f383,78da3ac5,8d79081a,1015b133,1ce28e1,821eeec6), -S(15f7436d,98885865,3d74e5bc,8210a6d0,73e906f1,25f2f317,63636f8e,4d2a5bad,9b7d4de9,b9379a04,edc9b47a,851385c7,ad8263a4,a0f0735a,d990eb70,dfe860ef)}, -{S(dc728a2f,6062da93,9d72b4ff,2595991c,5eeabdf3,bdc7128d,2fc0f25b,aba482d,297fa2d7,8f62f21,16d3a68,e60bebb0,1bedb0cb,370bc401,30062a3c,f5e57c8b), -S(f842bf23,8f136dd5,db77b46b,7b55974d,dc4f02ae,80d80d4f,7979212f,442f2ee4,fee53360,1c8ae94e,b7fa61c1,5daf3bce,5f8d21db,1b38617c,d9a5d547,58279ae3), -S(5234fb57,d95b1033,21e67c8e,cfdf9983,c7f134f,fb105e6a,c7c11dbd,95a39d85,85abe819,a8a8df4c,c77eb61a,8ac1536,2985c508,f10f3280,e8585c96,f21fdd66), -S(bdcd155c,dee8a06,f8d6449a,f43af493,eba8c6f4,e3dd53a7,a7c880b2,155a04b9,be820a74,41ba1bb7,417901a1,99fc9f22,f5d8604c,42f10c5f,7d423081,505daf20)}, -{S(a00355b4,d41ed117,b9ee9146,de418905,aface350,60c02d8f,d8bf4af5,a20b77a,bdd0dd35,cd5857a1,9b3d0a67,a14b6047,acc7ffeb,70cf4409,633f53d5,bd85395c), -S(3604927b,eb1fa6ac,409d084c,86c8cbae,484e46fb,c9262f02,fc316fe8,ddce379c,5c92529b,1b66b9d2,9b060a9,10ed2da,4637e466,3957349a,83e9ac45,5dc17d53), -S(a681fd19,69da961b,35aca5ef,3a4325e2,12766646,4f63f019,90267865,1fa896c2,f3becaa0,377d0878,462005e4,795bad58,daaae64b,67b7db29,82d2516e,4c72811a), -S(1a87a251,7b770c6,705140f7,cea0bdb4,5abc9a6d,3a0bc0c5,1d801caf,907b635b,c18b4034,f7cddf7,b23673d,b8942ab1,93a698f3,15ef0849,b2c4601d,aca264bb)}, -{S(69ae3d10,523302cc,bcbafd00,1f40f48c,b4f918b9,65190983,24cf0479,f9175e18,e9583688,9ae86eed,ebc7f99c,19af452,7d239906,aa96c92f,2dc91f60,4704909b), -S(18641531,3ec224e9,dbdb0254,f810c2a2,85d477fd,357ec222,1b31617b,7bf51e15,e2900618,7bdc64f5,bb04c80f,7d7ea5af,2adc7d24,57862959,5a598240,219b2faa), -S(c3eaf844,8e1506db,eb0ad332,b26cb2c6,ed2c1d76,36a445b1,b0af2743,122fcf50,f6171ffc,88d5d448,d828a445,d59f7edf,fc37241f,2af04d39,1cdc4d99,8b3b9172), -S(2019838e,f4cc5420,37d97952,ac870d9d,abf443f5,56226166,9ce84839,df69e527,a70ac8e5,e8f76443,fd4765c3,84abb1bc,5ab66333,9c4c555d,8dd840a6,7f87049)}, -{S(90014ea0,f76360c0,aad4ec54,8698e053,1445716d,57e7bd8,9ad0c952,b806ddb7,d039a3d3,717a3b7,68822dfc,94c216df,26249d04,d2995fb9,559fc8a0,53b51fc6), -S(769e1d8f,67248191,113b7ab0,84103fbb,cf4950c8,7b19d6d8,65cafd44,b8bd18a4,8a7d2d69,aaf91be4,d4e86de9,35883b60,8b931f61,67b9e76c,ea43db6d,66952560), -S(a9ae4006,c04ffddb,ecc638c1,e348a014,b179dfeb,b9e8743a,b2d9fde,1a48ced3,30f74acd,4a29811e,718baea3,11d4f5b2,b70d4339,e83550f1,f4ed763c,52907908), -S(13f000d,912ade2f,c6a1c2a1,5dc7f3e6,380df54,44fabc7a,80ee4723,ea27af10,6dcd578c,12d35e33,1e202b81,ec93fd6c,30523f82,a524669,2b7896ef,53db20fc)}, -{S(8cffb25b,9df2cd59,a3d5efd2,bcd2f2f3,f96bd063,14c04246,a5c29083,eb08b219,113d1c14,753ccadb,4b5b8991,86c93f02,13c43711,305e7056,fccb8f5f,8f265714), -S(a3cf6723,3fab81a8,5c04d80a,5118132d,df914239,67a5e486,3f30c792,668fd49a,99274ec7,9a8b0188,a91971fc,631926d1,72923ed8,a91eeaa0,21494bbc,33ac92cf), -S(470e48c9,18310136,80712b3d,9a673795,91a4a7bb,2e25f6c5,59700ec9,b5f87692,3b9a2d0,d9ddcabd,511336aa,f0c1977c,2e09e37b,96664531,48b82476,6c562b8e), -S(eadf65bf,cb609b05,b000aed4,98e344ea,1913d376,c0200c2d,e2747e5e,a24d6900,c42cd81a,756dcd9e,687b42a7,2ad9621b,dfffa3a3,c8b7398a,ea0aabe5,fd737b96)}, -{S(68d83fa5,58a5eeef,8695eb2e,409a1774,61d43b2e,81e2d4f7,efcdce27,25a515f1,679ae994,24e430ae,7cc6d403,afcade07,eede7dcd,3d597717,fe93d1d2,3df076f8), -S(5a55b581,5c824e49,db51f218,913eef58,e8a666c,4191a290,b66ffa0c,abbe6546,8674ef7d,9ea73c1d,3a3915ba,e118c742,fd4d4e88,78adaacd,699963a,5eb9f796), -S(48d7425d,376cb7d9,d32b164e,920cbd7c,e7d174c3,7afc191c,66267221,6ab5489e,d8ffc4e8,29de5c69,dfad7fd2,3353bc49,a6e4fd42,c31a4b8e,16bc0bfa,ce26be4e), -S(ffd5b298,ed5a84f,e58e09bf,8df83308,3ffb4a1e,8c5ac3f6,1e594b03,406565ce,f56678a7,fece6530,6ab4a556,d7bdf41f,353c5470,d2b6293e,a97bc396,d8ee0fcd)}, -{S(3432345c,9df2e165,daddc0ce,9903a17c,2070e055,748a0695,123971ff,440a92d9,3b05179d,dfe73d48,4477c69b,434c05fd,55ad860f,dd286362,ac39cce4,5b7e5c47), -S(abe99ae7,698019bd,66615a5d,7df9c4b,cb498915,a868a48a,25ff29ed,747cff8c,f9b3f71,113c791f,b3353724,a812351d,3988b8ea,3a93821,db26631b,6907ea72), -S(4c493f53,3d4c0b6d,17fac73c,4301a054,75353360,1536da94,bca3b454,767b86c8,8c9743da,8b125a52,20a493d5,2c31440e,e1fb6fc7,dabe35e,7ac97c1c,94c85e0e), -S(2b73a96e,70fdfdd0,ffc601d4,9d78282,f997f73f,eea4ad75,f8c5d753,65db2f2b,994d51eb,c58dcdfe,a5fa01f7,522e5d70,1c21b325,9350b7f6,34c75fa3,1d4ab6c)}, -{S(bd721cf7,30d8cfc2,3bfd5778,67f40847,4fa01225,ddbf427a,c7cb73d0,60046af7,62fdc9aa,b8836c11,89e4cdc0,3d1c6c87,927e36be,2e4d55b5,76b1e6dd,91d7c11a), -S(3c3dfaad,d52f2531,cd835de8,b40a005e,aa2c015c,40366487,962d1363,64f4fa54,a2143a66,a76e30e8,150918d4,1d9eb97d,a69694ae,c426b6c5,5125f88,a22e9ef9), -S(bc075398,462afa25,57c6bb69,b6cc9ae8,75a490e3,e7c65b06,f7d70efa,166534fd,47309e89,1e0c1c68,c6a5532b,b34989d1,658f95fe,7dd7ce94,d2346e0c,15936758), -S(407ef9a4,a92a8471,400e2bdf,7620796a,410c648,e5a12c41,6fbab33e,2119512,60a1d1bd,aa7a7e88,d67b9d50,b20cf09,7888d0d4,5c83a55d,4ae93dda,49befce0)}, -{S(fd8ea149,749825c9,1fb53bc0,329e218c,2b49f62e,a56e7637,730f766f,527b7981,3c4cdba,1c38f4a2,82864b88,a58300bd,d885780,c63ce34f,4c7ba30c,5c55147), -S(e6163d4e,af44e81e,1e32226b,cbd676dd,1e299b6c,249f4fc9,b2706601,ae17f754,4f754176,cfd4ca24,b7c14b79,8149cb8d,40809aae,57a11764,4eb43e6f,22403d84), -S(c23ece67,f8260a8d,4d18b1c4,14ffa33d,d93b5a19,ee0903b4,c4765c03,414a17c6,8b448722,5b20ee7d,fe6cf78f,7220822b,e8afdf97,190511af,ac225a8f,1da22526), -S(3a73ac57,746f5de6,7deb557f,2bd4686a,72c69f2e,b9b2afa5,d8389719,5f955da2,7fb97414,c9738999,51310a0e,85e1e92c,db326de3,a5621318,6ad34638,832112cf)}, -{S(c6188e3e,4da144f1,a71ab806,22998e3a,cc580ae8,28b08c4d,f8ad88f5,5d0723e,d16037fb,b08be935,f89b12a0,810b2574,b7b0f9e2,5039c610,b60267de,1e8895cd), -S(f4eb0af6,b09cbbde,4203443e,2db7cd74,25b3aef1,4bd470,84fc9c6a,7781c45d,84e7dd03,9d221757,d29ef906,efc5124d,7d2833fe,b0d381b2,1d4a1e25,45615bb6), -S(4457652d,9123f6af,79613e87,eb90e62c,e4c7b4a6,3a5b2b2d,b183b23d,bd659f12,c3879b4,c4f249f1,f0cb1a52,874afcc0,46ed7c4f,5b346a63,dd798d0d,9179c3f8), -S(e5aa444c,ba5c8588,33e215c8,a521c552,bd6a449e,a202d2f9,32dbb6e5,4162adf6,111a1695,e7513c72,69e65977,3171da1c,8727b590,32de1df2,1d0ec7ed,67f5c16f)}, -{S(9d12d4d5,8f12e305,f34f165b,c5f000ef,823e4229,6e57a67c,22f3f2ec,bd5c5f7,f8ea4dc4,131d6d1c,d97bb52f,1c03a060,f1ca0af5,71269506,609f92e8,1409dd24), -S(1960c8c4,f9eae197,29769442,a86fb7cb,4a4ee4db,a577001f,13fa0fc6,342ccbed,dec5c3f2,9fa2f71b,992f3aa6,213f5bf5,d7c8a0d9,360c25af,b35f2bb7,776fbb74), -S(d5c94e32,5fad15af,bf295b61,900bb004,51cb568b,ffcd7f2f,c04e0f00,5a596114,e44ccfda,83eca7cf,babf25e5,9be125b0,c04c8130,4f188706,6824ce3a,7409a551), -S(db1b05d,cdd99edd,c6645c81,47aba91b,dcd1ae44,18e4a5dd,94812318,fe9f1e8c,f9818f9a,8b094718,2b88fa1b,689d1495,e94adb67,6e924637,b8dcd799,a1ee3262)}, -{S(7f07a821,c2102e7,c726a07a,892539aa,85e5e3ec,6f79691,37d79611,43b79b75,63411bd5,5ee5f782,e1d2788a,317d8689,6035663b,68b96438,711e74d3,aeb51ef0), -S(37d2f5b7,c66b5439,26e89aa8,f265679e,3b213098,6467fa97,27f365db,ba93c0c2,a1675968,10cf3f94,84455ede,f6ccfdf4,afc726ee,3561c081,8e535f74,cd324cc), -S(d041cfbf,b5f525c9,65fa7741,25b8f9bb,cda162cc,2b1f280c,a41065c0,56474a60,34c757e1,b819fe3d,fd62ba93,801491d,d4c1d05c,b973df22,fc64f23,1cc68550), -S(c640c211,f3004673,a3d8ca66,a18872ba,bbc1dacd,61347d87,78bb4d04,4892ab83,ac305f9,8a267919,68214e95,47d64d2a,c015c740,5619a73a,162287f1,55b1ffb1)}, -{S(760a6682,57ae7b8a,96c5c769,9039a102,cbaa111e,ad076621,88a45a4c,168a482a,ac81a374,c2da5e80,d22db86c,37302c9a,1b154e45,122f9d3f,b5c59b2,bee89a36), -S(5770bac1,871c8262,b4fff00b,a7520d55,d65bb0a4,7c9598db,3fcfee9a,27ff2763,825274f3,44421047,2390a3f3,a7b98de0,ce70bbf8,6d7241ca,a93b5955,24ae94db), -S(9432cd1d,8a62e580,16278ef2,c1ea2703,e628268,3eda8ca5,bd1a718e,6de864d1,5c7e685c,443bff0c,1eac25e2,489d0c15,eeac20be,bbfcb62a,a277938a,21901056), -S(32fa8231,6af1360c,9a58fefd,baf51580,6860463b,7325443d,ee873f40,8d7b8a26,b9879293,6561b733,948a7b6f,535e4699,515a442f,1006eea1,999be950,d2e04295)}, -{S(8f2a3f96,165eb6ed,6e04a3c3,6bc98bbd,8e224687,7e1f5279,4b9457e8,3a098653,cf4e0357,cabc0d24,b1eea14c,1b9bc9dd,e513584d,4d476a02,bfa3305,f9561360), -S(b590c88f,653caf4f,ef1395e4,3438781a,594966e1,fa38d019,c6297350,7cf9e142,b5f13a30,c368d049,7c3dbcf7,f7b07a19,350c5b32,248fb27a,a2a9ba33,5dd18a11), -S(71836bce,72f6b823,8edf858,ea84f2a2,4a0bc6d1,7419d751,e14a4813,bc2668d6,3156f04d,c1b89f36,1e7c878,94b92a87,2c63898f,38cfa4f0,48cac403,ca57fd5a), -S(1996fd72,66c764df,a93b77f5,c158a41d,adf46d38,ada30dca,62919df7,ab256fb,3990ba0,814ff4c3,48822de7,a4e67059,242d4990,78bdf784,28dc6c97,f66ffe48)}, -{S(fec456a8,6cd530b,d0512eec,301e3ef3,d5537be8,974bc23d,60e2efba,71b55ce6,bc77af1b,426e3427,6660dd70,2ee322ac,d1e19d0a,7b1d41a9,8bbe3866,9d087371), -S(9cb7d661,759605b,2237d552,e4967b9a,986fa9bc,8a602343,edcc429b,1b20b0ed,217252c3,1413ebaa,d31cbd1f,d0f6ee4c,4193475d,581806a3,6a864be3,918c9f8), -S(d95a3a88,9c8420d2,fc6b4d65,7f868305,3ba7888d,c946973e,647c6acb,82f4d86d,d7f4973c,bd3ca3c2,fbed8b4b,e78d665d,8140530a,ed5b81e0,c5ca04b2,c8cbb617), -S(8cf3ceaf,7cd77738,d6941ed3,3215ccf,cdaf13dc,910f126e,43356a45,bc9c2822,833e822c,cf90bd9a,dd06b052,dad6b73c,b5ee7678,c1a5e35f,d3e851bb,a9a9a6ce)}, -{S(a258e5e6,e1aac3d,707c5567,a9caae47,1b21224b,87828cbd,537f613a,6cdaaba7,d349347,e8f24cb9,1202c076,6c7247cd,e2eebe9e,62baeed4,aa51191,522c2c07), -S(f654c148,6e9e5a4,2ecd19c6,9b42e27b,94f3c3bb,3407b584,42684229,da0bb67d,cac5b906,d0665fc1,d7efd4f8,d1927f4b,98b9199f,69ce7614,b40ef0fc,dce340a), -S(f30d89a3,a536db35,b040eda1,5189a2b8,166a9e06,4cc92952,386be62,2f43f389,79ace00,4153547e,bbb903be,beceeb9,a916135f,42cb9a29,54817f9d,cb11deb1), -S(3e6e3577,bc22620b,e9a97210,74bb4bea,97379d57,bc1ed61a,33882224,305e4e1f,f634a97a,2e483822,3c4ce4de,50dbe0fc,117ad913,c3dbd75a,69ecaeca,1d413d62)}, -{S(316c28a3,63bf9651,2cd9f688,1bdf7430,dbf7e594,e6a7cff4,bd991c18,d2c0833a,4222087c,65b29e96,7c2562a3,4a491c0f,5ab5db22,2fc30d37,4c1157cb,5bf17741), -S(3384a50c,9f621970,2bfeb9f,5b6259ca,6062004f,b4375f22,22259e2e,ad496236,37afa3b5,23a6c185,3817cb56,e5f87e20,5f57f186,75b66ce2,4c1cb55c,fbe63b3), -S(32082a9a,45f6bd5a,90cf0efc,8c362da6,5f01a679,2c735f2e,a14346b,984279ec,fbfa9371,7ea480f0,a05c9de9,f6a50ed4,5a36b950,fe837c96,b8eda38c,1ad79b9b), -S(d7d044cd,fcf11946,97c63a98,94b56b2d,2b328eb,8fbdb2f7,f919479,2da1f0e4,46da7078,4a495b7b,e839d3c8,10cd7624,5f501685,15661bdb,4e786135,271453c1)}, -{S(3ce0395,6908baa4,1efed22a,3cd2b18b,e14bc3c,a17e8e46,7f757e56,5314f27f,fce17fc7,7d007d1c,25558760,d730019b,22ac9cff,6f4ba689,a1885b2d,5f0d0440), -S(2f5a7352,11a250d2,cb126237,c2c8ebdf,e9d7c628,9a319903,5a1ede18,b585cbe8,e3095320,3f1a2cde,eccb1e9d,5be869eb,f447471,9f7670de,f1b86cdc,fae5da73), -S(e86666e2,980948d,28d2baa4,c4a49d55,fff25b39,55695ac8,11ccd6d8,f882988a,823aa73d,20c0f848,66a8c63b,5631db07,b8a15f5d,90d79e3a,16c4040,a5106987), -S(1b1ce843,955f9c8c,28dac111,5e8a357c,dee3b723,70d1cd36,9d03a3c6,1b7e7342,5f8648e0,4965445d,cc8d6917,db45d7d8,3145d7ec,71f6e117,8e773724,a39e784f)}, -{S(feeaf523,3f208ccc,11478774,bb05c1e1,cc7ee923,32e6f84c,970a0579,aefcd4f2,47f6e6c8,3e5bf7be,5743f776,e607ba73,a83ffbc2,f1c581c5,c0cb1d98,b10be58c), -S(42086c81,d2685972,b69cc8f2,8fb8e949,80417664,76c11dad,1afddef7,773d72fa,b0e1b1f3,79082879,512302b4,1314b3ab,5a3f739e,aa8ac1f3,cb82ebc2,c2f9d13a), -S(5f8dd0eb,57f8a8f9,d1605e28,987aa1dd,bbbd05fe,8ae2aece,48fc6392,3bd6,c7daf790,b90ce9b,a73a3c1f,4b30a508,d41c0d53,f375ca86,b0ba2901,dd9ad482), -S(c92aad54,6d6046c2,4606c934,63391e5,a13be77d,e3eefe17,3b0011bb,129d3ad3,288c9ed0,2db46521,c9249b02,8f262b1f,9e684530,2cba4ae2,506025ad,ca0b8168)}, -{S(e3ee8330,33377c46,d51c8aa0,7919485a,ce3c3969,e533150d,a3e15479,f26c80a6,f757943e,9569814d,1d6bbb71,55294783,500c75d3,7510ac98,18497bb2,9388ca8f), -S(95811875,6d6505a0,89b46ec,648a2297,de391535,d3873b83,a7db485a,1ab8ae01,baa7fd9e,bf67d8a8,c1ac73dd,69bf264f,e0da962b,e26ce223,dd3dd5b9,8154e3a4), -S(1ea76ec,a1955521,2aab3141,173ddc67,8463fc79,2e887297,a713fea9,b6064fc8,c8b34073,8c73318e,d757034e,c947c5b3,ba7baed7,3eea8ea5,2c4d5b37,6186e283), -S(38281ae5,371b347f,bec1e9c7,841cb3d1,5a7ddfa7,684e9e93,e2c12cd1,acf0ee5d,8bf4f92d,92fabcab,c814e790,21ade825,448ffbc8,782ed1c5,60c72149,67fd5cbc)}, -{S(6bd00cc4,657b1902,51f8dd4b,9bec4668,b0c8cfb9,651395f4,8badda1c,a1dbcd3a,84d71092,e37a7401,810b17ec,3e0e4871,27c4847c,afb24d91,241514c7,779c61e5), -S(804cb958,a76c7348,17a62e10,2b1247f,462438e7,b0b3a96b,c202dc5b,c18de9,c775f60e,9e39fb0f,788e4447,fbc40690,ccaef5d4,2e9d7e89,e6ae41b5,8fd2fcb2), -S(d1050190,fb46792b,c29df9c2,5f2b9e48,99125548,336115fb,b7449c74,681c16ae,d677925f,e9448af3,76734c13,af2f7433,a9ab84cf,b7a6c4d5,d6091afa,766d878), -S(b81ee327,adb39987,c8d65543,7b7c771c,9061623c,bf36da42,ecc7c226,4ef708d1,6ec466cb,a3a52bad,a9f3f7a3,6ed90d4a,857a3570,610023a0,94fc5107,df2056ba)}, -{S(725d64c,4128d78d,11b4f7fa,eb9f04fd,9075ac9f,e1129eba,8544c3f6,685ebe04,36eaba03,94b7511,31a9c5f4,292a7307,1862fbb7,c43fee3c,1e5eadb2,7fb65db8), -S(40069204,ebd45314,a4d757ce,5a4020c0,e36f3bd7,fff73d30,60628b53,8d685861,d81134bb,5ebd3d7f,10a90cd,369ec3d6,9cab48c6,f49e5583,d766aae0,4d466d27), -S(901a167d,19e00cc5,14b3b724,759efa64,3eb7a8ce,9466eaf1,b6fab1c8,63b6f9bf,e100d9d1,e1451f09,2b5c1761,1e2d2376,75b1c95a,a71a052c,e7497a63,a9fea105), -S(f0fabd37,39f53d29,801e00e5,304cb5d9,a3553226,fff9ba5e,c8fe1030,26739c1d,cd23a575,ed09eac,f8446c8c,7f311ecc,78acac27,3a0fd6f7,988bdac6,361a4678)}, -{S(8f4e8dd8,20d7e026,ce2fba81,19028ea8,758f99ec,f7bc2f09,d239d60f,24027c9d,81b9197d,7374975d,1bcce80f,1a8a1e84,19a7a656,70a5dc21,49b00aa1,60055743), -S(e8e4ac24,1b8568c4,cec4f08a,9badff38,87c132e2,47add60f,3c39cb7a,8905027c,89c74e18,74737819,6fe1a4b6,3b2893a4,865de0b0,775598f9,33504aa5,ac453a91), -S(e6a8a510,f7316ef1,4e50e9f8,c8843220,c03df75f,e508d820,f3fa0dbb,5e9d0f94,1ecda600,14fc8668,32b1f2f1,b80ccb12,aabcbf94,f74f0a6d,dc6c692a,a20040af), -S(752c8264,bfb10ae3,aebbf561,3f65d191,d2956e3c,a7578e53,2a8b85bc,eb1d294e,1ff5c140,6558073,da1cc7ab,fa80d4c5,d557612e,c990206,6fd895af,11cd493c)}, -{S(9a9a4dfb,615c1e79,c2c19a19,34300742,7329b1f2,b7ae815,8ed8ebf1,5878d02e,39da7ba5,f1b9754b,e6fabbf7,a45b7ea,5cbcea2a,da2cf2bc,82aac66b,468af931), -S(14159eba,90d658df,ff2a3726,9ab60c0a,7540c68f,a77e0339,8caceb5f,6262d656,4497a299,27b365e1,35a77f61,bb6bac74,6918e3c6,79f97021,972c6013,d8109e6), -S(d4d3e7c,2ea5fb74,45160de8,19bec4d9,bc843b9,fc14fa74,6c0cb842,1b02a765,b55606cf,557bdebc,90da9255,f6a38a95,5ebc5998,bf021708,ee0a91a2,147ac684), -S(1acdbd72,130fda7a,122e015c,f3101670,d8090193,828710bd,1ff2b242,5d3ed896,b8cc1086,347ace8d,858ca6bd,56a80125,7d0f4333,b26541f,9865fb44,c5f349d7)}, -{S(93871b45,831fe55e,82338224,aabcb408,26c13f29,64c57fd1,b93711f,4ea53cff,79303c6d,1a8054f9,d66c5524,8ff9cd8e,17b5fdca,f9fa4388,9b0055e2,15c0a54), -S(8319d182,59cb7c75,228d314e,7db1db16,e34c9f62,2bf4e893,f06f86c4,3122dc51,5cccb4e,e295cade,ee396b80,10f6043d,d9141412,b8eb4216,60f9cc63,ee96f6de), -S(1d139778,64726f8b,7713beb7,6066df5d,d5116728,d5688fee,e20fa12f,14f9857d,3fd0294,d9ba6e7c,7a08bd63,d747365e,eadabab7,5ff1ca8a,95174569,c6fbe910), -S(a2c17270,296ad5e1,7ce111c2,899411a6,276efb6f,d6794a7d,212fc3cb,7d9fba31,b0a2e976,582022a3,a2c636c3,2c0909fb,533bbfa,193f8366,e65702c4,e0d8629e)}, -{S(24b75440,39c1351c,ccceacda,d31c758c,206331da,87a277ea,588a4376,82dad76b,854ebb44,a351e732,d900a1de,dbb0a5df,168a311c,4af01dd7,64722531,a3132213), -S(c89cdf5a,c0bae450,ffe0bdc7,f01ec47e,8a036cc9,43e0cd72,245cca5c,308d0087,e54935fb,6eea8620,a8b85fa6,d63d14ea,16c2edca,92fd6adc,7feabc35,91599acb), -S(255e5f4a,2bc33aed,aba2b7ec,b22ec225,30d3bb21,f7a63be4,bd5e2f6d,ad48e927,79cbe440,8da8c79,74bfc4ad,2715e2eb,eec2c950,8a01538,be795d21,c462b208), -S(e1497ffb,ab348f03,ea075d4a,bdc3d5fb,b2b9b413,5dab5190,2d8e1959,2be57e00,e3194cad,50cae1f3,7e713ad2,5bb635fb,74f6cbbe,83782411,65a8dbb6,ccee6faa)}, -{S(b9ed5a31,aaa443eb,99d8afea,7b32b81f,5860946a,5a5e63ae,def2a6bc,25c43f9f,e5bf15af,3e0a5fd5,12a14a6d,e03ce09b,a82b2fac,6fb8e16b,708752df,95f080c6), -S(45b0720c,7c7a16f5,9e07c7a2,b9f79ecc,194c4497,2a076bfe,cd662189,f51b5f4,b8acd754,a68d90f6,928fb515,d51d5c86,b86a832b,1506a251,447430a2,f255bc8f), -S(8a4c2587,cd27e533,7d848f56,43327489,19d3aa88,6d4b944,d4d44689,5cbe1ad,581ce4f3,7471bac8,9e904daf,c42013f4,2451a155,6ba12aad,deb02653,95926838), -S(4cf058d0,f5959eed,87402967,781dbfa4,29df9de1,327633f7,a6b354de,ebde5aaa,9254c0b5,709fa08c,684a59e1,1864a10a,3c4e9359,dd91b39b,15066b2e,e678a1a8)}, -{S(49208997,3351bf26,e5245cf8,afc6a69c,baa24dc8,5565ef5,d39e6a05,8b3cdf17,a4276fd0,1f754f88,11bdd14d,d1ced0d7,8bb7843f,a876e7d6,9531c223,2e9c9b4), -S(7b098cf0,f897637c,cd32c99d,de95acd9,2e05bb47,b16a58cb,d5e97827,734648f9,1d4e7732,2c99b9d1,dd330ef6,e955138a,6d0b606,1948b067,edf1c39b,61ab0505), -S(222b1686,82ca8f4c,b333da8,3a1f3cfb,e19f9e3a,8b597ceb,ceabd65e,720af23d,7278370b,c722a13b,d90164df,41323da4,6cb7b346,3c1428f7,265cbfd5,6d0d8d35), -S(97da8a09,8a3507b2,b5f330b,b405762b,cfd5c631,ed835bb0,842ad75d,a2175c31,5c051aef,a278fcd9,a2e230eb,993fe8da,f0c06306,14a5a6b1,799c0cd4,d3911144)}, -{S(265747dd,9f0d0396,faa54221,4a050192,3de7d376,f13768a1,50daa098,92ca71d7,412f5e39,db7cb201,3d083c20,19ddcb27,2ffd0a0b,89413e81,7718bae2,f1120fab), -S(918a2f6e,863bc4fd,87b5db45,15571d62,50e87c47,fca0914c,2b76d9df,185c0a32,a5551dbd,5c739407,880a5487,8ce218b6,766f0553,78f1a053,179ed3c8,3f362ff6), -S(6da6ff1b,ecb936d0,1ea353c4,ca3f949a,90153ec9,13329206,8b9be293,ae28998e,822ea180,8265bfb2,3fe6c6c4,51f62245,4185a813,e3f61604,c89044e8,555ae0a6), -S(bc0730da,9a06486a,99364ded,b612fb7,ac36cd21,466f7acf,e0be262e,55e0d269,7cffd8a6,13cf43cf,7eca904f,96a9e9dd,8b54dd22,49372095,95483592,64d7b8a0)}, -{S(96f6ae9f,84281919,50583f91,d4b76ec5,3c01dc20,6d06d33a,2560a8fa,11fe5daf,aac32455,acc71276,efed23dc,ab42fb8c,24bd18da,604b913e,bdd1318a,d1bc223), -S(f24cfc1a,9a29848c,f1d996d0,7fdc3ee1,ff14d1a3,a7811f18,e8bdcc47,a7806534,e0e4363d,2a227fc8,2df704b5,316410d3,a671ea2f,34702c0,7208fb27,6c1d12df), -S(1123af94,e86f2def,561f490,94ab160c,996f1955,dc2597f8,fe765c2b,d4793679,39d160a8,caf4b2c4,e4e95087,6e9a3183,55d4da27,9c7e2429,9762065,af62b2c1), -S(f5b8a7e4,6d4b110a,46d12dac,d308dad2,3f7f497d,b5a8a76d,c9577da6,f0943430,835941c3,b12ead86,6ca3f05e,c4b09953,9a8ab640,3e450590,37a990c6,88c1922f)}, -{S(f307f4b,b76a7bcf,1fe75d85,60a4c64,c748b32f,489e30b6,170057ed,225c9e95,fc200ac2,3ba3be6d,aa4d4f86,c89fdc5b,8eb00f8c,ebcf6a41,51411042,ad181fb5), -S(dbcf10f2,e43ae854,85fd600d,ca9ab27d,7ba393d,e6a333c0,7901cfc4,55352569,48d4448d,8ce674df,d254f09,17fdc390,de9aa8ff,29869da7,4c2529cc,dd476fb8), -S(38a07202,a23d26fd,663fa7e1,8e8a02a9,2631011e,57731024,3e717ac3,a0390078,fb6057ac,aa4fabb7,c4e922cb,ab2b7fb1,e4f0b3a7,6be215f7,7de296d3,ed709def), -S(5bd3e7ac,5f8619f,5db77e69,f7416149,b4afa5c7,95d25fbb,fb1da1ad,9e4617e3,9ae709f0,d7278b4e,b66919b,c666d63b,46bc228,8ca956eb,2e20238b,24725d56)}, -{S(35e48872,5074158a,8d2ed392,d178f6e2,e4c43fc9,689b32d,5f374c05,d637a53b,95143742,7bb0105b,5e7f60f2,d95ff164,ff808b7b,c2ad592d,68988e5e,bb5d5679), -S(8619863a,d49d8ab5,6c999e77,4653e1a7,4acb7a63,edb65840,76f3b3ae,903f3579,451500a1,3dac87a8,ace7fe4e,64dc6174,896b5002,67163bea,1d3db275,b8274cc5), -S(afeffbdc,dede5aaf,dc91475c,100918d2,f59039df,b5754f58,a330a469,1855e858,e05eacad,fe537099,35be0173,3d4b4dc6,7674d1a3,7d911d02,ea4f74f,6b63da04), -S(2b697c1a,2d2de701,16536722,945e46c9,21f02fd7,d8e9fd46,8fa9f159,1dec4273,6dd6ad5b,44541355,83b4833f,10de56a1,ed16c5a8,77d593ed,2538b95c,ce8785ef)}, -{S(cce6ccb3,fc1cbcc1,1f40457f,25157d24,6d3fefa2,24c340f1,ebdb3b02,3f02e3cf,9797a15e,ace0c660,eb93b185,7f6de7de,2d1d0f36,8c9a2eeb,a53b2860,b392bf2f), -S(71e75cd4,592214c9,556dc1b7,a7c8c5cf,77ab0249,a6a7ad9a,378e3e5d,d150939d,4e0c9607,c1b2866e,214f38e0,d4759bf3,b38f1f7a,35490b6d,70cf2e65,fde90bc4), -S(dea94d9b,c0222c46,c66012bc,91a3be34,d5df8157,56a9d97d,52c8c4b1,24ed243c,b3df667f,2615a0cf,2e7c0122,63af5067,b47d8cb,d22425f2,1bdba132,5e333588), -S(67bb4796,c88ec279,87e7d4e7,bd2e4e9e,bb1806b,95d3d8b4,e1a5d367,64e6d01,2af04b47,62d5a122,3bd0fd46,49be2b1d,92df5d8a,84ceb205,f2b70f2e,b5679290)}, -{S(86592c40,71b619fd,27e3825,ca585cdd,ea068958,7b59e3bb,b3581075,a3cb8a96,923844bf,2a197b85,b232b973,2922ce0c,a2431dc4,a59d27f0,2ff3b2f4,af7703bf), -S(e82a2871,fbff9467,96109300,26ffb096,d9509b43,6e786697,e85c57b3,389f4fbd,7732b419,f0d682a7,9ab047a7,d4a51685,fcaa3c8c,cd8115bc,4f7514f4,1717c804), -S(9c079fba,32d2288e,a0829fa1,1482dbb,8032397e,c676d744,c7b0ce84,a1c4f539,2b171739,85fa643a,ba7314d3,86f086c0,d4884b63,4062a4c8,3f7f05aa,575936a6), -S(78ea5f31,1d3c1943,e438601e,a885ae8e,efee93e9,26768d82,3e88a71d,9c22d773,953cb0dd,893aed33,9021e63b,277cca61,4d772c7e,a2b8ea3f,bd151b14,5cb144bc)}, -{S(4929a368,f9842917,73f5236f,dd5cbd7f,a8e8dd9f,261cbab,5948ad57,798cbf79,26a2a40b,33630e55,7b376fd8,134a8d48,542c08e8,c2d01a99,586d33c,66d37426), -S(bb4b9ce4,b8dd22bf,2873b2de,f29c494f,621d89e4,aebf3c23,566e0cd4,b4ffd288,d4f81742,4f778966,1274fc8,e8aa5c54,4434fca7,6b73b639,a04aab65,8bb77c2f), -S(6ff70715,17bdc2a4,c0267caa,38ca96ad,8a235744,2a24db87,a07cdec6,c3b022fa,2f16b295,a2db7a6d,321280c3,a53dfcf4,674dc215,38e2a556,75cd37e5,d3ee7362), -S(b5619c5e,edbc92f0,c88a9cad,9955a08b,764dd683,361bb7f2,8c611857,d473c45b,11f6864b,36116181,d2af3f6c,fe738c84,7820ebe1,53f0c82b,14e5c67a,b3a2213e)}, -{S(c7452697,d7691662,ae3b754c,7be11df8,ac70cc8c,e2e80a9b,9638b0f2,a323ecd5,fe84e963,3231caac,63a5c7cc,90cef693,a69ea140,c846e1b3,b96a6fc6,68b43c68), -S(c797ca59,95cda70a,a33093bc,4f7f83c6,1a31ab1e,dbd6f10d,31e0da05,64f41407,ce4a64f9,ae7eef1b,7abfad94,f4a6a7f1,c746268e,9006995e,8f7d311,1b81f85e), -S(288a2e26,8fb8fb28,29bd9d21,4ec5860b,fc1ed577,f40c6184,79a0b921,c2f4b67a,8343d03d,556bfee4,b66ca598,f4fecbcb,aa2723c2,f3c35203,ee12710d,d9ff0b52), -S(7aa02a72,adefd779,fd994c77,697ee142,dd25d168,38c8b8a0,5178b7e7,37f33032,a060f7d4,8e0c2929,864208a7,1668129b,3b3908c3,7e89ba0,e7e55aa6,5e3ed98e)}, -{S(34925d1a,b1c7c081,e945d66d,60ed394e,f474e38a,423562b3,95bc51d4,c4f55321,8ef8dd58,ae1661b5,a7c327ba,ac4105e6,d02d6a30,2263c5f8,62b712fa,b064e562), -S(2bbf19eb,9a6211a,7881c7e0,5483a318,c9d91280,d09e0634,2a54a9f2,b5654be8,3cf7b41,bfab218d,e182cf34,32450abf,88da1e16,fdb79699,ecfeb962,39d422d3), -S(97f1b30a,6ce2dd8e,1d0358fb,45b432fe,be6d9916,34ecc7a4,b7cb4f3c,f1663fb8,c7cba22b,88a5f5c4,498f0f22,cea6830e,1bb44e1c,7f9d9833,60139c2e,97dab7da), -S(b5d0e718,621a0a40,c2adf34a,3e1e64d6,bbad3598,e6944436,f8f87450,575d61ef,2e43eb70,8fb8e2a0,f24a1a12,7a890c07,d79b51d,60e3a281,649afa3c,182d5b77)}, -{S(463080f9,19ecd42f,593dc20a,2d3160cc,74d9592e,446f299d,be5446f4,236a5b17,2a65200d,e1b16975,9d5c75d6,fa6c666,ba45728d,343d6339,48233391,60c14a16), -S(547eef23,516851a2,2f160ec0,781a49f1,1480d07d,2607ab5a,89656c94,2f774b5a,eb6f249d,ee624cae,cbc59f02,63da0fcc,e33a515c,843c3632,661f13e4,39c4f0e4), -S(77f0c9a2,51d48b39,62f92e2a,679fd9cc,f458f17a,edf588be,d4bd6448,47f9306f,355f4827,b10e614b,4590242b,da546e53,dbd419de,1d1a7fa3,208d9350,3496db0c), -S(81e606c1,19b6ef80,418aa008,7ebaf9d3,7adff1ff,a81f739a,172a580b,27c7545c,ddb0404c,e56113c5,93920382,6d2adab2,6590b509,45865406,ce1fd256,6565209a)}, -{S(92d469ed,e0969dd6,7e9d7b31,f0f703e3,97cad53b,e6101b2e,eeb8714d,645eaa9c,24a0a786,916297f4,6a53c7c2,29a3c95,80eec521,355b823,f0488460,39595dd2), -S(e5035341,5c49c24d,f672a74e,4eb2d108,57fa987a,afc50178,ffba8797,5503006f,38522661,fe682984,7b6dda61,9dbbe47b,35c0c9eb,b79b5d2f,2c6ba882,26cb95d4), -S(d0777020,cf6dc469,cf020ce5,e64bc2e4,1e2bf116,4f4e814f,18bbbc4f,f468b0b8,997b2163,c4670401,281ad84b,a914cbe4,e76a5cb1,cb90c1bd,ecdac585,621cb0a6), -S(881abd9c,717f0a2,360de50d,66a9b655,b9459e62,80a985da,e811f2b2,154e307a,beec571,1375031f,354dda5c,b9d8377d,1cb49816,1f4c738d,f6b9d323,f9acacd)}, -{S(ab7d18ba,955fdaaa,b1a0bb25,25844e2a,9d2e204d,ff224588,ae96c41,e690e010,4e0090b1,dcd619c3,10ff5027,9c534612,84ec2467,77b63179,c80724c4,42d00204), -S(1a5982e3,37e3eb50,e679f24e,c3473b4d,1af3dcbe,ac3c7a96,a95f51f9,a9875266,dca6c614,85d55985,1fdc229,56ee59cd,fac74069,6276299b,a199f39c,869e5c9c), -S(bcdf870f,8d5394b4,f1f3446c,a25ec6d,5b4c939,b598e596,814a6dda,a054bb2f,71cfbdd,d1aa7722,892f83e4,ea2dec50,81c4d14e,548a16c4,2818b76d,5721fb7c), -S(cb28eeda,338a5088,db505da,949cddf2,741e071e,378f92f1,dbba270e,9c322c57,d98cba61,cceca53f,7d84d71f,f892b962,6f26e156,841d2dfb,7aaab839,3f515903)} -#endif -#if ECMULT_GEN_PREC_BITS == 4 -{S(3a9ed373,6eed3eec,9aeb5ac0,21b54652,56817b1f,8de6cd0,fbcee548,ba044bb5,7bcc5928,bdc9c023,dfc663b8,9e4f6969,ab751798,8e600ec1,d242010c,45c7974a), -S(e44d7675,c3cb2857,4e133c01,a74f4afc,5ce684f8,4a789711,603f7c4f,50abef58,25bcb62f,fe2e2ce2,196ad86c,a006e20,8c64d21b,b25320a3,b5574b9c,1e1bfb4b), -S(6ada98a4,8118166f,e7082591,d6cda51e,914b60b1,49696270,3350249b,ee8d4770,c234dfad,f3847877,a0a7bcda,112dba85,1cdddf00,84d0c07,df1d1a,a3ec3aeb), -S(a94ae8,63264dfb,b910ea95,4ce9ca7e,4f86f92d,9f3a95d1,ed61552a,7a3f5743,7f53f7f1,6ad2d08f,15e73314,6d80467,41557acf,19556c0f,ed7117ce,37040823), -S(b692c750,d23d3674,c351e3b7,e1a8a87b,14a5df81,852eaf35,209d0ec5,6e22a2cf,b18c4f17,252db89f,838de32f,b3340ea2,bb961a39,54b38c47,f9a8219c,4820a0cb), -S(691fc741,80e75b55,47b375f1,1bf60abe,451d27de,1743a436,5f8e4bac,ad421c09,8eb5fd9d,f3c03240,6cebf370,8125955f,bf2ef703,475d3fd6,1a0291b6,69b52d9d), -S(703b5f14,a7d82473,1196b52f,ae9ca8cb,b245b004,7a9928d7,d0c42f33,391411dc,5ed74eaa,49f276c0,4d61f31b,6da4137c,bde5673d,8e3f815d,efea7951,f88585c), -S(29b8ec47,d241eda1,e51bbb1e,3928444c,3747b4fe,7cecb365,2bbc4587,2f504875,88693238,8562f8bf,f7d72324,62ebc54,6b93a95f,77936b02,eb1cd6a7,d4199bcb), -S(444a07ad,e81916c9,32bdeec2,21c556c4,6b7f6491,e99b479,2cfec82f,4ec17910,2e084c2f,eead5200,77c151b6,eff9375a,713b9d15,5306708d,b3f538e1,8eb18cf), -S(e0dd618b,226ceddc,f560527e,20b4fe58,e5fcf28,39911ea6,c3e8a4a7,e15f9121,a063a157,3377bbbf,1b9a5ebe,afbe11aa,660c1e65,df1392b8,97205858,3c86a3fc), -S(9b99461a,2e8360f2,f2ba0bb8,bcaeb699,159e0652,69d9042a,fa0c4e30,a7b6f30d,3fe7fe04,3cb45303,3d4f5560,7d41cd76,9036a49b,82912350,6d8b9995,254154fd), -S(504da3a9,d9d9c81b,c2065398,4ed28cb1,b5beec9b,6ce5dfb6,cea94e54,fdff044b,cbd40d1e,858133c9,cd20b9e4,ff9fe94,f7cc9579,39e6df49,7a6bd702,797f96cf), -S(ddec0aac,1ebce6aa,ad6300d5,60f0e503,829f0bc6,479641f9,b19d9f6,484376fb,332ff5b1,fc83085e,736736bf,3c265e4c,8f80925e,6f38479d,6563bc34,e5faea1), -S(dc530ceb,b82c246e,41c522f1,d2571d31,4b14edf3,91577a2b,64e42172,b23562c1,563ddd93,857d6529,8b81de24,19e5cede,7a4c5b7,a2fe98f6,9efb8906,6f32a98a), -S(7604d60f,418dd132,78058942,fb2d2153,c0a2bfeb,e83c5011,a451bcb1,58db0773,38be14ae,d9e1c404,63ef92bd,d62c599a,b37625a8,182a3763,4fa2de90,535d50a9), -S(cb896744,77b20829,f5e2bd42,8852c70b,91cbd0af,cadf219,a69727b4,cbec8d7a,5710d17a,20ea0dff,980d3f06,38d8b910,b8940d00,dd4a323f,d777d942,213e1093)}, -{S(1b8462eb,1ccdf7b2,b8372f2f,cec1f479,ab07c09f,cb26d6c3,965ec73,4d654f81,62f6755,b4a7891d,55de6427,fbc37d33,e4eea418,a2c04392,a3d11807,ccc9025), -S(f6fa4c02,1b697e93,ae34145b,481a3ac7,462343dc,6022040f,834dd9d2,c69b5d,5de5e04b,351f9928,b84abaed,d3319e61,ea91fc59,8d6fcac3,401d1ae7,c08943e), -S(cf805a58,d8f9b414,aa73cd0c,e545c9af,3f7d6543,8ae57688,81d30866,e81242d4,f455c617,99a2ca5c,fac3eb6f,23282774,7c9e914e,fce447ad,8fd71ffc,4fc3306b), -S(48dbd9a5,88d1f02d,6eacc5a6,36c0fb4f,de87eb44,11329442,1265b0ff,a72e473,9a206d25,5dc1d916,e3b1e301,cab1bd91,ea29eb7e,979c0b84,608ed770,4af325d0), -S(ceb3637b,28997733,ad6ef0dd,5004e32,9c87981b,e6d811a3,88804884,652780d4,6aed5e97,c0e836b2,73a309fc,5d389779,1f6f0bc9,246921ef,5fa9767f,dacac3f5), -S(8940dca2,52ebefad,61db720b,e709c749,7302b5e1,a4174893,9626910c,43708a18,e1b0d7be,1e36c585,8bc6125f,7fd5c423,5e643f7f,11668026,c1536e9d,f6305efd), -S(aa33c3cb,bb97ccee,5b8f452f,6a615900,392d78f5,b8c1f022,5266b8c,cb3449e0,e9ba50b4,7d3e3279,2253e925,5261f2f8,263c30dc,e613ea9e,737c3b92,8c8e3eef), -S(39f3965d,b455a466,930e5e82,ef214452,ef5c9019,bd805fe9,67fd362d,193a1b2a,8f69a32b,35bd6f1b,c5ada308,f61550b1,534c07b0,1a3465f0,564ed6d,a8f443c1), -S(6725d4a6,a827fef7,a0fb0214,900f526c,e23cc0b4,a6e291d0,ccb96ad9,e77393cd,69f91bac,b09facdd,b55fb70e,68164028,a8cf1bbc,207653c2,d898992f,89244f35), -S(3b71b2f,84d355f4,d246a57e,b235e396,ee236c57,d6ab3a46,f89b5d3c,1a911c1a,7616be06,59e5b42,9f105499,38d17654,c605f81a,e4bdf2b7,b9c1817b,c8db03b3), -S(a346e9c5,d8cc2ce1,1a733026,3136d92c,925f1b22,b27d3037,d9c4b109,9a06ecb6,4a3fd930,54f0cfa,6799e236,add0f928,6e45b77d,cef57797,7dcdac63,485c4f00), -S(8e3c768a,ee07f0aa,3eaa43e3,f6986805,b7829c50,d67861c0,c75ab390,5a6fb794,33d3c292,7a9e9c54,a671788a,fc0ec58d,cc2a0574,a172665e,347690d7,50de0acd), -S(b231176e,d39a928f,76a60397,79643e94,d5e75d17,238487be,f9b38b60,748711c3,3ae1ccae,204fb13d,74705b0b,8a0689eb,aea16e8e,c2f3d5db,177609ec,64027f0d), -S(8afbe02e,161ed971,44075da2,cea389b2,f53562d2,dc771d3f,9405259c,fe4232da,e2c16621,f38a0831,d2839585,9cbceb53,254398ef,b58308cc,bcf3d79,ee0af228), -S(1a263c8,c2c9080b,b0d4d61a,bb5d6b55,e6a7f520,80ef3f36,706e685d,7a527957,3925a458,779c3c25,7b546b99,7399a56c,b3c0b9ca,f6c77f9,c41b708d,f831253e), -S(35d88ae9,b1d3ee59,fe79c24e,de6cad1f,6d822f57,708ee54c,26e7495b,357e92c6,de74f353,d8115188,724c2a32,39b18661,6b8f7951,34aefc75,8e724a30,8be7f31e)}, -{S(6ae991de,18418b49,160194f,a735eb72,c299b987,1981a4f9,aa717ad2,bcdcf13,7ee8011a,40f384f2,e50add2d,97005173,2787cc7c,89dafb66,301bc94d,24b913f), -S(22165bce,e76e1594,5b9041e5,ccdee553,eba60e4f,1ece2d9f,e0ad7440,565f2665,fe8f383b,bae7e284,d1d890bd,569ab7b3,ebe5f1bb,b60ee19e,8e8de65f,88f3ab96), -S(a2600e0e,9265b7d8,fcc46a5,51872122,66ad5334,4ddedbf3,ac8cdf2a,b86f2b8e,d00f90a0,97fe3863,b4854dce,fa5a36e7,3f94015e,f892303f,2e5cb2c7,aefbf15), -S(38758ff9,5cefa7c1,b7a2443a,ba29b65b,aee1fa81,5ed49595,a4ec760f,b995df1d,43bc94bf,dfff3c59,7a6e41c0,52194d41,c1601b91,792f42a,6872ded2,a5e8f4cf), -S(57122897,d98019ae,a6dcbe99,49682895,c95471e8,d53680ac,49927e23,16abfd27,c30cb105,d9edc36c,9e237e93,2edd6bef,3d553d67,fec3a37b,fbe0ef56,a3cb6c), -S(7b7247c7,73470f13,2477c974,7820ce4d,51dde95b,dd14923d,e31dfb13,5a8aacdf,2e7054f4,a33361a7,a4282bb2,7e738884,3a91b211,3f71e160,60fb2235,6b40ffc1), -S(1d3f0661,13c271db,374adce9,ef0c444d,4ffbc1b2,a34b9c91,55986371,52376f68,1a4c07f3,e3752c71,f772c55b,d269f3ae,a9cb40a1,ac8a96b3,7387cd1c,bf22e864), -S(456ada98,2bcfa52a,55018711,6926b843,82754297,9af5c113,8af21e1e,3b625071,a7141c4c,673e441e,f67ccf99,53a7a6a6,3a77432,76261717,21f581b,2893243c), -S(b898efae,8582d8de,b315220c,dc79d2bc,1a221072,300e0971,c4a610f4,7f6b70dc,8da8b020,8d674418,5620db55,fa3cd928,be672c5c,22897030,bb5a5957,37758a8), -S(b732f7e6,9280227d,c1f56e84,7e72989,b834be6b,f04e2e3d,ca8553b5,ded18493,9157298a,5ff6e6e4,d705efcf,7601f33f,76cd2a64,6118103d,98fa000b,8ff9ad99), -S(9601ce19,964403b6,a58d1d51,be876199,d63755ef,91bd657a,fbfac3ef,c85c78d0,df06aeb0,517ae1da,ff3a48bd,7ecceaf5,b10ac9d9,67e7ef4,520593cf,d7502058), -S(a95814ec,11446773,36258a94,56670207,d068d8ae,19ada794,52210f2d,bd67bc5,29d7e4b3,5e5a4300,6297f9c1,f71a6a26,118693ce,fc738fea,ccf1b873,339617b3), -S(d3533330,c6afe33b,ae921c0f,558fe47d,b97e7711,ce98c884,3abe894,320e8926,e1be0b16,72f8ea16,b59a6b9a,20c27621,e63854cb,4efde5d8,d1da8929,4f777383), -S(4f05f649,e8ec9fe9,f675957f,7454a89e,c020feea,217782bb,43bbed43,b0a62881,dde64c2b,255d8518,da7461c6,b160286c,5222baa5,483fd5cf,dade9ae4,96432904), -S(1a06ead0,5ef3dcc1,a9080234,b6158fe5,681cc5ca,acebbbf2,c336ecdf,3505768b,63661e6e,816bad91,1c7bd073,a15b185,c4c7b7b0,ae440dd7,40a54286,3a86721f), -S(e2b163f9,f1b6ad48,e8bea9d3,b199cfe,378fbd2c,8f005cdc,e5959154,b2eca0e7,30759d6c,f55f7f15,a156a705,1f702294,72b9544,ba73fa40,27839cd5,67147083)}, -{S(64850a04,76870a44,2cfa57e0,4e4707f7,eccc5e99,12dbcb07,3b457317,717f5686,7c5facd2,91a6defb,a1837cb9,3bcbd0f5,bc37572e,68ccb2a0,c062a155,46656fcc), -S(4afd2a50,f79b1403,844523a7,e88e0156,f77f7856,8668ac7c,79d2160f,cac27acd,40346549,fb5b8450,165c2a4,c47665be,b1d31f73,1cd758ce,6c8f2b17,37a832d1), -S(f4132840,9cd5ac7d,7a0c92f2,5e39eb57,b8fcfbd5,d535ec00,a281d3d5,1275199b,6b66ce56,99a92cf1,8f635a0,7441f0c1,3561c8d4,cb0075f8,8a1596da,b6da6d29), -S(1a6c66d3,1a54ae12,59b709b4,c70fb434,f3347d11,7921ce06,fd4f0dbe,d211e4f4,b6438fae,74524dbe,2d03e27c,8af409ad,67af8eb6,84760c85,1e81c6af,a4cb004e), -S(3afe6f2e,8b5f1cf4,20ba1dc9,f527c662,a3af94c3,9d0e726e,b7942a2f,c9c1a91d,892cde5,f1420590,ff801f3f,8ec2ace,69f0dd74,31ca7e7,aed14c37,c2c12492), -S(28afcf30,a1f5079d,e6f340bc,9e616ce0,7a89b67d,4e7f0dc0,6f54fe9e,d17f1519,b7cc26ec,9a25b585,33a43369,40b6bdc0,c2462e39,2246a863,e67bdefe,1ae51be1), -S(13980996,af67f2e4,6dc5f389,d0269d1f,39a9341d,5e941e6,b4ff7bdb,ea54cb65,37a37717,d206b584,9eb79193,96ff5af0,449f3164,4c9eb31c,f27d8a,be66c741), -S(b7b75484,8966d79b,aa10ad77,4c447872,dc4c78db,84a58b9b,a112f5ca,77630bab,ca5111f1,55becf6f,1a546463,8a417af3,2c72cfaa,da56f86c,d7654c06,bc8fdff3), -S(b957ab6a,c7d7692,65adf169,492b00eb,4d8a351d,1f189d24,3e66453f,17696dcb,47474297,433f0297,231e0d7f,e51f1846,3af3e463,e071859e,d6b12b05,2191b839), -S(53f2395b,af57e626,f977dead,da52c4a3,f8b98701,f57eb79a,735e73b4,4d4be4b5,1a31bf14,36b5dcfd,5dc24ff2,ab5fc7e1,15940bf,12ae40b3,73859ce,5e26d55b), -S(31f8493d,8a81860a,3762fbdb,5b623358,af37ca99,3ce1bdfd,91f41acf,5d8502ce,1b231e3d,9604e28f,65d06f18,10931210,3a4cfba3,95c6d856,ecc374be,556a296b), -S(77da894f,ef83a273,22138b96,64df3b02,fdb5bf02,4963a103,1000ab37,a821460f,86cdc4bc,3269d02f,d3e97843,fd2c9dfa,c9ad2d99,f7503222,ac4c4da,5394809c), -S(d222a486,cdb8a4a2,8c1030c4,39b512f,f849033f,cc844e08,fcfd8748,1f68430a,2d7d7e4a,281ba28b,75f2d966,1d25a46f,5ded9066,7422a92c,bfcb1f1,797b7e02), -S(e4431b98,21cfaa43,8a8dee6d,b7a19a38,729622c7,67cdc941,789a6b78,c7a2ae4d,770e652e,de9172c3,4f50ed14,bd8f83b0,720ee2f5,8717fc8,a07de08d,5f8ac400), -S(1bb4bf1,1a1fb6b,78093ad1,5fe5408b,f9e1477c,3844e243,a14c37b4,f394254b,d9cf3fa3,25a0ad1e,fef984c5,8cbe25d2,f88f3051,788cbd42,a8f71791,5229e944), -S(a8fc65fe,e4df466b,d6651ce5,7ef030f8,701e364d,f1de5334,92938856,deb74235,b4c7da06,4f7bcc17,b3308c1b,e7924317,fc02c53a,808b47b,d87700ce,1adffc97)}, -{S(92133195,a4fd0c59,7e0cf65e,8ce1d939,e333f7a8,441523aa,31e339e1,2ae51e8d,556a388,7a7d579e,87de7f49,8c54bf24,2ca4b8a2,8b959e21,ceec4555,b8fabccf), -S(1badb614,6a647a09,894f60d1,6544e992,6da742d0,32df02d,ea347ffb,dd52f93b,6927c950,828e5449,bafee29d,e9977bdc,cd6a0185,3d3ef286,d9854f9a,75f5d4ac), -S(dbec52ad,5b8257f8,f41612a2,70047e4a,715853a5,f22091e3,496a238e,cf61379f,1ed383f7,dccbdff5,bebe8f0c,235767dc,ee220fa9,8d1b5ef9,6aba5ad7,87b46252), -S(5d2fc0e9,a5b1a743,131b4b16,88d504d,76422862,942de800,6c6d3611,3443999e,f7f89299,64793634,4156dce3,ca77c2bb,40536f50,60afd3b0,a3b37d3d,869dc11d), -S(761a1b70,83db07d7,340fb1bd,d5309ee0,e9e05bf5,6fc34a53,b6034365,ffd91ac0,82b1fac0,3d382fd0,109e45b5,8a07638b,1ce9ff2b,f45d3cd9,50843b69,43c75c7a), -S(ea397afe,9dcad2b9,4ad000d1,7abc4e5b,739e4132,997a7898,3c6c5c29,ebf7222f,24a87ba3,411ca610,5a696969,f86ab751,2c61e189,5ff4ad18,7193b5ef,7d8d2034), -S(3dc03137,8776b2ba,83a8124e,821de26d,1a52855d,d610eec2,d5c7eec5,9c92e81,b774a839,6ad7b7ad,9e6275eb,2731ad84,271fb8b4,6c3e12df,b74fe942,e6dcd35b), -S(49b98bed,ac9bbbbb,75f4f3fe,310af59b,1ec779cd,41b75982,6a929bcb,d40ada85,c09f3d79,3b143720,dbc1d04a,4d559f35,c650d372,12668736,1d824a9c,b100630e), -S(786555cd,2c6344d5,7f819963,1ee8536a,ba3ed77e,88501a2,20df332e,b41c9aea,f3e046a0,3ea9d39b,31377a11,dcf7c2bb,13ff138f,f021902a,4f927e3f,f48a60c8), -S(413259f7,3ac4366c,1385e7a3,79f54796,4b6295c1,298fdb7e,6046f711,44ee3055,a7a62864,4717b82f,b3fbb73f,fae2318f,985f1923,7df110fb,260434bb,81bfb4dd), -S(64922735,de394c7c,1d42e1ef,d8a19ef6,ef34e69,dc12bce7,c320f748,3993bce2,84bc17d5,5711e228,7e81ccaa,9625c73c,60923b0a,f266b70a,435b1c11,e7d29fff), -S(32d0955a,c57511db,5f27606b,67cdef94,a001bdc2,cc228bf2,951f5426,69d6dd51,7f9bb41c,d62d5863,c2dfecdf,8e3cc9c5,d104abf4,56b9030a,552ed607,73719520), -S(2428069d,b3ff968b,d1559c74,c3f38f17,e725340b,e956e6b6,e6ae3a70,4fe8af4a,1f074994,b487ca2c,9bf222ec,41cb54b1,bac8dd57,50e47f00,59ee74a5,1de0fb4), -S(a7f35a96,ab880ce6,b4e3c5ba,6502af7e,cf00c685,b260fe0c,380ff875,2bcb3e34,7d47fcf3,ed09412b,ed9fc737,212b6289,8b415372,c9338673,a14e7f42,7b4ac9d3), -S(ab624def,ee301beb,96d2626a,88a9adbb,665f9e83,f85640f3,79e4ee7d,c9282b2,4dd486c4,3525c5d4,668c5fb2,7d03c985,df69a344,62187396,ed9b360d,fde32f72), -S(f6b26f3,cb13dfe9,dca461c8,5b480140,df4a0c0e,b1d2f5d7,58de5173,eb4c4746,a5ab6d87,e6852ce6,9965a774,ccb94676,a440d1d0,c8b02f54,21c11bdc,b8406cfa)}, -{S(ae5fb021,e9256cc0,6236d667,b76b9bdf,304a4683,d2916ffe,489cf019,6b4c5683,e768366b,5c8d36b6,18e45550,d57493e2,41fed17d,12627e37,b29b4b74,d3603696), -S(a4e569c7,5d717deb,360a18b9,5bc0fc36,af132603,b74f3e0b,1bca3e31,14c28e64,a70e832c,e3d8d514,84136fba,9f81a2d7,8ab65b93,dc9f9080,1fcf3712,74340130), -S(2e7c85c5,7e68056c,e10ae193,66807434,c048a046,430d2087,92fc9b01,dbe06508,8c3f82a0,b8cb5022,dc7b04aa,6445b06,d251f9ed,bee00246,c33785de,979140eb), -S(fadbb0f0,b4bd864b,73527365,6455cc26,71251519,6c63dec4,41052585,fa86eb52,bcc086d7,54f08f77,1888bef7,4bd3bf9e,35f8498a,aa7cddba,acd63f0f,ef676738), -S(4aa439c5,2a0dd24d,c5f72b14,9a39e991,6dbcd4bc,4619fd34,94012a4d,430a2b0e,5482d41c,7fda4591,4150d653,2173b658,b5a06046,8270fc7c,2ea19d58,7b96e9fd), -S(2e1c9639,537015af,7de6bd50,e2697661,8ac633e5,f1946af5,34bdbc5c,9797aa4f,b6a39518,c607d0d2,94a36682,f4f6493b,c80f1624,792fec2e,e971f080,37dc6dcd), -S(63f28872,6d86ffbe,28a516e4,75f67972,e6266038,3be45c0f,d22e9a6d,d5d240ed,f62ca816,59ac13,10854091,c7851bc0,4d315466,b6187327,3af16f9f,68597dc7), -S(576c051b,2f4d2ace,ca5c067e,290a4d5f,d8f9b6f,19d4652a,449fc1d6,9d4b762d,a2b94a16,903d80d3,f965c43f,b751dc44,690f18fd,bf3e29f7,e21b855a,837664bd), -S(876afd3d,8466f7ea,eed3ee7c,e809528f,c4b392c9,efcc1f9e,753b4dd9,b84722e,e4453b1f,c3fcd636,b2c9bf97,6816b60c,246e254a,67bf2e59,22f835af,103c1107), -S(5a2ca063,6453a00d,b8cd6f60,3434f0d8,8642c119,b6302766,8ee67dc7,c10c9e3b,17be303e,40bdb2d5,9dfe354b,e58a387b,ff64112,3f6a13b2,80876a7,24c4d601), -S(46fbb84c,d08ce9d4,73e3b00,f5ba4cc2,f10fb84b,ea34a8f2,de114c31,8616def2,62410bd7,2ffda863,2400747d,1984d1f7,da285e9c,592729bb,ad9cee72,d266fc78), -S(417f7895,e2bc2999,469ce63b,66cc9bbc,4581b42e,c62171a8,ac32bdd5,23435283,1a5e10ef,826f058a,175fa5d5,21594182,a61a5a07,406e1f00,396935be,f78c9ef8), -S(916866c2,f33c0942,c8f12e54,8771645c,e1581ee8,6f58a90,67ededc6,b70e93b4,c7945f0b,d100c3a4,d624e527,ea9a8d9f,cedc9934,f903955b,aba58be3,c23819b), -S(c3630c36,acc78b38,8c5e8604,8110f113,3638c78b,fad169d9,d25d66fb,728ed4b,5788b6d1,7c74f601,e2bf5d77,eec182ad,1d9b2a89,6da8962,f9887bdb,5a6918e0), -S(64fd5fe6,cf91f11c,970692cd,d2ba6bd3,4d17faa7,77ace6db,d161e63b,93a0ee19,37ce3afe,f75712c3,301e4c97,6456ad79,e09326b2,28b23e10,b033bc53,a6efd060), -S(2ff8f0e0,5d514fe5,766bc683,f82af019,471a173b,b0e2ccb7,53eb45a5,8047041,9a13b872,e26b58d8,68e1db1d,7391afc1,ece8e410,a4bc3f42,dcae2b27,ec9a6e98)}, -{S(782d5c9a,d970322e,deff2e7b,57844184,c589a4da,c042fcf3,86c1a9f8,26c1babb,27bba565,405cb392,64762d97,cbaff552,1bc38b20,56afe313,556542d3,f200eb06), -S(69040dab,81af8b4b,759b852,40c16380,cc2bc3a5,bc8e9e68,7cee93a3,352d8055,e48d161e,b63c619,26c78402,528ad5a7,19a7fef4,4c03b933,37d51bfa,ec497817), -S(d00d4407,f7a1bc4a,57ce72b3,6fba7d8e,ca4f2303,292c2ebf,6940b34f,fd98aafa,ebdee075,32ccf753,1806337b,54a36a53,1641fb80,64d928ac,5a3626bf,e16dba4f), -S(9a3ab165,66f8c8ab,7b3d0d5f,7a3ec7bf,3cb69c0f,31346486,10c552f8,17a4abe2,7eafa760,7fb4cea0,dedcfb1b,1c16ebb9,8904a79e,37395aa3,1ced5c71,fc8c7774), -S(f9028f3f,4f5752a9,9ce55412,876c7067,a199a338,1d707bb9,3d2fc44,b165d000,a7346d7b,6ea796e3,2a19f104,34a7e0d7,b7e90326,81374d05,9b81badb,4dd651da), -S(e7bd1e16,60174f67,13a8db0d,2bf88a45,275a44e2,9a461c1d,cc6dc5c4,fd2b5c0f,9732850b,41082c88,5ab49289,fe11094f,c26bf80d,1b0998c5,1ce63cde,d7bad0fd), -S(d8b88e20,ee8db21e,28bd271b,46d77769,b446994f,5eb35ea8,d0613b29,67f8c1a,8b9905cf,547475e5,838e9191,388b1c64,25fea463,1e4ef825,e84e2226,2888d0b7), -S(3dfae04a,180749e7,e6949aa5,600ebe40,af61d644,ab5446dd,4b3334dd,f9bd7ce,963fb79a,a952447d,e274666f,16c08a2f,d5864825,78b870de,afbd98c6,adf4cca4), -S(4e0f4c4,b4905983,e12cf9cd,7dbcdf18,db9782b7,d4ea7e11,280d1f,7bc01e53,3305aeb,9b5f23af,bf1c759c,14a811a0,1bc3a5aa,19e26176,71690393,f3318bc6), -S(d74e6ecd,72453ee3,f68fc29f,f0de5b36,82c295df,2fc568a9,d68ad747,d4409b77,46dfc1af,819ee0,fd04e0cb,1af0835b,e8f6e53f,1ed28d67,6c0c172b,2e56a74a), -S(d1ef8f37,78dfe4bc,83c48c4f,e9aeb917,34320f2b,a86630e5,28f735d4,fd78fc68,6cc62683,1e417caa,9bdafef9,92c7267a,e7ace1a9,27d225e2,a5000b97,c45007c1), -S(64457682,4f541ec7,d8ba1964,32146322,3d1bd634,5cd09f03,a91aff2e,b9502b15,236ca78e,bec84846,74c43c52,55e2cb76,b41b01da,ded4dede,1a99e1b5,8fe80638), -S(f557af63,f3d8437c,1c48619c,4bad3e7f,d92c6ff6,63b86121,55bba4b7,efbf350c,efe2dfea,62a12ffe,5e4208b8,e5af4f07,13f8de73,824502e6,94b08d34,d1d92e2f), -S(f45ade55,84070898,1d244e7e,a546a34d,85fb1164,5ea86188,43d753d4,2baa1ecb,ec25cb2,6574f472,69a90070,3eff9a68,770ffa2a,7b12efa1,dcd81ce3,56a46978), -S(e3169959,74f4127d,e9002439,582f9790,6047bb58,d4bfdf74,3b6ebea5,b5663d65,cf7afc59,efac3d94,88260d14,a3e252e0,b51345bc,d3e07c1d,b07ec4e,28b6d60e), -S(bc9112f0,137446bd,1a218167,72b6afd7,65b19569,90f8e53a,f8db935c,2a88686b,a74e4d7,1e24d149,1667dced,bd7f58ab,851d685b,1c29e38d,6c9e613d,b65b7864)}, -{S(ebc119d3,8e794efa,85fcbd,5affac35,f73c7428,590ede0f,6365f1ea,87c65b4b,183a9992,3911b1b1,cd9b0fea,3667b6e1,52af7499,8d32beb3,d2ecb91d,af6e8a06), -S(7ce4a044,e4656f8c,687bc693,1c6fcca1,95322643,db41d,8407d880,4d6b6cb0,14fe83fa,eb944cd6,dab9e7b6,279ebde1,6ce1028e,5df74c77,7e6e00dd,55f69465), -S(5226b60e,b344786,bf572e3e,33e5aa14,6ee6feaf,35c3a2b7,22118560,183cadb,cb650e9c,e4f93861,cdb700d,13557323,8a7d7686,e22943f6,433dab6d,96253b10), -S(21c0342b,9a723249,ae7193fe,aa00baf6,beeb376,1f1bb125,7d0d9549,d46b403b,5b2dfee9,4a67c6a4,def4f55,a14af716,ab1be308,ecac6042,f86679a2,1f5114a0), -S(82e97dbf,f1d0d9bc,65797145,7c5aad62,ea75753f,df9d3e15,efcd3ba0,285d3476,7f67ccc2,f0aa795a,890d9a30,6838b9d3,c64c1371,75b0ab05,68622b3c,fdc8d25), -S(6c02ace6,1f479fbf,11059054,d8dc5761,ca0a97a0,22e520c4,8aa2f32,448b7392,4e57f208,ceed832a,3626f347,f8a30956,13a17e57,b0159ca5,33143166,77b91469), -S(8a367826,e40db24e,28fe31c2,fe24151c,8e4702b2,43a99d86,5448d83b,cf49a6f,b2bf6c78,299dc024,2fc66392,cf6c5097,42a05f15,935c835,3944e66b,bbb87c26), -S(c1c3921a,14f64598,11aa70c3,f756e689,82233a48,588bdfb7,84348459,19125af6,6f7109d9,47dabea5,da858a4c,75ba6c3f,162ad404,15e7ab46,7247963e,8f4a1326), -S(ebedcd5a,e0f0005b,2eb70d40,4a1bd4a5,f0537c48,e8f6149c,c042f9a,773c75c5,2b7103da,d29bb9d2,c07def6e,1094fa50,ea70f7c0,4f609b4c,bee0d576,57e506d6), -S(bda6fac6,99e09a50,ee0131c1,efaaec6c,7cde205c,d3b55c83,176d20c7,80678bc2,881c023c,86b948ed,31a5cdff,8f3f985e,cfec9111,627d813f,177afa76,89a16f89), -S(f6d335ac,66fc71a8,319eaa38,3eeb7fb7,41118280,531434f9,cb0b364e,90babd42,b14c40c7,8846262b,e117735a,30a3185b,49f8852d,2e3aa8f3,3dba4806,ea7ff2cb), -S(c5588c4,fcaa5c53,79f910fe,9bfa1224,fd20aacc,f1efdb2d,7ba87c5,3615ddbc,e60ac5b9,fa96e150,57378c1,11f384bc,16fb32a0,a0482f26,603aca30,ed1315fd), -S(db88be26,bbab7b99,f0f20c61,40ac77b0,28afd465,aa4d1294,9011a47b,b1d87f89,e126d612,91ef9a77,e90a8522,ee6e7dfd,fbfbc2a9,90986da5,65919317,dd4ebd1a), -S(1150279e,e9c0323b,b122c2da,6e8b28ed,5e5b02a2,162067ba,67f5aff5,e99214fc,74d876d8,4d00e091,ef0aeaf9,5aefda58,f3da4d52,51b2b28e,cec41a23,4b420401), -S(1bfe1d76,43526f3a,e0799982,69f9679a,9a54f1ee,bdad1f6c,9c8e096b,6e771023,ad94d693,961644ce,a37ee705,e06b4b5b,32c17011,7aba021d,6cf48746,d8637dc0), -S(928b3e6f,a0e6c2c5,896f6eb3,972fe96f,7e446782,50d313d1,54ffd666,2b43a615,50f2d7d5,fa221867,3f18540,f2f7b513,b6b4875b,9ed4a5ba,73de7800,37f842d8)}, -{S(bc4bb9a6,292aa09f,5c66dc9b,667c4642,6b08211f,a9a80f5e,f3f17b,21f275de,5d0e0492,39a862ec,b9649572,6f11bc09,cebd9f29,d9407ab3,1603054d,d9b76b07), -S(bf330f50,a9c015fd,8ff93153,561ecb91,27b84420,62fadf17,3dec27e2,a5f7b0,931f0891,94aefbf5,9c530d74,8ccf5a5d,83f3fb1f,cd9043ee,ebf50994,d8ec1248), -S(33db24e,b1ba1a5,cbe2832e,50d877c8,a4fea4d3,e63d7c71,fe8cf9ea,9fcd1cc5,8b0db6a2,37555121,ec8a2ed0,e8f80dfd,37082a0a,883d3fb7,d7d2dbd4,7c01f6c), -S(eefd96d2,1d6639db,6a7f3a79,26f5bcd6,618e6ae1,70551973,7dfca216,565513d3,d7644dcf,e46715c,1821babf,5ab153bf,a80d20a1,252718b9,b72f299d,21ba7218), -S(48c08093,fc737bb5,70a31154,290f709,3467c915,c4afcf6d,ae372e42,3ed69815,29581f74,659462b1,3951d930,a8912e33,a2928e34,5e3563fe,f88b42d2,28af2f26), -S(68c61ae5,15c1ebb,d395feba,8661a967,162dcbac,5cb13303,9a354c11,ee217267,9db2d6cb,b3880ab,ddf58293,7f76ad7a,70fb1c58,d2eb9a5c,468331b4,55c5ece9), -S(99afe669,baf69344,16b388b8,30b97e80,86886c62,86870e7f,58d6efc,377ded78,a684a9dc,84881a2f,bc340b96,4180a966,d00aa5ce,513693e7,9052795d,74f08f7c), -S(3e893680,b103cb80,e6a4eadc,abdd4eed,6fd53341,d08d6d78,85fde37a,49621bdb,d342db6a,a942396f,76b79de6,a6d48943,2beb59ec,4d1d6399,9244bd1,731a6855), -S(e19eee8c,7206fe64,a217e60,c791c834,de7cecf4,3ae1cf42,b697941b,c556252b,cf79152b,76b0ef1f,abd36175,48701716,32ffe2a1,57b006cc,4fceb313,17be8fd8), -S(50d544c9,b3a10831,e325dbcf,6b13c6ce,a06ba82f,ec3e5b9f,9442101a,a4c64d46,a89b1cfb,169019ac,19785c9b,8fd27f1f,177adcc6,c9b995b3,43b373f5,cd82c9cb), -S(e34ff94c,729ca264,1cd51264,1eea2aa7,ebb5c577,71bd1900,86a02aea,7cc2c1b3,454dd58f,c46f61c,30efbfe8,49c7b2ee,b1a99bbe,6c8a4f6e,c0063a46,a1f63f86), -S(50a5b0a6,919974b8,14c10ffc,8c6233f2,843840a5,834ff5b6,75134ee8,4f40a716,6cbafa57,ec555bd5,2f656a95,3d592aaf,e963d403,40a7540b,644855fa,7c94c3ad), -S(b5f7dfc,438a381d,edfb576,aa62f2e2,12264e1d,8222bea4,f71ba06a,b2b6f0cc,396484f5,3a14cd16,58813612,2fc55f7e,89c4fcab,6d73e5a,fdeffadc,3c9f9b0d), -S(4e2a7b73,1bba01ce,68f4becf,34ab78b4,3c89f711,3214fc8f,ba3e19e6,a449b7f2,aa85874,bca558b2,e674623,3e0ab93d,4ec34eb,6998f0df,3f153126,93739077), -S(3835d447,f4da18c2,1fea247c,9ff3436d,bd60878c,dd347f4c,ca1168f7,ae189ece,df5da21f,f6a6add7,17e53e6a,ff0220d8,9b1e71a1,30339194,81bbec2,40414a1c), -S(82452834,e84617fe,d7d32149,6abdcc54,2af5fa13,8f55faa7,c2245cdc,48c89f06,c01d6da3,96b923c7,290dbd1a,6c16a69d,8a872638,4f6285a,f589a0d0,20e892ac)}, -{S(c8e595d2,666f4913,1f375b67,81b9113a,d0760e5,9477ca17,8863828b,307488f0,a82cf2a9,d823af13,5c23a04b,bc12dd81,2c352a48,27e19030,8e089d9d,9c316596), -S(26da38b,1bfa8363,6be480cb,684ee5c,70957f93,7f9a2d57,3ec75396,bfee49fa,9763277d,f3c228b8,515bd08e,b29dffcc,eac8e3ae,786a9655,5fc1be21,cdd20d47), -S(52063926,34d12242,b2ff32c7,d0a8bb47,fbbd005a,bf7f92ce,78808a5,7b1cbe55,d0cfa8e,49b45823,881819ff,fdbb6d2f,5c65f35f,3572e13b,ff7af252,95efe81e), -S(af61f7dc,8ceb2277,db16412e,dc469b2b,f0e188ac,89c72bcf,20654379,716115f7,524b9b25,925b793a,8bdb8e06,83cdb414,db0f6dfb,e7e06274,d61ef87a,13493b66), -S(39e53a5f,f553d89b,dcbd6688,9eabd7d3,8c5fc6ba,24618d98,88bb6e42,92658f06,ae8439bb,6d32531c,45ac510e,20f1c7d2,b8dc70a6,65c11f2c,cda73603,97c6580c), -S(b687e250,531efb00,f7e12690,659bfe25,429ea2e6,f1dec5eb,74bbd1e4,89a95e31,1033e5b7,9c0adb6d,c0f12ff,afc5d81b,54d7930f,f6190dec,737bbb3e,c4c774ba), -S(4c17f5ec,34cdd368,dbb62f20,c3b86483,24e99e0e,95a7e624,64cabe76,222981a9,1e37e3df,b690b574,a11c9803,f1cb5618,ce4a0331,e17c5cb5,4873ed6d,de217019), -S(bb7c4b21,77b77a9f,8f78c2e6,25bb943e,9d05dbed,abdbe02e,497e5dab,c31dc477,a5f38fb,7ebbe67a,869b90d1,aa4fbaf5,cd7173b0,46cf3c5c,b31a272c,c0693c82), -S(3b18ce78,6688a74a,7256c067,a412aa59,45fbb506,fbf801b8,61734ab6,400744c8,d4f01881,47809cf6,5226529b,acf6e81b,7fdb609e,3eee050d,ec0f3140,2308ae20), -S(b671371e,2f0b770d,af8fb77,6a64948c,1481cba2,afd1a3c1,bd233946,e34c86af,4a58dda7,ee794384,496c539,7ccfaef9,fd75d05,c551e26d,2ac631e0,3d124fec), -S(caa559f1,b0afb30b,d62ede02,a9e28a9d,8bbb437d,e9a8963c,37e25898,428b845c,f73a14ef,2078cc23,92b99742,9dce6a50,5682bdb8,c2b5e587,31786814,9c777411), -S(2676f258,a761c508,5176ceed,a95cf9ea,4d6640df,a2c4abc3,e4954225,c23acf9f,fdc42fdf,b1636050,67786940,3aea320f,8ec1e8fa,b9033c3f,2b919f50,fac0271b), -S(ce17ef68,f6c7b456,4cab6be5,22495389,874f296e,b62d552b,6d621607,192005e9,94fd30c8,71add5fb,5161b468,ab60d254,472339c5,2668437e,7e172ec4,957d00c3), -S(42fca34,df3ec118,417d8d18,4e507f2,91d402aa,32c00b5b,a1dee38e,7fb0cc35,a046e52a,fb7eaf45,bb3205e9,56e0e780,977bff46,ea65633c,cb0cd2b4,a3aeb2aa), -S(99926617,c15dcd0c,95ff4903,ed9d6050,ad0e1982,84a3c9f9,6a24ed55,45641b13,64437785,afc882eb,4a78844d,14d79cc7,cead217a,3cdba8e8,473374e3,4d416b56), -S(3d4751a6,99a8e88c,aff3daf,3ddcebb2,63f0d56e,6d305245,4c16b0c6,f80e0d93,162f562d,32595699,172a5c6,4ba2dd35,11bc5430,f21495d1,2ae9f6a0,638c613a)}, -{S(49e7429b,e0d97bf9,3f17e9a8,53fedb6a,a9bc6edd,8e85f44b,9d2f1469,b2d3b178,ff9e5dfc,2746679e,9826039d,578bac31,c08fbaac,a075214c,73c50f,74568fff), -S(1d1c9798,3eef36d2,75478b94,ecd3e172,a39e49c7,1c79f932,2077f410,e1a9d0ae,5d8d6ec8,aef80d94,3e75ab6f,68408d84,6cf94216,af6e06ef,dd7e9e72,4abcd7b4), -S(60f8ca6d,1d60f524,8d582e8b,ea2fb8a0,dd2ddb3f,49bedc03,5d24973e,aead0b41,7c4e8b11,b0e8b135,bedc60cc,fd540dab,da868d50,78386aca,117bb71e,e108fc51), -S(c6f57fa7,6d2ce583,415e0366,9136b21c,725126e,56187c79,577949d0,797e196c,2772eb6d,94a50849,e58cf22a,eaf1e35d,6e2bf171,f180a44f,42cd8659,41ac2348), -S(3766f2fc,83c96803,e590fb7b,ceb842a0,8cd5602,e57cd00b,5a6e340a,361a7daa,ee3e9d18,da86e137,27560281,8806fc26,199514fb,98c76526,54c85842,649ed048), -S(20de0b0a,6b2200b1,a89499bc,5cf2dad,7dbb6c2,e9805259,21c5e6a7,29c40cff,b680c2e3,33083337,3fefd833,68986b50,d2a28319,9912a092,fbed8b5b,1f22663), -S(d2f06c3a,add7cdb5,ac606876,e4093fad,8c626408,ab6e6dd1,ead7ec93,4e0a1088,990df428,517d791f,ad749267,7666dbe0,6b71436c,5112295e,ab7bfb74,b4cc89fb), -S(c583dce0,f9c32b0,d8c87a9a,dc7dd093,d12037a6,ec162d5e,22ba72ff,beae41e1,d9390ef4,9f7f10fd,7b8641bb,f2ae8388,ed08cc19,3d1e6a13,81d8c198,42025aeb), -S(80f61ba8,a99d2081,f0652a9e,a25b8d23,716d55aa,c9355891,9a4b4d43,1e967f58,b8df023e,56eb796a,e70296b2,b47dea6e,d74ac4b1,99fa132d,c9c464f0,ddac27e2), -S(4ae1535c,dba6c272,6e78dae3,bc651f16,cdf6634f,95584886,899c829e,df12201c,ef66789a,13b7244b,ced52d30,c9af6613,55d66a9a,9efd3a40,703d38bf,c69c7c75), -S(2143bc02,b46d41b8,766db211,61ed21ef,5b0973,b7cebb00,beb89b71,4a6e16d7,7dcb12cb,137dd6e6,96791345,69e25e2d,57cbed88,ce39aff0,3d57ec3b,85160fea), -S(5c0b84bc,ca8945d3,a2356c68,afb8d1e5,d45357b6,b37e5afd,c2b00e6d,1f6c5eab,1608a492,bfb97a7e,746218c5,f673078,c70f5880,de8df87f,8aa5bfb9,89b43ee8), -S(f6cc5210,fa45c072,cb95e88d,ca93b9e3,f7b35e98,13c29976,2ed9364f,8c021e3,ae959f0b,5ce17592,5046e320,f86d9751,a6ec37a3,a773e5ef,c4681ebb,f5aa1baa), -S(d4df71da,5f272934,8653f60,bb02deb6,c314943,f50cc5ec,e4974ace,b5b4d0ac,17caf288,b3286dbe,2e8d0616,df592027,baf3e59f,1e52fe51,9644cf5b,66443c35), -S(44e8227e,177bb9c1,5aab6cd9,d987ef1a,af087d4,bb2672af,1a8d5412,a7d6cb59,4b9b2602,152e1152,92fb191f,2cbbec91,5ecea9e9,ed75121d,5cc7a88,69527cd), -S(97f092f2,75d1ec04,96f6b14c,10a280f7,25c9e4a5,d16afe2a,3f0837b5,422bc5db,12f04418,c131046a,e5c7ed64,f69d6a8f,d3a3d35e,30dd273e,72ff16df,a866822a)}, -{S(9a1db7bf,53241ed1,df8d3ea0,f70c0b26,76b43ebc,bcb4622a,9704b0a,3067400a,e3638ad2,95740505,455b2e1e,d495c57a,54ed8e8f,c647a6b9,c69b7dd0,715cef52), -S(5aa4d7d3,745f341a,c2869a8f,ce1e2a96,e25e49f7,1e5cf140,c0ad884f,47d8ae86,9f03a2ba,989bd4b5,9361448f,abe607ab,210d3887,8da85782,260937f5,9910d8d1), -S(91910df2,7ca6ab42,17ddcf1,d7efbfff,e69eb9cb,24a6648e,3aa7d738,c76290f7,e99691b1,d883491,e79e957b,4c65f975,601aa5a3,b056ebbf,abea6c7c,d7b9ff2f), -S(b5b7792f,99303195,4024caa9,e08bfc16,53f535fe,7bc3e34c,8491864f,74f48799,6cade2ce,595b6714,5d376b7d,7b435a3a,76b15912,6340f6aa,68ae15be,26a159ce), -S(8b54ad71,6c724ad7,e47e5efb,e6b7c93f,8923e7fb,8517ce0e,6f732486,f37ba1af,fb8aa95f,4a6e3522,371cdaf4,461f4d6,8a45481c,da065f7f,a697487e,fb8ea80c), -S(b4896855,b2614337,8c5842ef,b7dfded9,ba6c80fd,2eb154f7,e83c4734,ed7dba2b,30e20644,fd8a9a81,9c622641,b525647e,ae35b892,91410141,1a5df15d,36c4efb1), -S(5bc3cc33,89816b7f,414a473a,2deae3e5,ad3e7803,b7532f36,d2b31598,7c35d6ab,4dfe0f94,86d1ecf9,7de9b0a9,3e437f49,c015b9a7,677aa2a2,74868a4d,512c2ef0), -S(230bee0b,5eaaf145,f18ec782,1e861f12,26cec876,a50ac94a,4a88ed64,4a3f7d34,331778b7,d638cc22,269a7a3e,abd0c393,f7e08d0,dc761da6,25b70b5e,14f18c26), -S(8f55920f,c479e736,3000b33f,ebbb1559,d41a5873,93429368,78a6156a,d476b8bf,94fbaab6,7a49ff13,2435b28e,df7253af,43420841,b721221e,b5606a48,3061e441), -S(d64edeb3,709907c3,761afdea,f9b431fa,7c0d5912,8a603410,39e89346,1561b7fb,d64ce942,eda3a553,82c22d7e,f9b20c61,ba09fb35,4401fdda,c054e891,15134b9d), -S(ab22f920,a97eaefa,25e46069,1123f499,7b3a78e9,af738ad2,266c6c98,4b5fb63e,27f41b98,a05a5599,eb82b0c,37a9a70a,f19df223,5254816f,1b9411b2,52b77d), -S(3a409fc6,f4a19839,c6bd2187,5e2f9b1d,5e10ca36,5711a0b5,67084612,ebe049d6,21006d4e,399d55a1,6a7c136e,b192543b,36e73785,36506555,e9c5fea9,3e5bf265), -S(57305b7,7613e53,635ea239,c9e35edc,1a2a1680,fdf58358,93cb226,c0f11f50,b3316b71,954f5a14,acfe28bc,9e90c27c,715204e5,9db9a74e,a5b5cecd,2f43aef), -S(d5c78499,3727b6d6,18bc7b22,4b1da72b,1cd9122,81e8e58b,cf2dd698,b400cfa2,d1aab246,fc2da7be,de9d90cb,2c438d65,310b4785,ece43715,dd3a1a65,c8abca8a), -S(13a05a02,7191a7f3,eeb453c2,8b76afb5,150bc141,20b90f50,dbd0d218,15453e2e,94ab710a,3736322a,ed6b4443,abcdce44,a8556a3f,85f9d3a3,701dde54,52aa3927), -S(3e6033fe,9fc41a9d,6037d9e7,ef11fdb6,93d1af71,237d3983,2da15f12,aa080ff5,763af526,e9187e31,89955a60,b3914307,99ed7de9,e41b6c,39d8ae8,748af8f7)}, -{S(50cd2e16,997d7d45,98bb2d9b,61aceaff,5ad5f38c,8286a0e1,d08055ad,726c7800,dd19c3b,c08b8d97,88f9de1,5941f5fa,6402bbbb,5fdc708b,cfc08844,eb23733b), -S(4e83070c,e3eba290,c6cd520c,dcb4252b,9098270a,55fd47fd,eedf36da,b1706d47,561a3822,cd94b2a4,1f30bac8,695e05b7,69de8ae7,4241d2ef,f084922d,ccaf09ef), -S(4cb0754e,6863546f,afe0bfa,edc94c15,6d9ac68e,db700281,2a24933c,a0a30401,6cf6ab8e,306e4400,427b7820,52534566,52d2bc98,2510c84e,43b4ec61,3194c402), -S(a3689f89,d4874967,1b205a89,8e6c092a,b0cdbe2d,f1530bf1,99201a3a,6b0e3da5,5a58acbb,e6ad1676,a328e193,30c3297b,81e52e9a,4abfcd4f,7e0bdc2d,543bdf61), -S(79617bb3,c57e2db9,b2978984,2544e9ff,61055023,80faa2c1,9db34d60,b6cc0c8a,e63a05be,be1da5f1,b74450d3,60092dba,29122671,6e07280a,d78a1f17,5daa191), -S(6a474afb,415121c9,38c73c20,27a5fc93,f7e8ea81,d7df1144,a50b1c66,5be0d8cb,5c643389,af9fd383,b7d71966,d251dc20,db8b0d22,8aa94a04,289ee8d8,247877fe), -S(7bbcb86a,ebb40626,ce142507,b8cf0801,2f706862,7a46c76b,fb8eb115,be4163ce,b18769a0,735707da,4b1d7a1c,7690f190,2a3a1f30,67d54f8e,188f8a41,3826ade0), -S(5caeb262,447b4224,19f66418,4899762e,2e2a6b9f,f8aaccae,a29fc3f4,68a1b645,b894f2df,20dec514,2792de69,86a9582f,d6e1e3e0,fd97c5e8,9798624b,9d6e2236), -S(a8ec4087,e144437c,3acf2ab9,3f339415,74e79f9f,cd48bc47,cace25b0,4d4e451b,ef3ce687,12f91e5f,b38ccc98,5c0641f9,d57a6ac2,b72f8814,3e85e128,c7012a4b), -S(724a5b27,5dc8ff8a,e10b34e3,5d05a592,c50904e3,32153a20,78809bc7,5d69ed79,488b7096,f471a9f8,583a9b68,3119a211,6ede4c52,bf817b27,123488d2,9ecb8328), -S(1d1ab819,80b10336,75e10627,b7293cb7,7f31cd83,ad1a043b,ae9aceb4,aa0a7463,cfd42f33,c57814a7,acbb3f08,dd882a4a,c572412c,8502e82f,a3180452,7d2e0151), -S(98b12e59,8166e430,ea43d632,f8a4b981,f3745420,6d1233e6,f9c8756a,47dcf4d2,4f65841a,b8f18241,a46eac62,b875173d,350c78da,6d6af3db,d9fb9bbc,77f33b96), -S(58dab35d,9ec4e48d,6a7e619b,e926ec2c,45f67be3,3d89bde2,38963966,c96b3270,e5d0aaab,6191f65,e6340837,747339b5,acd35b86,823e06af,85eb54c8,7f926564), -S(41dfb55a,cad77bbf,80435b8b,7f2366e3,f41e64f4,74bd9895,dfe86e8b,50abfb83,147a71bb,3809c321,d960ef5d,9f767bde,7873efa5,c590e799,db46d8ba,8c1dd2cd), -S(d739d1a4,72dadc,eb59a120,3b8de564,5d5c1e1c,5ee96ebd,533442e0,de0c8684,610f527d,8cc0ddb6,cb17e24a,51aba4ab,5ab0d8aa,9ebd61c,5d26cf93,30a18293), -S(f887ab66,ed92339e,8fc9d8ea,1af72d3c,6426ba1,a8be283,e2457a97,342dfb4f,94de30b5,4e69b56,fefae855,51fd5a5f,111671f9,c5a733f1,1ef7464d,88d5d66e)}, -{S(4bd266bd,4a730879,cb06d8dc,bd8e5854,c50b6221,d83e0a10,3afcb2a9,a64cca67,a4654a1d,835a51f0,5a877200,1768c549,909212e5,78e3b1d1,df935959,93650863), -S(15fce59,bb77b091,90e5c39b,ae696127,4d51068d,ea51ce52,6c8525e7,b1ee3d1e,b55eb928,92ae639e,da63a4a6,f14fc6f0,ee2450b1,94df32da,9a1004a8,699797a8), -S(d3e5b06e,7648321e,4fe95ed8,e1316474,43996e1e,2cff5283,26783ba9,1906cf7b,2ad6127a,9e45be65,26ccdf8a,460cd441,cebb5689,9f3cfd41,2aae39e,c838b2c5), -S(114032d6,8e474d1b,a9fc40c2,f22f5b1d,6d12b9dd,9cbc286d,38274501,218c54b7,9dd3d787,706a063,c0d81bf,d1cecb6c,b7b5b446,6d7c955d,22cf05e0,822a9ef1), -S(a230cd33,6bb82fca,bee35435,dd0d560f,d286785a,f5425cd9,a4c9abdc,819e58c,57d99f9c,aef9cf3d,fa66dfb8,bedeec77,e21746b4,27e4869,39cdd8af,5a9182d0), -S(593e3646,546aafcb,fc8a293c,6cf0530e,5f1f2639,2f3ac2b0,b136583f,2981e8e,15c4b596,6589f9eb,5fe0d0a4,91e768ad,fc7f5283,875bfcd4,3b698a3b,4f268b43), -S(37729a9c,3ad25a03,e1cb6fbf,ff486df7,d518809f,66099d27,d203dab3,3d33dec5,dfcbd1b3,7905c99,21269ca,283405c5,208ef5eb,e96c0801,f8868631,69ba2c23), -S(46d8c723,f0b889bb,3272389f,ba3ba57e,d30d701f,7f730d0,c7ebc34b,8212cb9d,bc41f981,2017d9e1,1e4e2277,92b6e804,6318776a,d552960f,c751c36,c6d00a2f), -S(fe29d8c8,fd38be9f,c316c2b5,ab74dc69,ffbcc390,1e59df52,66aa345b,6b1408a3,338ea0c3,f80e4400,53858842,936562f2,8b9ea4ea,31540868,11e87150,89e9e304), -S(99ddf18d,cc6505b3,78a4cbb4,f45bea9e,44726ec1,cd51397a,d536dad7,b1b3ca2f,fa8e8ab4,b6071958,c237e5ed,5e0c0962,61825572,3411bcf9,8e923b1f,e748ce4a), -S(14c9fbd4,a0fe77f,1f518efd,13dd7eb0,cb7695f8,219db1be,d4e76fee,813a34dd,991011d6,f67f3e84,a54c2357,9897dff5,f2a58cd7,40bffbf0,a876a611,535f2540), -S(3cc95333,2788684f,bbea85ee,f49a2ae7,51d5e29c,48642a5d,45236bae,a122e5dd,2ed99469,8084af0c,44e7c819,cdeaf311,72f08aa8,ee70644f,ffa2dbbf,bf9c0bd6), -S(9fd0c95e,f60c6831,959f2b44,5a15a366,6463425c,3a64d213,b014edad,bd22e711,8bf7b7d7,50558a66,4481df71,2c14fe8c,9411d8e7,13fa61f0,fcaac1c9,2c1990b7), -S(b23e3552,9d02bd4f,bd847080,a5e9dc69,964b324d,e16af0a8,857f46e0,ad9f32f8,f3b98226,f77e4393,dc35409e,69269fe5,957a3e74,e5e5d7c1,ec11c4b7,3f5ae025), -S(9b674b33,b7bac25e,88896436,b6c80dec,be8cc797,fd34603f,a4007318,415b95ab,50811d7b,bf49c464,de0b274e,2acb4dec,5786043e,6bbded6f,13d0e131,c3b223ea), -S(2cdcffd1,ac351cd5,21216262,9a401b63,2f4f9c64,9fd0e250,2adbd66b,3a0855,54ca3d4b,6043a79a,66cfb5b7,37127ee5,c0a3e0fb,a4214052,6da020b0,c757f73e)}, -{S(217de5b,a47e8de,cb9d8dc3,dc8fcfd8,203c514b,b9d7bb5e,fb03584b,aa1baaff,c77bddc0,3af15e63,912e51c7,19bd8186,67f999ed,9bd801b8,11bc289b,f12864ed), -S(799812b7,d79876fc,7290c3dc,18fc6ea7,1d224373,2e79d17c,9737a47f,29fa8502,4118e843,99b5d024,a82002f2,7e791cf5,badd2e5d,98ae1f30,6d98ea6c,d1d9b4fe), -S(8be7f251,78840efb,df56c470,c4db43dc,54bae1e2,7cab2bfb,c7a6641f,e34f00ad,6db39ad,c7ad2102,90c29073,e48225aa,6d51f27d,d97c0b0f,e241f9fe,dbe1564), -S(bcba249f,59646b10,4f6aba48,1e886117,be0fd815,a6220e4f,f5a08eb6,ac16c612,e8d84c45,88ce9926,99b2d6fe,5ead0615,4b32a372,209e06d0,c3d8c42f,a0e22b86), -S(ae1a61b5,deed4d8a,915b94ca,72aeddbe,2c725ca2,86311610,476d94e0,73fb1415,e1f62c42,efb2da24,47b3b5f0,834617e,e06078f6,78ebf4a3,d38c45c2,f384e1b2), -S(a1e069e7,74cdf680,41c5aea5,39552c4e,bfefd4b6,3869db9e,c5532b09,e8370996,cc1216a0,cea149c1,f19ffcf0,eea82fea,29fa7f3e,b19d5eb,7307904d,a38652da), -S(e6433844,64b7b1ce,bdbbaa01,aea053cb,a36e0cbf,e1c9a652,8c714a45,6b6b66,22f16bb,17b781e4,47fc81d5,1ad5ec9f,c158b069,7c446bdf,52da86ee,6b4ebe8a), -S(accfa38a,10f8d4c2,f8342e29,272f7c54,73d10562,82653714,8b67a26c,5735ab9f,ac0e6829,1043396c,be583305,106514ae,354532ac,5ead4594,dd5a6d4e,332cec1e), -S(d201c17,a1e9efb1,7bc1c655,48c100e2,450614aa,b45b8125,9f2f7e31,4cfc924,4677a168,1eae4650,5c5d6c94,a6984480,43f3793d,ab496ba0,ab86064e,8b48ae23), -S(6612ab47,b35d942a,98427ff,ba59b78b,fe44437e,b87442a7,794e3274,89c3b335,cd540fda,9abe6c72,e298eddb,6d8c5a3e,c0953eff,4a61cc54,22d01ff5,f7329785), -S(35b1b6b9,ce9d1a9,802dd987,745c615b,87a96a83,d1b2465c,cc9f82f0,1c73571d,eee3f5ce,aa7961de,dbb80107,36e6758c,e9cc8b0d,58a6dedf,ecec9f2c,7a73865a), -S(c798e22a,59e65aa5,6647a86e,f9a91e80,98cb97e1,81e07b4d,c3fdd428,dfc3b1b2,45f881a3,1b10db23,ca93210e,22398cf4,81a6a61,6496fb5,ab82b456,7f99a392), -S(39d9dd1,955b77dc,4f4d7436,9d7785a9,c8ebfbc3,d359f15d,8d38d8f3,1097a2d2,64040f85,819c8a31,94dc8ab4,5d794fd0,dadb6826,70de6629,5afaaa1e,c669126d), -S(a9168a3e,d48f2332,48bd4a53,dd37e37b,d24b6284,a2522671,c6494bf5,84738bf1,6ec107ed,6f749a16,27a57227,4d7bcf8f,8ff71417,7d38f6cf,64040ca3,3292bf65), -S(88b92b0f,67c3524c,3d7b04a5,bf539b2a,a244f3de,64867754,bad51192,292a6f3,f65e55f8,f9239573,d77176ae,c976c545,a0e4668f,8c2f2fb6,cb2499ae,94af11ed), -S(6c7ef071,c8f4b0cc,67e66561,38d5354d,fe5c9edc,5cea2eb,a43a5751,317da5ea,40894203,7cf76552,33da385d,43e1bd8f,cb871737,c4b7f044,a44042a3,34d4bb6c)}, -{S(761cab41,3916a1f5,e131f337,e9023519,6199f789,87ef390b,3f2d8bfa,b0e9bbc6,f10272df,f7e91c40,3565da85,17fd3011,bde7b797,526d3c3,f00fb28e,f26dbd91), -S(a6bf4e6,9cb5faaa,8b1308d2,da8e2ada,516b5f18,733156dd,2de04cb9,ab1b0e9c,b84be8fd,2ac4b2f4,2934490d,2c7de2a7,8be093ea,907bab1c,94681e51,3ba7f4e3), -S(4d280f0d,190ce936,11ad117,ad7ca092,d61fc8cf,db1fc752,5788c7d,9cc97535,f20a17ec,c8fdbfb0,2db3b21a,acd35527,25a7aa8c,d20a6e23,bcdeca87,a6fc2112), -S(fc0fecbc,c71d83d7,c888c451,f862474f,2538e8a,800c8a93,f4c30be8,ef98e709,3e809271,356b87ad,87d15888,26b055cd,6ec7e44d,3c9e404c,a27a473a,8cd093cf), -S(c3746b0d,f41e4a85,be3bbe25,c1d64961,f80ed512,8ad3c3d6,2cc5b9f9,b231dabd,382a6d3d,d970f8d4,abe3a72f,58f0cbd5,33dfb21,b92571e0,19a0ed82,55974b77), -S(e5749369,b1e25400,2927cc8d,3b15b5a,dad570b2,cc6ab264,a8af3de5,fcd9a458,38cc0e66,e5b86153,1b8b7aba,c266235b,fd34833f,9b0a18ef,9ac361cb,407d774e), -S(d3463d82,782ece5,999dee44,cca08ccb,1d908f11,7f19d0e1,93f42e86,505470ce,ebb2cfb1,f948fa0,4204c39c,cd3c12fc,6379418,33e9ba07,cd714715,268e8c85), -S(9c88be4,50bee26f,14afddd2,80e247c7,7d07dade,81c55945,4091d1a5,6acc28e1,1a943839,793d91cb,865a3213,4d4ef1cb,927a90a5,e9da30c6,c88d72cb,1fef79), -S(77d8a57e,81ff4149,8703d289,c6d2d6f,209ba69e,99350060,d8e53d5,eb3709a9,6b692bad,ab736bc8,ccc1362c,24f05260,5c3d2b0,23deacf4,641c56f5,c2b79fa3), -S(64ad7f39,a9e7027a,51eaade,8ce6650e,2141e655,b443fe8,f67afbf1,7c970189,a730c9ce,acb21c6b,ba834441,9f417a6d,47ca382a,904e432e,3fc2235c,222acd1b), -S(6f1c3296,67d9cbee,7c44cdf,e5614882,1ab9ca61,1731c1a8,28520698,7f94609,ecd182d9,eed899,f9b8e5f4,71e5805f,ef716180,b8d1499c,82f6186,d09a0338), -S(8116e0e6,75ee5fe6,f0bc86c6,c3830977,a4432546,4d027eba,fa242f13,abe10e55,8cae3d9f,af3e4b04,f9555752,74eb60b,1ccd5f10,8b3e52e6,47871a5a,1671fd), -S(1593b19,7dd26cae,e667733e,d4b564f0,ff212f26,1bd6e81c,61acabe7,37b62f8b,3c9d3e7b,52301084,7a5c2f2a,39cb68d2,b9a88605,a12cfb39,fa790749,7107b746), -S(4bde92f9,1335891a,1f40ff,e4310cb4,10e2b172,27223f80,672b313a,184c9a26,c24904b1,c5d83c4b,31748a87,576880f2,73719ea,4413f945,e8233811,5282347b), -S(e04ce78e,b61966ca,ccaad985,376f23dc,7f4e5c22,7bbba119,a99911cc,b7fe0674,f5e3bee,98daaa6,1f45a2de,6e95e919,68f33ecf,4a71be8c,8fe5d925,92e43989), -S(e30ce87d,35b2a79b,ac96ede0,c3b632e5,506b5b86,22a0c483,c4a6038d,d846d191,d92e324c,c5d9a340,e69050bf,198063b5,e4fddd9c,a3e466b6,9fd00831,3eb13453)}, -{S(60b01067,25cf781d,e78ba725,40508697,3f2ff6ec,1511515,6e19384,1fddda7a,624ccf87,f0ec21b9,82efbc4,6d4db878,5d20fb8e,dfe663fc,46660bb7,98c96eb), -S(3e169750,b508233a,580f67da,55ddf909,a6bdedb7,7a7c8a6a,ca262be3,d6e77a93,d8e9c3e8,733dd591,722f7020,a361b2da,e6a4e71b,7001f1ca,2ac8c89c,1b56fcae), -S(a502b4a5,7f7da399,710ced24,5452f975,314b44c5,2c6c1625,3e4c183c,d53f18b1,814e29d1,67240f5f,2a7a406c,bc0e4980,69def56d,c7e1c16b,2a67a903,59400c37), -S(710d4fa6,d7e2ef8e,373a011d,f28b2a15,88e9810d,c1c74a69,3b3e5de6,4bbba781,c39916e4,231ac0bc,90d1c25f,6768b4a6,cb3efcc9,99b42dc1,27065953,bfb3b307), -S(9735e24d,98430f34,7dba7882,9de4888d,1557f650,ca2ae2a1,48394c36,9b4931ae,9b5e03ff,c52da7a,4119c4e0,c86aadc8,eb3172a5,fc430cb8,ac121fd3,d2949b02), -S(3eac990,f2b5a7b9,7ad3c31b,830576f3,ebe86f15,efc78a0e,ce51e592,190710aa,2e75c1c1,786110a9,785a21c4,d72576b0,9fcddea0,b1828f8b,4a7eb45f,8d0f7081), -S(a797ac71,b5c615ab,52e5341d,5420684a,7ed20dd6,b7cfd205,2ef23b45,7302d01d,32fdc8e5,eee8870e,6bd9ee55,821bf2d5,30798606,85f4c9ce,4534b4e1,525e782a), -S(e9b05915,1e029c34,7c30a260,138378e0,a609051c,33b2da36,3dce9dc4,19b2deb5,5494d79f,9edc31b3,9259c82c,14f6c757,be0159dd,c79a8797,95af6150,484d8683), -S(8ed4c8af,27fa4013,a9d9826e,becd79a1,30cb2014,96e583d2,e2d80eab,573a5eee,4bd35c5,cf78a79c,d5568968,fb1043b,c8cb021f,b5729faf,509a09d8,b82e10c2), -S(14230106,2f11cd2f,b0e8abe,5a76a7c4,2eb3f019,ab8503f3,afa0bab4,487a4928,480dbfeb,2b36a3d3,4cdfd029,dfe3a42d,6297724a,15be840b,ff197fa6,ef5f594a), -S(425fb125,e156d90c,31dea3da,6ce5f3f0,2d1d78d5,9ec17c65,e89c3817,d10df34e,2e2a12cb,d621042,8cc2ce77,df2ec8cc,ec1a8a8a,9a2a2a3d,b537f1b2,13ca871b), -S(b54496c9,57e6e359,88118db8,26be100b,affc546b,511aaa43,6be0f72b,2072d698,4174ec3,ab8c5709,581d797a,831c341b,131d94f4,25715984,7c6b95da,e42d6ac2), -S(edb85684,1b5c164e,eed9b5d5,740972d5,781922c,e9d365c1,24475785,2d4c6602,56eedd35,dbb97163,df4f95d2,dc106a63,114e3f44,1cfb2d74,c57a51f9,87eebfba), -S(de82cea,e7a0a2c0,32db9642,49b47662,201721ea,754aefd5,b304d7cc,ab3ab426,8f533e0,81b88901,ebcd8547,3ade77,776ccbe1,fb1d2ca7,b038c205,be8a915d), -S(7e74f42f,e8d3e772,43d11177,ed249ea7,2e87ec05,cfb5af22,2de3120f,22b8214,2978928f,ca85867e,c9563f6d,5e044fa4,2eb480f0,e2ca86ea,acacb1d6,66bfc426), -S(995857b7,8066f2b1,473eeacc,fadafb7f,36fdc5d9,1ab5fd0b,3ac55be3,91935876,631de25e,51831901,aaa62ca9,391ae54,7dda101f,26ac6fa7,3396f885,3b9fb916)}, -{S(a707efc4,89165c75,7edcea3c,ce729b44,91f04142,3fc6ea9a,704f52df,c8a0650,f2e7657c,6c618494,c01c5a90,d06b625b,c9416d63,f7b8f809,dda5076f,74fa2c92), -S(e670a33e,75e7d765,9dbc17ef,a0466808,3c57e661,975e8197,84ed85c6,838bdc7d,df5e73e7,4a1f7445,d140fc7c,eee1038d,333590d3,6626d5bd,bdf399e,9d9b1843), -S(751a8413,11be980a,5a884850,c9101021,393634c4,862d6806,2b1e6855,2fb42d9b,26a416ba,afadc235,425ce35f,d72e17b8,6d13228a,ac64f30b,5cab853c,1d80a1bf), -S(f044f2af,6d6842d5,946ad6df,43784921,47c45378,721d1e39,ccdbc033,eb0d07f9,68e474b7,e3b1a102,efecbe4a,a20134af,9f3ddcfc,45213188,744f7816,f381f942), -S(24208410,f23c4fd9,42fca91,94b5da3e,de46e511,7b0446f6,e92eae4d,bfadef52,b17efefc,ca0bb9a5,1544f8fc,15474328,84d79be4,bb7cc122,9aa5d66e,450c4849), -S(6aee88ee,18046ce,6399c111,2ed2e9d1,5ae30b0,663b75d6,a20baa10,57a0287f,44155fad,94ff97af,ff36d407,4f0273a5,adaefee4,e2c48bd5,bb1973fb,53d65d20), -S(b112113b,921501f6,208ace14,74cd923e,c4ed6cb1,1b1fbdf1,2786f43,6d2efb0d,d63f1ebb,f305ae31,2b0fe166,23a9cabc,b7c7b76,1e62c8a0,3eb2388b,5635cdb5), -S(74cc4471,707dd64c,bc0688c2,1d15d3e6,863adbcd,3b6a0a08,78556ed0,239ae027,43c03176,1fcf3c22,3a7e70ca,9e27690b,53f8b3d5,a3782461,6d41fdd0,7202ee6b), -S(a23a0d76,d391dadd,23e1654d,a654f0ff,eb8eb983,fb4162c9,a9956c12,fb77d5cb,66e0fc9d,311c830a,3a2229,fc4f82e7,43592058,536a9e7c,722a037f,f87f1363), -S(ea0c9f05,6e39f66b,5ab9f833,5c8e4655,f4ec160c,7accf824,aa1b5dbf,2fc1f8c2,cbffc05d,64ebfc35,7df2966d,a170fd7a,a5861376,f8d7f3ab,6c004671,e0dc812a), -S(ea4ba4c9,2c8b511a,9559c223,abb33c27,22cec491,e48cd519,74b3355f,4e42cb7,4a4db6d6,f426d463,4d6717e3,d3b6ab71,88ba832e,8a18a4e0,4f17a698,bae7a41b), -S(939ad0a1,a64da497,1a6ff2a0,a709c485,30d752ad,a954c8a,f632f969,95561aab,9a763429,5ffe700e,e36d1d65,f53ecbdb,92bca222,e5e2ccb1,55cf3a5f,c751149c), -S(f2548d26,ae82f5d4,38ac89c9,f8a5f974,4632ce26,8fa7f62,9446a19e,2f7c8cf2,7e584e28,b1590b83,31ae2228,81eb28d5,14ac4360,b60aff7c,d5061606,c5cf4014), -S(a4156ded,fa8d19ad,6471653b,42342986,74f4f87e,a9258de7,6ad54fa6,f3b986ef,ec77cd09,b77e2ca,c7b4ad0f,5e05004a,593cef18,6c57145b,3f9510a4,24ca5ab9), -S(12575248,e8aba15d,28a06860,b5a03e0a,942e33b7,e5099128,da2ee781,98333c51,bd3aa2df,cf99aa06,593a3c9a,3d22dee6,bdcbafd4,414a47bc,38916a19,7c2c2025), -S(b4262622,5bb55310,903f5f23,3b0591b9,adb2a909,e09cac82,503ee54a,64372572,997ac9a4,f1a21373,121255ca,9b622dec,2b4e7652,89731f03,37fe5d94,24402685)}, -{S(6efd8760,aed4f239,bd97a00,63794c4,ef14acc9,f5b94862,4c7f8b51,3ff35278,74acac29,694c5307,aa221b37,f2ea068a,a269fcd3,c6d85aaf,a8c8eac1,17d7f997), -S(da759133,159b8d93,d75c9aaf,616d87df,8f7dcebc,a518d4ca,da418b7e,39a264ee,8ad545ae,37548bc6,1702d08f,8de7a2c4,3b3392f2,3b44b186,fe1592e9,2f102577), -S(29bc8d55,faa61a53,643e8a7a,8f8c039c,bb808abb,8ec4a96,b294e4e7,a5a1fd2b,4a170217,7131ba3,275bb1bd,797809ce,cee979a1,d2f161b6,8b632622,2f92100a), -S(c15e640,b71ed510,37d92f02,7de2ffb6,3524e1c,208a6722,aadbffe5,977de2aa,b208b26b,eeeb6d6,1d783e21,35e71c04,1ab78e0f,96315560,d3729c6b,cf69c6f0), -S(9a738ad5,89e86d47,84abc74a,ad4c781f,72ad7fa4,91654392,510ae297,4464c1c0,234423bd,6b770214,7e157d65,e35cab77,62794253,c3e82487,8a4fe726,6105ad55), -S(3692b32a,5be3acc5,3320e434,42c8d1b3,235d0635,49a493e2,e4a33b49,f02f5504,ac61c2ce,38ac1b0e,7b3c5d80,ce988759,18e9ff5d,669f61cb,b285ad07,6d436ee7), -S(dd501ea1,3aaa02ce,619171dd,4270fda,aa164f14,c90302c0,5a3e10c5,bcafaf5f,20ba19c0,8561667b,d24c59a5,a812fb32,972f9231,19a4d42d,48aca05d,9fdfb61e), -S(f7e3ec26,257636ee,74eb2c22,dc9da3d1,4d6cd511,a6c34d18,a59e3d52,b2099502,a2a302d3,50790316,f99cd37,66e61ea4,8b9b3a92,eab54f08,dbd6a061,5f495eb5), -S(281dac89,3afdc45f,4dba86a3,fc5b863a,23f55d97,e49137da,c7a31f64,a0621a04,12f9a757,c8ebf05c,8bf34270,77c6d2fa,852aee99,af3d4ff0,9c6522d7,5becb9b6), -S(8de33df6,91ab87b2,9e36c69,687cc788,dbe100bc,8be07786,892aae4,e44d5834,1a9c323d,65aca9dc,8a11b116,4fb2ad88,b8625f61,72efdcab,88da47e0,7cc74bd1), -S(f2b7d303,6342168d,75c1ab90,c7045095,d8f415cc,96a86154,97425cbd,e4067750,ebd266e0,7a10d930,80241d0a,218eb94d,51596e36,953ae60c,25fff023,25920883), -S(8148dcc3,da9ce438,7edd33f,484f6bc3,6ebf7b2b,5d5c88af,c22542f8,5c943a95,591a62f9,9796dd71,cb18f64a,8e30d6e,9ab8336b,e9c3a684,ecf891c0,3c6e836a), -S(ff688510,eccb5b50,957de634,e4324f21,5cadab7b,93bf0dc5,ce94736e,a93cde8a,37d46d44,e61fc958,6b0da8ac,2023bcf5,75f8a9c7,9d30c993,e3d9a650,764e1ce), -S(eeec9568,1a66969a,e524bd76,580efde7,99302202,16aa7549,d39a98b2,59d717e1,64c4db73,487b23fd,ab74b50e,53fc8d1d,336db703,444b5844,b0d8756b,b84c289c), -S(3b2616e9,b51808ef,430e714b,ceb9a747,aed9e31a,a9caf6c3,d57c1565,cd9b7f88,e6b4bdaa,aa1ea551,4af2705c,47f07417,b2a03bef,2b406760,e86765f7,23cb0438), -S(5f0eef38,c87db43f,6498709d,48c445a1,ac50b40d,f882ecb9,414a56e2,ec927ad0,8197f585,73b0c534,49c04d6a,b0baca10,3c97d9c3,9a61dafd,fc793c5f,df7104af)}, -{S(2def7e67,7906cf3f,3677e7b6,1b0a8f8,985fbd9b,23265ea7,18a5c16e,139f0a8,650a89bb,df8c8326,d364fae7,558de827,a529780c,9b7bf8f1,c6925632,7c59c74c), -S(170634ad,de4863bb,3090218e,543c310e,9bef094e,94003fb7,5f89b076,757f8900,b708e4e9,cdb53954,2bd573f6,eee4774b,ad2cd18a,ab0b0157,dd1d3aa3,aff70dd4), -S(caf1623e,21907368,7d3a686a,7d48f9b9,953fda37,3f68ceee,66b5647c,ba9ac0c8,95ec09e2,533a173e,1773b047,a0702977,3167a96c,c7a2bb42,74ecfd4,9b1b7948), -S(dd21377b,234e31e2,7a42e856,305186d6,33eda53e,5bdfb93b,f83159ab,9cd37bf2,27a40d9d,9bb0437c,c079c24e,e3a8a10b,c54c8af7,6dda2e35,ab61e260,ddf6feaf), -S(5d6d3e69,3865d2b8,4c0061c8,fc85da28,edd6ab37,bb6bc5d,eaef0d,6ed7d0a8,bb15835f,e6074d1d,c05e4840,a22532af,b33a1131,80073cce,17b77822,33dde5ce), -S(3df62006,31fbdf0d,8ae7d924,370927ca,f27587a0,d7bce798,e6556a8c,62f108ed,c4aa6712,405c44e9,389e0a03,952ce263,c073b849,ec66cb7,b9e203e4,12017771), -S(d49653b7,639eeba7,e9d82b1a,61b0e1c5,1363337c,eed06916,47f81c25,b2f71e6b,f1411513,77e6553b,66221284,3f390c4d,ef25b316,e1123b19,a5f77c97,b4559e79), -S(fb4a40b9,77153349,3d316d3f,2688f6ac,32b63e35,6f8fcc17,ca1a9008,b9a90745,d49d6d04,ba60238,5cca34c2,6e5e3ea2,8396a459,c9f54478,f1e93e94,fd3545e4), -S(2b5f9b4,512e7676,82d7f93b,39027d9c,4d2788c4,b587dd66,8e7e2a49,2d1fa3ad,507b76a7,33682d56,6a2773f5,c3cda342,2152e9c4,9c204aa,bd015dc3,9c9469f6), -S(55e1a77,2c3406b7,b300e7de,d35ff44d,76fbb312,7859c80f,841bd730,45c0c006,f7f2b9f4,7c2ec8d,9b476229,ec773a2d,7316b391,8f98d540,e110d196,58cdd0c3), -S(269a6ad,e6e25392,21f59cd,10456fe1,b5e3a756,1e13e578,3cc6b7c6,ef145ac,3827d2be,94cde1f,ded8306a,6619b933,ac2515cb,45cffd75,267caff4,1e76d6ca), -S(e48e1e7,87d48c62,8e85040e,2c836be9,cfb20d10,51a251cc,9e46b589,485a29f8,aee94719,b64713a1,ff2f2402,ec6a19c1,4df12f40,6214c49a,d9b00234,4325730c), -S(7612f9e,691cd23,701a213,79582527,d658be1f,526c220e,da6fc536,b3f7780d,a21538ee,e80268c9,ab6dbe6d,1890c4f2,99aa8dd9,82e9978c,b6ea37ed,53308c10), -S(34761add,2f2dfb4a,6adf1f0,81aff3c5,1faef7cb,bc1a989f,3e23afba,288c11ef,50c8b3b2,9424d319,8d55c10,3976f312,bfa480ee,9e93caf4,b75fa97e,1517d3a1), -S(8e57bcd4,5c8e9789,624ad4b3,8a9d5be8,bcac139e,a0abc310,a1c272b2,35942e69,8daf7fa3,43dd401b,c8aef9d9,c102b577,28535818,3e379de4,5e5ce268,e9f9b548), -S(b9c35f36,2b93a8fd,21c9307,91c659b,270fbe0c,965c8de8,b5b45ff1,e4c8eadb,2e506d1f,a9fdb177,e0a818d,b40d8f67,2b5ef2ab,72f051e,8f6eee9b,fc74b9e8)}, -{S(9705d56f,f75c7d2c,bacc47a4,a6cf8b10,300c688c,fdbd1b1,528f41b9,652d49fa,c53f7f11,896f2edb,fc957dd7,2cc90856,c5df9d86,43e42489,70182843,84201b98), -S(1fb0f8f5,ce10e878,abf40518,116bbc18,ee77a22,f701108e,a8c4f9f,f6562080,8f761286,34089abe,b48bae3b,882019c0,9bcc5386,20fa98dd,4a3710a1,e4e9bb46), -S(4a807b29,3b312ca6,acb43f49,6436b137,36748bc,15c48dcb,7dd35e75,fd2a5668,6115f059,e21f7257,c8888959,d1401db4,c77a0086,34cc2206,e8a8d4ba,1540def8), -S(288ab400,5444930c,15410269,9757d7fe,b8410241,38c45db6,d6a628c8,e0100ad6,bed94f18,78f4b61b,c0b557d3,cecd946a,f9d105d7,a298cb73,fccbddd2,4210cf48), -S(22a7d3c8,85001932,985e9543,1e470770,f664ffd8,e4593aca,7c93a7d0,9fe01b93,65172aa0,9a61749d,d0695269,4a15696a,947c8b37,7ab24041,d76aa7c8,3055290), -S(4470823b,bbf22c97,7602d166,dc895df0,a562a732,f905ea78,416a74a1,eb0f35fd,1b1eeff,736ef902,aff3980c,36b47ce0,c7611f5f,cb83658f,7c5bc15b,c6e35414), -S(bf345a75,c16ba113,a4255ce6,cd485235,d7b71b8c,11fd0d49,1bff369e,240aaaa,8a8b2999,e06ffa8d,89932713,b1bb5c5,6837bf51,aea390ba,9579f2e5,566e7c1e), -S(9ca5d558,2737e890,f9a7dbaf,d921177f,459d791d,21f9993c,481594fe,b9aa7112,808fbe3f,cc3e80d3,f6e2703,f55b32ad,cc1ee8e9,6fdd0250,d7373b15,83918a6), -S(4d3b878d,ac7d1878,a2cb8ef1,29c488f,59f26f1c,d56d5476,7b008e47,eb7a293,ea8ade6,a46ce8f9,4602d631,e0147981,3422eb50,e87cddd6,792a1ee6,2c338f40), -S(2bef9f5c,accfea49,697aac36,24c7db8a,62f03620,109f1cce,fc46af89,25489a69,b39a88a0,d7d59b29,b7773984,53e6eb2f,7b557171,20de3625,a917853a,ed1f8d83), -S(74a0d8dc,415a228f,3bfa9533,e7d4e544,f03551c4,d55b0d2f,fd524d17,835c3132,d3c7c720,c44b1742,49c2d9ad,3e9c5f9c,eb174ba1,bcecab7b,5816cba9,9057b5c3), -S(33b23068,27e030cf,f0673254,ee13b94e,6d7377d5,fb8c9a83,ed50e9eb,4ac6d5f3,b0116426,ca9fc25c,a4f9834d,6d8974da,1571a54e,1f507696,879ecac2,5f23b095), -S(a45a4cb8,24d90134,5ea541f0,6896387a,12711d70,6f07a850,69478780,2e49a474,bb236a74,96161e43,f708abb8,80e3d0a7,a6354a33,cb760bcc,593bc8c8,7c8f433), -S(fba31e01,2f38c223,3750fb25,85c2c33,4fe3afb0,36b17fed,5e8d513d,552dc2b7,d6d8f5c2,745b2c90,d5c201f5,524f2b0d,49020ae2,4eca8e21,b95cebdf,af25e5c6), -S(8a5bf15f,e026e897,190ee896,f79927a8,a8658d05,f9a0f6a6,79ac8971,4ca26fbb,639849f2,41d99df9,d217d702,4e6c5bf2,9e44b7ad,63e0b091,bd235d45,4cb07ebc), -S(43daf5b8,4f1706fa,cdbfab46,e4ee5188,b8697efe,f6d1274a,77af6bf7,b1ae23f7,d2fae1e8,721553b7,e63130aa,76f61e96,a34e60bc,fe7bdb8d,6879a39e,db08d8a0)}, -{S(5b27aec1,c644f0a9,ba7f6486,9a960ea6,28343ab,da3feab2,4a2d6add,754866a2,3d1f365c,2aee6c1e,ab2f1879,429b6275,5d1bac85,2998ef25,8a914bfc,ca280b43), -S(472e2d82,220169b4,e249b18b,ee3d0188,70b91ff8,77fa9f64,9a23ca43,a5aa9271,908226fc,2704e162,c96297f7,6af76d80,32b7845e,9b998466,cd106e37,1a61feb1), -S(e9d0d14b,3cdd4531,f8125e83,dc3ddfda,18d64976,bb4521ae,83a9d9aa,8609b431,e1f950aa,821f586a,91988d6e,e3ca4db1,1574041d,140c64,2ba9a1ad,cd1c52ea), -S(e47190c1,f5fa4910,6160e301,69e8a087,76a9e996,aebef7d8,2b1d7248,7d38ac4d,50abab42,dea32fa5,af0d65cb,3dd950f1,d2e54bda,47d990ee,9fd9cf49,cc552d1b), -S(dd7cc010,b8c93c99,84c19b2,37aa2b6f,1e51c765,7b93bb9e,e4d0ea60,2d6dae8b,9f2773e8,15aa182d,f6ee5e70,8af9e8cc,6ed5f82b,994633b5,545ff889,c5503e5e), -S(6e4656b5,aa8f321d,80a46a7e,721ab22d,f5216f9b,602aa74a,84de050b,a3851d8d,170a272e,f646cd5b,e3c1d9d,14e19601,2f7b140a,136b509e,580c4800,7c0fa08), -S(d0cccf87,813d74c1,e0ef5315,2a2e82a8,9d6729bb,23c8f450,d1e5af64,4b7f6341,b5c903e9,dc51b73b,5cfaed20,b9986f80,b19aed65,d11e624c,53162315,2ab2cb5e), -S(87f7d90e,8f519af2,34262929,c4801bdb,fe472f0e,3eb746a0,cfdde906,1697a540,36b97cec,b6a1766d,b349034e,a980f0d3,cc653b,5ae732f3,e9868d37,1343db0f), -S(feacbc45,43a59a7a,3fe37bdf,5f05885a,a38cc3ae,68e423d9,e90da9df,15569f45,f1aaa0e4,230faf54,c1a394c4,fab80639,184d42bd,62fe74fa,d2b9d8de,2bd13779), -S(db4aad1a,7d5b51f4,be47fe0a,d8b14711,e03e0283,3076470e,7291f310,bb88b65,51b5928e,9e6adc38,be8e5e7f,a93336ea,4ae1f65d,de69b73c,62e04384,fcca96d2), -S(f6a6bd4d,3f763afc,721fd2d9,ed42d34f,df38bc9,4fec069a,8f8aeb76,8b23f74b,d513f993,f97d6fcc,9a7fcd74,458dc00,437fb611,b7e09b9e,a9e85c93,1facecb7), -S(982457c5,6c22522d,e0d10fa0,64a0f8e1,52fe9924,6f20a794,81df8fac,8fc08ab7,2e080dde,a66a3e43,af44f9ee,bbb9962f,16110b33,b0e9d83e,38333aaf,89be29c6), -S(2cd27cb8,d3646f0d,a549cf0e,94e70cbd,c40082df,b4a04456,47579397,e3e12d91,c17377cb,e2ab57d1,1d6c5cbd,c5fef865,440dd8eb,cb5cec53,124872dc,a49409e1), -S(6f34f416,2a190923,8a2b5561,54a056e4,9549d6f1,72929ab4,fb49175,b7da0cb1,2a0ff98f,98422e19,e394f868,7f2eb9d6,dbf7129c,c98df378,31895799,445a5211), -S(3190285d,d898dd64,770729cf,25f59339,eee3971f,16b08450,a87c9916,efb1adca,5423d919,1eb4bf71,fa55c153,161ec8a0,6f5930bc,17ad25f9,39f229d9,8af5382d), -S(3a150c48,d4c56e7e,9d910864,29b43219,9c95881a,d481e0d1,59aaee93,b19ceb72,290d1c34,f241d3b4,f7bcd618,f585578e,7d17a89b,9be52eea,41020f37,e1f521f2)}, -{S(53512a21,4a659914,82cc157f,da02880f,7c4ff9e6,47a93136,c1e55725,9ce7132f,3ccac75b,13cc40fa,5ab2e017,80f55f2e,b8e6a7e7,22b2e6b1,13a28316,b3c99d3), -S(941512ff,9ddbed5,13d60b50,1f3425e5,d210fab7,f30b2ffd,db6bb10d,b102cfa4,ce038b23,257413b9,f3bb957e,43b25747,49fdb5c7,a975667c,72de28a4,46cf4572), -S(cc2210ec,ee7d9560,753ef5c9,1ff9590,230ea13d,8416d73e,47332720,ecc63f9e,cc800501,dadde2a4,152ff67f,9d430ed8,3ae15e7a,e5bb493f,95d41167,327eea9e), -S(384629d5,414c9230,60077a1d,e52fb3ee,ed883b32,46d6f21f,e18285c9,2b1562ab,9aa889f0,f0bb4632,7ff7ffab,beb7eb30,d8730560,edc85521,425d7f6b,372b2272), -S(1ff9dac3,a65aafa9,8693a45,3ac3ee51,915cf4ea,1651a456,b1a03aa0,250e9d97,9245a361,a7831503,be192d77,2f592cb1,f9129287,9ccfc15f,494eb437,9edafcbb), -S(448f1c1,db9f6274,e49511a6,26ad249,e2c0b808,1939a383,609bdabc,dd94ade5,6c142261,2a8a6cf4,1d4bf7ac,8e6e7c87,2dc33b72,a87ef595,e9e0ba72,c68fecb7), -S(c6b5006e,8fabf0c,d3e72c2b,45368021,b6e53820,59fcbca0,3da03181,b72e6eb7,c579f919,cb4bb266,a527a446,80dc9300,629ac1b7,4a5ed005,f5c455ee,bfd5aea7), -S(f4d156ae,da9f6e55,f455080d,35fc507a,bcd2b23f,de6d893b,5ba039db,27493953,7d45e992,a2d4b8cc,41c2849c,34e785b4,8fdb39c2,e715328e,9f7690a7,31bb5e66), -S(bd72705e,9d2a78f5,6d39be16,b1aae55,da527752,c3ada8ad,3f715d37,7e3784e4,5b5f856,7559fc2d,b7088120,9e71be70,db2a4404,e9076084,7f4d7bd4,e2aeb3c7), -S(9c6bce85,191030ff,c60b2b07,c8187f79,249fc982,47508c9f,2797da3,c21c06fb,dd7be1e8,86931a24,925e899b,347a81cd,85eb17bc,b73f9cae,1097935b,462d0937), -S(1a357743,84feeda0,405e9e16,28657462,218f4b2a,7921ed05,dccabcc6,6fe5aeb9,8e44029f,7b28b880,9640e5c6,60131513,e283ef66,983770ce,686aa706,81b1aaa4), -S(d1908dd7,f1b5eaa2,a1f9f066,683db7,b3ce644f,77a839f1,488c90a1,e372f18f,a221de7c,15bf27f4,ff71f3ee,fb068463,79d09aa,3b6e8b82,bbe9eac6,8c00738), -S(b7be7d12,1e964dda,820fb389,2f9e99aa,36e8dc2e,7498ea80,34af4397,ffb82b91,88813b9e,c333a6c4,78b627fa,afe0a657,dcf449ce,3a5adaa5,662a81b0,68b8f5ea), -S(6a66cc8d,27ad7843,ea1a9b74,373e413a,1b3b23a5,fd25a58d,6b75a231,b97538e7,afb5aa7f,f3cbdd2c,a4dc9694,e56141d1,85550285,8dd6c89c,7938be2c,a2856c4), -S(2b1e7d33,b7d1ff91,ac03cd10,f3756e9a,d39d358f,2f63c2fc,e89df693,5e16d3e,d42588b3,d1b1fdee,b860b4aa,d0ded901,bae1bb87,681fc257,e843ab8a,76280692), -S(f7745d72,7b747b4,e9d6e7c7,1242705d,140ed4c4,d43d28cf,a0a8afc5,37ac932c,f640180b,6b8b0eb,c94c8931,2f897e5d,1ecf427d,7c86d2d0,772ed63d,f4cc3444)}, -{S(534e9d8,bea140bb,4970b516,c42f2677,dc413f42,9b7c56de,e261f60d,ec68f9d8,e55aff90,1098b0a9,ea377acd,b62dc479,da109514,2654107a,28c68e9f,73b1cba), -S(f0e363fc,4c8761ad,bf4245e2,b151a7d4,335c9856,bdb9fb2c,1e53fc76,28a9a69b,4629a699,3f8753b8,6d2190f6,505e009f,6fe56739,9dc77507,a1cd4cb8,920b0ced), -S(a28116fc,5e3541e8,8ffe043,160a97ca,b1d6e898,b6a3acf4,d150860e,5bb6a1c2,e43aec5d,22795bcf,7979e260,de7da3fc,46023dfe,8db4851c,165a2fb3,47c204e8), -S(cf6eca04,328af9f8,e461b6e8,9251f94b,3156a63b,d440d6c2,b6dee5c8,7ead5b29,1dcf90f5,9bcd5c0f,362de1f6,1b7a93d0,6ab64659,7f77bf94,b8bed972,9f096f2d), -S(44bcd74b,2cdc4b13,f48e3cbf,b005bf74,bd114fe0,5c2661ad,46642f8,7e952fd3,8873b17b,67848110,fd200c6c,bba0782,34dadccd,70dd83bd,cafbca31,df373440), -S(2dd5eaba,e7cbff44,d2e56df0,14fe3577,efbe6df3,57b870ca,fcf5bfa3,78d35cf3,6922806a,4ed044eb,d711f510,e7c5c846,ce892189,ba4479d3,7ee95a8a,11983756), -S(98294f63,5eac3fdf,f8e07f53,d24e650f,2e470b0,6be9193f,1463f1ba,c37bcf5d,6a03ece,4f397658,f232bde5,71f33a4b,a8058641,e301c99f,e1df978c,74236a47), -S(c68b7c67,36003c06,d29ed03b,2faedf60,5ef705f0,f1172166,b63bdcc5,437bcf0f,a62dfd76,c1df5d72,680eaf7d,51359a63,82ce005d,fac432e0,672f63cb,cc4367aa), -S(10da4eb6,72c088be,d2d4a28e,3e48efb5,f4a456be,b501183a,816615cc,f23b598a,ab798e69,26e55eb,c0435828,a8006356,5cc6ea48,892f748a,a6ed1685,36a3bec7), -S(24363000,a821cc76,4bb2c552,3c37457,9462263e,df791598,cf7ab8f0,89178ea1,c6d07d19,d53ffbdd,f367f46a,6fffd5ac,e2236f63,26fb18cb,3a7d543b,9f193b01), -S(459ff583,3501bc72,13c135c9,be63ef4b,fe99b731,917dd475,b356fd72,21705c8d,9c3ef5e7,4483e1a7,42316df0,9f313a10,17858e7f,ef432763,df139b4c,548aa325), -S(43e3d2c8,44b6ec8b,b5ffc06b,d2a48ad4,39893fc6,a9748cce,e55adc76,d616b503,62efde43,b6525e9d,6de6a7f9,8831e194,9296aeb,7ffe715b,4a064166,c18144f2), -S(8d6eb1ec,5abe1d6,2ecf6a0c,e1283a22,e1259cd9,4ae96c8b,1fa03521,8439f798,9b7e03f,f50082eb,38098a19,c417c4b2,74432e47,79faa37a,2ed5e43f,daaed45), -S(fbaf2899,4a9ebe2f,cbd854ca,d1beddc6,7ea94f73,321f3006,7d75b327,bf25b65f,184a40f0,777c4a8c,6614f8a4,d5ffd514,3215c0ea,9caef82d,c20285e0,4477cd77), -S(c58395d4,623cf0cf,8c7b0abf,686f71f8,6c0b1977,44ddd642,7a1c05f0,1e9f938d,1d8eef66,7d5b8ecd,af794b8f,2bd30b17,966de31d,83ba46e9,73fb4a2b,914b06bd), -S(40c74e1f,f01ae64d,85f958de,6d1faf97,6169b00f,aef64c9f,23c5cdba,5e17d294,b21a6ec2,1b409a69,f8f6987c,1b1705f2,47781843,73ae5695,14b46951,48448e6e)}, -{S(dd7503a2,a3e15e7,39eb9b1f,856d6e33,be4890b2,f40cfea8,1bdf516c,b942731,ca9cd04e,c3789ab4,5088b819,953e08a0,b8adb8b,b2b6f7c8,661a2d3b,83a54c77), -S(a1df11b5,743dccf0,90fba9af,bc699089,bc923e16,96a7841e,5dd338dc,a8aea428,49a697c0,45f6232c,d0d7d5d9,c7e33701,758e6a12,9a9a50d1,f173beb4,5b9b601a), -S(fd7b2a1f,cce0c2de,e11c9f85,c245f43,1b9aed6f,a542d401,4677236f,4381b927,77bc8fa0,5639307c,463fd419,a784dcdd,be1bed1b,be42c315,dcbf9d24,a5c7dc1b), -S(7962833,c1cad761,fc1ecf60,62ab6f9b,b11cf765,2c5c2aa9,e4db18c0,544ec275,7a8bb3e8,209f1876,d3452f6f,40c3cab9,f7166dca,160e0f51,afc35302,75740cc1), -S(bc8ea787,2f386ed9,24197d6f,cde66dad,43b1bc,390ea517,ade69780,beaf444c,12f31c87,9b69c7a3,bed748db,6c0dc465,3a0c1cfa,e4cc7b97,c00abbef,1b86fdeb), -S(eb4a5a9,5957f070,73fd04fb,4f1d9403,ade11ac6,62f2db35,23a3c16e,4a34c040,277d8694,e598912d,7b1266f0,493d9141,febe0f46,bb69eb24,c8be701d,9e8c6f74), -S(391bb04b,b3b924d4,bc548329,64368cbd,7cbc1a79,c3410cf6,63565b9e,e62c5d44,951554f5,fc6b8ff6,40a0aa39,39929e9,41db1056,d05bf87b,ded15a32,f06197f0), -S(4b6a608d,baa71d6a,e20f543,f4a5041c,a06ab5a8,cfe0b331,6a6702b8,46212ea1,f3c31e22,bb3a2f28,bf1f0594,4f798603,107cb301,6bca7ea,a8b863b,5f85954e), -S(a560f348,ba8b5a1e,885158c2,a4e94464,1bbc59f,3fbf4851,3216f4a6,cfbdf8ae,98568f29,eccead17,257e558b,b3835772,5af94f69,42b943a4,36a95824,b92c529), -S(2356a93f,c5cd70f5,f5fde88e,6744efe3,d0d713f0,31f228a5,1cbe2c3a,4baf7107,59adb751,7111910f,9e1a690,139b10d6,f30c311a,4ab6b82e,d1ba7077,3a4994eb), -S(f7fefa64,ad63903e,66705d88,d5df718f,59b7e9e1,f9180d21,647b2a73,6e2f1d6,30b5d8fe,5393f9f3,b68dde98,1adfc77c,cb3953f6,7fbb3445,52fafe72,b9453532), -S(73d5d8d0,95d6c533,60914bcf,5b279c5f,f20145e4,e0ba1ee9,468c2edc,b59ee4e9,56df32f6,dad0b462,487d2b25,79dc14d8,34ef8705,d5efa77f,1f371bb7,641ff145), -S(a1d772f9,4377b24,c98933e8,47dcb51f,7a982940,d205e4e3,c31c2cad,9b90e410,617a72d2,ea1b82b5,775f13fa,1086eb6,2827572f,f6182101,3cfe60d2,7df6aadf), -S(28725dfa,ad66c6af,5f980f25,653ea5d5,116fcc37,be615037,48d71033,ffd322c0,67f3cd88,1ba30b09,3bbc1a25,34826f06,90b149e3,964e313d,e3706f60,31dd6c0a), -S(38573246,ddba2c47,a9d85ac8,c3a13ec8,4133da2a,cf6434ed,98acf5a6,84d89ba,e97fde8e,6b2c1395,a9f242a6,8fa989c9,5dabd2f2,ab830949,4c100a1e,fab317cb), -S(e69ebcca,426dc9cb,474c5f03,5b6e6245,cb18fad5,2d990ad9,6d29ea8b,e032c220,322ac73b,d7c6a5b,89f3926b,82578f6e,a6fc83de,a11da204,e15bad7b,51ab70a7)}, -{S(c8116b60,1f8d72c6,24957215,46b844f6,bf6bae0b,7575a77,f1f6c6c2,5524fa2b,b7477ca6,de2004df,34882c65,3a46821b,53372f13,ed822cbf,40c20bd9,ddd1d6bd), -S(db0d3761,c6b76d0f,4b3f6423,daa1acef,19d01f9d,c6230840,c4ef120,9e4f80e7,2ea359b1,f19e5d6c,e8360c04,12ca60b7,a43939ca,36fc873a,7a80a884,90d3d359), -S(a4539230,a9c0b4ff,65e2a8e6,47490c1e,752706bc,ece59a96,f2581cab,1b430bf2,9c80b433,f87ca7b0,3662b22d,73a99e91,a8c63fa4,9fd3b8b1,b17d669d,aaa9604), -S(a77cbd99,8019c652,7ad38d8,f8be3ce2,dfaeda98,d378cc3b,7f86e291,15a56adf,3d5ef26b,d797de9,6f8a0d9e,d14a5209,ffe8964d,2bb768ce,bc0c3422,85eacf77), -S(2b99d5fa,a416b572,c796d92a,ba9ad7d4,5b020fae,95aee14d,f114489d,cdbff30,4b89c70a,74e07b43,cbf503d8,86954759,9c3862ca,32bf168e,20a913c7,4fdfd266), -S(a007a8e7,a60dd06,6d11f1e7,4912eb12,91908cd9,a3fe6a8f,53393040,f9c6fa52,24b8c6a0,6160c947,61645355,ea365434,323c1d9b,2858f650,5526497b,d148873), -S(7f3f4e9,24fba80b,702f3252,64186077,2879a2e0,cf86c721,cb97c5a,cc1403f0,fa6c055a,4eaa3651,3746385e,c69170f,f3a1ce56,d9c06440,e49bca94,e97220db), -S(70f9b6fb,c3c4a20e,69c75791,2289936,4da614a4,dd49002b,291767cc,304309d0,5becf8f7,3c414163,6aecfb98,161da5a1,ddb08885,545d946e,c4f2f39d,66b15165), -S(ffd34a18,cb7a72a9,19b97602,2110dd29,484b3fbe,84ee3c9,46b370,f710d86c,b03c2cf3,84b6502e,f519c55,b40f0037,cab3e513,2304243b,f8e7117,cb4d4bdf), -S(ef8bb54c,c1fb8d0d,7be9f5c6,85dcc465,9ce9d874,bb1f860d,60bd0954,d751cf7a,79216699,1efe79ee,bd5232c,687af3ee,854c85f0,cc61888e,c2981689,b03060fb), -S(d1cb47ca,c6b4609b,3e7e8f00,76519a77,9d8f4494,baada6bb,43d3a034,5c3e93b5,a8bfd148,a40922ce,1a2a3383,ce323c5,32041c5b,f89917d8,41c79867,d6efdf49), -S(ed2c9d96,38443a38,9a00241e,ce1edea5,4ba0561d,a084d166,9054b486,89bcaf5c,f81239d9,ad7a2fe4,5a9ba8da,9aa306c0,3d22d79c,c80f7953,53c13a90,c81d0505), -S(d7174d31,4126e219,817fa00d,140990dd,43cbebb6,81c45d9f,c5e0dead,d8135ef1,38093e9a,ba7a7223,6a5e8a8,6ad4ee9a,a5cbd614,da2543ea,34021578,8938fcdc), -S(41dbba9a,b52c3f9,98ecc1cd,aea6a093,ce702077,8e5ac6a8,91be5bb5,f73cb8,5ef35b31,829851df,7c3a2304,5777b6e6,89e79e3a,a06c7b73,f3bd47dc,fff8dc99), -S(f9ab0480,d24efbbc,26f1d2f,f09db463,f3d50993,af39d822,85efa32,97c73b6c,40a5a11c,c647b069,4536d4c,e154a58a,db0cbaef,77b24591,bb39020b,ff9c72ee), -S(e59e905e,fe97f343,7bc6ef6f,b8e06ed4,1eeb5666,c3bf72f8,5fcd3fe6,d0f68928,28faea3,4fd42596,c3880cf2,74987c2f,2f228442,5666ebdb,e357d9f5,e8886c4c)}, -{S(e7ff8d5c,83bd5846,5c967b5,37ac0f36,b9ffe9d2,fc7531e,ef183cb1,7369c066,9a9c3c4b,e482031b,f6dc69fa,843ea90e,de165479,26ba201b,5f05b00a,dbcc30a8), -S(92932066,93f2280,8bc088eb,8b50cf83,93c0a33f,5149976d,27b837b1,2e769b6a,7d86f6a,418b04f5,2d01b933,428d1ec3,ce62d349,693d267f,48cb005b,1499aa0d), -S(10e4d4cc,b8efba85,37dcb831,c6badf34,85a3184d,b571fa59,55e3ed98,80fa8e63,270a80d8,ed085ced,f4dcac74,481a75b0,b42775bd,9a844a9e,e2de9be3,92781c96), -S(763ae8ea,212d756,ec3e6a55,9ea9575f,ee67ca83,9e61e61a,99315231,304eb9e8,4e1d3eb9,d1a49677,6d1619af,8acc9b35,c6135fd6,bf82845,5eb55a73,6137d0c0), -S(76ff82ef,27ad0b4c,157d0b24,d89aaed3,ea654fb5,e0492304,ab02b214,81eb7574,701384fe,e57f56cf,62930a9a,e1b5977,8071d8c1,c07746e1,b1b6e94b,1cece9e0), -S(fca9c2e,b84ac3d7,7a32396f,a0a1763f,7483aef7,2b171608,e34bf24f,2c0e3ba5,8678a539,d5b12652,78f2feff,bac321a4,ce2acaa3,d0983d29,27e9e90,1d46dede), -S(a75ffbd9,4ccc3e8c,93a54e06,e4b5fb2f,4410db28,b980283a,51ce071e,83572733,b0151288,ec977854,aaff4ae1,18b65289,ef356df5,1beabbd5,77054a42,da145fb9), -S(178095a7,416460bc,c42fd250,472e6d1e,3db37a73,5bdc0012,e52c4ca8,cf65d4bd,b9c37e8c,a7cce01c,9adeadd5,15759ece,60776e72,992b7c9a,c23b24a1,adde790c), -S(8969a958,1ebfb858,cac5b7f4,88c56e0a,966947d1,adaae934,6db4041f,4f8823a1,5c1ce169,fa336433,1aa72a02,e543cf69,9ebdbfae,2cc00ec0,f83d6f09,8e78fe3d), -S(a7e28d50,eb9a52e9,e18edd59,6b291fce,7024e915,e7ab8119,2cf4642f,7c54d8a8,e35bb3fb,d67ec191,b3a752f0,58428c1e,a92c2c8b,7e84223,363b15ce,28435dbf), -S(7a6542c5,2560ba89,ece8a01d,e9c9acb,e534ea36,48186e75,3bd214d4,cc8826b9,eb9a65b5,e5d3cfef,50f0876c,c9277014,af67ef01,b21fe8f7,13aa8661,f6be4c9d), -S(459ff50,f27af905,a415ed85,26564031,8e3a8b5f,11aa25b8,b0c27cbe,83448bf1,4d86fd56,e083330b,9053b2fc,88cf532d,7672912b,db7c2429,34c8be24,40be22a7), -S(e28b9feb,67173d65,78a8e38d,fdfa8a8,e71bb840,b1d97046,456a7aba,b1bdb4ae,9c8712b5,d2d7e596,d42e088b,801cf20b,7f6dba46,8438032b,c4b25d4,dfc5daf3), -S(3c313413,6261f337,e5b2b81a,6641acf3,4458c82b,524b88ab,844387a8,6acde303,c1948e72,3e2481f5,f0898fed,9c1def3f,8f88f0f1,b58cbc9c,69992a09,4fdf128e), -S(77774800,3a50c6fe,65a5772d,1e01b8be,d8acdfa7,da1cc233,ebe2620d,11b570cf,96522ec4,23bd6dbf,45969c79,15494f6f,bc4a41f8,b99dd400,b7f9b59b,8b45e279), -S(f491ac54,4678dc86,5ce81d7,60465bb3,791c9c38,a7f98016,3de914ab,4f488f23,9e62efde,f5eee54a,ab244604,a3357af2,729e8252,a04f006b,f0d61d7f,5f13437)}, -{S(d8f08d18,ece61855,5b06a3b5,ac8e7cf,a6375446,cbc7c8db,ad924f78,69e7f00e,46a91d23,910957eb,db830624,73839954,2cea0570,2f67a09d,d7d19217,646606e), -S(b1238187,25e216c6,631d4b98,d8d3c743,753529f2,8e02bf80,d1e9119a,f92d8b50,487f7171,60b8993f,a90edd77,3f7c1026,b5961881,895ad804,51b66d8b,d300e0f5), -S(b2ff5766,4b8079c6,3c5651d,e0b2fd47,80d1a18c,60d78c24,b2c57809,9429a552,c7ad3672,6d7e0618,eb506d65,c055a7ff,cba848f4,9b69dcc9,c02a85d1,5dd8ef90), -S(901272b2,bbabc0b6,12dba006,1d4e8ffb,e177c070,43f6ec6,2b437bff,9970685c,ad7c1fae,4b80cd30,c45516ca,e3433e8a,2d3272a5,79e4335c,22e452a1,845326a5), -S(1d5740ed,37452eb5,c645f8e3,cbc4969e,a6f419a,fc0e4662,8b017587,a6871ad0,c7a6436e,b66d164a,685a1b96,3387519f,b4179d38,40f2be68,28c9cd1f,8780bb86), -S(21f0eead,ca362d40,1abae7b9,2edccf19,70bd8c0c,35ffdc2,76820d7c,478ef1d5,d3073714,5d577587,db806eee,b9dc40ee,191f4b68,1c488f64,fee83a32,d1034ef6), -S(bebf44e,4cdbb310,16e0e43f,b183ebd7,263515cc,489fbce1,90cc104b,55225481,f7ace0d5,3dcdb783,e10513cf,2e6c5c63,c60efb67,fa0bc316,de0e571f,d399f519), -S(78f6920,e94f8d53,3dbcd31d,aaec5e94,76919efc,ddff1eea,4e79e1b4,3dfeb4f9,5696bc3c,c8dfd0c,490250c6,4263da19,36454cae,88f653c4,2f9004af,10eba182), -S(4a2d9099,949f854a,e13ef6d8,a0179957,a47fe355,92ed0ab5,b22994da,3e616e20,c922bf45,8feafa64,66e31c20,d99584b6,ab390f2e,5b97009b,5254d229,d2ea57e3), -S(762eb751,35672a8c,26fac373,af7c7396,70b8c0f3,336bc099,aa1f02a,7e804df1,edfa83d0,6cec4971,6cf3d1e7,fd2fcf3b,7e2143ff,8e67a5fa,c24f14da,b3ee01a2), -S(fa4621,897c70c6,8b62619f,c040d058,cc68275f,91b4efb7,b4f902ab,3059b822,8c1c575d,d6066045,9aa7908d,2246e846,103d887d,3b7549fc,b4ab9f6e,e1181a55), -S(6a61b260,3d77f92a,c4df3f3d,30000179,e6f0fa59,a6570233,1ccd0dad,6a146ed0,416c09fe,711b40d3,92723f10,688fbd1f,e30131ec,e8a0a547,9acaa8b2,ae8e335a), -S(8a80bd6d,316dbad9,41c345a2,6f3f7ed1,738934d3,f00efd65,edc54fbe,9d38d48e,82bf1bc2,468b4ffe,11561406,2a2f9ab4,71d40e72,a2f1a40c,8c573013,5a86228), -S(174daec7,77872ecf,46832a7a,ce3c1d5f,47304048,c9cf1248,124c2eca,3438a110,be42dc6f,b61964ad,59083c98,e459ea4,db3298f2,ea8c8379,be76859b,958b6f3c), -S(e11397da,68e78b89,c8f30102,f779e014,f572f9b3,a5d33ccc,b74c2234,ba9d294c,bff23953,fd62c1de,a4dcf767,924e5448,e6529bd3,85a1acdc,3efc0e8d,864fb9cc), -S(9f883f,27e68e8b,201d6ad5,28a04a8a,fce8b706,a4d6f2e4,5d07c4ab,8b0dd96f,965ecfd,1563f640,97f42529,305be630,12f9edcc,82ab67ac,9bee6979,b91ad5f3)}, -{S(ca3c008e,cf9efd5f,75cc1035,f9edaa7c,46b17d25,9895b0e3,b3523b6e,eee9daaf,a676aea9,3ce9bb,128ffc34,deb96b0f,72179d28,77406d04,6d0c8b5c,3572f4d2), -S(59d2d70a,2e90a652,54e06ceb,3793db1b,a78e9b4d,e043a3d,c5773b9e,4c200ea1,80d83c03,5aa47ae,956ded05,cab59b97,4f25c32d,9d6aeca1,32603249,b6d360b3), -S(4d9ba25,f51de6ac,3b63b60f,576354a3,40d89e09,51af3e9f,8d8eba83,c00160e0,218deea,f7a87a13,f7ca36ff,b4f85923,30ed0337,2665c688,e3632048,97dfdcb3), -S(41093dc4,cd6c91ff,67df50f,11031e3c,56d8e078,961e74f3,bf01b010,564e732b,b836ff47,2e29fdb9,c75a4a68,a3277d9d,d4568f0e,43333765,a7246fc1,69d6c074), -S(8a37aecf,7a111e82,21bd8aa4,756974e,adbfc33c,9bd6268b,247270e2,642c8abe,6a9cf7f,d48bd71f,d7f2dbf2,1564737a,2acff559,9aa3da27,925b6140,3e940bfd), -S(7b893836,b2777ef4,2e4a2add,c50bfe33,37f7c75b,f0acdb03,1829e372,129aa8b1,31b64a8e,fe772afc,eb8f631f,b3a4b39,39ca4a47,859a0fc8,59165c5e,d8fc0331), -S(2f493e24,6425e2b0,fa036211,5352d455,8357a2d5,b838ad4,232cf6e4,e4b7dc85,9cc11b9b,5c3a4da1,fdb1a119,aa5a546,47cf86f6,b5bea9f2,a9b6814d,6158fc63), -S(5622f09f,c50ac0eb,2a1fffc6,76604755,9d3a5046,54956aaa,640515e7,91000316,33e375db,350fc408,fff91c09,fd6ec673,4c12f5e4,46348864,b0586d8f,fd1205df), -S(fbe24d9d,29eead5b,72952323,df6e8b87,322d570c,37dd2191,690e9119,8a5b65c9,ca77d605,fa1c71bb,acc38061,f4b04768,e93ccbfd,dd626796,debaf531,6c17e89e), -S(1c324df0,4c5d8f9a,7cf6980f,7239d5dc,94f49053,5ef06925,6341ad0e,5099baaf,97611701,e282fde9,9263c30b,9439c244,b0fc4844,a61c905b,fc03d98,f81d025a), -S(f40508e2,4252b801,f4b34d4e,2941673f,be39a018,2d9e6b4a,e0fe3052,da22d16a,5477f0f3,f55f1571,8e070280,f3e5cc80,af79dc14,9954c40a,8c1aa63c,f1b52686), -S(fcd09f44,ebf12a38,8f12f1ac,1bcb6856,217030a,903dde22,5dd25986,2ada9b71,7d5fc263,6dec7d82,167f40a1,cf00cf9a,fb82a10c,a293c64e,8ff4b616,1f9f9d9a), -S(666675cc,1d4084e5,f4ac65ee,71fef1ea,66fb7b1b,f348d980,b11f711b,fbfa2517,93f65e6d,4038c57c,3e04a0ab,b3b1a45,4050098a,7199635a,ce8c8617,e14c6870), -S(8bacd663,9b1d1f4c,2038c96f,bfabb232,87aa6574,13b3b0ee,5aaac2cd,b8d629fc,50aef7a4,fdbf85bc,e0876914,ed1692f7,7f8854ea,a07022c0,46fe359c,e87284a8), -S(efa17098,da4d08cc,f879897b,ca2b4e3f,e19f1668,4428ae3,94a37f37,cb678d10,c43b0e05,584ee017,80956297,1c7602c8,3784c807,a88b6c51,7f25105e,d16596ae), -S(6c8eb955,497f33f,a1c0f1a9,a4f5017f,3f2613c3,3ab944b3,abee9171,d35f582,9e647007,dd811c9,bc1b907c,e1cc70a4,ae07722d,4dff6f06,d77f5937,9250d8)}, -{S(8a4e9691,3533875d,b8559500,65c90785,a78233ac,ef24113c,f6ed543a,e6a40024,57d9444,8d091df9,602e6c7f,c3f88934,d45a7c76,18da574b,4d4c15a6,6925bcf4), -S(d25026c,edd7663,2a256452,c6585ec2,e8c475f6,247f621c,c4438bde,b4a49ca3,4f8ab8c9,bf340f6d,c38a4830,3e114ac7,9406baaf,583533c3,bf6cc0d3,b529ed36), -S(7bb1335a,3340e2d2,ed2e88b0,5daf002e,6a903241,e142f9d4,e48d585c,a9cff8d3,eb65860e,c2a34d44,1f1677e3,f3cb2bb3,9d0761ee,200dcaac,68f683f8,7066bdc4), -S(809ab901,4a3ca64f,7dac499d,fbe84b51,6566f9b7,f504fd24,681fb9b0,be3a54a7,326d607f,e41037f1,bc1a4d56,4db58169,c637e902,99d52c37,d625862d,faeee076), -S(1fe79a30,e681a701,9c437773,1c99f7ad,b4b6a52e,289baf55,e67bc468,3a20b65f,b4843af,94698c22,ee928995,61418205,a745912f,3b0b11b8,b3a3cf5a,3008aa6d), -S(fb9ae54c,b674e5e9,ccb900f5,53d9cc06,949a6eb,76bcb6d,e7c8cf34,a6352936,3d2ecabc,841d29b0,b81ea46a,7b061c92,103c6036,5e9ce032,286243cb,91000b69), -S(d93164cf,ff3d386c,7d340da2,31479b7b,5167472d,a111e9bc,287be7e0,bbc06ceb,563ac770,b23ac56c,ba093d88,17e1a8a,47c9b607,eb773284,1c8b0c6d,f9cd9a9e), -S(3bc57534,178dcfb7,b80906b3,9db964,7e989039,1e13c2c9,f82d7b63,2a1b3367,5eb2254f,f7547cdd,745ca32f,e3ac49dc,2dadd808,558b7905,71a46132,d0293e09), -S(69c24add,b825c48a,ab10d0d8,36d2f4ff,79535742,f07bcff5,cfd568a2,ce28c8e4,a0465fd2,fd1f7924,e60a96f,472059e2,4df02324,7bc79e7,11f64d8d,a477dc06), -S(76d9304f,8dcde85e,9a331a6a,bc066d5b,72ce9fc3,a3e65614,37c376de,f6aea72c,6a31a164,af370f6d,2ba9729,fd2a7e5f,69d62729,bcecf340,48feb388,541e40d8), -S(f45517e4,13d15400,29e1bf03,aecbeded,9da08531,65a38956,79ca08ef,8d7c8011,7cb4b383,62f330f2,bc54d555,db060911,d7a0383,eda89b65,913cac4d,4098a1d1), -S(2e3b0113,818930dc,f9e6d0cb,d59032b5,e0aa1da8,1cd95f3c,1dfc8520,51135a12,22f9bbbc,e023e03b,d00f1c73,d2aeb9d6,96de61fa,47f5f6fa,31a5f269,b4029c5e), -S(11c85357,5073bac2,51a5f7e1,41aef0b2,8fa240fc,e8045f2a,e6fbe0b1,cf99d9da,ee8a317f,78545477,732e325b,4695f5de,b3bde843,11fb7fde,1a0e1cab,d8bc1c16), -S(f3cef221,8bfdda19,99885c8d,ee2e16a8,b53921e4,6045de20,94775856,9f2c84d8,a95ecfc8,e058dbe2,d57144ad,e65ac41b,b27cf4f,83150b13,f7f80878,81b98480), -S(b537bcd3,3bb129b1,db277096,afa2f42d,d63662cf,849a5c0e,f7438443,fd8d0e4c,76cf0b80,461e8984,bba8d8bb,f926ad96,6a7e9684,f09e4fbd,45657e65,d45ab69c), -S(4ca9dcbd,fc4ccc48,62c1b2ea,cb624698,40c3a0b3,95bbf084,9dfcc410,b89c3718,be50d6f0,845daab8,cb857c24,fa995624,dbf8c938,dbd982a4,85e66d4b,1db2c765)}, -{S(458f8dbf,9cef8cbc,5d2046c7,42ca6297,e8fc76a,ad22fd3,af4f9a8e,2173d857,57074c8f,14a36b5f,6924517,6e3dc7b6,4d12a08d,8d00565,e70e0ca1,56f29820), -S(d4e74c10,91365cde,4cf5168f,f4f523a4,1fe85d27,d50d2b8,76218259,10c3d5a2,ed9fd256,43ca55e9,53a209e7,5fd7e965,7706855f,d47d7053,ca9718dd,a834c691), -S(f992b772,821fc43e,61771037,acd07e54,96f61845,d5915056,5babc86f,11a766d9,8a8806f1,cf24eb13,e7b8cf1c,25d550b7,4aca323b,e3026382,e0dab78b,217a9f98), -S(1e9971ab,68dfe587,fe0f4612,ac8bc090,5c2daef8,616dfa6c,b7505e04,424f74c0,4e9c2118,6214b25e,6bca1e61,57ae70a2,5fcbddd4,7690acd0,e537110f,c08918b5), -S(ff3717b5,f433f50,9a4480c,80e6d115,c41767af,2fe6f0d8,679798dd,cebfa8b6,4e443023,e6bec3dd,f82b217b,d1c0c235,278d6fa7,8209e009,4c716c71,163ef474), -S(4dd0d667,f0d72439,b3d3adec,15bf05e8,129a1218,a8d7c645,307aefdc,616cbb0f,aa592262,93fc13e9,a11bf634,56d81d7f,fc503f33,3a523af5,1b1e9a9a,921a95ce), -S(c5475eac,51e02585,9916ff52,efac5c35,bf9b1b43,bd88e949,8807d772,f9e23b1c,2daa42ef,55198235,e8c4137a,d13bed86,d994fd1c,480ccbea,89c1c545,cc26fb27), -S(588d521f,6f9d2c44,e2ee47db,c05ea3fc,517d1d69,7c66a3a8,a62c72b8,645a6a87,24749bc7,3d997052,3eea9809,66701cd4,db072ff2,d9284255,e4f8c22a,afd75504), -S(d597241f,298a7b8,a1139b92,a8bde9b3,f91ea694,c450c808,e15df89a,feafe70e,5d17b691,ccb6cc27,79337e2c,8906b73,83876759,abf728af,c6889182,bf8301ef), -S(5d2d98db,c2d6a0f0,1cb8e201,516f65da,b43e704,78b0e5d7,deedde32,71614c03,c46181b4,d08d0555,7b031d3d,e5966ba3,6534c010,48875986,93584851,80ae7c53), -S(dceeb9b3,6e8e802d,f2ee9664,b3654b46,741ae546,6031162a,c83bb6da,98bae12,bf6e5152,53aeaf52,8ec5a0e1,de1f156,d64c9123,236178cd,ee9b2c3c,3e2710c2), -S(d4984e63,4d173439,e212d2e,2e8da9d0,d00d14f9,1c1d22ce,c37a537a,f3b0788d,c72c5356,63000ff1,9b17ebd4,be15230b,56528faf,c9622b2b,15e88318,4a5c359f), -S(13ccca15,767ae67,ad5a1b60,36bf0e3,e617d537,adc87238,be522265,b8fb813f,ac7d0ed8,2f30ba14,a4817fa0,9dcac107,3f3abde0,41da268b,c3bc9b61,38df6fce), -S(d891e13d,678ebe25,c129de51,7925ddea,c89ad77,4503bee0,d3be486b,2ed397,9a9b4d6b,62180606,9c6b5d9c,5f14701f,bbc8c436,9d148d40,dac50a58,4e87736b), -S(b6c1f018,2bcc65b2,be194313,9b2d61d4,20dbc415,becf5c44,356b3687,47c215c2,b7bae889,fab9f1a2,6050d82d,b983a6b8,c7edf242,69de609e,d963e0b,9230f79e), -S(853be70f,c6df02bf,271ad18a,6e94e277,53810df4,602276c,c5b0e9d6,2f55e587,bfef4966,5addf7bd,efe505b0,368be840,6fa2bcbf,316be956,53d2dbe8,c3db190c)}, -{S(d2fff4de,9ecfdbd2,dd99ebae,d038415b,19b6c44c,9717926c,9e9a668,3fdfd377,a7e8ef8b,89877e3c,cca566cc,7b7dd537,d157cab,121d1623,b6880567,ac66fa8b), -S(f88cac5b,7ef229e6,1a12c335,1603b853,4911e6e6,644dff0,16924cbe,53aa97f6,e853d434,c1dad0b5,4871e881,21673a90,71182684,12f3362c,e43486ff,61307196), -S(7e61ed71,5dde7b01,f1baabaf,bc1db38a,8074c3eb,ca665c4f,d70cf352,624d3d38,70bb8d04,ab22e016,1c5836dc,f08e2c3c,36ce3f67,f49e0a5b,99e21b5c,c6ed9069), -S(9df9045e,7deba246,11e8fe62,fb323077,dd495d3f,8ebbe4db,384baeeb,aa6b88fc,4d5f0bf9,f5cef832,aec0ae94,f204d1b5,18554378,440675da,8bb2d91a,8fcd5960), -S(5d134cde,d16d21c0,2bf962e,7f12f2d6,4e91586c,8070bfa2,61499edd,e00b2a57,b7b6bc8a,54e118e8,8cbdafc9,325fc6e9,125b46c3,66c85501,33561f0c,49c962be), -S(a565c3cd,2dfe5f28,4c98abad,82bd1a61,76bdbb7a,4ee51f80,29782d13,849f32e0,59ce572a,ff34600d,26ac0c17,4b5b508a,81e1a9f2,7f3ada66,44234439,63ea61a3), -S(8bb4eba,3d2b83f9,d6bdde6f,82253b2a,717cb133,f0a7512a,ddfbd29,c6b271ab,f0a0bcaf,14311a27,da09d57d,ce87ea6c,b2156be9,59982e18,5c92e64b,861f4ed1), -S(8b93bf92,a0f791b0,e60e4a33,8ecc5919,6fcb8f55,b7cd886f,cb71d66e,519333c8,77e26206,945f5dc6,ca3e3075,5834eb21,5c3111c1,4bc0b424,319d7d50,f42dbb8a), -S(b8a91ab4,eab1e465,e9ce0f05,b9cd5cc9,d7bd5ca0,29018129,7a2d2142,a3269d49,35eabe73,94dbc74c,e174be38,81b56b3c,d2ef6a16,4a7f92a3,17034917,239aa67c), -S(26f3e105,9bc8f39a,b56cbfce,cc7f8cfb,ead6cf57,ca4d6d4f,61653fbe,1934e2ba,7a970b03,a86755df,f2465be1,ba1634cb,dfad7486,ed7a8a57,b236ae0a,22993b3), -S(b1775563,68b77fe5,896d8eea,e8631dee,788d6b7d,b5fe84cf,66782308,3c0536c8,ed42a54e,36509460,ecaa422d,fade0836,8d96dfe7,ce4b0af2,fac64b84,a49c4a8), -S(7e8f9d20,9b9ae3e0,d8bcc4cd,8f678d77,b9ddde2,f85b811d,63558dc9,b82b4c2a,317ca8e7,697667a0,1d60345a,acc9eec1,57533739,683a3610,baee81d7,bbb2afe6), -S(ada7a37,a54998fc,ab666fcb,78189cba,f07ac132,d0ddb59e,26a959ed,2281689d,ca658fba,d7ef940e,61e0bd3e,41e04863,cfae0703,f997fe20,b6c4ff96,c1a6d53c), -S(93023c4,ec822347,55893d89,497ebce,c0a884ad,e93a5ee2,23514127,fefbd7e9,cbb91515,e8ce6330,55ab91df,96ec77e8,52a5ce34,f0fe3a08,315c30c8,660ec7c2), -S(f70d11bf,4b476ada,a3329b90,e5673313,2107c27a,da354d4f,53ca0913,117f3efc,38fe645c,7adb5944,cf396af1,3bcf69c9,f952f55a,57274f05,a88e5ba9,51b64064), -S(111c1a35,fab368ad,e90c5384,b0412268,a1a8f8d3,49662a83,4aa7c0d9,830a307c,bc8cf412,238469b5,7a316a27,1fe4ba42,f3fa6a62,efe1e12,54f20f61,8c0eead0)}, -{S(b3b5422f,1361ce5c,bf7cc061,3c78aa88,a02683ee,cddeaaf3,f5516cb,291632e0,1790cb50,cc2c760a,c7c2e97c,c44aff29,86c73be5,59a88180,8d036e7a,94347156), -S(a7087c6e,3cc50e11,5e42e86f,855fc0bb,8a0deae8,4c1f92ba,370152e7,69d7e73f,86a61264,c5ea922b,cf1dd751,b5296539,bc2c41b1,29d3881f,2affabe,51f6d1d3), -S(53ef19db,13d761c4,995bce5a,55365036,def1321f,e0b393b7,41b55b86,8ecc9ba7,7a7d9ef6,61ec075d,19e719ac,56f028bd,403609ef,ccc39881,189673ae,10ec05), -S(9ea51d5,4cec52d8,58f8c082,e4362b84,6a83e0f2,9c99df32,30c9a2d8,e5269818,41305f7f,a9535eae,fe7316d7,6ae49d92,47667649,5776c712,214b8fbd,f0c80cba), -S(9c0db1ac,fa10880f,d4da60e8,a8a7c6e,b4117f37,80394e83,fb591307,14dc6460,55b73b4e,80091775,1e680a18,6df01b67,cf0b38cc,e10bc0f4,dc98e0be,7b5c5a24), -S(9734eb47,f47f2b5,4edad15,791b890f,64794567,df7b4866,b8ccde2f,9890cc38,9bd277e7,7cecded5,9dfa120a,f6bf322a,910e972a,57543940,b74098fb,af5be122), -S(38aceb92,95b480d2,1ab23f0f,c2ffa615,ee4f6903,32aae091,596d0aec,a99e5efd,8a3c1050,4ca2b73e,c5249f9a,6edf0b67,65a8b02,4e8ee2d4,e90dd3a3,a8e3c4b7), -S(bc517f6,658a0f2,ec9bb49b,19573f9b,7c74a37c,c3f40c99,7c31db21,170fb0e8,b0dad7b6,18e1e061,902ad53e,a00d3cd2,e9a7821f,172caac3,3c1fc1ef,fbbd3c65), -S(6726e4bd,5ea071e7,43bdafd2,2fc7153f,49e36504,e8482db4,9d64f995,b8b073db,7cdfdb2a,6a42f050,841631d9,779802c7,3ccb6844,1ad48508,6598f6ac,f91533ab), -S(b586e330,a91d81ed,d9b972e3,d7a33c6a,b01019e5,6f809583,767370f9,2803be7d,8bea5cdc,619dd2b0,185a3242,1fa7dec3,662cda7a,9f1302d4,ffcdd31f,5959628a), -S(6a713584,e0d2fe01,64ab5ec1,f31f2798,fb85518d,7f91d512,d4380e11,3d3fd132,3a864153,4be74fa9,6bceb551,15d2b3f0,59fc61cd,54a046e8,d6216f2c,3cfe61d8), -S(2919d598,7a521f25,5dcdfb55,3e5a707f,696f3aae,47226585,248abd19,39519f38,bef08437,9a346d56,7c800354,e85aa596,6a0e2b03,91efb233,7d4a2df8,9d14e9bc), -S(78bd9c63,35fe26f8,68d85fd2,6ad879de,f582e074,fdf2b20,f6bde782,cced7a14,a5b6404c,cd6059af,2722b328,acc60b6,87759410,161c25c0,6866a6d6,89a26877), -S(fecdabd,1951afa1,406297f6,9ea98463,54e14a30,dec4e3de,8ee107ab,43f7e32c,d3095b1e,5d01e350,2a90289e,c508eab2,ee888bb9,fc72b16a,8625a42e,23ffec30), -S(e97f6e7,5ca07704,dca90e57,aaa27502,e1a1293e,d99e6126,d03c00f,53bad532,e07fe66d,9a2543df,5b618336,f75b0907,83c7d74c,d63d8914,22524339,1f598b91), -S(f7270282,7f520388,5412f3c7,9fdfc9ea,da219679,e78d089c,4c1117ce,d990c5e6,9711ff7b,4223c8b,f9aaed68,f70090b8,1f8163b6,7429ba7b,a59ac7de,ec2412a5)}, -{S(2e01d33a,c10caa03,ab514f75,46226f67,69a08f01,56017b64,a2436a34,447bfdbe,f5bd77a1,2c61f2ef,60a8c937,cf29e1e6,882b12c0,3e7a7763,f1ea498e,9207836), -S(7eab2720,b4dcdc09,8d85ef3,869bb07,9640ab46,2d6b186b,88f92426,ac563a0e,a8a15397,96e48dde,8137ce65,c55c6369,766b5df6,7dd0a6a0,6d4bdcda,a0c4c70c), -S(e6a98f52,eeb51268,91c4c6df,b6ae474,6cbcf21a,7352035e,6bb479d3,25a64de2,61c7b668,e144fb16,e72f06ff,71167211,6f6ec90,4c6ca901,61a71b16,f176e0e), -S(33cca5f8,bde4431e,40c3af09,2242f429,2dcb47ac,8b4954f7,3dd25dda,d572594e,5c23241d,46ad4994,1fc84c2a,9aa42bce,1ee4f3d1,cba680ee,8760cd37,e9924160), -S(e5daf317,a0024ea5,26bc1939,7a54d0e3,ff325e60,3ef6a0db,4ba1b366,e1f65c23,8d70ed47,6895c5ff,ec487a26,b7a3fb0d,73a32e8a,a4a80db0,ca00ac83,4371957e), -S(6131d574,7439ceac,e77bc0d0,b49981a8,4e3033e0,185b63b8,a6ea9dda,cb45e7ef,6e01f69,cbe2af0d,a1826d6c,ab34121d,6ab457fb,770f7450,c366010e,20dbee4a), -S(8a7a6e0c,5deeaa35,f13a9bd1,51c737ba,bbac2fc1,924318e5,8b71bb4a,87ececbe,92fdb178,b2834b39,7dfba6b,69e8ec68,e8db5368,546c54f4,a1ecec8f,e4e0c351), -S(585670f1,f244de6b,fa6c9b23,6f034fc9,47e7075a,59c7ddb7,f744e6d4,af423e9e,d337bcf,822decf2,3ebd7101,6b54dfe0,8dad6082,4a6307cb,f0ed140c,3bb14a59), -S(75a87820,7db72c1d,355cf92e,a74b3b78,fdc5c56b,88c698b3,7eb94e2c,f02d6dbd,88595a5e,e6444a98,3647cd80,cade49cc,92a764d8,f710ba67,63e012d6,b12e5d6f), -S(b6dd4054,943d57ab,3ec4897a,8f755e9b,42c3aec6,7860e182,804490e1,91b342a9,dc70eca6,9f7d62a5,8bdfbd97,dc0e2b83,18d1f890,97e8494d,9632e3db,c6168783), -S(fdd92a7f,566e855c,cc134e03,8b5eed94,39023e36,7985a077,875b150b,1663143,ee7b815b,19e1fea3,fbe2d687,b3611895,48407e6f,b4136865,cb2df984,fccd893a), -S(20734455,8b2ee591,756fa103,2859a08f,9218b547,ca7b67b7,266bf648,25209de6,b389f394,2c3edb68,468dc1e3,73ca3649,ee0f0bc3,78b8da6f,aee8f4c3,90867040), -S(1d29060b,7b0f6884,2ca58992,48e6dc57,f491248e,3851bdd9,80837ee4,a777f4e5,a3ec51c7,888554b4,1b21b6dc,da472271,8e5e70e5,8d7bb22c,b8045fe2,2a9ca251), -S(324ff1e6,4d1ef0bb,e5439a5,a3642ed1,f97b7ad6,dfeb6c7c,9af9400f,f414cca0,9810fef5,762b6517,5bb1469e,9ae69f94,68dbce8b,131a7e,6859461b,25581d94), -S(ee2e5e82,e7106cbf,47093a31,e88fdcca,5e00957c,1020f858,bcaeba82,f21c5b31,d75b0c29,e9360215,7a8d0359,991b5991,8bb17a64,6bc27e9d,4e5d2a27,3d4b43e5), -S(a2b27628,aae04348,72814af1,392c5872,1b787dce,6a78256f,3af5fb33,43fd9fd7,d2ac734b,639aa92e,40362fb6,42bd3de,9272c6de,81cd3c56,c802db25,1e20622e)}, -{S(934807e3,60b79e08,d1e28924,2478db59,331c171,6366f421,eda4417b,c0699286,f7f83c26,50e7a77e,2f760e68,7f475858,b2c2d770,195c199d,33a84324,e23f02ef), -S(73da18c8,9bfd61c,b2b6cf49,f776d53b,ff85de5f,796bd870,efd66099,a97ef7b6,fe5b0c10,1c109bf4,5112ec0c,205c1fdf,6feae62,e907c57a,c4c960be,22dffc8b), -S(19239b6e,d7dfedf2,6b926ff6,72905d85,1b0b39b,a20d0ac9,d24dff81,9aa44b0c,68108879,65ac0e8b,e19a9feb,70980400,fed7d280,a75f1990,65b911d6,39a734ab), -S(e03b6633,7b60f200,38d28ed4,1cbe30d,c84afc0f,1bcbb14d,40b73636,2ac08147,e3dcfe11,5065cd9f,f7ef8225,e9ee3685,fdc1c8e0,66306022,ca5aa599,977db560), -S(7f1744cb,eb8020db,13d21f53,81e7dfdf,b98624ac,ab4bfbb9,1dec9f5a,ef410ec8,fea6fc12,7ea0ebd1,bb3772c9,499bfde8,cec1cc40,e33b2e1f,a4fddf45,d03ce9ee), -S(b1d67d78,979a525,2093be3d,cf10125e,df13734a,eda07905,ad2fce0c,11015bc0,9d6872cf,b685ca9b,42e808c,8f854da,ed0c3939,40ccbd82,49856e84,ca2c9de6), -S(cc9c4e59,fdb57caf,bbdb63b2,f9c8d283,5d332666,96beecc,28d8c28b,2bbd4df6,a8aa77ce,fbdc1413,8d9889e3,55338948,82a8c56a,3c80516d,321d38ae,27c55ae), -S(c0a0db13,6f2dd096,412fec0f,6fb2652f,63346063,559525fc,1da8c67,12e1bc30,3b6257a4,13efda21,623c63f0,d78668d6,93dad095,8653942b,20b8bf3e,ecf8d542), -S(72abfdc9,eb47ad36,86fc6428,42d99247,d6331a5c,113f3f04,b5ada07c,dcf7b706,79cbfce7,65d63523,c7b02011,af3135b3,a67be602,c8e87754,53c45f6e,8538ba70), -S(85670d7,4dbf0d13,4c0ebe98,7f88972f,82fea44f,da5bee6e,8c865ba3,6010e45d,8a7b053e,f8336fb,a9e198c6,b8b7707c,20fa2224,a5d239a,7e40acc3,699d7bdc), -S(21c37875,d3577979,8693da88,85d2e0a0,5faee58d,ea74b21,782ad05c,7108f56a,30f8e75f,6f7caecb,ebf8353f,f06264dd,7b5638f7,fbe48e70,c76b0704,6ac2e3bc), -S(f73ef2db,94358b7a,ee9b7046,8a345c4a,94845bf8,daee156,f5fa9332,c9c2cb5,cdc5fde9,995563fc,612e8e6d,bcd21863,f8e83162,4d3a85b4,9a3d750,665c635), -S(72a27f5e,12944a7e,6406cbce,dd90c43a,bc6c1016,3fc0d325,f3dbac3a,156a2767,e09d85ec,963ebce6,26cd0f2f,16d882fe,488d7bd0,9888a2e5,ff05f570,86206a9f), -S(1e6f7788,61257d8f,ca81902b,394d9815,26f5a703,688c0636,a51853bd,85f05ead,a10cb6b5,e935cb46,cb1239a1,3d08c85,bb387812,9c21af4c,5781c345,f8a3ec5f), -S(ec27394b,44d9f24d,59384965,4c3d3662,a9a45cf9,cfa23557,9320c4bf,1e1dfc17,d28e9133,89c41173,89b8b665,b7ec1f7d,b2cfbb6c,9ff7363f,1f26948,517a12a2), -S(e27482fe,5e305f85,a4ecdc26,22f25c06,ac7f82d6,230b8c8e,4d8bff9a,8a78db10,e426cac3,b02eda3c,1b1f90e8,76f9770,29ed1623,62df1ae6,e68986ac,c346d7d1)}, -{S(accea070,aa6709bf,efd88be4,bef1d485,a0da83e7,ac9a1eb0,eda8387e,b9fe666b,93fc1c9d,fed8fff9,60ef750e,94dd2342,5fa08c3d,8eda3eee,7f51381,196080e3), -S(163e8e65,fb6e7ca8,585fc072,3750bf68,fea588de,5e713e7f,9538dbf1,1524dac8,1217686b,7ff2f144,88d5c121,df15026,b6757b8d,e72b1303,b830f516,4b4cf3c8), -S(7bc1be5d,358d6d0c,a42ebfa3,7d208024,d3b2451d,fa0dd7dd,d6c43159,76483b08,42dbc796,2228db1b,8268dfa0,2725fc82,5814a893,dbabd144,ec5a1cc0,fd8e31c3), -S(6fd5e39c,872cdd15,19df9822,6a0f84b9,a5cce99a,b72d3d54,27e24d24,d8b9655f,7969aad,162d6db9,973d2f9f,a1475ccf,39eddbe1,a205e28f,54594ed0,108136fb), -S(d65d659c,adf25d7d,6ce5fd2b,e8794007,6a4ef262,7284bc70,c4557021,4239e812,c1092daa,39ab1efe,480823f0,6038e5b0,35e1d2cc,1caa879e,1b7d057,8dcdd241), -S(754ebd39,5f6a7a88,b051016c,3631ab36,68733921,b9b95386,d924f6b7,aaac42df,95a20483,80e9a9ad,6b165cce,db441b6d,e439ef5,92802fb7,e314387a,94b2624d), -S(67340806,fe427a46,b9c3939,3dc5c7e6,680f5a3a,275c1008,408a2a11,ec43e2d8,ee7e2b49,b9e508a4,e7a3b6f4,72ec3a51,b4bca79b,897b08fa,e9ba77d2,90a0b4e8), -S(ef822b5a,2746c477,4f4089ef,a33f39e4,2e4e3675,69cb95c9,a6b75148,c0e76e86,9784c76c,6d35e6fc,aeb97de,6daf3401,4e594b81,c862e8f5,cd197e08,3a180888), -S(639bf346,fe9a3915,5a718e2c,c4191bba,4985c628,b5d504e2,de39a421,ae0b0415,d1bb783b,4bd96366,c4e9f82f,e6544bce,df39cbf,592a4aa4,7695182b,b632c443), -S(5de8f2dc,825fdea9,a0fe2aa9,a49b38a8,6f23e639,ee25668e,7445b607,df79ed02,a1a17c29,df23dc19,c013c05a,25094dfe,984591fc,a825aa3,577dae9d,6bb1c513), -S(467a55e3,c7f904b6,308f943c,fbf1c9c6,c8489622,9533bd31,5b008c0c,df5c6e5c,59c10ba7,ddaa2005,a169a884,6f5bdc83,633d260b,762a6bab,2cc8d9bb,401d0ca2), -S(6064e78,170d3667,b0226c1e,628c25bf,3fd01939,132f6fff,bec47896,9cef1880,d74e855,68d86986,f8850360,e74faa47,697a7ba9,9d7cf241,fd131af3,e90b0daf), -S(8dd19520,5cacd63f,7586954d,3f1cf4d2,25303baa,a56bfab4,c25fa9a0,63621dff,e772ecc0,dfa4fc98,9b6ac1e8,4a96e4dd,f1cf84ee,37e0a2c5,126f3dc5,6b8bc142), -S(178ca7d8,807067b9,253ce61a,cf0b49d7,1f973fec,62bbaf65,1af01974,c102ad33,293ae890,98cd4157,db11f6bf,c46414c5,47e152a4,e5276433,6d3a4ab,f9f2c798), -S(49fd915f,42daf79a,648d30de,c913616d,46e89e11,afb9d46f,b18aea34,e4203d2e,c94be4d0,e2ccb36c,c306aad0,940f23d5,20c2a29a,4588a78e,c4a8d792,2d96bf9c), -S(a76cdbb6,1982ae31,8b5d3be4,eb03cefc,8958abbf,578bc99c,5081bb2d,ecca6328,8f0ad9de,7d0a36e1,e27e5bb2,9510734c,509c5f60,c905982f,23865986,784134d7)}, -{S(a488f83,2bf3e57b,5225f748,754ba2b5,cd9657c7,175198ae,122c3d1c,ee336ef2,4e326d40,648cf269,2db42532,55391fca,5c2b48d7,44a9e39f,bd1293dc,827e9021), -S(c2e4a4bb,4cc75a7c,4e5fdae1,3b6910ec,7056bfe4,5c0ab7d1,2146bd69,5a7eaeb3,72b2d74b,6181bedf,4bff36d5,e1162304,65ad711e,c13c099,1dbf2b43,c567a603), -S(9e95d628,c5278b1c,56863ad9,e595739e,8cf36103,75e29168,5a5654ba,562292d5,8abdc7c0,8a472f49,4279be90,6d575b7d,17fbbfe2,47d97022,533fbdd7,1d4ff8e4), -S(76fa079a,2b9a0dc9,3a12d28e,cbede965,e33afdf6,ed28f3c7,c7d5295e,6b26943c,cdd558,61e9b7f6,ba779158,65b37c6,ef665077,9344f7ee,6e8d4b3,ae658c96), -S(a0269bcc,a3d91987,737ae43f,2d1b99d1,18a139b2,5d5b4ba9,cab55c62,66e4cc78,6febb984,7682c796,faf098b7,60c5ab58,b1688f3,49abaf25,3456c3cf,d60fd361), -S(f197660b,f5d0e191,d2a75f95,4230ad48,4e28027,f5e61d49,64f02fd2,b239b18c,cd05cec7,3eecdbd8,fd186f5e,73d121d8,2ae2df03,29bd7e44,408bf7f8,5b3009e9), -S(584dacb5,735c38ab,366ebb74,8ecba797,5be0576b,a52eeec8,c6fc353f,17d783ca,198e2b4,5d1e6ee2,888581c6,5dda9b44,a2441d09,4945deaf,77232861,4d6f0c98), -S(eb6d53e9,4f34c551,9fc21d83,f2092221,457e9697,9e535980,31c5a853,615637e6,b958d521,d74b297f,6e537d1a,9512c5bf,74a3a134,b2354d21,b24b30c3,1eb0e607), -S(d32c2816,b28e0bcf,d477c631,7ca9cea7,51c3d7a2,a4d2aa70,b6ea5568,63581e21,7e42e895,c6cc4eab,c85b2bdf,301e37ed,359ac182,ee1d6843,a3c1c7f7,d253cd0c), -S(bab8ec85,d297ac61,8aeca643,d3e54750,5974d165,4a2031d9,3fe2a865,7efaa8ca,f4544105,4f81f7e9,1a8c773c,369689ff,ee5b286a,ea652d22,7812c8b0,57ffd710), -S(7d75e064,5542097c,d70982b2,92697b2f,c3439a6a,26f1d51a,15766ba0,10c80b5b,9868b21d,2fd0340b,712b2958,ab4925ad,d22eae92,1ca2015,5b578d05,14019501), -S(4885a359,cbdb926b,3d2918e7,a7bfc8a7,ca9c6a8f,870824aa,fc2911c2,be3be588,7cfa2021,bc9eba8,27729709,ba83cd2b,d6c1d68b,2217dd07,c7af1977,35ce7206), -S(52c4990,8a3b1b8b,3eb084f5,33f5f559,e9113d53,8d753027,3b1f9bb5,d0fd03ec,adf0c562,21176de9,b5d54273,97feec53,735f430c,44082b1d,7233ad36,472815bb), -S(b07e4e7d,366026b1,e4487f0c,3a2d6825,909f526d,dfeae840,334fbcb7,b1681beb,26d3eb64,c795a304,f226b341,d49adab8,4b427557,1f683268,140853fb,dbf65459), -S(41d028a6,260d5c21,f3d31771,eb876c10,189c367a,b513b761,2530e974,6ef3b4b1,f8b295c4,a2d2d5cf,1be8fb36,9d2472bf,85263bcd,3a36a42d,705d2555,1a501791), -S(da36f37,ba62c357,1fff8b97,39d77d44,13ff457d,5933e77d,e4dc3d18,7bc601cd,ec0e35b6,6d1ef946,7f59d7bb,534beb75,13f8d2e5,1919d914,f10a7778,4d4abbd1)}, -{S(a473de46,a554667a,368fd573,168dea23,3f81153d,e1b35b26,90da8863,71e6c131,4ba0b462,92aed936,7a2bf9e9,de48a08a,874fd681,aef86a15,58b49e4f,13dbbcec), -S(ec3a1d66,a1f76399,c683837b,7b53e05c,5df3ffbe,325d3d4f,de12cb19,c44a8fc1,73392723,41f63fcc,d994c0af,d1459f82,c5479fc8,1628b8a,34b4d042,e68a23cc), -S(8de418b2,77aa4dcc,11619e6e,f76d6a5d,8ae48448,c6dedccc,f32b7238,b58a2e55,11e44fa8,68811549,8a7cf95b,91eb8c53,7119ef6c,3b9fd2d,37f428ce,94060ea5), -S(eaef8564,efa35058,1ffc48eb,329fe037,60b85bf7,864a433e,70b5e227,9282fd9d,90eeb6b4,c3252fa0,ae0ff9c4,ab2974ec,12cd8b43,8af9a0ad,64b8b3c,e404d35c), -S(6985a408,1a00ef94,ac404379,dbda4471,eb99bb45,69c90da3,241743c1,afa865e6,2485252,3273c205,8321276e,1cc4af69,380642d,3e2ec299,64da2d75,b17f3865), -S(df779625,ea469eae,1463fa21,b088cc70,6ac9d3e0,9c4ad69d,554222b7,7a2bdc0e,56e00902,4defe4e0,5f097ebf,ae0c4782,a93500db,bffdd525,8ab8ecd3,1253f224), -S(1a2d4b3f,29fec403,5b3cb811,147d66bc,70fcc480,4f07bc3,169b592,e4622665,600cc9e2,370d498d,d4db60ee,963c5dab,8da8a23e,8db3cb01,d805ac2a,d77ddb46), -S(2d8e71b5,17971a2e,351221d9,44e82447,e913772,216a4c40,f067087d,4106aa7d,d9284393,ad9a63f1,2e0981d7,aa9107de,21a91a16,ba43a25d,26895b4c,d793d525), -S(b53f44cf,a4f24aa5,a57aadf9,cfc0ee9c,d621d482,3a7046d2,8058f086,cdc91b1,8148f9da,95142591,dc71b505,ee60dab6,a680d0c4,1ddd1fcd,d59aaa3d,dd4a901d), -S(f31db738,2a3f41d8,d4079efb,cff1e3e1,e818b2d4,f83dca09,4a044a73,d64a7452,8eae5b98,cb9e9dd7,2a9332a5,5abb49f8,9bcd4b0a,d8f6913c,e6c1cafe,294ffc87), -S(7ce5ec00,ff2a3001,9eced47,3a891bfd,f2c2a9a1,8fd7e18e,3999ad19,b60d42bd,c514419e,272c3380,a7ce5dc,1883e7cb,2df64c89,5f2a730f,cde2f3c4,945b6ff7), -S(57ea4789,f7e02c29,7a089cff,9ae71fcd,f511cbc,926b9299,25a1e184,c6157c5e,c696731a,51132560,c77afd16,15cd5072,4cf0d136,7c4fa3ca,b19aec05,a8d701fd), -S(5cba3f4e,8aab710d,878697ef,9a1ae299,821960fc,caf88887,9c6f38db,4be1dbe0,336cd748,99412e3f,9ca14d01,2cebcce3,42ee9e97,638cdf3f,df5c0077,8d3e37b6), -S(56b0894,7d551fe1,2e9ab57e,a70d342e,3cb74d74,f549edc3,f7551eef,ca9f9fc0,e7ac85d2,a4baa20c,4e1bab03,7190490b,e3574ad1,f9cbc392,f28f45cf,db4dd2e1), -S(7ca03c7f,ab7f76a5,a258365e,55473083,5a9850af,6c83c311,b487a8c0,4ba87a28,1d144504,193db309,170a3ca7,36b39bf,46d08596,552a2962,6a3c40b0,a8f95e4), -S(5d041b98,b864a305,117791ec,21de3fbb,cbe58a84,8429d291,bad63895,442c9fb,46a179d0,decc9e6c,9b642c1,5fa126be,619872f,17c6273d,30e2ecb1,1d3c0252)}, -{S(476d7ba4,35177a71,299267f4,14ef275d,48b434e1,380c1afd,9fac4606,f8e02be0,7f1255fa,57a60447,c14d6574,1d7774b9,695e6d25,1b46912d,d33c77f3,f756edc2), -S(c68ac953,985c624e,dbbefae0,148f049b,c9de0f23,7b192e7b,e8f13921,dc478295,77efcfbf,a08be5c4,632cae8,c7e9e6a,520ddc19,dbc1271f,ad0070d8,366dfae1), -S(31462a8,ae0be4c9,b3d7a28f,3fe28e1b,994961a5,80cdb3ce,4ced5b5b,20077b77,3137a2d3,5303daf6,441b0ecd,244ee32c,1c87dcf4,27449c65,d3cd9bc2,6189db3a), -S(d78f7afe,6bcb8574,27dd87fd,3869e74a,760045d8,1841a895,f8e78697,189ab251,8e419b36,47160117,af77b5c7,97e6d695,65ac587d,ce16b94f,c11ae91,72b8eca8), -S(827f5436,f983e162,42213577,76403af3,d700ac7e,57e10ee,53985649,19922086,9f64f7aa,ff4c6234,5ef6017f,e027dbd6,26592cc4,f050ff48,ca4c8fc7,5ce87356), -S(6ba0ce5c,6893ee03,629f90e7,841790f0,414410f,8526e56a,b0f74f24,f5c2fefa,25d44a39,961099ef,b341c985,d1f7604f,298838ef,422ccd0a,91195f2,2b48e7d7), -S(2c43c784,bbbcdc5f,34789f99,46a9a5,59be71bd,3fde6f66,b6faf050,99b4dcec,4e5fdc4c,83eed83c,db5b5030,91bdeac6,a70cd8e1,ed187ae4,469b9057,18fa5386), -S(4faafbdb,1806f138,a265e889,db4bfeb7,ab53b2c9,622ed6b4,c6b392d3,1f7ccf07,d1843334,387f73c2,da122ba6,a633fc2,26fa3f70,e42d41a4,561e111e,aed5b357), -S(143b5028,c0bee52f,9dc11734,292d62b,17672d64,559ed0c7,49e02f20,8bf84bfe,887d583f,b7d6c57e,c1c58895,aa99ea4,7ff5406e,fc5e15eb,3d8db3a6,e8cbd4b1), -S(394ff209,a9586a19,396143ec,f8ab1785,a661b80d,8d2d9b28,c66c372b,add96e03,5ce203f6,801bd8b,92a673b5,486f8f03,8bebbcb,bea85bd6,7cab24ea,92a54895), -S(3e2670a7,794a06f4,2928430a,8bce2866,eebb6e38,90fdbc94,6b2c794,d32f0452,31d2e49e,9a6ce422,36bebb25,cb243965,6aa2a1fa,6712f17e,6d5d2b58,ae91c3b8), -S(c4cb5059,31eb4fb6,66fab44b,6e063435,35699e3f,8c3d4957,b971a271,78430a1e,9fb4a0e3,8d46c234,eba2ecc3,8628150f,41cbbde0,734453f7,c65f2444,c52a9565), -S(695d0e52,b32cf29d,2230b84,c1260595,8470dfe0,713aa116,61710c,8ce74e91,f4ade5d1,6d27de08,78d907aa,34b61f91,4135227e,97f0979,f4ff6241,4164ab5), -S(5aed2254,27ae4f7a,92292498,a345b20,49b00c0b,284d55dd,51e6cc82,154a4cbd,6da49cd4,5a48b051,f20987d5,415d58b1,9a4e1744,d83a5ff7,6bd95cec,1c6dbb11), -S(390aa9f6,18e5660,cd158531,7d0e01e5,5e6fb9d2,aa785533,6747eb80,caad2bb,bd7e8ccf,34e718ca,947500ca,a2d7e3e9,3cb0c6f7,d8b7c50c,7aeede81,95d0271a), -S(41ff7ecf,227a0f62,236265b,1bd5649b,96666154,115a2840,c37be05b,776c85d5,fa47dd69,a1d89724,f8801024,dbb52b83,d162f2e8,b8614224,4744afa3,530aa1c5)}, -{S(4f62ab4c,b7fb0d13,12620121,9841e932,b0de312d,674cd002,315594e9,81dfb3a1,1145fdd8,c5d16653,a9129b0c,39fcbbd9,5968d22c,ff2127bf,91e89847,35e2834f), -S(99813c3c,dfbda83c,a798f7df,5ea4f172,3de535e8,2f257577,de67250c,6e11370e,38bdd34b,18bd081c,83307a5c,fea76990,11a50437,ff93fc6d,aa22f9fc,d5021226), -S(75771c9b,9b6e8b88,cedcf4f4,3772b3c2,45f72319,7544d57,c6c920cc,137aad40,d8867e96,7b79997,c0526603,a2a6c201,18d93115,4362d804,1542e3d2,51a8759f), -S(fbc16489,7bebf96b,ca01a281,f2ca36c5,dbe51bd4,1a465b43,3311e163,16bbc85b,7959724,16729f2d,9ade6f1d,97157761,a81baac3,fff31e85,13b9989f,12f72175), -S(2d625707,d2c68919,8ad1b321,d60f6ba0,5e106abd,41bfe029,cbc60bb5,d5e0ddc4,5b3e78b2,a007c909,3722440a,d40c2ea3,6f71717b,c5822eef,322a13ad,614ba310), -S(cf23f492,64ab8e60,afd8c0d3,a8a6e938,fb6a3b06,66b9abed,23b6cb45,d5b33a78,479d121c,571eb9c0,e24c14eb,b3be4816,1363d752,fba522ef,a010ee7c,324be8ca), -S(c2f0f458,e56f387c,a92c2def,f02c3e44,dcc010e8,c2b7917c,751121e1,3e49df7a,d2bdb0a0,f56b97a0,ffd8664,1b34a1f,24ba9123,d089b256,6a50126b,90dfd936), -S(4bbfdb7c,8b393fa4,bdffb5d6,cfdf0721,d17e03d5,ff142b34,a0741039,4c84bed6,c115eef5,b815b3b0,c2f2ec4d,98b6a09c,36d8a320,2f81e777,eeea800c,662441ed), -S(49868964,9201341d,bb24a12d,ac0cd8cb,d973640f,19f13540,dcc9d21,d67a7d76,3bcc0077,5c6c7256,fe0e1d3c,a812ce2a,c16294a9,7b9ac6bb,32f796c1,3a2b50f8), -S(a1e22bff,d0567bc4,f0261a3a,db9c918b,a7d81791,d68e99f7,f8247ab1,1fa7591,9d1c7ff0,db87b176,5e284432,11299012,94ce44eb,31a4d6bb,49fc3cc6,d4735aaa), -S(2ad5fc7b,610a3ddc,e4950765,a86b12,e1f5e0af,89da287f,c930c035,b81fbbd0,9fbb7378,36c20ee5,bd5c081f,5588f57b,4fff0b1c,71a9f334,cff1df26,60085c82), -S(fb4dde8b,40a51684,ee59627,d5adba43,50d2ad89,3b0f4aac,6f7a9900,22b0fa1c,753d7603,674cd3cf,46ef3a5c,e19f0d8c,3be64921,6a581cb8,6dc62674,abfb221), -S(f36e438e,9180c9a7,19679a88,51f96690,6dc096ae,4a86e60a,a2a72bd1,b06ddcfb,3fd68d3b,64d890f4,aa653b0c,5a670273,a53409e9,242f0ccf,fb7ea68c,c91a553b), -S(7ff1d3bb,8de59536,19b5fa0c,9519cecd,fa121bde,ff31a689,65c18c42,d182e4f7,2953d0d,7b0d215d,f75955d2,97a8ce92,4b0f6ce2,726b29c4,2b7a2786,a459c551), -S(9385aa58,1de6a3c5,4b479bc5,8823f699,e65da4df,bfb277d4,b56b76e7,c41ee4f5,95d109c0,5e67ff73,2ef10f46,350a7578,f7aca034,962a573c,707b3977,97af5c72), -S(4f3891ae,e86c16d7,73237e7c,d2db7c7b,7ba260a0,4b85f6dd,91e2443c,bd21c831,a96dbd49,371bb1f4,9ed1dc90,17927def,30810e2e,b938de57,ab5665b,8de5e86f)}, -{S(110f05a7,489138c6,51e48771,d505c7ce,68bd6e61,67cf4c3,3933441f,a236f263,761652d,178d0d5c,f6189501,d02d7078,2f10f835,27894d79,4f93dff6,e90a3b16), -S(928df081,cd85c375,e53e825d,4a250160,a1a893f7,95e0a9b8,5378942d,e206a1f8,1f86b51c,49582064,f21e9673,3786eff1,dab4e713,69273cbb,9dfb3d7c,2d930fa2), -S(ed504706,702b297c,e62c2788,54a29419,e7e0f76d,d6eb602,e0defae2,8f74882b,67f3801f,31e2c8f8,5c3e409b,b104323d,ee41c794,802dbafe,ba832409,4efd3486), -S(d620c03f,dad08f0a,a67287d6,7b68e8ff,57d8fd09,2ecc0731,a236db54,83d897b6,f2a66048,6520abff,aa6cab39,b90c1d3d,89ac4738,fe560114,94117a73,60f30a41), -S(fe57b1d3,b1b33889,148509af,29a3c797,3bc726d2,593b14b,1118580e,6b8fc04e,d69026bd,820418aa,74e6c115,b2bed0b,d4f48cf,f1022367,230679e9,7d878547), -S(1de846e8,8e3bf169,465b4d66,6c0cc230,36c0bf12,b35ac6ca,5dd59935,59c11063,d925394c,c8eac4bc,31a49318,1821560b,bbe38d67,ea0040a9,42a1747,defb69da), -S(7a4dd28e,3ccf40d8,7ab743fb,6011acd3,981e4322,486d38c,6b6bd69c,368e9391,89e0dc28,680ddf3b,1a6ee4f7,b2b5a0a4,c417a9ca,4cdbaaf0,b08b4de2,e2653010), -S(593296c8,840e55ee,f7477ce0,e9d5747b,ce2a24f,e5e518a6,7813da6b,347fbd26,7ea971f6,37522c0,f0bfebab,17fef91b,8216ed49,1a0ec5d6,55f12062,6344c124), -S(b784949b,4228eeb8,b8e9979e,fd7309d0,3e5e3a2e,e658b017,86b664e6,db7afe2d,7f836c1a,3f93744d,e4f0563,456e3f36,56b536c3,1e8e7b39,5c0bc78d,9864910e), -S(2298a36f,6e66645,5ef8ac54,a3564c12,59b2ebcf,3a1dc1c6,8f290f78,fa366974,da9db0a6,26701765,293d39b7,1600c991,effb9ab9,2bf6f95b,a65f6b2e,9c3477b1), -S(253bd683,f5421bc3,4bfeca7b,5b48e6e6,d1db6398,983b451d,6f327288,513516b4,61b02eb9,b3d32555,9692df42,b4ce3267,297aa78b,7ac94afd,c08c3534,3346f8c8), -S(cd328c8f,5aa7ced4,d0b0744,39be20d9,f44924b9,c84fdee2,8363fc9c,1cfc80b3,9b0dcad6,5365b7bb,822c2c73,30105fe1,907e674f,9f11b13d,63385bba,b3278d3f), -S(29c6e1ce,3f8caa9c,d366a0e2,3b86fc16,986c3d12,7c391b2c,aee4ff5b,5c229a7a,dbd8686a,e8f95d99,cd7f133c,3211620a,b02d341d,2a50d04,e27a2430,de9f8371), -S(c2a3ace5,382bdf5d,a5dc3c5,9994d92,88efd495,32a3f0b4,a129cb69,a77fdfc1,d79b9211,55651adf,bacb249a,42ad5059,9bf0eb15,1d8b91a5,f6033c13,73db0480), -S(778c13f2,1cf131b2,86bbe8d6,9c4913bc,a0932939,a79a9446,a8c908e8,bfc396d8,963bd25e,461b56af,990fef90,5af101a3,a96299d9,44ffb8a5,e6c59359,a4d0129c), -S(c65a9cd,15f3b7f4,c0f668e8,53227b2e,4ac01865,37c58514,165b6bac,93e43112,ae0f8b04,1d5dc2d0,7a8688e5,ffc70da8,e7d5b4aa,92faa455,64fe31db,2d24929d)}, -{S(81f4223,6a39a14e,d2764665,22edb719,f2fb72b2,c571ed67,343e2c57,4fb60e5b,34f10ee5,6c1d5e02,51e8ba8c,9f129391,521f0601,2ebb4549,7377967a,d8347e4b), -S(bc6f8e27,8bc0f3f8,6bce4dc9,8ed98476,b4d7427c,3e3f3a79,f488d8bc,3f11313a,5a54bc1d,4b08aefd,53d16afc,79b5065,b637c0e3,d74dd46,62728307,ff6c7611), -S(259905bc,501d58da,72ff446a,315b9f75,89df7c14,4d9cc937,bd962d74,12ac343a,3c233cbc,a1660e91,fd41cce4,674386a5,d949ddff,2477cbb3,737e03f3,3adf25b), -S(5051c982,aa4a5d22,d8c4f57,42130c23,4665bcb3,4cfe0567,dfaf3e4f,a03d9721,9413cf4b,50784ad6,1afd8a6b,8ce23ae4,80480b86,6c08ac48,24379d57,8a4062d0), -S(c0158ef9,e70349fe,2d32c1ed,30c87c8,90de8ceb,46ede75b,2addba8,de2b26b,b462c3ff,b14bd8ba,c167709b,dcae0d46,a908fe55,2789e2ce,c5e43d62,b71aab70), -S(740d9568,b420a2dd,389b3fc8,67065e00,10eb2961,56eb6774,15755b4b,5e277ebd,eec4d9bf,693994b5,13ef673,987ec7f7,2d2c767e,9b41cfd7,858aacc7,edda7aaa), -S(ff333278,480b444e,99b65b7d,926675ec,6b16a64e,dffa2b75,9c5410d6,5fba02ee,1d0f842,e584e31a,480c8202,1824936e,e2f717e3,df72412b,155dd2b3,fb1aeb4b), -S(79b0a263,dd3a2b33,31d1369f,8e94cc7f,aa9b8364,2918f9cd,aad62d9f,7a5cbffb,225dec00,4437c7c2,2055851e,1c4968b3,f699dfc5,846c373a,13bec08f,5cc3890d), -S(2a12e289,7cc085d6,30996a53,cd9b0e64,4dcba64c,7a9c4a5d,c4affde5,42717d25,2b8e848a,43566c29,fc5242e0,4892cf58,1afb0667,9bb15b87,69252962,637e00f2), -S(dbf0d2c6,29bb1f42,10cfd3e7,2d119391,16d23a94,fe0c2828,9140a498,1cdd0749,54594d41,8b87961e,b6486d09,f717471b,13f4d39b,1b82484d,8463a4e7,b28ba974), -S(2a1eeaef,b3478200,de3fea29,c1368d22,ba52fed7,1175ec88,4325833a,e93ec8da,1220e686,97e0347e,d0117f98,ce8929ed,eac74f0b,2fecab82,11bc5eaa,638742ed), -S(8ecd4b9c,beaddc70,f20c09cd,67314d2a,3cf3c115,44cd3508,e74050ed,16e9f34e,52ddfd1,795af7cf,9f083a22,35c15084,87bfbf79,4e3af1f7,2183790e,a27b73c), -S(82ae9584,b592fdba,88ab48c,ceb9ff2e,b95f09be,29ad4700,104bf18e,bbf3e036,ac06c9c9,4d3f79c8,8ab2313f,dd507808,36cfa91b,f65c06d,76b547b1,24067fb0), -S(c3b19b24,35c6c07e,4d3254d2,1e0a30bb,21c2f45f,68a441e6,925c3ffd,72b230a,3bdd5ded,600a0c77,3c620ed1,d9545662,af5f3ec,b3b0763,6022a466,866aec3f), -S(49622f79,9672c94a,26f86edd,22e9e5aa,b8ad1a62,33abddc9,fbbabbb3,3fe276be,c114c6bd,f30f79c4,194100da,847518c4,f5688a3b,70dd60b6,c4f765a1,cd324d6), -S(c07b88f5,cd465622,2fdf8cfc,c7191c4e,a3dd6d18,21adf780,63d62d31,2b9e02d,e601c411,839e2371,8136fd1e,e5adf8b7,c5e59969,35bb152e,955d2ffd,58964059)}, -{S(2dc8f27b,b3bdcaa9,2feace80,f2f6212f,8209477e,531e74cb,f497372e,9a2f2263,7feb63a7,96b55bee,ffa180ba,fef47776,fc4fabd4,2ccdcd97,64b4bab3,10350790), -S(ac8dc04c,1c1b8c7e,abad287f,a1f62206,f307ee19,4ba04fb2,fdc0a908,98a13387,a06c53ed,5fce8db2,a52ccbde,38121da,fea83bcc,96482765,26522b5e,d762b0ae), -S(20c34368,618099a3,d6713278,7f2b5c9f,3aa0d419,40329291,3c97237d,b44c9072,e1d3f30b,8c4f9d31,df2dbcc,435a0bd9,e4ab9342,7df8f04,90c820d7,dd620444), -S(dfa3550d,49bee1f9,304f5bd2,5deb92ce,b1e5d49a,4e3535eb,5b55d429,e133d559,1ddc87e2,b3cad5aa,922391d2,b9bb11bf,a3db93cc,244dcebe,147eaaf7,610caeaf), -S(40510142,20037393,7df28434,48899fe7,2f6469a2,1d77e591,d77d2a16,b3cd9aa8,588afafd,85ed985d,ab38fee9,306ef133,ecb087cd,30ac939a,ff13e1ef,a0b658fa), -S(120068a2,65e77949,5450c83,c6ec07e1,b6825840,ca7a00af,6ecc6d3d,9590e73a,e2eff01b,d4aa986e,dec9248e,f69d747f,65dfa98d,537d5443,c1e7d9be,317d371f), -S(52a1135,9611cb35,6b71c05e,c0376ea4,27c9938f,1191cf3b,dc7d17de,9c29b39d,6299f3f3,2f0bb14b,f1c94b36,88fcc301,cc25c90d,def2f2b8,7b0d0050,193c987f), -S(23000a37,c68fb1f,4ab535a2,db033b76,10f252c5,7de5c03a,47502282,1200ea26,3ac23fb1,f0a42714,829cf914,ffada79f,234e1e5a,dacffd5d,34d3ca52,976c934d), -S(810aaf67,f149fb01,a64e25e6,55888a74,f6eea8b3,c5e96fa0,9fd9c689,3e7543bb,abfe36e6,3418a26e,7a19f2ae,aee72cba,416880a1,770e2bfa,79eeff32,35885e82), -S(cdc0b689,5afbdb4,f1c9521e,280cfbad,7b543619,b8d77c2a,20fdfcc4,66129e45,9d59f91f,bc3894f6,820fda03,ae13748b,572f9a2,d06dc312,4f824831,778d62ff), -S(1bf8e290,19706636,e5d2c34a,39de3f02,331460ed,916c17fe,8e36d097,9a5edcac,e15e619c,f4f096db,1ed1d51,ea5208eb,41625ee,6546f40e,324b754d,e0e202c5), -S(e54a04cd,f5893d80,1a1cc8f6,9dae01e5,34b92457,ab7319a2,4d2b6c2,78f57f76,8103dd9,b4a89691,b079aad5,71267e5a,f601dc04,858f065e,aeed5e92,34dffc0e), -S(711f6808,53d18d8b,911e2342,a301a805,a1c76c2b,b5987775,f5867df,e2325d00,91630ab,cdeca550,a32e9df2,30f02e64,983eeb89,396487d6,4b3c9d59,8350ca01), -S(765b24fb,d42d4d4,a9dec609,48ce7f91,7c3eee70,49a36373,9e44297e,3cced026,56408d2f,d859a211,26d14e77,81302eeb,87371c17,b1f9bf50,9e15f545,c240b79c), -S(b68f07de,6b13a7ce,739a7e9a,1c6a526e,d1df5cda,b7fad149,df46ace,3acc9919,5da1b851,a81fe645,47ef84a8,fe9a39ce,fcdc9abc,a3e95818,b34860f7,f54230bb), -S(d98bcef6,cb3e4a1f,5b9ff8c9,8ef7138d,ba98e80c,200113da,e7508497,54954a96,456c5f23,96fc1c71,79f6b3a3,a82d8bb7,8ab73d62,61b6a098,77527964,5ad80080)}, -{S(118d5053,fa3ef05c,810cf906,3a410f53,38a9e6bf,513b9a7f,5259112f,f84ad7e4,a371fc9b,c9182528,27d6c842,32e4e44a,9d32eafa,84f1a02d,a86039d1,6309e92), -S(ce68cb2b,ec0e3f64,ecab8273,71f248b6,9b25f4db,94ca333d,c8d3595,e6f4db70,a8355f23,f22d8225,7adc9865,55350250,8c0bd086,ad7d8b74,ec3f3ea0,ecc17e88), -S(7834c202,977d96dd,d2897bc0,b2e9b093,6b3bb91,36f78002,85dfba94,cfde7d74,62df13f7,87aecd0f,5f299a98,1b4b6763,82b69aa4,997c8419,1f93eee5,5a8da0e7), -S(5dc11a79,34d41b29,5b384824,89cc2fc6,eae9c348,2baf631,94023e2b,579b750f,bc8719da,924cd9db,901bd524,a5eee1eb,fc161286,508e192c,10f3b786,f167057a), -S(40f1348e,a0032b45,3f2b5339,d687a06,3790503,b4cc7b5e,374828dd,5374566a,b7c04bee,58dd65a2,b5417ed7,236557a9,5d90f89f,2f9be760,408f3806,5ec9c1f3), -S(5bb43572,6cfefc3f,dfcc3a89,3abe627a,3bb9fe92,2dc39256,368b630a,1bbc91c2,4266fcb6,cc3d664e,72943e33,3fc94db2,b76b9b43,1e5956a5,5fcdb36b,27d175a5), -S(c61ca2a7,48faba61,93325019,dde522a4,b4ad7ffa,ffade4ad,84bc46be,390d6833,88fae1ef,1728b211,6a24bf40,7df169b8,5987f26d,75a86b84,37b91bb5,607b4eff), -S(ebb9b8ba,c980a86b,9955a450,493875c1,1bc446f5,ead71ef1,8eeee3a2,ace3a417,77aaae20,a2959de0,8b53b7ad,6434aa02,f3c56dea,877d07b,fdff41e0,aa463b7e), -S(fd3b8946,296987d0,22123898,bffec5ec,b1072fed,c8e66617,a8d1b00b,6bbd9889,54240cbc,7512e6d4,744393a,439e8b4e,9973dc40,34c68b72,df04ddb8,b89e6acb), -S(80aac570,6eb40c4,c6b5cdf8,e25e5740,3aadbc07,f75b190a,444ab53d,4743ca1b,196c7cc8,3ce92b15,ba110e5a,ca1ca0b0,c3205f61,e58c1e4e,fec5e957,72274710), -S(450df283,6de16aa3,3b893d69,39c46224,6ac30dab,941be908,42b3d5c0,714f9670,970c934d,5b242d56,b036b8d9,4b1e8661,45181ae3,cd286bc2,962035a0,fd852a57), -S(64c57089,83eba9da,d7871fb5,64481b9,12612c20,4f2bfaf3,635314c7,3cc9bdb3,7abcce5c,fcfea03f,74665734,13a66116,d6289bad,2209253d,45e77ed4,bae9a738), -S(4692afdc,34fd208c,72726495,7517fe0d,b463d39,6ba454ab,c1b81898,cd7343f8,57b67c27,8a0ab12b,5eb4a55c,933cb45a,d6b5d955,2110762b,61fe79fa,535a783), -S(511415a6,1371abd8,c86d7fbe,4adce11f,f6cdf1bd,330eb95c,7c40ead7,e5fca53e,4adfb29,87b9ac39,baefe7c8,69aa931b,c07fe15e,5a5811b,9add7b77,1d56c8d9), -S(4aee2f4a,ab479df9,b2e1ed5e,19230669,e15d153,22b5472f,c8b138fb,7d542c30,92c8e16,fbea4d0b,114a7d84,292a9643,6839624b,daaebfd3,9d621f3,7f8b141f), -S(8c0bc6ef,25a255c9,3816cea7,599c39d7,acee681,9373b82e,96b81a43,dd267223,8ce9ad90,e893c56c,c0392afa,24109c94,2098b5c1,15468b41,e444568d,9904efa)}, -{S(568b3e2a,2db4792e,4ef4ee66,14e201f8,a847fdca,38bb003b,adb06d74,1e4f999b,7334b395,61cbcce4,49d83eed,205a4c40,d91d2751,938ba7d0,6ed9e5a5,e1ffea7c), -S(ce433da,719f5582,6e69f248,3c3db9db,de45e0ff,fa2cace9,f75cd210,433fadaf,c296f641,5200cb35,cb8e1f23,20b86cc,9b341541,b9256d77,afe302c0,1e2420ea), -S(ea19269e,945625dc,138b9e60,249baee6,8c63bbb7,2b898569,5459629,fcc7ecf1,f5a7bb81,53552b33,86deb8c0,26d88504,f6a85ac1,b9290ef6,f91c0278,2cbb370b), -S(19e8e269,b972af70,c61983cd,cb7446f4,23dc93fb,b0e3d8ba,3fd02476,477e596,3081973d,f2123602,770716d2,6937f31d,f0835148,8c9d1375,d2bfec67,24df9c3a), -S(4968feff,d34e4649,9ca759bc,8e90d374,de9e3199,a13e2b04,28a10df6,15fb7696,2936b2f5,8491cc78,38bdf347,a4ee0b36,db288e5f,9727980,810c6eac,a8d1edf9), -S(d258654b,45fe5366,3552e85,a7da0755,c4598eb,68aa96d4,624875b6,580ea359,52501a5,e7d7d931,417373ff,ce85e0fb,43ef595b,2056729e,b1daecb,91998d1b), -S(b86b0c06,76f64537,f9d38200,66aeadad,4f3b68b4,2b5974e0,9f218d81,a547e04e,52a0e4c2,b827e0b6,894ee674,88a894f7,577cf3f8,fe83ebc,9e103a28,3c054690), -S(9212971d,b38b95f4,e7b9cae1,f1519878,80ca177f,73adcd28,a6d03e8,cefe9a31,9ddd4828,3b079a75,74afcdd0,e7cc4c24,45a4e893,ddc2d2e5,d24c413e,9c676041), -S(42a070d,929191fb,fb691944,a311c931,40740061,2bf33de2,809dceba,ace68f50,5429699e,47e22e59,b6cf8cc7,dbf2c81,23d90d2b,a48f6839,db4dd0c4,7caf4412), -S(895744c5,5b460749,a1e8b784,19e8f6a2,1e53f06a,ae99bb50,df9bd94f,e1a20610,a1ebffc6,da8a497b,bbc52ebc,4de1f196,881d88c1,948b05ca,5b0641e8,c56ab005), -S(c9e8e6a1,414b54f6,c19e9ab4,bd9bfee0,86a3e8ea,7a6b3e58,80cc5988,20fa512f,6878f69a,59a5be7f,3e60c1b2,6e9b9663,9097a6ee,7facc8e0,e242f56,e9a2904a), -S(dbf66722,d309634,872fa8d4,d9ddf8ad,2d198344,41a8515,7521b491,1e9e3473,1823095d,dcf42369,f3ff23,cb3a6ee5,273b8f98,7de2bff9,67dbac10,6b76928f), -S(b133817c,f965b7b2,f5d80c05,b82049b1,464713a7,7cc80d53,1e930434,387ea7d,db03e202,2eec1d26,4cccb613,7679c6e9,e08ef66c,f11378ac,add8985c,88f5e693), -S(e198a2c6,3f0bbde2,f31b8d67,776b8aed,bb86ad58,e2896a67,11b5d5c0,fd3a8d3e,e8df361b,ef77d3d4,4ca4f7d6,c554fc2a,9e2401ba,96769bf1,503b243,8d8306b7), -S(5f3ff8bf,148ec6f7,18aba1fd,8ff0b37c,18e440ee,51beef26,59652c0e,39ab7255,5da559a9,40e22dca,bb4270d9,31acb7b0,2b19d7fa,3495abd6,d5ca7f50,d6281445), -S(1e9ca439,c93cd0b6,d9886234,105fc1b3,178ba0b1,c71742cd,5c043ed5,56045c5,f7d31c2a,1890f586,214371c9,77501788,cf162d88,641a5540,c49ce4,323f3ad8)}, -{S(7c32fcd7,13305cc7,44fc4ff5,2d315e2d,d4cdf7c0,31b41a64,db6ecbf9,fd4edcbb,7f002bf7,b8e1b8f4,a4a4f2b,1922983e,fb901e13,59cbe934,8a31d91b,7bc86bf4), -S(d8aebd7a,db0ece5b,ff422046,6856ea0a,6446862a,4d0a94ef,ac7327a3,acb201ab,6e96ecfa,e9697649,faff155d,cd01bc34,e6c8630,616dd143,1c816c4,9d1168d7), -S(7dd764e9,40746adb,e6dc9e23,f113209c,7fa75c21,7da4cbc0,dbe257f3,cc0e3064,97e244c1,a0c8d68a,fc7a3192,b1f029e8,dbc41d85,8e0b273e,c4eff27,97e63ce0), -S(394a3fb7,320acea1,cf99bdeb,fe686508,15b3b06a,500df196,c05459cb,80b7781a,ec88e635,9615da20,cdb6a16a,245c694,ff550cf,cfaf2939,39103517,653f8986), -S(a394cc44,e64c4b5d,b36b4dad,d0a458ea,9c760e80,342b99f7,5227e22f,6acb0de6,de19b475,9fe10976,e9f38b74,1738b12f,e69df952,26c20d19,5f9135,33458682), -S(1277835b,322b7118,9ea416a4,c9a51518,e3a42d8,419f723b,d2b242ec,f904e26e,ce764cd2,558ffc31,779f610e,b33be553,a80a0dd0,1136132c,6e84b142,e5f5a8b9), -S(7c7527c3,ca6c3b60,18d6af7c,9ad79f0d,461e3d0a,c426e0a8,3bc1610a,80897370,fa7dc6af,7682554b,9c6f4b9,3822bd91,46bdae61,88fd2626,6f13af48,55ab23d6), -S(aa59dd0a,2e342733,a151e156,a82d63c8,9e992530,7bd774d5,d08c327d,27409a89,f14bb267,18ee5ac4,44390439,b8727f1a,f5b62326,fbdfb36e,23ff2f08,3a60e223), -S(733fa3dd,25e41c7c,4e548de1,17572b87,31bcfb22,57f0b822,1be31943,4bc2560c,976fc63c,e29bf97c,499e220b,80bc48d7,1fc07e4f,27afbe03,fb4a610e,e79bf820), -S(d6bf5a3b,ee8b720d,266586cc,70fc5518,a577cb70,44dc30f,210912c9,f1609bdd,bbb5bd29,290cf1b4,28fd9150,db667219,878b1507,121c6fe5,b1730f05,474f98a5), -S(b3a7824b,4da122ce,1120fa6,f5046205,e2989b8d,7c4bc118,d540c91,ab1e4b30,c7e452d5,d23ab126,28301b38,d2286c89,87d402a7,7b5f1fa9,ac033675,4f4461b1), -S(383beab6,dccedb68,d6c461bb,dffd27f7,1dee3acd,2d9bfc78,f9c723db,2df57ee3,913f9d57,286e287c,594a99de,f59ee375,c8d5fa1a,ca9db39d,6397d1f4,ac524650), -S(1de5be5b,6fd264a3,f9445660,995afa2,39587660,9d224d8d,6d02e600,4e7f74c0,f3abf699,af7033f6,cee828e,3bcbdeb8,fcdbba9d,d0f76121,a77f1e9a,cc65c1fd), -S(787be997,f12fb2ed,744bf579,eaf42ead,86d36029,e3063ab0,78e1c932,da1896ed,d652cb82,20ea596,70a51612,71249ce0,62e5c584,bbfc385e,622d7e0a,46a243c6), -S(f5870f7c,4dc65314,8c4ffaea,79154e05,1fcd6769,54939f5e,cc33779,f99634ab,fdb57c99,9d115b59,6d77bf19,e42ea2b7,c0dbf4c1,acccf2c,ef82949a,2895ef3d), -S(721a5aaa,c5bf9886,543b1e42,aff4c222,c6a63847,df9d72bf,7feb57a5,a007e26,94fb4bb8,fb1f945a,d53dd78,82f6a789,ab0dd874,9d1621ce,38bfa0e5,5b50bab6)}, -{S(29d70da5,92094c96,e293c115,42b9dbab,b30df8db,ac98416b,65b0b75b,b3ca446e,a8a5aa3c,c3269596,dd8a9d98,87a3b772,efa1c668,3f8a947f,ff80c662,31c70799), -S(357c14b5,2c0eb735,74f675f9,cd9ba0ea,9d0b5334,d7cd5dc,a8d6cfb1,1359a86e,85ad0fbf,9b2f48f,86fa016d,89824a4d,eed06ad8,3db7340f,986cc8ad,ebe9b5ea), -S(72047bc0,29b36192,b1549087,5e360270,a7fecd3e,1ebe8815,61e7e0e9,2ecc6973,7d1153b9,54ec6a42,3df1157f,fc9d413c,f8c3837b,d4c84bc0,40ee5654,6ec95d2e), -S(a459ac94,974bb47a,8e5d3ba9,169e7327,349ad551,ba8ad12c,fb4e15bc,d4894e91,699eedc9,aeb4bc3d,cdb97dce,2ca019e7,218ab0af,2790bf80,c59ba156,9cbb8c74), -S(e6f35f3,4a17a4a0,a76d997,afd9a480,bf8ef1e4,29441d2f,bd9f9d2d,b3b93bf1,67feedbc,de8e075e,fb80a4d9,2959104e,a990d813,2b0d395c,8e893212,d47a2047), -S(88924114,3997a2ef,1e36bc46,7e7f2fd0,52fb02f9,cd79f4b5,e6ddc9c8,51e26aac,3b1ba5f4,8b0a89ff,a4ce1113,934d11db,26b88e8b,2eae3680,57048db5,e5488936), -S(9ece7680,448a953e,5469839a,12fd31f4,f6d07a2d,434159ab,414bf7dd,60d783e5,2d60b5b2,e6966e5,7969016d,74059dad,c03cc7ae,f7b80825,9a629041,e0cb1b1f), -S(aa98d665,de5df68,9e7d323e,943d411,e98db3fb,51124855,256d0b00,579caf90,ab791e6c,ebca5631,22965594,b52b43c9,5f323834,53b37368,281c895,7d1226e2), -S(306bf517,c30d81fb,1d931b26,49af7c70,87246821,8562e255,42576f53,2ab4e48b,d0d15fa8,1391438a,5416f0e7,1c7b9ca4,512fc802,d4c46a4b,779cb1d5,2842059b), -S(2c8ed21a,fb154f9c,c3e9a6d8,dd047af9,c124e6d2,46da9faa,36a580ce,91b1788c,7dda9e28,6803924c,d8ce710b,d68e0a85,fc2f8678,45258f99,43bbeb2e,f6a7528e), -S(4acfe8f4,6ea97663,56ecb2e1,c3055379,cb4a311e,7e4dfe9f,642fbfb4,18abf5fd,a5d6abd0,d44bc614,ddf25ec4,24526070,100873e7,c4501c65,c3045e24,7478c836), -S(f7b1d348,378a094c,3e8ccc30,3dd8ca52,fcfa019,24c52fd7,32544a40,cf47d783,b92c436a,8c7e7ca6,6dfc1223,c7fad4c3,c65aa955,b8ce913b,45437e54,9dbbd1c7), -S(1ea80a5c,38827511,69cb24f8,64f4c1d,a78f4dd4,6509a73c,381627a1,7862ab8a,126c7a44,5fd6d3a8,f57a3a55,4fbe3f1c,eb9bde07,99afad93,fd7aa6a,11a0dd16), -S(e76aaeb3,9cc18870,6067a0f6,54bc317b,89a72313,2b2bf079,9ee88af0,41597d5e,6d75f6aa,19727219,ea7f6f57,c0a7d801,3b9bf256,d8764219,d261b79b,48ad6108), -S(c6d1b9ac,f9fec422,e89102ae,4fa07021,e6c81049,dd1e66d1,d0903ad9,e072398,2e971363,41b318a4,dfc4e5b9,31a79f35,f90e673c,6bb7aa17,a2ec5f35,def14ff9), -S(d9faf06,ba5bd56b,ee78db82,4db777bc,e57aa5ce,5c4b98ff,8c736164,d4d8b2dc,97af746b,fb890c20,7af10658,38d9b850,2d8d0524,7a5592e2,89f6ffec,a66c5168)}, -{S(7885bb79,25196ae6,f45b6658,f3c04f5,a3b76cb6,1d60eaf2,45cb35c2,2552267a,9839aae2,b4d9de01,1a119d3a,d269a821,dd88d287,2f031910,a2f3cc22,2e8555a7), -S(fac317d2,cb5e27e7,74deba28,d3c2cf69,4364a190,329787bc,e325d80b,150c9fbd,c56d5053,b0a73378,b0d5fbf7,940ac348,abb46107,1b9f0100,c721154a,4d084e7e), -S(9ed46b01,f4e56c79,9b3f582e,2e35434a,25ec32e6,ab497137,6eba881e,7ca96ad4,5e8d2e27,96b8dc65,867f45bb,a623c59b,a365d840,1d9e889c,23d6acd8,d5bfb365), -S(6acaf24d,fce1919f,c8d8743d,7a5b64d3,3010a8e9,cb6340e9,7400d143,53620af4,b767f30a,87b29f8e,308a95b9,6848eb5d,c8bada19,74cee095,8fb75735,86f1d733), -S(1a2f9605,fdb3e5e5,3445c350,4e550312,b36a7dfe,5df0dac2,23aa53e5,dcd7264e,cc4b4a0a,6febc03b,155a755c,187421af,52a7e6eb,2227858b,c56b9feb,4befb45a), -S(4fe527ab,42540438,9d9afa,2a1da83c,968fe9c4,f678256b,d4998bb5,af963a2c,66dea7b,7e0540c4,75799ec3,3987a775,6ae86d43,56a295d0,fe8242cc,27ad7c4), -S(756ee16,fd1019ac,30e50f18,5606d1f5,fa91a7a0,b01329e6,2a949c80,b7590bba,4d190439,98483880,6323163a,6cb23a8b,e47152e5,a5439d24,513d30e0,21511050), -S(63935d2,711ec4d9,f33fb116,ce09ea58,b45b29ab,79614b14,278539b3,4ac44e83,703a7f21,c47d413c,9235fb0,36a7b441,87a90768,2d435953,439f0624,6550944a), -S(fb6bad0b,3503cf55,8a75531e,9e8915df,9a88277b,c766b37c,d9685b58,a91e3fed,483feda,8c214ac0,92ba5274,8b158b62,3a0d541,65fb5b0,7ce07e58,78cb39d4), -S(30c7d349,a9fd4825,82fb09de,f7d638b8,633fca82,b9bbd65c,ef8f6dcf,1c8c05b2,56c76d9d,6df4bd0a,a8030dde,a3839728,71aada1b,61bb34cc,1eda08ee,a14761ae), -S(13faa439,f73bb77d,d2423e1c,9989808f,96d98080,af214cb2,e0cde511,9eba8a14,ef6ed341,7ff03112,ece400db,b274d225,bea30a63,c9a063cc,9a987827,d3e380f0), -S(42112f0d,7628b3bb,7a0e4f0a,eb58d2b,9915f797,10aca7e2,67214532,2ebf502c,a1ad23fa,d76d983d,6cc4a654,95da8d6d,c5372849,d7fdcff1,34e5903a,e8441ce5), -S(d23fef28,114b49b9,77faea5,2bd0e30e,6a9ef11b,c513cb8f,3107e04a,e26a9ceb,5a4cd8b8,b0dbab13,2abc50af,c9d700bb,bc28dc84,3c12060f,612134f4,fe40aea2), -S(463bd8fd,21ba250d,1eee7500,e88aefa8,38211947,fee2be73,d6511300,6d28b5da,20f6f300,e2744ea0,1ed033c4,b5b9e7b6,707c06d4,d97c4771,ad35e305,b11aed86), -S(21795062,e337d1fd,994a7cb9,7407d33d,f40ac1de,4a585c1a,2b3ad400,8e03c4a8,e93a4632,da05b347,8be71e28,c55af8c6,b4b161b8,9f48064f,31755a1c,f6b0ed96), -S(e8f77f4d,272c5dd,f001f939,4b658b96,d58a54aa,bccb9de2,c501211c,6cf9364b,7044feed,21d1dd9f,80705bf3,d68fd160,31c02dc8,5a708f18,1bb7ce91,8655ea61)}, -{S(422f029,1f51c4df,af233322,7015e4c1,ec8175b1,a8ab6b2f,60a9e291,7242d940,51ae32b0,ed5d39d,e1d61437,d363d59,181a68b6,4e052bc5,9d132da0,9c1f422e), -S(f560c762,be8f90f3,b12c1447,4c3a2d37,53634a4d,fef3344,ba8e9a65,1becd50e,49bc8c46,e3207440,76082021,6d203410,fda33028,d3ff4ee3,af065502,ec96609f), -S(edc545ef,2402bc41,c4d7b437,65830ad7,f79128d5,91b4201d,1acb5f90,a7ea6a46,ec758c41,e0ff7bb1,fc28a91c,435c09d9,90338a6b,216504d7,a538691,6af80454), -S(67709f77,e324ec1a,fb57e5fe,43215f07,3cbd3d48,f6cd0bbb,c01f3ae4,1a3c5905,e65102d9,c33abbc4,82f2ed0f,fb156cbc,20210eda,19b5b345,f21150f3,ffb29e79), -S(6b73d1be,a5b5ffb5,438e4cd8,9af6d9c2,bc41a2d6,a9c6b405,ac6fe5d4,6ff920cb,84f7e06,6dc9bde7,782c7636,8aed4a2f,e570e51a,8494864d,88e6c1d0,ed732be9), -S(5aa1e427,64c4f0c8,60423a6d,54cccad7,f6093ba,b6a0e383,9e1e0b63,cd652121,3245d2b0,fe27d590,15cac18a,861d9ed4,a5131871,38faaae,4c01d1d7,759fc9dc), -S(a8460aa6,9cd68695,94288486,1f92a61,e7e924f,1d61b9be,1d31f923,efd803a6,f6bf9b9b,f65a68eb,925f6c63,4d16a6b5,6d92d68f,fb807084,7f09c0d9,d95b852a), -S(fa3b7d59,bcd32e9f,a4cee765,d9b54c1c,65d8cf67,8a88f6e5,3c3192e1,64143cc7,95ed2300,2f55b1c2,21061dc9,bd26f0ed,82c05ee9,4bcf1bad,3bf878e1,3ff33b84), -S(febd5d39,68446d45,fe1daf28,2018c980,f4a5030c,7710edfd,b79daa69,c10f2296,b8c37c65,bc7c42a0,65be333d,1827feba,70eb75f3,5f289e1e,413e2325,5ab9d551), -S(9d696bb4,4dbff608,af3ba93a,e98993e7,4a6d8902,42d406a1,7ae9c609,6bb9b29e,d92c5408,c0ec7131,9efb50d6,18875060,da65855d,8b2d1cc0,9f07f3e8,c0e1d77d), -S(8f4c98cc,21d39520,e837b075,479b8646,2837665a,ac82541d,1bdda842,ca5c2562,3de70692,afbdd878,5a858fe5,51321576,95f464e,cf2c1237,545b1e06,a1cbbe6e), -S(6d31e611,2317acb5,f2ebfc35,a4f66f05,af86ed84,720335ec,535c0f5a,cd14d952,8d22c3d8,32324673,9b20d9b3,7fc73b78,fdaf98a9,6cded077,6e561037,b2a85b1b), -S(dc891a7b,d96f10f,b6d8fe8c,1c749ea0,328ad2e1,353b49a9,8056c5c5,b637df01,475aca0d,c67d1f8f,92f6ffea,20c48300,2b0f7d3f,f5d2526a,cbd8b89f,25ed3eed), -S(c77ede67,1432ef33,73af321d,7d8fc6c0,f254aaa8,37feb14f,34817740,a54cb5b,ec2f427a,cbb9cd4d,96f83c7a,450efa09,6e12917a,122eb466,23c6b63e,dba11010), -S(7334718a,cb39692a,91c140fa,67c21c0c,da368242,aa1d0d2d,7223a0d8,5ce102c3,e3051cf3,4d5e51e3,901449a9,3595fcb4,327c59bc,1e2d92cd,4d4699c2,26ae4e84), -S(23c7e5d2,2b0bab9b,b95fbfe2,e39e6902,5c7bcc89,fad1a0be,1f5da48e,74b3f622,bc5a3ef3,c4679a16,ba09f2ef,4fb202a7,83257a5b,3f95b629,455e4173,9b5b317f)}, -{S(43cf2273,e372157c,2180640,594c144c,93f64fa1,75f28cd2,5e7efebb,14028a93,1f8b092d,4cabc600,33782374,10eafd04,37d6436f,6064932,6f8de6d,94059d4e), -S(83bf8ee2,2a69edf4,74e5b45e,50aa0bdf,4879b4d9,61d4b937,ab18d3,7869fe5e,296e8081,cb72663b,5223c040,a64c7aa5,273fc6ce,70261af9,cb3e071a,79b7c3ac), -S(66b8e44e,c913698e,d68f3b1a,df750442,442a4376,9ebe7859,84e4d233,9f666b1b,b09c7c2f,852bae4d,f90bcaaf,a664c792,ee88ac87,2d2e046d,aa6009b2,2412af94), -S(fea69879,e4eeadf9,275589dd,6339111e,5d29c581,30f22fb7,c6755d5b,2f5840f7,814a6766,65b54689,b3e2d415,4519bc8c,9676cf4e,91b928ef,3586da12,416f546), -S(bd147b40,5c3ca694,ceb4fe83,5f95676c,5428a065,add89f79,ac5859c9,7dc4d5fe,67544f50,a639f7a0,602a5fdf,2d425fb3,edea0cdd,f2cc5f9b,c61189bb,79cfbf58), -S(b3806514,838f93cf,6118c8e,f759cf82,394bab94,e020ca33,7d20c8da,bb61c79d,bf4c1bc7,35c5a806,d682a1fe,239a1027,51a547f1,7d1d87fa,59c9384e,3ca1fe45), -S(bb002b37,60adf886,a89d4ba3,23c17868,83f0f3dd,fd4232f1,28410770,563ba5ea,4aca65b6,68115f32,186773d8,41c061d6,8d4a860c,442b3f8b,c72776b8,3bcd22db), -S(7857b661,420c4251,3db90fad,ab97bfe1,9a1e3f91,5d524f66,86d0cc01,70652ac,75205776,8c2e420c,f255f9b0,df58bf4c,39316f63,612711c1,fc7fe5c0,b4e7ef7), -S(cd386b61,bfbd43e5,109b74f0,5d765ed0,5c4ceac7,85bff4a3,c8386ca9,54fb4553,aeef237e,892a3a1b,84183222,91f9119,64bc7240,2f32da46,47a159dc,4a7d6611), -S(94dcee6d,e36b346d,4dfb5ad6,3f488761,2a5734ae,e251b07d,6f81a3cb,7d255409,3265f73c,af4ef3f0,40919637,4e273be7,c0588085,1940bdc9,9d0ab66c,c488e203), -S(53199671,628f4a30,89e65e28,67489a1c,7f29c9a8,a34fe8a,c144623f,9ef9fc4b,45740e72,3b787de5,1ddf66db,96c91bbd,19954170,62fed0d9,69522916,7b2b10aa), -S(38596053,40ae3e91,d005b3e2,3a998796,195a5c5a,81b24286,458cb7e8,ec905e3d,5484588e,c9dc9485,bce07479,b1dfe9d5,c5007d9b,eb7c372,f52e526f,7627131), -S(594e1bd2,3a5ced9a,98e48bdf,dde40807,b9c2871f,79e1948d,7167b59,9ffecc53,1d7fcd4,bb9bf0ef,e0af9ed9,8da3e36b,2ceb0ea9,e1e3358f,4a590022,f5c530ea), -S(bef8b23f,95e0bdbd,3c0ba1fd,7afb8a58,1f038e23,e3e9eac2,b8848a08,6f23f816,9a234d55,f9c810b1,afff2a1e,b1738d18,4308d19d,11a0e1ec,cc571eaa,b9663c26), -S(632003fc,f53c8833,5542f216,e4020ef5,3eb225a4,be6c0e59,b92ebfe6,52721652,bb4d2dc2,f255b8d2,5c1803b8,88f40d8b,bbe6b2d9,f6754511,8264f809,cbd61844), -S(b7ae730a,e74aa208,9f3266b1,5358369c,4970c009,e6318581,4d541b07,c6c80a96,43a7b349,66b4bd5c,a1e45593,42642d35,ebc969da,544d4cc,65519915,34e80d65)}, -{S(9f10aba7,5a7b9fa0,233bf53c,d819ba2d,919f8acf,9a5e6717,2c93229d,547a40bd,85485295,254a4456,87b065aa,dad21f32,b31735e1,96333fb8,11117a00,d0bf2361), -S(75f8bcf3,831197e8,b9053c1e,5194155e,dae1867d,52f74911,a478085b,52d916b4,90448c24,35180385,a15a335d,a33af722,c9a395a7,16937aa6,b861aee5,b0b9567d), -S(2c05f980,7e24fd5e,87e4562d,65aeee0e,315ebc12,35731606,81e99bc6,be544c8,3a3c9e33,2e78cb5c,8ae90d20,edfc9eb0,3ba0ee07,82a158b9,154999f9,55e89210), -S(c8ff77e3,76a2c4ce,46664e1d,b33f281b,90e34103,500a9a46,83038062,42e59969,1d609bf6,2f6d3e86,c0510de8,4a42a45b,3fdaedd3,77101216,e43c2d86,751d7456), -S(b3205953,aa71cd5c,88ef7e55,3b94c8e3,ec4fd654,b7524c80,51908174,32850864,2c5d67dd,479dcdf3,41db7c5a,e0d03776,f3fe9ece,32dcda0,274a7955,b45edae3), -S(cb903c76,7ad3cd58,66c66429,9e9d07f1,cd35043,66784cd1,af3fc75b,73c4499e,8ef65e96,f1998688,2af0fedd,e0266d80,780ec031,fa47cc38,9e7bd059,eac83ba), -S(1a975b06,9e3f032,7fa9b706,3533fee9,f72c6c11,7ece27e9,cc83934d,a0c5d1e6,2cf46c5b,9f3596d9,5739dae3,a87564f6,13eb944c,5d1b6da5,3be8d76,14ddccf9), -S(d708ccf9,4dd50c89,de00a127,1cbd92bf,29f440b6,401c28fe,699f6f6e,50e0367f,fb173384,e0463978,a15de0ea,2ce146d7,b826f6a2,616d38ab,ae0a3dcf,1e11a1e), -S(11d850b5,4aa10ef7,8959f5dc,4aa9ce13,8ffa25cb,1034a365,234d0f6b,46458146,33162f6,bbb5ce33,af19cdaf,57dc82ec,69291c12,38e8f266,fd0becb0,bab02e8f), -S(7cd60401,be3033a1,85784a4b,adf9dd84,f4bfacc1,952597f0,6730f2d6,924332a2,6efade89,37b517f2,e1a1d41f,d6e6c137,d581d7a3,b55ec632,74ef8b87,1d9dd370), -S(bd82a0d8,34892e4c,974aa93,a64edeb0,9aa2e3b,16785166,c970206b,53ecf157,541cd14b,1fed321d,5a044abe,aa3bba7d,74c3f44b,db3f1fee,b05ddaa2,1f034ac5), -S(6f77bfc3,760934c0,edad8b77,f56d6309,179c8fd5,bbb731dc,42c279d,89f99a44,662854fa,e1da57ea,7e8eeb13,b3bf6744,f28cd210,ed461ede,7883dba7,f7b59d6e), -S(f31d35d4,dd0b2e6f,5b236e98,df56ca98,a5b6db2b,a2a8e0c4,eba41ab3,20cde154,e33e127c,b9c16469,83d71085,ec7ec9aa,12d41302,fa769c61,55af26ef,a7d1785e), -S(c0ea3ba7,be2030c7,790a3d48,7e720893,2e070691,82bd0024,5483be62,7916eab3,f5055e6f,298bb6b8,47e99275,64cb29f6,54d2131,1ff0a3ba,20a89ef5,992c0342), -S(23a696b0,e70e4197,d299abd0,b301b383,3df6f123,80120247,9e8b59a6,10a1fcf3,3af29a3b,ce23b0ce,afd9a25c,f1505958,b85d4f39,318a402d,cc48f98,ea953edf), -S(ac79289d,c14206be,742005e5,f367c4b9,e2b645a1,2c21d30f,ffeac884,e6f888da,27c49ede,7c0b42cf,91de7682,e6f224b,2a19f98f,72f40054,69c3121e,da2c4379)}, -{S(b365ce49,d21ca341,c173b6d7,2238c56b,f080d218,a89e57c6,ce1664f6,5c290a44,e77935dd,75d26531,d4045f72,3b4b5dc4,6608f8b,60f58989,d2ac4002,c304cf04), -S(af35612a,d1230c6b,3a260abb,69cc7099,f7025c1d,2a14d196,1914236e,4d4e1a44,b67d23d0,8737e96e,f629634,44b08f82,822c690a,b3d2838e,46ba259f,bb951b2f), -S(183181ca,37069462,5de3c48f,b8140ce9,84029874,e8189b4e,bcc8d91e,eb8d681d,a1780f41,8e7f00e1,e5ff8147,33a34699,79e6fd38,bfc03491,8acb042e,6ef4d6de), -S(4c1db656,41753e4e,5cf10f66,9a3e4b06,e18b3d0,1b56961d,8c400ae5,9ba239b8,cc57dad5,77b3d6c5,d96109ef,1006e33f,9c888598,c7248f60,5a531800,dd0c957b), -S(f0f61e45,cbe01564,17fdf9e6,db32d3b4,84fa0bbb,4be30aea,95dfc8ea,31529ee8,4b0de888,b71c441a,1c54849c,7e4a8129,d757213e,52b1796e,a5ab02a7,87087757), -S(84e4bc99,7066633c,a3997a55,a3fd3ef1,b4b99302,74349fb3,5da10b39,2f49a022,64512422,1acc41ab,68644fc,73b39a3c,6bcf1268,849bfc5,84aa7c85,4a48efcc), -S(a71007b1,e0747b7b,1b8b4398,232ee970,97f623ec,4924b8af,16ea98d3,6f98102a,91039909,9c42dbe9,1bdd719,d31bd00d,e040752b,cedf9927,77e0863a,96a5a259), -S(2f72cb7f,f0aed6c8,ef75c041,4ebc413c,21705889,de3e33dd,d3057668,4f882553,86450b7c,bfc89e63,ba1a1754,ba42125a,8b41f12,d5a5582f,ad86675a,b05bf998), -S(99f0e44,e11ea919,f16fa130,5ac6e72e,c11ae9dd,e08d3143,2ea9aed0,f902cc77,43f4e6af,ca0605e,749623e4,18027ee9,c64c059e,560d6c80,6219eec7,e475367d), -S(1aff311f,bed263a5,edcebb0f,e149302c,c0cc2b0b,92c69d33,d31c5522,eb9c9a94,8533cdcd,97190439,48d38bb6,845ca07a,9a9485fd,dbd44868,7f06143f,e85f046), -S(4a2dfcd1,4f601607,43273bfa,3702be5c,57f99a6a,29fa7f92,666d5020,6ffc852d,95931301,821cd6fb,63203fbd,a894de3a,57eb75b0,2f273f3d,bf462727,301dd9b4), -S(59c5a0da,480f334,944608fe,a580c302,965d26a0,dcd43b31,3854b302,af6abe35,40e27b3e,932ede7b,40490224,7b937b7f,2938edb0,a11b667f,16a90ed0,2a0309e4), -S(570bc6cf,fec905e1,564906b9,ebdecc13,60abe5a3,61f7c5c8,f03cd2ae,3ef9d125,55bff728,1f73045,82fe61e5,d4a92697,77503b39,9b320c45,ce5bb9bd,35def5c5), -S(bd7dab69,88ece4e3,621efa68,38a24032,ae9721c4,fcd835d8,6283b5f8,f9f02ee4,c7442cc0,95009f1a,193766f6,d050d165,d8cdca90,2ebe6d8f,237fb922,a1b6fb06), -S(a780a23d,eb8459fd,7195ea96,e8fedf8e,8b38edef,e0e0865a,b1d69d85,1d27c65c,f8c94632,a11f7185,9e3c7963,f24904a6,536321d5,f5e4652,3195f854,355de49c), -S(f0ab42b0,bb80f147,7f9fe3ae,f5944100,14a94142,e8312b91,86b0d6fa,3f0243ea,237a6ab6,b5e08f03,a7b58f98,e72227ac,6d3660f5,43da0694,b6821c9d,332724a4)}, -{S(38186a1d,6092b158,554f3f6d,c6de049a,2037577b,2da8db39,163fde30,b19dbf2a,a8cf045,9c7ea28a,415d01f4,47566d54,f986cab5,eb272326,442f32ef,cb6c43c8), -S(aaf937eb,c2084f16,301bdb4e,aa106263,cfe483a7,d0ba1b16,b93d921e,80f03a4d,7e18642e,8be01d91,86366b3c,c94aef09,c02501ea,e084a87a,a94d2d2,f85f84d9), -S(128b8279,ec2731f6,cf2ceed9,fed2cb49,f53d6237,112a84fc,c678189a,8e19867a,fc0dedbb,32524c1a,f44fefc,6b0e6bd2,ba65f23a,54f69986,52953154,41a89489), -S(7c3dac1e,6d89c8b6,e9645ec9,39dc634,a2cf5adb,323be29f,625703b,caeb21e2,a1b87f33,b5bd9351,15f16702,ae411a91,b3e9eb6a,814e678e,b3dd7431,6dff896a), -S(609d5c22,c8c7c1ae,211b4ca2,f709a1ab,75624b91,cb95d2d,6ea6baf3,eacc12c4,65a7b252,f13d08b,4b007967,69e6bee8,edb5cc68,d4ec8c46,527bcf77,535bd7bc), -S(691534e3,2faa9206,5fe7e8a1,8a863d78,afeeb581,97b1f48f,4f090bb6,9d3f9d11,2bfac0b5,35202013,60268e74,2376b901,a027d6f8,f0d91aa6,59341544,118a325b), -S(e6736a7e,e2f3f088,27012faf,3b3d1b7e,ed8dc136,3421e438,8ba70c5b,72eb4eb9,5a9b2651,26652e14,8fa3639,be0b4d5,1ba519c0,1285964e,7aa8a699,45bc71ef), -S(e3f05d6,2aa7b9d9,6e9480a0,a3eefe32,f1f6d45e,2fb1215c,ee5a3fdd,f147b154,47389f33,e03817ef,1051db5b,26efa711,46cf673c,12831163,2ee13576,b8508013), -S(b5041a3f,cf8b742a,dee6540d,e9974cbd,fe527e2f,4842a208,630b9d2,239c0657,4ea01569,fdf5b2e1,7631d2e8,2c2c0bbc,291d69f2,fdeb077f,4ea1df9a,6303ad57), -S(e5463af8,5dc090f9,9ff72771,c1cc3585,dfbf9dfe,329e69b5,fd0ac2ef,3f715ad6,c54085dc,a966fa9a,985d8e46,79335dcd,2d22d470,790f71cc,1d0aeccb,be9c5fad), -S(104b12f7,8fdbd727,2a5716f1,51238362,94261142,48209abe,e4dcbb4c,d7bb0416,ebb07749,12a3ce9a,e20b6696,e485811c,6a15ed53,a1015291,90672c47,e4442c6d), -S(1699a1d8,d04a07fb,32fcecb6,ae89092e,fcaaebd4,fd9c4af7,d79a5eeb,2c18da72,cff1a93d,4ccd9199,9c6259bc,fc975ab3,4992c8e1,8d1cae10,b0c1ce2,83101103), -S(13df43c4,4de2fda2,4b932131,e7c7fc62,896f2747,706ff959,85f98248,4cbc6179,1da341b8,734cec8b,74de0c08,a040ff68,d8d30ef1,dfe1ffe4,72ffc73d,a6a82a74), -S(2e101469,1b7e08f2,d3aa774c,f8f91ae6,e9aea711,fddeccc5,d816e5a3,dd752dfd,cd4e7f49,998ec720,a3ed2e45,8136fbe7,9942011d,da5d7fd4,2c56ed77,29f55b98), -S(b0296b3a,f9e819ac,a7b01bd5,7977ea85,5d2ba87d,24f820f0,c1ad5f84,6b9d10c1,192cc5d1,b6782d9e,e3f444ad,61c0b8d6,9772062e,7b03c615,b1cb7550,a76e1d11), -S(f9a11b59,6e369694,fd62d423,518e355b,a796269b,d2b5a88b,1c8bc812,40fe464f,8c919e60,86160ff7,8d1ce269,4512c16e,75f8a79e,da39df1c,ad104555,6d1543dd)}, -{S(d8e5f3ba,c152215a,8cf8ca08,40aaad6c,7d001aa0,140bb0b4,dcac726,229ee272,e59390a8,21e8608b,e53fb258,a426dfb6,ca762fd0,9d574f7c,5555cb8d,7174b381), -S(c2d7dc95,6c6721e8,6effb64d,5e1c4ec2,ffb13a28,706669fb,ac30f035,9d202663,8cb207fd,63af5339,f9a705f5,79f446cd,1a11c0e4,cde750cb,803b840e,5a4970a5), -S(bb3445f8,d7f47cf9,befd1a73,76dd9c96,f6d76fb5,b6d4b7de,e7f96dc8,c9e8f025,c1fddada,756d03aa,7d92135a,a8dd783d,63920238,1c2f5af4,7e702cbb,97ea783b), -S(1271c587,d72e74bf,286ae688,c022e129,f9a95567,9f74755a,24e85d81,486699eb,1259045a,cb14f2bd,7d5fc85d,d8c58303,9181d367,63e4733a,56172be4,b19c4a40), -S(76274ca3,884de253,ccd8e9fe,b2f7ceb6,1c7b6c49,1a358b42,e64994fb,80808263,d2639e7,539ec38e,b14c7d83,47fc4d10,c2a2d83f,81a1e4ad,1ba8267e,bfdd4dfa), -S(8d80c172,ea0f7e79,d3f2569c,49d49bf8,330cff73,fdce6b14,3a4a349d,e7cec2d8,86dd76ee,63fb3a85,ae315029,3e2d024c,ff1649d3,c823ca63,5a1fd992,975fda33), -S(441e6584,10404939,367bc434,f1c64c42,5b2bd11b,5beeec47,35919f02,4a4626f,3db30e8e,29e6cedb,7bb465eb,92526c4f,4b7d8361,b151ddb1,da878a87,86d83573), -S(10d89274,b0d498f3,d29df723,937c3838,49b4ffd8,b87427bd,a1d142d3,160c2b88,15df3d2d,b11e35fd,a423c709,24e497d9,77941b44,20e3093e,539d3406,e2fcf435), -S(3960dea1,9431a970,6bc4e886,8cbcaaf6,dfb9c87,17e664d0,4ff6eb5,4108f2ce,3cd86dfe,6d967078,9f090213,4661a7f,78e4854d,7e79e519,7283f8c9,a89ce6b3), -S(a1f9b8bf,15de0a59,141449eb,3a52a335,ab881489,7a7ae82f,964d3bff,f1dd38d8,dd563a40,ebbf06d0,84e21a10,dfd117e3,c8806975,53556b4c,2fb51100,6b498d6a), -S(17cbba26,9cf2b92,7d442075,396090da,62a2026f,ce3b3eca,858feb21,76659de2,71f31851,a2561f97,b0ac2495,d72904a0,bdddd83e,83a1dd87,b0db14e6,ff1348b5), -S(10dd7c20,902512d6,6484c830,53063a20,c7474504,3a378949,280a90b9,f8504102,1624bb25,937d3b47,43214401,c8016fff,f770f7ae,7d78d8df,381c2de9,13bc856c), -S(7ecc1dcf,5e9c56cd,43cf311d,5b31d269,50db89c7,2b51b624,745b3c75,eea68899,3ae1b7d,2e8252e6,43b73aa5,6d7c9b62,1f79d1bb,1d2973c,1bc3b150,a17d1ef5), -S(f57d8aa8,ca4c8377,14ca1ac8,e2fa456f,4c94b304,fd0b268,2084ab52,3768827a,2c5bb2ee,e4b509b7,7cadd78,4202c12c,3644ec47,9c599009,581f8b6a,7ef5bc83), -S(74905ca2,7116aec3,b96d16cf,fba3431f,5ccc3cb7,e5747525,124b5b31,bd6fd066,7d26da6c,1268cf67,846954f0,48c7dcb3,3a1244b5,8f0a8026,c3dbc651,68cbe871), -S(4e0b7166,de12f0ff,baeb2464,ba205624,e85b9238,4a3ebbcb,db9c6038,94ef0cef,8a85223,cf784126,3419d777,93fb66d9,19e3428c,5ab844dc,d3d9cc46,7ea95c10)}, -{S(f41bd2b0,e0f49133,747e831c,af4c7a0c,22d2b55f,1cd4ca53,1115d81b,b47754b0,869485d7,26d4687b,c57a9eb6,e90e93a7,bce3b523,998d16c1,297c996a,b68c4fa3), -S(ce2e4f9a,3c32ea4a,2198e61,8d7d88a9,153111cc,fc114a46,cb9b47c,63842146,5c90a793,c4f4b290,240dfc0c,1dc0df9d,a33214d8,3024304a,d49eab61,8c4d64e9), -S(924f51eb,823a89d1,3194305b,45ba1f8c,40a58987,73cb1a5a,a4a4017a,b55af76f,8cfbe8aa,d3b759f6,14c98aea,3b3443ac,46400a2f,5cf741ac,c7f590b3,39f3ea0e), -S(9f985579,fd32d32d,90ec233,c5577a12,b1fc350a,e94b5f08,ccd31cc0,33495f5f,ffae345d,8bae4446,bfd5b6a5,117c0b77,49cab9ff,eabbc8d6,531e0c34,fdaeb328), -S(b4d25ec2,6afed742,2ae7f209,f4201d0,91dfd595,3418bb05,12b1ce25,455ba8e6,8a13f82c,47489b6c,72223047,e8e079e0,165edf0,4c335814,b971a5d8,27d2cab6), -S(7f4ce1f9,acd1d262,6c6da2f9,7dc19ddb,ba3f15c7,7b6c88e6,3b0d4e41,a40a3c7f,750468cd,33a35da7,242142e1,e68128e4,b5210635,c4739aba,910ba9ec,c9c01fcf), -S(67f46710,16d87e34,b2d53d5e,c54f9fa5,f22c283b,a3dc5a17,70fc4a16,1a2be4c4,70503598,1378a67d,16827d9e,c87c591e,afb16fea,6a5ba182,4f6cf6c1,fa92b772), -S(1c30c0ad,43b0a74d,fb199442,b151865,7cf99e26,fca6e2f2,1cb97a6a,53c15893,3728e682,72a4020d,8365b4ca,eb153fe5,162e79c6,ca6a851a,e233a160,400b625d), -S(d92d821,8443e951,ad6ad28d,b7bd7101,756d91a0,cc3deba4,219ee34,ba2f6017,fc3dab7b,ac2436fd,a39a65d4,596dabc2,b65f8f0,c1195a51,5d8f2bd8,4f5530de), -S(3b6264bf,a47de486,3ceccda8,fe6c55a6,ab1d8188,d111b222,4aae150d,c3517ee3,e3f786ce,5adc8660,98965a41,62f4f510,8c1f34d9,2451af03,8f68e5f5,8f6c58d9), -S(c6b7190a,e4d0c14d,b3cba3db,c72fadb9,da9391d4,2eb7ac68,4e1b20fa,d89749ec,f4b7f04a,b1358c35,1b2c622b,aabf3e5f,dc5abd87,ab3cb388,86f73d91,202ce359), -S(c2846da6,a821c506,e022a927,257b8d21,57d82def,196f32a6,78b8cdca,d085779b,d5431c41,4ea1417f,3f4d90cb,c776ee29,9a6a8557,a256b3a2,58a887fa,fb5aa256), -S(7bbe2521,1f987b2,742b6266,d2c598b4,1de04ff,70b689aa,8be97f8c,63829bc8,dfb605ca,3491a434,e53fd0cc,d8bb2188,c6dbb06,cb18a9a5,cfc6844d,400982fb), -S(81a92f34,ce6c4383,a058d74,ac36b44f,f4bad7ad,b6ec6a92,87db84c5,9df3469b,31639fd5,7842ad40,4b204b26,7570a557,91dee70b,ac71630f,90924443,47597c32), -S(9e309152,54a25340,8a533606,d8f8dfb6,9ff93f1a,9d97212e,c261dcf8,ea3d1d7b,ab95d903,ccce7769,cc185c1d,4e24da15,b9c05bc2,7977c754,1b1023d4,39d75d26), -S(f72ff9,92e06721,559e127,28169de4,888efbee,e87542f8,fe0fa971,189baee7,db2e60c0,4678d370,cef335d1,d3e007ec,30dc03c1,f31c02cb,796de00a,f856e440)}, -{S(67c452cb,e71c61c5,8aaf68cc,b1f6208d,5646432b,86774f8f,60081179,6d5337c9,d5f859de,a125aee2,11dcc7cb,b50b4fa3,ef4f9767,7eb94f65,b6a181df,9b938c0a), -S(b068a1a0,e36426fb,2d959715,63faa818,1da81aaf,3ba3654a,f2570e0c,3d373d2e,9d29d11a,9333182b,3202e348,f547a9ac,ed5b6468,83608526,682b10b6,e1ad0f0b), -S(e33d0069,dcc14230,760f13d4,59c4ae5a,8af0383e,e6f37eb3,13a8b7c,587e0c30,aca7fc55,47536053,97b56a7,4d814548,993e11c7,4b89bf1a,b50ecb40,b9cbb5f1), -S(77f40f78,10b06a83,71c1493c,61a816bc,10f3b70d,5fcd025c,54de5036,eb6b2ce4,618187fb,f124b864,d69ae6f6,c9eb674a,eb73a074,b95194df,967b804b,c66d3e56), -S(d0ebe599,772c1450,979c403,25ef498b,69548f62,907bb455,1fba8f0d,c7b076f7,d0ffa315,3b96c94b,cb97af89,2f845295,ccfd1146,d8c682a8,3bb7488c,3fcec2f6), -S(2fe20698,39f33753,819d4b74,f0a036e9,2aefe03f,5b55f504,d3e1af7,eb5cc0eb,27e67641,1aa1a970,fa0fa0df,8a147716,b52ac4be,489194bf,3f192ae0,eceab892), -S(94dfb5be,319f7da5,ef283791,e6375480,1c337607,32f8e66e,bc649943,af99262d,4fedb692,4c6dbe8b,daec8caa,4273f77d,4736b73f,80446c5d,d4116329,5008225), -S(a0147c3d,f958362c,177aea45,908de2f5,afdb005a,89182e95,edd3f4e7,74ee0cf6,c81c0014,b273d2b6,2e7d40f9,d9b169cc,67ebc773,be51d8bc,7f35ff75,f0eeca0c), -S(91fd8598,f0a9c4b2,130310cc,417e7a3a,c1374b1c,2c76e675,f5f1a7df,32b1b96e,f2f277f1,154afaff,774390e2,e87bf67b,a722ee5d,b502a1c6,24042a7c,779d5a45), -S(613b839,a2dc9731,a2ba890a,e8f7c966,ab3c4237,fc14b05,7c561f6e,208c77fb,22b63998,85a758b5,848a318a,5aac49fc,aa14c4f,cb29f020,842280fa,618f235a), -S(653389e1,3b7f87e8,8d22d0de,d8b1de4a,b4902d12,a0c36e76,11ed3d0f,e1efcb86,ba710bfd,95e40d1,a4e8b4c4,cd1ee147,e01ebf1a,74f52483,4fc5148b,65a86e4b), -S(7b5aaf67,bd31c86b,e4877624,85b35fb1,4f6f480f,69aefa91,30e3208a,f9f9997,afdce71,1bf55d3d,4cb01dc9,3870e40a,851a8c7e,a7217607,1d3285f5,c727a9ed), -S(bbed5d70,be29d810,51bd811c,7f237856,7d097da5,cfb2d891,c0bc86da,7d680dec,229ba9e5,ddeaa4cc,498cce34,abea1d19,567e3a6c,878f8fc1,31be7b06,f8550aae), -S(1c4562b2,1dc0d0c,1c4bd826,603d07a2,8b7545f9,29e0cdde,77a1ce23,5d378d1b,b8976266,79671f6e,bd0b43da,9eef06bd,99dff8ee,5092e19,f260f468,ef16ef0), -S(a9edf307,c7fd7446,d71be12c,267a7135,688bf7c6,8f1dd65b,eed8208b,897dc380,9a20e692,9437be50,36a7b701,ad3a6a77,82234965,cadca1bf,4992da4a,24438f9f), -S(3bce25,ad7ebdd3,43645652,954ccfe1,1c5e9597,fa3a9f83,d51ea36f,2b55aae4,cfdbf98b,7f3575f4,4d37ac16,41352d12,bbf7e13a,4315cc04,3e9ab067,b3e41c52)}, -{S(56d09714,cde8f0c,f1956cf,a56bb0aa,b73507c8,bc0399f8,c0fd17de,19e48e9b,d62e1f31,b40ca6ba,71de9059,8a9fb911,6c5f0007,df0c33eb,f50db688,ef0ab90f), -S(8fd887e5,50b3b108,f17bf25a,12187b64,4b173b13,15d5dbb1,c9821c4f,9d05a37d,7b2d3e3b,731d83f,535c0c5f,1df2fe54,b1eb7c02,e43e73e5,42d0efc2,c9175fc1), -S(64331c37,736130c,78f719a7,52603e28,d8a48c9c,33e3676,2ddf079,4647588a,9f214dce,bcf18bea,5aa4823b,e72df87f,634e37e4,6b8e696f,41ac44f9,76834a5d), -S(6bed1320,7626f62b,4e323e92,ffbca06,4b682d74,59192c6f,a3569567,cadca363,8d435e2c,da580046,755f375f,b226ac7f,86d15c33,71114737,fc09b8f1,ff9d311), -S(e1c8c67c,56fba327,fa0b3790,8dde77b,a187df50,e2b0217d,8a151344,4cef208f,7be39f85,450ba36d,b2d46fa,457c68bc,e6c7d140,ac1f6f60,cc95d12a,b3dba197), -S(9e927dc5,427d6859,30da46a8,915934bd,4483374d,263d962c,fa0e9710,6cf285c,cb9b2596,90224417,d65d7bad,f89a946f,df0f7b68,2a28099a,118c146a,598ccf01), -S(fcf97f06,f70b77dd,47ee5661,ca5c5653,5b770d5a,ca61e88,10542124,92fa3748,5df3187,1f5af498,605324c,81dea770,67aa4952,7736a0e6,cd3cd6a6,ad4f185c), -S(f8922d31,8ee1c47f,29a5df4a,66ea44e7,7ac4ecbf,2440c4b9,3815f249,bc5a1b28,9377d8bd,548e7fa3,bfef786d,bca70039,24509e9b,d22e483d,9218fc48,34941d62), -S(6b7de62b,9c928cfa,e9da1197,951c010c,34dfbb7b,b111274f,ed5f4552,20909188,207d06d5,719938a4,f69be3ad,ffe9e83e,17d2e500,7d3dea3e,f34336f8,df3d226a), -S(e948b128,c6217752,8f1d0569,697c656d,92a92b37,34360795,73c9d7ab,61db30b0,7518e35e,1a5e4e2b,64966fbc,1185e7f6,b59766d6,a8fbd37f,36dd9354,14d68af2), -S(9d932075,5fd767b5,87d8cc95,3b2b7d49,4967a9ff,9fe673d3,8b7aa621,3dc4d7ae,80c62686,e574233b,21f8892f,7f8e3cf,4e05c47a,db687e38,4ce2079d,16fd7d36), -S(46eff49d,a6d4dd71,108dff71,e706a9a0,952a8774,efe6eb8,6cd28a90,1b89a8f6,8b26310e,ee49ba70,77f085e7,cb2f82a7,97fa3d50,c96e7148,892f57db,f89e3544), -S(72a59c5d,6286d1fe,c37b7bb0,ff34f67c,4a632530,37a22efe,7dba0305,2cca87eb,a3770634,995ae65d,c48151cb,f2e5efe4,bdb30825,cccb1277,e9728741,ea2832b), -S(1eb0e1c4,8471f8d4,1e34c22d,16bad4f8,2f0cc863,db92d412,8d7487,1f7f2f3d,232f76b7,1cd83c5a,4349358c,a661639a,b4d6a5b6,8eed0f11,a674385,8ce7bf95), -S(d4173198,3c8645f0,ec134630,7c6974f3,1aa396ad,f01a91b4,b618304b,34cad3b9,3825cdf0,bd454a15,ea3d18d6,b07dd5fa,42e1c46f,7fb6a1cc,f1a707e4,74b83550), -S(aa030fd2,52791775,e051f0ee,be7d6902,7da01452,67b4e712,960692f,1d59f72b,fc83d72d,5a0edc4e,c05ecb54,7111a10d,9341df1,b0544177,c2eda0a6,70980ba2)}, -{S(31095045,658b8c85,ec0c4ddc,7cbce691,d060181d,ffa08855,f3f36722,4c026225,9a8cc527,1c231ce7,aeb6e73b,9acbc16f,4b331b01,4bd457b8,799bad40,547c210c), -S(372f6cd,9a7b7907,4f730fa1,8cc1db50,a9747818,99df942f,4f2ceaab,e85c6678,7c9b42a3,81ebd00a,8d4aadaf,2e34daaa,e57f0633,94631677,ee675952,3c72753f), -S(77e7096e,7215e184,cb096b45,54f60fd9,4fc5f7b7,28bba5bf,be2a85b1,1984daf6,4a913cc1,dae55633,9a90de21,746d3e55,7e8db814,c23aa361,be967ccc,cd319643), -S(fd6c827,34bfd6d0,a6130095,d2c38135,e7992c34,6e85d7fc,e5b13410,767620fd,a3996aa6,1e87830e,6d2da97,5bd318f,c44ec9bd,ef552204,f3ecb761,b4541df6), -S(24824f95,be9fea47,be33b438,d855e2c,d0d8982c,2d8a0b0b,d84bba5a,eb8cf0b0,d7e5c1d4,d6c708db,a5b51a46,310bd68b,18b521b,e765fb50,e1d8978c,6460f1a1), -S(d1d2e882,62b62a1b,63ee8e90,31f37d7e,ba90b95a,3b577af4,c0bf5d4a,9cbc65cf,b88f4f9f,62ecbd5a,5165ab8d,92126053,66d719b0,9c5d41c7,539d9991,76d004a8), -S(9118fd29,acf4c565,1ee732d3,c606d374,c4e5306d,90614ae9,d5aab499,4ad300af,8498b6d1,dfa4b247,ddc437e6,cc2f4dbf,d46b4562,3912a2c6,1dea8068,c86d9e54), -S(c303d808,8f33b08b,ea8e2490,d8f4a108,27569644,9a116564,41166838,d6602b9,af7a213f,d6131447,4be0c27c,39abbe1a,3cc45c97,6f28182d,cddd7d86,ef1c26c1), -S(4f09e673,cf4036ca,6b466d49,11b21cb2,421ebd98,f336c6f,9be27aa,7dafa17f,d0b9b5de,d7517f0,f452d744,cc5c7201,f292df97,e70cf642,4879267c,160ccc96), -S(cea44dbe,7286698c,dfb48302,deeb4345,71ccabfd,844411bb,f0d63c70,626c8bfd,2cf9e22e,16dbc1fe,8f159bd0,36ff4496,7eb0d11d,977e181d,a885b200,a552108d), -S(799d8d8e,8297a1ed,5052961d,646c44fa,787ec15f,62c0ea1d,13ba4ac0,3b42dc4a,9ac6c9fd,e28c5dbf,23c76484,6ebae2ef,b4cd7e57,592d6608,9ca6fef6,faf148ef), -S(b7630524,9472c060,168677df,775b6696,97f281b1,3204908f,dbaaa74,b87d555b,5b157540,7c35c69e,9537a1e9,10410d6b,9c6d461b,9a00520,f6850bc8,9628bdcc), -S(9866d83d,7d9fe0b4,8db8c7bd,557326db,c74d757c,d0f063b5,a05eea98,7847758a,f664b109,f96f49f2,b06f3886,4f7c7e99,de8ac6b6,ec08f946,3855bd5b,c74f512a), -S(6b5cf6bd,565f780b,ad85093,3da4f5e7,6a168a5e,bb3c4658,c9ad6945,99ac1d0a,210f9b03,96d9d3c5,f2fd3ba1,a889cbaf,fcfe0bea,af2771fd,c021659b,835e639f), -S(1164bba1,af12b041,55796a4c,d5b17da4,db37470e,782b7875,ed553675,201d72e5,9f5e04a3,3b913c09,56e72111,bd99f2e5,1de13c2b,f496b72d,3b7bf9f3,42572d37), -S(ee09a791,3ddaadbe,13b1b198,a3e4e63b,5cb2f591,475827b8,1f9b81b4,1449dcda,88fafeba,bdd965bd,19bc434,8447f3b7,91de017c,3f89b292,4a6c6f76,839bc6f4)}, -{S(da34375c,e38127dc,cc88a823,55d763a7,2dd5d733,d9bac216,7c3e621b,ede529df,13426579,db1353d2,8095e1f2,a007904d,5c04a725,2c621ce4,41157aef,d2e28cf2), -S(a781c07f,cb52597e,f229d634,b3036507,c297843e,3e784024,d38b0025,72dc3009,e4fa3bcb,511877f0,8369465c,475dfbfd,e0973309,acd09a80,a9d191a4,e21aaa84), -S(d879e837,bb9174e2,19108746,91cbe6a1,9e19efc6,199464d5,2c9ba4f1,d32fa31f,e092c41,35550370,40c786e7,c3d5f72c,6be6988d,441829e3,85b1bfc,f1f00bd3), -S(9fe2fef4,5f1c5e21,110aa61,ee83af2d,2d409120,c6e510d4,dc2945b5,936c8ff4,a1d3701e,26007255,f4b8db48,bc6ef057,a7c146cc,ff50ef2a,e5f8d868,5a684a4b), -S(f2266efb,749fdf5c,dca22eba,8b9d8141,4b8cecf0,1bb25dbb,85f6e3fe,d88e55c4,11acf31c,ad2b4ab6,f3036259,a3b54bdc,6b8100f4,36bfc1ae,a17ba08b,8fdb8bf5), -S(527063af,4e7ebc65,2d45ae2c,e2149c26,f591b12,da157351,bf8b97d9,d998d007,3cdb282,740ff232,d9ac9988,8f0c20dc,96476b79,133af243,eeb01413,54c71ec8), -S(aa067591,c038a16c,2bb18b54,c6357140,731440f2,2b972152,d08726cb,f5654abf,81e8b530,a4997fd9,ff4122b8,b559c6f7,915b3d08,96ecc8f9,dcf01aca,f1f4a61a), -S(7a147e92,6e2b916a,c23e4fa8,d9349aa5,449e65fe,c52f01cd,a7be7863,fa2a1bd4,d13d4e2b,4e64a8c7,824b3051,e277da45,fd947048,ba7f9f09,6e6a6189,f6ae356b), -S(394773be,c4c8587c,a330f243,5ac5057c,f833333c,4693ed63,3d0e780,8d31dfdc,1374bfc8,7b1a7ad2,7c119dbd,cea325b2,c663aa4,18e9f62a,d5cdc878,88c8874e), -S(a1b4edda,14ce5c2c,ed276886,5a3a1519,ff2b56e0,f0e06741,613f7b3b,37d001b9,e462525e,6a1ca74c,be1e0973,139b2f1f,2b1458b7,dacf6f66,cd80ba4,1195516f), -S(a2a20ab,b8cb4a84,9625000d,a2ab6d80,6a2006d7,6994069b,2e50c83e,4aaa183d,3850f9d7,bfe1c1dc,b066f603,8a71f78,352d4cfb,44a7d646,81b86a7d,23b0b468), -S(d66412ac,30ed909,4c282dab,c40624ff,7fc5a593,494a9be2,954d0cd4,961999fd,ad6ad3d1,e3be49b5,402880f4,c67d1546,7b6d01fd,63e4f45f,f87e5901,7b8445a1), -S(ca666365,71fad850,3205e1d3,6c0b0062,9a6347b9,b9ad0a92,10ba208b,57fcd0e8,821d0dee,efc2bf47,4e575d10,83d63505,67235026,e50d9fad,541fb097,2cb196fa), -S(310184cf,7c38bb82,b04a80a7,5c4678a9,985336b0,f60acee2,2a048e87,bfbc6970,4e21334d,6440e46b,a12bc971,31d55598,94ec8648,ab901a94,c757b957,662b41f8), -S(e051316a,62329ec5,add4bf12,4fe30288,dacf5e82,b0977184,7c64bb4a,8c77802e,3358bcbf,94e23384,c9be2d87,79d56ab9,cc0fe4ce,23eb227a,741a3be5,3fdf36ad), -S(1dee1a31,e28d970d,11436760,7861cd75,292cfc9f,533197b6,7ce40e8c,62db266c,7f9c4f61,f534b388,7f00bf73,469601c0,9c6971cf,3ecbded7,63560e1e,ccd0e32b)}, -{S(a80dd274,9cb3c40d,af91b91f,6e8b0850,27fae17,96e416fb,8a172c27,d39e8789,466161e1,e9519ac5,e1b03652,cd1ce6cd,1d7dc696,aa59ab5c,565d822f,af427896), -S(493c8d4a,8a53ccc5,67d531a4,c833a8c2,6ebb3337,9f1f2330,9ffc7a5f,90ad860c,eb52116b,e4f5075e,e391948e,d7970c28,ce156e22,cd3e5820,ed0158a2,1158ea73), -S(42a51205,5158eff9,ed9b2df3,3f17a809,ddea781b,b0cad4f7,5ee9b16d,f03447e0,4b305c2a,987f11c,1700cc3c,b09914b1,cb30379,257c122,cab089da,b0115e93), -S(eeac8ba6,c3397ecb,ad93a0b5,1cbc9108,29aefb53,50a9bb5e,1db9ea58,a33dcab5,e0eaa01a,4596cbfc,76f418c2,6fa382ab,699e8ea6,1b700f76,98f5b913,da774b70), -S(33e903c6,ee45628,db06afde,dace17e8,bf8ff9b2,a4d1e3c2,c43ab4df,693d71a8,a9abf657,94edb2c,80a50e5c,e210f39c,fd37ce86,5eafac01,65191deb,adc9f379), -S(4af6278d,2c4ea624,c4a7c264,5fc4e5c3,85a983e0,1f5c0c2a,bab8c101,8ab36425,4af48c96,64a8e40e,33812cf2,6a4495d9,8bb7bc4d,3455e03c,21ed94f1,e6fcb069), -S(2855cffe,89b73f36,c4851fa3,92ffec8,5b7b4c7d,83998c67,ee8e710a,473c9f72,ecd7c273,c26c1d7,4de7bffa,6bd26a51,cfbf9716,7e9875da,cab2e632,25766e83), -S(1b06d384,d0fb68d6,396314d6,a6f12d91,3853306f,1a904494,24fb2c2e,d73e88e,3de9709c,cfb21234,f8d687a2,e6364caf,74ec05e2,82245cf5,9fe5d37e,e7e3e7b5), -S(cef34326,559a1922,ff354887,54a1bc1b,72d70955,33591c3a,9a2b871d,8845a9a0,aa2a7c74,6a149ceb,b276bc9f,860a96d0,285e9a46,d62b2c15,c9a78701,7cdba153), -S(39e39d53,d9c619be,c9204156,1c8dd8d1,4f5cba0c,94d93295,352c8448,d9ab988c,56c6817c,a33aabed,d8b724,754e8764,72e065fa,357917ab,d9d03199,4c04c3dc), -S(28cf0dcc,2765d3a8,ae99c40f,57d14adc,5d21e730,271f2465,142c5369,80b21878,908d84d6,3774fb34,774931b2,12530d35,8565392c,6ec35541,1cba899b,3fa29e7c), -S(383ae3fc,7967167,ad6dc50d,4af64da0,f5c44be5,4ac33d3,6779a8e4,7ec657d5,11ae57f7,6ef344c1,263974e4,25f27e6c,c68d25af,3c748935,f554e4f,5cc16ba2), -S(9f11beee,fdf9dbbd,c9487b01,869a7b18,c8db78d1,36027914,bf363f,951b1b6f,335899a8,7abd3401,d2ca87f1,ca330c10,c098f7ab,cc2d0206,faa0d8aa,e7726aae), -S(34278948,b6755e7f,2faa3674,f766e6dc,5029c644,55f7ba86,34e45370,a244eac6,f6e04f4a,f27a8768,23de58c9,d2ecfcaa,63a5027e,b6c7cb1b,428a159e,2110537a), -S(44828d6f,29e24d8f,1e1fd7e6,13bec429,27a1fa28,803b1ce8,ac43804a,bc2a4411,4781fc5c,6039f0f5,fba6d3fe,4fa8cc9d,bf9c3ee0,4c42a0f1,8835ecbc,b15a2168), -S(903910a7,1cb1f65c,838f84af,a3167c3d,f396436b,1c76403a,5526344c,ecb0a948,19978bd9,d0563fbe,d9cb07c6,f88e563a,7aa007d2,562feedd,5c8fad6,e555e66a)}, -{S(b3dee3f6,cc08c0ba,5b7ba3b8,50469647,34f7dca1,630e806e,f84157e8,2992c765,d523bf3c,6b004cbd,59db62b2,58395f63,d487d6ce,31799ee1,59ddf96e,d9bae2e8), -S(f5c52e87,8142cf16,d01aa78f,179460fd,7a8d7645,498118a1,a1ec386b,c2860a44,868b7621,a41ca177,84d6b4a4,d5a5ac40,ecced5ea,d8d5bf13,e5bfa29a,5f998c38), -S(26412ec7,e11e9347,d515de0e,98e14920,522610a7,2c090b51,f03bf049,86738df7,11a10543,394f932,19284377,1a2d0741,ebd89e8b,4a0c0dfa,8f8cc5c,db7cc207), -S(8e313452,7bc65ca9,241666a8,bec7c6f9,b92f2f46,c91c3843,e430a22c,4e6a92fb,bf6e2a1f,122f4b35,aadf5b3,c03be0d8,406c0b74,c3e48b1c,85023996,a0eb1214), -S(ed72bb0f,4800c2f4,2db83b49,137af4fd,40d53e5e,d690fe42,b93d8cf4,a603d3da,4dc24219,6e195c7c,c1bd412a,a0982a97,80ed39c7,c1f34181,6540ea3a,e52f0c27), -S(a84809bf,a6592d13,47f1f37c,e7a052be,d4a5e06e,e27c369a,61a74f26,552786ca,7bb26691,5e544c06,cb7aec5,aa61979c,a77bbb52,67dbaa2d,13517b40,3ead93cb), -S(889c0732,6ba150eb,cbe394a5,3bc9eed1,1c6759b0,4f8b82f9,79f24efd,b2469dff,6c9a2c99,7ee4f506,d3150dda,71ff54f0,88d8c904,596fd99d,d2f5017c,9d72fac6), -S(b6f64c81,b5e1ea08,8b712eb1,7a7ba7c4,ff4821e9,3e68c16,7f385e5c,d5e097e5,99286e7b,2c2b49f6,2c2a5d9a,58db244,5e5f4981,b1a7f40b,b0f86004,40e249a7), -S(4b131fc,5d5c5020,48aa2195,c079cb10,8bd101bf,bf4f54db,793bff99,3c2e4a0f,a689fc36,fb782cb5,c9722f4f,8f123ab9,5fc02dd,d1caafd7,eee117e2,e58c6609), -S(8bc5c221,9248c065,b713a126,facbeb63,ef435ce,6759ced7,62e189d8,82adfb92,6663fdc7,32a65abc,8b207cad,dd72ed15,68bdf3bf,c2e84345,9f964f73,fa325216), -S(ad8ca6f2,f29699e7,c4b055c5,bac3738e,d3b390db,21512a70,c3bc452,e231722,fbfd004d,174964ff,273fe355,d76281f,b47fa1be,eae7ec13,6e4cb5ca,5e703b54), -S(12270e16,b82ac7b2,20bee7f9,8c45c6d7,87d14d3c,2e9a2201,67650e2d,c56110b0,390c44c7,4d01351f,78b80029,e84b211d,4cba691,1201864a,d0632466,ee747bad), -S(48cb4d0f,e669f556,5c7e630b,bf435d0c,b0b47511,553301dd,a9bf6e35,b59fb9cd,be02b272,e6fb4e3e,79d6655a,aa37a132,8649b74d,4ab6d733,6cbcd1cb,d02d3f60), -S(558b4a91,b01ae7af,dbe952be,e03987d2,bc64337a,8178c079,f06ee88e,88b4fcc1,1dd61340,ab7dd93a,6b6e169,a4879fbf,75d24270,b0708cc7,51552ca4,f6018052), -S(af5fb90b,d4d48260,9fc8f8b4,34724c8d,162997f2,a6afe68d,97a6bf46,629aee86,ddfea22b,6fd0c331,68a196aa,29c0f0c6,7e828768,15527132,99c37e69,f788c4ad), -S(2ba58b64,b588a995,3872a303,8f478ee7,ae03b805,afa95c54,62920a80,8a12228f,b902f3ef,aa4a081d,1260030d,44d31436,7c5a5b7f,4ccc47c0,1f82035d,af92c39e)}, -{S(df9c2e20,68e1e333,f6acc6c3,ba9928eb,e761d4b0,27eaa1de,dae18079,29705021,491f455b,6e937f91,35fe9060,a8c5b6c1,60de5af9,ba90aba4,c060145a,da1b032d), -S(17cdf19b,1f93cbf4,47e2f77c,6f4adee6,bb62f01,8011e8c9,965eb336,899d4b6b,5d5d7d2b,33222ede,aa07c15d,7f07981b,a7a80c94,d9a4f2fe,7413b4c1,dff20e7b), -S(de7b1e48,3d1e4e54,39a65ab,b74bf705,92a75671,11f83390,78699547,ad798cdd,61087a47,1c37aa33,f538234a,9179e9ee,b4af8e89,7d1f5afb,497ae5ac,8609f8ce), -S(8baae56e,4774ca16,4bb58827,896bb7fd,6dbde044,3e88eb57,aef2cd98,e3968870,7edcb7e0,29411a39,bdc581d3,3a8769da,d0bb62b7,49e2e05e,4b698b73,d77471d), -S(74bcf4a8,18f280ae,6216e44b,fa8c65f5,4de08ee,14f2451e,ab85dbb6,33ecbc27,a72d7c82,19b2307a,3747a6af,e17480bc,12fbadd9,f326a09b,442e5f7c,fa18aa28), -S(8c24276a,5f468d59,d55a0ece,ffd642ca,ad8a7dbf,bd3ca6e9,abda6a3c,3e66c01c,b7463b3b,6fddb0c,cc2b9006,a7af9ba5,346921c1,ccfd24e7,4bb2d09e,9cf78c16), -S(ca4c86a5,438e1b85,aeb79319,95bb4cbb,c2ca6eeb,22eb18c4,449f8050,f8403023,6a86b9d2,d205188e,f6bd4414,1f9948df,7d9bb06a,538d5016,fe310d53,b3a95d18), -S(768b3d99,cf1a2d36,972615c0,b9dd964f,74692061,1d36bbe,892512,5855ae6c,5e821acd,1a49c270,b589b382,159ee4aa,ddf1a163,3f00513a,935f0f05,d4174dc9), -S(f69a77b2,368aa4d3,55639610,d3a4d6b2,72638efd,4ae36772,3868146c,50a81e0c,afc09cea,e975c008,c02827f2,86b4a85a,25e9f5ad,7e26ddf5,fe73f77,edff3141), -S(4d266e6d,8805e372,2ae985c0,3f808e09,4012a97,23cde34b,cc119732,1e3eeb4d,5747f4bb,38eb2a19,74315a74,7fecf1be,2633e3b6,93a6571a,e08bc2d6,8ee984ab), -S(6ccfa6fa,a5bc8629,10cffbd1,c7815328,bbe40716,62b6e66f,3e6db1fe,d796430f,1bb21cdf,c4aeb248,454a6e96,e6399a56,e872effb,ed3c89b6,95d52598,6b801367), -S(2bcac4d9,ad3f7bb,784ff508,3ee24058,871f92c6,db50cefa,3d84707e,8576c271,c2faffb2,f59066f,1ef1e186,3510f9d8,236d9d6c,37a9d5e2,9dc1bd37,1a349074), -S(4ab261a1,8413f27a,328dd402,4dcdc6fc,6d31d071,f479d8c0,f1857f0,2ace11a1,e53ea413,8cd3ff01,21acc725,345ce814,a6739aea,e4600dbb,258df68e,9e3dc4eb), -S(7c276455,398e6e95,45e253a6,b6381d74,1cee69cb,214686be,a81435d1,eb90c86,704bebf6,c434161a,66db20b9,5c859064,a339ffc,35510e49,bc378440,f6794d09), -S(b3a041b7,cf5e1d80,ed040d11,851e5e5,292b7a20,b125f018,979d2853,4e0b2d6,f8f8767,5801504b,98013371,525962f8,d40b44fd,d54862ea,4bd33629,b34deba9), -S(d10e348f,403ae107,5ac0f8af,b81b17a3,aa0d51f9,2cc8d271,2bb2d4f4,cea9a881,5fd767b,30135e1,418ee9b,b83719e0,5f99c3a8,87733c13,695dbdce,c1b26ec0)}, -{S(afdfa934,6f7bcc74,ec473e17,f5048650,11c5251b,bd6c0c70,c25cb561,4b004da8,b16eec26,d575cec6,b8720f94,4ccdddd,78a5c446,a0cf286,fd933f6a,999a4a39), -S(5a4fce51,d54d54ba,b8148e3f,2f8da91a,50c5a4c0,409be13b,723f3ed,7879e1e2,5ae7c52c,f602d6d3,b68f6989,f6e7cb97,484de6f8,d729dbbe,587756b8,cc8b2d1a), -S(53831467,eba14563,3181b826,839812e3,36c1a17d,ffe4bfae,f2baec53,ff428d8e,fa471d8,73ba000c,8d23b0d,6bf79d36,f57a7852,4aa8c52b,227fc42c,400b4fe9), -S(ab384400,3f19fcfc,10055f6,290a0540,cf2242d0,ccab8a4c,40319440,54f0aebb,af368bca,e17e62a,ec0a5544,4d65ecd3,a497306a,eff4a439,92e7d1d8,ed5495ea), -S(ed08f215,50f6510e,e8cb5e09,53ca47a3,9a140441,cd7dc8ac,2c319ca8,cd51c781,39e4c088,589c9851,b78aef9f,33678f7c,ed46d4a,658ccf49,b1c4de72,9fe3b64f), -S(feba0c3d,930d3c71,d2edd2e8,e63e5f67,3f81ea4a,5f8890eb,3fdc6e6e,9c729830,a507a2a8,a0fd3d76,214f59d0,cab63525,54148970,7cd0ae2c,6488efac,7d494d99), -S(f5da1419,be3e268d,b51dea4b,af8867f0,a02a29c9,599266e6,e0e37b,d569d8b,1ecd596,4748be32,44cfe953,6fa9ae30,104b1e6b,8ccd69f4,1e5891e2,242db1c8), -S(eaae3a45,5aa38fed,381ed64f,b6353d0f,2236d267,97f5dc1a,4e7a511,1654be5b,24f1dedd,7f3d9cef,572e7819,b09be2a0,de1f2f4a,6b2314f7,57a81b18,cd1fdd08), -S(a997a9f1,e9fb824d,768fa890,b91ec55f,c851127,5c16eb4a,99577fe4,87d155e5,9cf136a2,c3fd76f8,d4921bba,9d61917,b6ebbfa,f55a4cf5,69665d47,bce7a44c), -S(f20287b,958ffe72,72d443cd,de9fa6f5,f9ab208f,a74c6147,10c44c33,3777f1,ce614f5f,87c3a366,65d7f574,5446d80a,35a8113,1fb4dd2a,aabed948,b9e09931), -S(f9fb85f3,fc4e45a1,6b6eef55,cd8656db,de777390,f20b576,a28110da,e8ce5713,51de9f5a,7b2f0101,cd02e6c7,c98cdf93,a430d62a,1fec4f3e,95bdc3bf,a2212e13), -S(d5fa0933,f13c1f4e,89caeba4,101f44c0,420da5c6,7bfe1ea9,66cf01a5,ef48b1d8,5efc8918,8b9eb65d,faa6e0e9,812407ef,35d8db,76f9e722,ff63bc3c,3afc3b1a), -S(93899e6f,fc291a4b,e986f938,b8b378be,bf4c3d35,f9a1bdd3,ecea5f04,d8f4bada,a19a2983,55cb62fc,43334649,1c89f26d,fbb67bc3,872f7512,9229cb73,d126293e), -S(8fe07488,b5b173c,d530d796,a18eac08,80164c2a,ed787b05,90ac8dce,3bb120d8,829abce1,43ea8009,e4f5f481,125ca6d4,ecff3f32,577cdbf1,c054a23e,67f18b0b), -S(10c3b093,5461407c,369494a7,631eb4a2,365b122e,ce0a6b95,7c1bdbee,387394a4,f09d69ec,925c9a43,57648509,f7db85a9,22f609cd,32b400ce,3a80567,88a74627), -S(cfe48dfc,f5566fbd,7562ed68,576a7911,baef64f0,dc63e158,1a29bf23,3e1a058e,440c6051,19f2a948,b4b6c3a2,7e711cea,c7983d7,f4a2db9,537536db,fdebab76)}, -{S(53d772b6,b18211f7,1478e9d3,3a0c061e,2d232358,44177867,af91508d,e014f22d,b2e85a07,8160d31c,3ca32d9c,ba025904,1bea0368,d9eb13de,8af8f505,73142ed8), -S(b9d6067c,fc26ba4a,1f5bab8e,d5f28ffc,bb6bd6,b61990c4,1b091ec8,2cba973f,532d0ab,7731c02d,91cc7e51,71b625b3,af5a605,d92d02a5,fc4cee4f,afa09ebb), -S(e8a93ceb,3db0a4a3,9a3b768c,700fb504,652161e0,4a1d4d92,df52cd4b,83e65e38,791b967f,22543fea,9ec38e5e,a14a94cc,9d11ea8a,73ca0c13,e022d53b,f8bf1148), -S(ac6130f7,41e1601f,5a92bb75,90a799a8,3e8ad9c,c911ed7b,7dee1bcf,da14f332,97ea5d16,d5c7e368,c7b97c2d,7283cb03,f215f79c,d1d80276,6f9923e0,ce80ce44), -S(ac34d4c1,1d2d4ade,2f044e88,6b57cd45,c1b23550,538059c4,e9855077,4132643c,7191e155,aeb3b578,6b55db41,652e8af2,bac1f933,d6f62723,808c6172,bf0eb0aa), -S(a7c4bafb,f1988992,1ce15754,187d41b9,eb653dd,bc97cf05,ddf449d8,c9ff734c,ccf20733,da4aab6d,81db8d5a,d3f12d1d,9cbc943,8b92165c,e83c5afa,5ee108e3), -S(c04ba857,e758fdb0,29c02712,1671fe33,9b7184b3,50ad952e,9d234681,43f7568d,9ce5d9ca,65f96b76,b4b06f57,f34de7e3,c64a1d21,f07fd6fd,eb7d47e7,bbf4e6c8), -S(8230e7e7,81259e58,e9b74a49,340733dc,252bef7b,5b7dc82,a4e99f0b,2998ba67,9c71921,3b3254d1,f53b4f30,d0a8e665,186e272c,d0e5d316,a7451eb3,2ac8bb3f), -S(720c2f5f,6465d38d,3916939f,8d095657,e547cc5f,849f4a41,30485b1,2d94b5c7,8635961f,5f74d176,e4ae0ec6,e4b3b394,6d5b1766,fcb902fd,9f9bd982,2ad4e4c4), -S(263b45ca,b3547cf1,5eca4381,3d1c402e,5c209d3e,34a288cf,182aa4a3,f04304f,3516b1f3,524bbdcc,fddd94bc,fb86a43a,27a7a78a,fcbbefdd,6692fc21,87364438), -S(4edb7d61,a45ebb51,1fb0c220,6f16fe60,5a202976,9007c3e7,11b94889,a983d0c8,b482fee3,fe824b1a,3251cd2c,3f38ab4f,adad1fee,d398be92,58d2c81d,79b0eb36), -S(f44c286a,b8196e25,87c225f7,2091db05,e47f18b,5b9a0b9,79d2cd3b,15441767,b7aa2018,5925845e,661ad980,a6c215d5,fd7072cb,46010930,ae64089,4c8a0af8), -S(593f9bdd,b246bd1e,19eeaafa,17e348e,5199decc,8e63ef68,ed8bff89,bdffad48,5201d11f,a4ac67db,dd66fbaf,5c2ba20f,8bb1a6b3,18cdfbac,6b257aa8,d30dd316), -S(823b4c96,8be9e125,262d52d9,4aaff240,55def10d,6353a347,e4248de0,7889ecb2,adfafa7a,fb1c60e,e7fb3e2e,73c66063,5a9e97e0,4a38a120,b7a81f17,7d1a6c41), -S(8daef78b,c46e0f5f,858fd74c,68be31bd,3b474d9,6bd74deb,eeba69af,5ef3056a,15db0684,bb6d4e7f,b135a4ab,f4b81d4a,a9fc7e93,c26e3616,b7b938da,25d44a06), -S(2b7616ca,eb608427,5a14eb53,b67a2ee3,b831fb55,6f63e0b2,e01650f6,e6900a0d,915e7dbc,62f8e349,8ffdf22d,d3604d77,bb701137,b6c36543,84cce993,c4613ca4)} -#endif -#if ECMULT_GEN_PREC_BITS == 8 -{S(3a9ed373,6eed3eec,9aeb5ac0,21b54652,56817b1f,8de6cd0,fbcee548,ba044bb5,7bcc5928,bdc9c023,dfc663b8,9e4f6969,ab751798,8e600ec1,d242010c,45c7974a), -S(e44d7675,c3cb2857,4e133c01,a74f4afc,5ce684f8,4a789711,603f7c4f,50abef58,25bcb62f,fe2e2ce2,196ad86c,a006e20,8c64d21b,b25320a3,b5574b9c,1e1bfb4b), -S(6ada98a4,8118166f,e7082591,d6cda51e,914b60b1,49696270,3350249b,ee8d4770,c234dfad,f3847877,a0a7bcda,112dba85,1cdddf00,84d0c07,df1d1a,a3ec3aeb), -S(a94ae8,63264dfb,b910ea95,4ce9ca7e,4f86f92d,9f3a95d1,ed61552a,7a3f5743,7f53f7f1,6ad2d08f,15e73314,6d80467,41557acf,19556c0f,ed7117ce,37040823), -S(b692c750,d23d3674,c351e3b7,e1a8a87b,14a5df81,852eaf35,209d0ec5,6e22a2cf,b18c4f17,252db89f,838de32f,b3340ea2,bb961a39,54b38c47,f9a8219c,4820a0cb), -S(691fc741,80e75b55,47b375f1,1bf60abe,451d27de,1743a436,5f8e4bac,ad421c09,8eb5fd9d,f3c03240,6cebf370,8125955f,bf2ef703,475d3fd6,1a0291b6,69b52d9d), -S(703b5f14,a7d82473,1196b52f,ae9ca8cb,b245b004,7a9928d7,d0c42f33,391411dc,5ed74eaa,49f276c0,4d61f31b,6da4137c,bde5673d,8e3f815d,efea7951,f88585c), -S(29b8ec47,d241eda1,e51bbb1e,3928444c,3747b4fe,7cecb365,2bbc4587,2f504875,88693238,8562f8bf,f7d72324,62ebc54,6b93a95f,77936b02,eb1cd6a7,d4199bcb), -S(444a07ad,e81916c9,32bdeec2,21c556c4,6b7f6491,e99b479,2cfec82f,4ec17910,2e084c2f,eead5200,77c151b6,eff9375a,713b9d15,5306708d,b3f538e1,8eb18cf), -S(e0dd618b,226ceddc,f560527e,20b4fe58,e5fcf28,39911ea6,c3e8a4a7,e15f9121,a063a157,3377bbbf,1b9a5ebe,afbe11aa,660c1e65,df1392b8,97205858,3c86a3fc), -S(9b99461a,2e8360f2,f2ba0bb8,bcaeb699,159e0652,69d9042a,fa0c4e30,a7b6f30d,3fe7fe04,3cb45303,3d4f5560,7d41cd76,9036a49b,82912350,6d8b9995,254154fd), -S(504da3a9,d9d9c81b,c2065398,4ed28cb1,b5beec9b,6ce5dfb6,cea94e54,fdff044b,cbd40d1e,858133c9,cd20b9e4,ff9fe94,f7cc9579,39e6df49,7a6bd702,797f96cf), -S(ddec0aac,1ebce6aa,ad6300d5,60f0e503,829f0bc6,479641f9,b19d9f6,484376fb,332ff5b1,fc83085e,736736bf,3c265e4c,8f80925e,6f38479d,6563bc34,e5faea1), -S(dc530ceb,b82c246e,41c522f1,d2571d31,4b14edf3,91577a2b,64e42172,b23562c1,563ddd93,857d6529,8b81de24,19e5cede,7a4c5b7,a2fe98f6,9efb8906,6f32a98a), -S(7604d60f,418dd132,78058942,fb2d2153,c0a2bfeb,e83c5011,a451bcb1,58db0773,38be14ae,d9e1c404,63ef92bd,d62c599a,b37625a8,182a3763,4fa2de90,535d50a9), -S(cb896744,77b20829,f5e2bd42,8852c70b,91cbd0af,cadf219,a69727b4,cbec8d7a,5710d17a,20ea0dff,980d3f06,38d8b910,b8940d00,dd4a323f,d777d942,213e1093), -S(501915b1,391e083d,e88c795f,8464c846,f699a79e,edb1b963,3e29f71a,9ce4d022,9e1dcc94,17ceb0e,15762f8f,7d0db85f,3bce3ad6,fecbe2c3,567853ef,ccd6d0f9), -S(a63c0b8a,4eb2cb10,1e556904,a7246356,9909055,f45aa4c0,e89c2237,cbffafca,9650b428,12374811,738f4ac3,a2ac0505,396339be,4eeeda8b,c35e6fdd,c51a1e56), -S(a16760e5,c3643d19,da15c034,5feced27,488ccafa,ad5298fa,6ee1070d,a258a761,736a7c7e,69db053,6f541079,158d671d,598efb1c,d75ec804,c7b2b49b,1ad7638a), -S(840693fe,73b96819,bb1b24a9,35d5dc83,f361273c,d0989e76,1edc35ef,50faf90b,4294e19b,49558667,bc6237c6,86c30aba,a2660580,563d465a,fde9875d,74c9a57f), -S(97273c3e,26e12369,1d0ade3,3aa261cd,a45b2d2c,d749af71,a60c0d15,85e18e03,2700c565,dbb08439,fb74317e,60776fca,d0efc1a5,5d0ad87c,18f82f2d,a97caf19), -S(978d68a0,5ce30528,e4db2dae,99f6a245,f69cbd04,3c7171ce,ce2bee57,60e68b9,ffef379c,1515b068,df562f3f,bdadacfb,8aabe5aa,466105d1,97a8febc,1596915b), -S(dfaea7bc,c78d275d,9f6a74fd,21fdec14,bcabfa45,e44070c1,9c44d449,c5d52231,927b810b,c2994b8d,2ed5124d,98e2f5cc,58410607,82b1ed80,d0fae288,8c42d538), -S(ca0b766b,8b8d76fd,ce471a88,18e043d2,604d1ad2,b689cbce,70ceae78,fddf5a27,ddf9e3bc,935ea0bc,22f977ab,98a92414,643140ae,be0448a3,35d6d44a,1bedfc48), -S(11dcc001,3be8d4b7,85e87153,e060d13,57cabb5,34a2c1de,2a4a70cb,9803a031,5b5d46b0,6a96c30c,b1901c12,eaa1c656,3a2f35b1,e9026954,36e087aa,3deb777e), -S(a828121a,18d23262,bce26648,ab44c45d,c5027ae3,f74786b9,598f22b3,c408bf08,37893209,80d7d2de,6074778b,2e8916f0,4043a616,982a9b61,d4089623,31375cab), -S(291ec5eb,e010daff,3ac00825,3452b065,d9f7fcb3,66e125af,22f11358,6263fbaf,4647cba2,45d190d8,2337f217,c278c98c,370120b3,d4e04110,e6df2c54,92d63bb7), -S(44735d48,4c584d70,6afc573e,8ece7670,c79c7b99,99eb0141,4a73905d,34a1cf01,30a27c9f,67b47348,583f1e84,5e7af221,438d4c9f,a1e0cc19,7312ec6b,908d613b), -S(fce8958f,507d5d59,bf0fb944,7be40c23,db2741e6,f89351a7,f29fc642,a60c7d4a,69de744b,9d2ef778,a7280325,bc699cb8,29874d33,bacc1fe7,6264eff,600c815b), -S(171a3251,bc6e72cd,630f8130,d4695e48,e0e649c6,82bdd5b1,b87c7b7c,968cf664,3492ac7,faf2ab56,cfdd5278,9831ea1d,e90ddaa6,b4d6e6e6,fa960bab,2b55a55c), -S(adc566cc,6c9afbe1,41a011fe,e121f0b9,a5dded68,fa9cdf63,45a00fdd,d38d69b3,38db9e85,26ab355b,5ed12b5e,84e795e7,7e2d2c57,24cec516,9cca1946,1d8d9c04), -S(9694e1df,8067defc,de9dd34b,4a4bc91b,653ede57,3139b9f9,4df55858,74f04,f002d8b4,3940cd6b,7cba586e,18f1616e,db907010,230445d1,a96b9eee,b43778fa), -S(8a90adbb,a8c32e,a9149e02,57bd9d24,7da8b0f6,5cd6332c,5803f83e,26a1bdc5,f7f24ef2,aae5a954,db200e45,ae75bdfd,5f4ec6d7,b203459a,7360a9b1,5ae2a9d7), -S(234b3911,f965ef93,5ab16aa2,392d2198,f5df9022,962ceae3,5e73f05e,d7d8f817,a66aa264,a24e1a5c,e9bd5ce6,164cde8,4083c7b9,c354ebbc,caac78c3,f5da2aad), -S(7d22623c,84ed234,5194c248,eb984ad1,28d2d4b,638b687f,730a3693,10f1c4ed,f97e515b,618719be,ea3603ad,7c40e827,59bff425,a8633365,c28c755e,b06769c1), -S(e210b4e3,cf3a2e24,951b0623,a83a8793,11cb942,8d679cbb,16a15718,2e6655eb,f4bfb50,43768438,592e7b75,41bee9c5,f263dc15,59be620,c0dc128b,d5e29339), -S(878c0097,ddb0f977,d75d579e,ca8d0bf1,a887fe50,e33b0c8b,bbaf2874,8875b321,a3401763,39f99298,9335879c,dd43a46e,d21d1387,55be87c9,2f486629,49918020), -S(9a6dee6,4c79975d,2adcccf2,8cbd8bcd,c8bbff9b,2811039d,5a6fc051,9a212503,9c0f3d81,5d56afc8,31de81f2,750cb54,9fd5fc63,b63e2c66,ae88dffa,cd072236), -S(3fa53681,f50925b2,710b66ca,1efa5e8f,b819c5e4,206a591f,d1492a1e,d13279f5,82a5c753,367d57d4,fdad7e9e,8b7ba625,7c50c07,10f93c8,5cb180e1,a459698a), -S(7ce51172,8f94ef7,7924a1fb,fa8b7d1d,411d0e21,65c4a1ec,e105d4a0,909081cb,dbd596d1,bda2f32e,12cdc910,2762f3cd,627cf29b,1b145ca9,dd2037f1,7daa6a86), -S(afbee9e6,d5b0bd25,1dd70bc9,e3b3a013,40116e09,905bb29b,797ba66c,16db5135,8a315473,84275d82,3c5296ed,b56ef5d9,7af96617,dc2e507,c009be9c,f3d3da4), -S(14d13a78,96bd0978,d4a4d4d5,2266afd2,e0f21ea,5c1a693a,9ed4990,81e43974,dc84f2d1,86d91fca,62ef088d,1794715c,c8dcd9fe,efb4aa5c,46800240,886c41dc), -S(7bc1045c,4960054a,fc979961,5cd7faee,5dec92bb,98b4c3d0,9620a488,fd32c35a,b8f420ec,cb5dd9ae,3f075e28,811ec9ca,bd770836,ad40371,66073db5,c1166735), -S(fa24d112,4cf21fd1,bfb06c10,9fa49f10,c3ab248e,3d08f620,4529612b,f7a5328e,c0745547,b64a0068,25ae8f90,82f8565f,ed94865a,d185a364,602e6468,277b3cb9), -S(8758ade8,745d4d18,c8f7ad6a,32fa05e1,c7a08bcf,c7cad42f,7aef474b,de02cff3,7864edbd,2efcbdc3,946dd250,6fdc2ea5,2f1626e0,b7300f8,9ef16420,12ae4853), -S(d2783741,6944bdaa,d212dbd9,40cdc7fc,2847fe5c,a6eabd45,dd6daa9b,9e122693,c7139931,989b4f6d,3acf854d,5aec897,52c69105,2c6d2586,27ef13b7,66e91875), -S(624120d8,420a5afb,64673e4e,b272f7a9,3b7f1f7b,59f4b145,10115691,70a597a2,3e055b16,ce482c12,88bcb9f7,40128b71,e5a441b,4c45056c,dca1466c,6491cad2), -S(96a21be9,a6e8b94c,7ebd4782,809830ac,f2a373fc,6781405f,a320025a,e7bcb4de,772ce6fb,711c2898,dc8446,aaa8cc7b,41608392,6212908b,705ca412,1e2c5e1b), -S(a9e2a4b6,4032f43,46ee1148,46ba487d,9a82f80d,3408b8ea,8434c521,33135ce8,c8537b6e,51846fc3,18898604,192d86a6,36ba3c36,f7ec9aa9,6185e7be,f160b5d3), -S(b43b42e9,381358ce,b8a595c4,77a9caf4,afc6e0db,1f58af55,6dc5bbdf,2cb4449a,556e4e70,cf7d1a16,9249e954,b749619c,dd87aa7c,723176b1,7361966d,2d2b6fa), -S(224cd0fc,393fb763,bfbc3c44,b829f61a,22ae6b98,22622367,2d0890c3,eb9ce9e5,97273eeb,eb71bdb6,5ac5c677,807a533a,f190cd12,e01ccb9a,d617af76,c3bef1ae), -S(6c997b99,b7349b8b,6f399b78,34bcf510,56f070d4,b501f8a3,28ef3a39,7f6019ea,370796ed,ee708852,6ae9ba78,2aac403e,5b57dd21,cc77d0e,1674d6f4,e4ec60e), -S(9c8970cd,125f1c6,1b845a19,a153ef53,594bc62a,3121d43c,e9890888,9c5a7adf,2157717c,55747f64,b8b51feb,9a6c8483,6dc4de7f,40908ff4,4e37d7e9,ef1354b3), -S(eaf2ac12,6894bce4,8862c0de,165c03d6,4c561cb9,d338cb84,17d8811d,55af309d,f9e8f0f3,eeedcb85,67232a8e,cdbcbbfa,1a3b1a67,7a67c129,f07e091d,bb82ca78), -S(8b69c681,7de28f6d,c539687d,28dd6a0,7cf16302,f0cc0f41,a340f6b,2a5669a5,576e108d,b9ae716c,91859b28,25de886,2de16591,eac5cf3d,5a802785,4551f778), -S(aec8ab4d,f8c21840,c3d449f1,cf1100ff,baa91729,a35efbd2,53ad4ca,92af4d19,2350038d,bed217b6,353c31dd,bee52f96,e1706e8b,45350e96,6c55a522,b536ab3d), -S(32b75afb,9fc485f1,744c18ce,8987deb9,51cfd485,26aa491,3dcff45,6b5e394e,c5edbb3e,4b95fb5f,55d24017,86fe65e7,9b8c20f,4e927e2a,caeb2b0a,1aa34ae), -S(a2eba275,e957dcf1,a493b7c8,6ab340d4,647b6951,f8919dd6,ee0274db,a2178016,b89cabbc,ead15406,f57f0763,9cc5e036,45ddc32f,1283c556,ddf94eb8,e0e9cecd), -S(6af5da12,7be295c7,9485e35a,e0a6df36,302bfac3,a20a4325,13e81233,142d4ef9,c7df8582,7682d324,5f7a8d0f,9d17d460,53227aec,28c1de97,23afcf52,96bb8c7b), -S(1c06f8d6,6cebe13e,7cf9ab04,12cbb75a,741a2240,6b89170b,8e11c92b,84d5c9af,cb3b69a2,7a55b2f9,ba3f9ccb,67c50502,c024e8e6,556e7c42,9cea3f58,ad5028a0), -S(a9e3488f,c2dc8af0,a913227e,9ceb31a5,171fcbb9,752d8e82,1249a152,57b655ec,e07fb0fb,d8c6320b,d64645c8,e6785457,652e186d,951e0f92,f91a7ec,171bc993), -S(9d93b099,9bfd6ee3,2919d4d1,88896b80,46f07249,f913d92e,e1c27cf0,40d47277,bac5a0b9,cc9ff8d9,b6274be2,15c49e3a,67131b92,53f7e30f,44d401d7,97f47b30), -S(dd25451c,57c2ab68,542392ca,91e58a50,dd578648,36096c20,bfa8783c,1c359a8,5fcb8e40,32265bec,f5eb02a2,f07980d8,b56fb0fc,de51f140,a1ccf391,b8928602), -S(ca0ffd05,530a0671,fe49d0a2,4a0a0eb5,b19397cd,e8f881eb,542f7919,e793b260,638db61a,bbc020ce,ae9359d,3876f8bf,5ec75498,7f623d89,c3da60e8,f84b6960), -S(117ea7b5,1440731f,403d8485,a300d59e,a571deb2,44dc5bca,20352513,b5d0f691,7e72f426,20ac70e6,2ddd8ee8,edbdaa41,e9e7f46e,c8143f29,95c77289,298ca3f4), -S(c1791bcf,7d2d5477,24c30d4c,d5e8529c,2f03d7a9,711395cf,ddc5ee69,d0745064,30ba86d2,abed8606,1e9d2012,a0079813,26b232eb,34356b08,1afe7de9,3c79eb1), -S(2faa17b5,81123ed2,af8a2393,6b941de2,1cd3d276,4ca47347,5b27703a,f9b4b401,4fab0769,85484ad2,d2352ae2,9a74e90f,7d5d9514,c333443d,8ed54283,c7634ce6), -S(4bc4063e,68d9fed8,185ee402,8b4e1bf6,87c6c73c,c21f6131,799edc8e,83884ccf,3af276b4,24dc5208,7dca3be6,a5e0a133,2c427516,7cddfe4c,ec0710f9,41c62ecd), -S(e0c4a4f9,5fa0f060,b986214,68eb0131,1162accb,ec452a6,2756d36d,8aea45d6,88a49bb7,a66866db,e6905ce6,c15cae3f,2f98de34,7bbdbfda,ab2cd99,fc06297d), -S(6892a64a,e22fa15b,c0e540b2,b75d307d,ccb20675,10ed3d59,702312dc,27882d02,ffda7d9,bac7a8b2,4f83c1b2,11dbc454,8eca5023,30829ea,f5b47a9c,befb451a), -S(def9f462,12aa6e8,3d4578a6,9bece7a0,9e91ec9,28eba3f1,54afac97,d2418785,fba8f869,fbb39c64,8613ce1c,1c36d86d,f326f334,6de2200c,93c8e1f7,bace82e9), -S(32e37792,4336c65f,b112af1a,6978b5de,bc2e2f0a,f6f0b4cd,b6cad6f5,e0d4c177,d3cd48a0,61f45605,e2cfbbe6,9b636cf8,3c8afe36,6e7c8a72,b2cc1b47,a58abd1b), -S(1fd685df,86bfb84e,8bb90216,1a6a0e14,e111667c,aeea586,7f45b6cd,3f411527,be7d8cb4,c3723bfc,f2219442,9e164abd,65258c57,68509e1,a72e3ea5,b13ca966), -S(bc7775ab,a334a06c,c284be77,8e9a8b88,358f3ebd,7fa2a370,2f7700f1,53c93e94,dff3ec2c,84f8c35b,fc869ad,76139913,c25b379,8ddb1e69,4802ac27,602f4a6a), -S(2a3f2aab,10c9e9fb,cecb54c2,c411bd70,38334230,f2286b62,c06db5c2,6b74a6d0,42497e29,37395239,c102a1da,a08580ac,54fb89fa,7f2d2974,8b4f2081,bf15fcef), -S(d5c9be7b,985d769,3d5e7b96,3778daab,49944cf9,8ba2a522,b33d32de,1a7ca3a7,3122fb41,440c3f67,478e116c,1db5b65,2c8d137b,65cb712f,9d235e0e,686ea04), -S(aa772a33,12f19258,b1165378,1376caf9,16c73e3,8b842fa6,3237bf82,63ca771d,95df79b1,ca3951fa,3df74e4e,90db4a4d,b36fd7ee,1758e7c9,9e853faf,959e071e), -S(1faa7b4b,610b3060,166011fb,6eac0337,a8cb6dfa,9e90a8bd,6a84341e,11577791,716cedd4,ce760e78,a2e664ce,baf834ff,725b4296,3e23004a,ef309b5a,662cc36), -S(50a6be45,e41dcf82,659d0690,9aea539c,10fca3da,73a00372,fe9b2db5,46d7fb8a,ffafe7bc,adb82924,6ba72ddb,776b39b6,4a77627c,d36ac0b2,cc73e5ad,84740acd), -S(e27561a,6a206e59,2a8c7747,29d2968b,294378e9,9014f9d1,26eff921,133a1e2b,bc80b28d,573f7502,56da86d3,4118e699,75c671b1,e38b1d9d,1859fb83,681d9931), -S(cd5de182,85de5152,312ddef2,10d36849,a0a638fc,4215e232,13427899,268762f1,f0a0a3ba,b9149edb,c5d6586b,b50471d1,a7db3ec3,cc94ea9c,f9240683,d4ec2c44), -S(9f51022d,30e18985,ae67301b,5db7a3d6,2165335d,e3be70c6,e4f703be,d531199c,43c934d5,39144f1d,43401b71,605b08df,1bcb8bf1,ba3ee1e3,5c591a46,12328552), -S(b014734b,7b204960,adbf1329,129cb3dd,5d9b84a3,6367e643,76df433b,bafc9d2d,56dd6c55,46cef764,574944b2,c9cca7af,7ccb438b,2ffb31c5,7faff8bf,fc21eb09), -S(43f9f9db,bee57d22,e77b51dd,8aae4b30,3849d709,d06353be,8454db01,89b4a34e,f8962178,ae383491,28950190,1a290ed,23ca986a,dd0ea6fd,861f0162,d8032d4c), -S(1ce55c7e,10453890,c9b9171a,bc0d13c6,2ff6b802,1da6c47d,389d0558,c643a8b8,3363feef,920ea3e,b4cdffee,582e91f,7a02bf41,d11afcde,236369c4,4ba76ec9), -S(b45890e8,1ec53e8b,fa7373c9,c0160e69,1d739b3d,538d70be,2c2aea62,b6f2a4ba,70901d9,5e139291,691e17fe,f0d48797,60ec6f61,245f2657,6b9ef283,f81973ec), -S(d8f16bad,a3430da7,9bc7beca,660154b0,28d44348,b73731d8,b2f23229,6188bfe,f7baf0b8,80b60a8f,575b10d1,988aab0b,c29cc9dc,66494727,9c728967,ea24f26e), -S(e74323af,218329de,4aad97b6,c57db6e9,3dfa53ac,784224e2,6b087813,6a74ec3e,42a427c5,e1c72445,881fb359,265f4507,13e933ae,f3b8b10f,b60593b1,c5440236), -S(f5dbabba,6a55736f,b0e2eb38,973882e,ddbcda9b,651a10a,abf0110c,29b6f4f6,74846161,4bd5a349,caad7c3c,46c534e5,3b7e5440,7e3e31c,1247f0ee,4cd181f1), -S(e2d744ce,d24b72c7,c65aac97,b0fece86,77cd7edb,5b2029c6,41a0acf2,8cf72009,1895df09,8d9fab64,b86a701b,efc9c69,ca083ca9,e962c270,bd7af27f,a46d6e75), -S(e4181c43,1c9c9f53,362ecfa6,685d7d28,4b0f09f0,6472a5ef,6f3f77fe,6d24e4e7,d2eb8214,6dc4bf71,dc30e935,c5621b1f,c09819a4,8e572a44,1ea8981d,191f7030), -S(ac36676d,10365635,72c8205e,af547ee7,3e15524b,ab15b489,a0c68f7f,854fcedb,71038dd1,91a1992,e0864fe8,3820eafd,693f05d8,b32df573,817cb314,a24623b9), -S(aad2148d,fd0dd61f,81456435,22d5cdc6,8beeadee,6f60c22a,f23f7183,83f96d88,d7115c62,3d8455f7,955d0772,3f083a7c,341f5bee,64aade0b,426e781,f683b7fd), -S(7e8bd881,b50374f4,10aa55f0,e45991de,737cde63,f03e8077,e29bfd8,55f3316c,244997ad,ebd2ec32,71d9604e,6f9b0bd9,fe330105,acf71224,b203cf83,26b3b1ec), -S(a68beaaf,899a89d3,4c18576d,d9041b36,a1fc14bd,bb8c1588,809494cf,e87ae7f,3ffa0192,3233f77d,f47d8bde,3fd04fc7,f57c2af3,52508343,3f7e810f,4b6330a3), -S(fa9317a6,7e2a74ba,d53ae152,6e3a8a4,d7e8a59c,a1aba4cd,ba46fb23,a1870f05,b9a22792,af785e1c,6b1fd9a3,626ba75e,28583f09,fbd0d3a6,bc9a64dd,23bce82c), -S(2f820b30,6175e982,b1951cef,551a61a4,f9595dcb,35b5f647,fe8dede3,f68e5226,d4f915ed,4f8b3bd,f7e8e0a0,ddd97719,d3e22ff0,8c24c9df,c665d0d9,c4b2e4bd), -S(eaec7330,271b9056,6e98cb0,717741f2,7957ec24,c51f22c7,c25c2cf3,db09cf24,6d6e0108,e103be2e,3f4c8ac1,4a216e40,d8a993d5,5b0e9b89,2219dce6,3e47ae47), -S(2cbcf67c,6e1dd8ea,888c2898,8f636842,ff4b855c,9fb539c9,f3a9a4c,8885c88e,4031a26,c3b13bb6,d0027967,2e1a6e1e,af5d957,e841dfc2,c396c8d0,4e816cb9), -S(9103dd8d,6265d5c6,7f50eb7f,2227977e,53a48e39,a86083ff,965f5d3d,2032a29c,6a1bc02,14930959,ebb9f967,2f9f693a,ff3cc3d8,df65af26,21cba530,425fcb1e), -S(b47cba2,cf3adf57,e6cde1b8,9edb3303,d7c138e1,b59ce4b5,a57a517,aa497285,8d173f6e,af4c0363,7486df13,3fc64826,5aa32348,24f64842,5e36e2ad,226cdc0b), -S(6d59d90,23507028,6f36a203,702fc9c9,c9936b68,b08e5025,9584e385,1410ca5e,ca676e85,cc25987a,4c8e582e,ff1d49f0,5736517f,39e2855a,20cc77f,c40a0860), -S(748fc197,201aae7e,80e01c30,ce77c315,2469403f,a3b85be0,bece627e,93f657a7,6cd7f6ee,73015cc1,28562867,44b1f7dd,33293c72,a54f3e2a,2edd7bc2,6d2aa384), -S(ba8b964e,aa862c8a,9075dbdc,a69d2b90,aeaccf05,27c562c6,f310b3b,adb6486e,6531492a,64203962,4f3ee722,1bfbfd54,c66ec11d,93a66775,c305bc6d,c9a9bda1), -S(7b3a1c20,dd36acca,83f548e0,16907006,4dee8579,1342818c,f1185e89,5f6728f4,1829aa73,168eeec0,897358cc,3c4b8d04,da2b8ed8,1654c1b6,816452a0,943feb0), -S(8e39a814,1cb73d12,a18180c2,50a5c574,4cd0f4ef,42500d3d,a0892da3,bf5d24e3,2496a20b,5e5e3dca,30581c10,cc099093,5ee51283,79b6672e,ffc171c7,3f4fe34f), -S(89bc0ad5,d0b615e6,1510abfa,6ee0856c,d3fb9b33,d53738e1,827f041b,c86547f6,d5bcabf9,f555af1a,2f365910,1af8b19f,a12089e3,21dc2053,8611c3a1,e6f6a904), -S(2350902d,df8c0944,da5ba2a6,c5a9f16a,eb735474,6fbaeba8,4fd5a58d,c2571ab,dd1bf357,ab9ac929,eba9b93b,3f311ddf,2f10aad3,18871982,2ef665f0,36ad3fe7), -S(e53f6624,70227a12,a01f237f,9ac59afc,685276e,440450b4,b8d91e1b,9159a61,a95ee3d,430328e,116128be,c17a74bd,a87b6fe1,3e0adad5,7834ad89,ed597404), -S(dbdc2b2,ecbf18e,58e352cb,aaded3,7324e063,557425f4,a8fb2a50,637f0af2,e5a80b8b,4cb5a7a,af1175b,fd62dbc,ff044f9f,4f03fb89,b768c6d3,72729996), -S(7fa717e6,e78c1641,82b2e,78c2fef9,bda57060,3d0df678,c4716b0a,55f7ca60,59bcdf92,4c9b981e,ad7b30ae,937ef1b7,63b12c69,9fe20e6b,a7c3002a,edf82d34), -S(330a50d2,1a87984c,e657be73,d2570875,75e261ec,ed17d9c8,7150d1e2,6afcaa0f,253f486d,642fcc6e,5d53b79b,8a24bf25,131a1b2a,25b931a4,fb2e6019,34c7df92), -S(762b5213,78d46c16,70251e93,2737c75f,f28e0500,eedd6ae0,62919874,660e865b,efaee12f,3b411bde,7e6e8bf6,3d875a89,68164f6a,ddf102fc,869613f1,e8bbc095), -S(717d699d,f3a985c,8a8a8562,cced0432,4b616e41,e4bd8ebc,43bc1b44,2e2f7b35,cba0f7e4,f4d544e7,6127892f,a5ef8bca,13241760,5be8e7ad,4fdabf66,e8fbe571), -S(124de3d8,54e69390,b6908c5f,c770f602,8439082b,9f9e5e5f,cbf5f822,2193611b,c9b9d896,bb1b5cab,58c10bd9,b6519ed4,a1d3be2a,39ebc4ec,781bd673,351ef376), -S(fcbf142a,a6d9930,33fd9a17,2c7f46b9,63237738,9b76572,2975407,ea8b2440,4366db31,a5acd6e0,a8bb3481,9a654233,e6babe82,bbcb5967,cabca638,e9a19987), -S(82858b62,5d2bbcc1,372e3c38,256b9b1,cf018f3b,3e9d0b70,c17d1ac0,fbf75ca9,e6543ada,7d9a8928,e3a1f6d,b8c15649,379fae57,f99dd8cc,3b096579,8e785840), -S(577b38d2,ffb278de,62ac0df5,ccb6f2c4,e8f40e5d,c5549a7a,4881831e,bfb6b71d,171651e4,7f9eee1c,60ce5d95,9e77b98f,ce651c3,c661d8db,4798372,8ba1c03c), -S(28a83552,9aed0508,34510350,14bef19b,c1f20936,3fbb447,6cf72fb4,26267c45,cf949cce,8b331182,670f5300,29e3df92,57a576f0,e5923a0c,146aecdc,2db60446), -S(621d99c7,abe3982d,889d3b11,6c992a6e,f035ba8d,aeddd4ac,d5d7b04,bbeac79f,2a6b0dc8,a6ede522,b86ecbbd,b057192d,84294e8c,385cdaf7,cc5777d3,607ca69a), -S(8c6395c0,3ecfbba6,82926be8,b6e8d4d6,cf204d50,9f805453,ee40a010,1fab3959,d22e5810,5fde2b81,b82859ca,97a05e7,4c278cfa,b4fac1e4,50e70928,d73b67e2), -S(80ecc87f,b9d4bc15,8e365e31,4518beda,7087f9e,c8086e47,91314d1a,9b37398f,6bfef3c7,8d2e91f0,67075036,385ed8a8,f3a84102,1e44df55,397290ec,68e44812), -S(22cb24d4,e1354314,b1f9bd,c7e37963,3ee08264,ea7fe2fb,2b23ebf9,a35c1438,6e88715d,9d5fe90a,d0940724,b597a55f,386bebee,5eaf32c7,6e95b2c4,d407c808), -S(285cc203,a4eb1e79,1695f8dd,d34a048d,58350aec,4fdc8157,fc1a8427,76b56e19,59cae7e4,435a37d,bd3c3f91,279c7bd6,1cc466d,b1831a53,94f7aadd,4e1e108a), -S(61275052,386f258d,28af0420,d010fa87,c55281bf,59b68b71,698eee9c,824913cb,8532eca9,645479d,9ef72ec3,6d96eb11,418f9619,b0fa95c2,c4c81c86,75a81e76), -S(84d391e4,d946c2f2,b40b5b5e,b6a57463,1adfd4d4,9e034ba1,3a2c862e,68b36c64,f3384ad6,cb7ccfaa,567a2cc8,73c9e509,b4c2de1e,95f7ad30,26be00c1,83ca7419), -S(34e2a77e,cce22a6e,849e1b21,4a6cc570,10e3a0ed,73799e14,51616724,410d854f,cfdd8819,f0af720a,a372b923,fa81eaee,c427f3b2,a29acd3b,ce6710c7,c186d039), -S(bc45065a,b558b2c6,a28b0cf3,8bd26384,f82dbb36,e2029774,561883ed,e6600bf6,22c5a0b8,3dc2bc02,93d7019,b4623b10,aea9d36a,22b04882,954e3daf,e1885b73), -S(4b92a803,94dd5669,c0fa2d3a,c4d1e7ee,8e2954a1,719d37b4,4b02e342,9d183ea8,9218836c,698a5fdb,f95e0e58,8b64ad3e,e3aaef7c,613b47e3,f1464443,a48e3396), -S(acbf0ef8,453addbb,9a4b04dc,3acf662a,d069d5eb,530d7a03,2e6a8708,be241f89,d46405fb,3c8862d0,4e7cc53c,51beead0,dffb3045,a6349fef,6fbbcb9e,cb414036), -S(adbaa36a,4fb531ce,eb084fc,e65f3397,22188967,a947acb5,9f7ea73,52aae5d9,719265f,7e9bf7aa,2d789d96,282e527b,819a252b,7de8915,f44077af,8cc1a8e1), -S(3f5a74c5,98b258ac,b1cb3ace,e55a7a26,78f4613e,b85d784e,1b3c8abd,978619c3,ba16385,ce0487ea,67932ed6,23aaee87,2debdc7a,2bd02ea4,6a681ebf,72ef5df3), -S(6a231807,3d2c0fe0,c89245f6,5dac4052,ce931129,85b83555,c4cdf8a4,f1574135,fe44cf76,f44f3d27,bcb7839f,588fe09e,c6a5aa95,d6ae52b5,8059c7a2,c6afaf71), -S(35555f0f,4fb2677e,dd12f235,2821ef3a,331c78df,3259128f,dcf62f69,85892dd0,101d97af,b1ff1197,3c8336df,bfbc346e,5c5e06e8,f11bd602,aa93f412,2f66c388), -S(d45797ba,61a836d5,13834d,abd3090c,bd139f05,dd67be2d,cd99ea7,66565756,61b0aa,ec1bba4f,6040382f,cb049126,f7e6ba72,9cc4dbe1,f511b792,32204a65), -S(c06dc164,8c07d57b,fa6cb488,1d9c96ea,26cccb68,d40d169,1890ec68,d42d584c,fd4ee4f9,16739643,66ead6cf,fcf31729,bae2263e,c57c14f1,29fc61da,cce93dbd), -S(6826672c,ebb04679,a68958ee,3f64dc3c,69248f3,cfe0f8a8,28b164ab,417a508d,ce38e638,f19b1a66,b5647be4,3ec24f0c,562a8dfa,1b278117,87f9292b,8cba215f), -S(a2d998dd,a82576d1,6933b580,40dcec80,1f12ef10,34ad73d2,de3ee13,7d632abc,e168ae1b,7f288808,efdba59e,cea51299,d65a2c92,76ee7190,3f253384,30ff297), -S(2a9361bf,67b9e8c5,6e8d7b99,ad8b63e9,e10dd96c,1ee1eb35,40244415,270d9ad6,62bd2398,8d35c3a4,dfa31c56,57d099af,e9accd49,cfda6689,a997c862,5e05424c), -S(88ffd75b,7c3e1311,79f885e8,9060a662,460499a5,b2a457cc,47443183,a3015e34,a5a174cb,7b9b9c68,3cfac8cd,4325e0af,90f61241,28a83e23,ce1344c2,532e3a98), -S(2b9baa0c,d7f27a8b,4ada59a2,cd23c80d,94e8ef7e,3bb77d5b,a45b0547,c70abbd5,657251c8,2d564df8,a9fbc5f9,74c7d388,22089c1d,c338805a,33258c8b,db692bbe), -S(1fe51134,d37136d8,f473c5e8,7d316a8a,f0c63155,815e3b6,489f7dd1,91b229fa,f0df503,ee85d7e,b3c03545,dc491cf5,39ef8a3b,68e816c,bf94d126,adfbb343), -S(1a3211b9,9d946e96,bf190bc3,3fa2fcd1,f8cc0646,45599f81,dc7f33d4,3623c41c,ca6892b8,f8452e2f,5a78a463,fb325dcb,913cb17d,1a43ca78,bf2729f9,27a99ca2), -S(a6d7f275,c3600aaa,ae16a1e5,164084a9,6f8313c9,a71961f0,3b6e1a28,e0326e90,528756c8,ae9f109c,3a803d2f,d78dd27a,a66639f2,6b1e2fb,82a683f2,9e2d7993), -S(4acb6c7e,745afc4c,8258f92e,3a706049,a8c4cd51,6462b230,1a824114,e25c4352,3894a647,436c904c,6ef52e8b,6df86e61,4300894c,e0e7f87f,529e96e8,6f20796f), -S(245fd53c,7b9b6698,89ba6bbb,2b6d5603,c423d4c5,76c68a6,9289c1d8,54bbba73,e6a65161,8e8fe90b,36705e0e,82c1728f,49277a2b,6feedd45,d431f349,c759682d), -S(58e89f91,3383bead,5ba5ad57,bcb85f1a,44ef0f2a,4cec383a,7bc4fd92,9d78fae3,56edff42,42716182,9ad3b3c6,339299f2,1b56085d,a051e990,3ed02323,d9ff64b7), -S(e2f35afe,b9e38b16,a29a8452,a17abf93,36a82282,9fd2a726,efc2160e,10e7999e,3a19d922,d2d2b57d,927ae73f,80c7e1e9,40679fd3,fe34b4be,c4c2deea,13d94979), -S(558be465,de2edf0a,d5b7294a,69703376,7a96a366,e7f789af,3b93743f,372f5e1a,9dfd35c1,d1670bf2,e8696fac,9405330,62a90b4d,b4891986,9c8f98f3,6c586880), -S(b49f1db4,206a93ab,9ae73164,6f5364f,7b261d88,3d025764,b2bcbb90,6fecef01,7c81be22,2a77c149,14e48d26,bc81bc9c,2e10886f,2dec7f4c,1e7c42cf,d87c5f12), -S(6cebe305,dbf61912,36e37c34,31029ce7,b0059546,d5984f3f,c6d3b7b8,804d2cad,5e88f74,fb307758,6c7b9c08,ec2697ca,1360bc21,f453688d,edc82cf5,c96f16e8), -S(4e60a6c3,684a0435,99435fd7,7ce52576,aaca0b9a,e2e5ed78,b4f64044,ae89f6f1,668aef77,3c0fd526,e9b7f22d,55baba05,99ead770,442a23d7,fa0bf8e7,75385b2a), -S(d184099,4640c319,9a00608,aa1d3aa5,9527ef7f,46a08f26,3b83fc46,a10c0941,f7f89233,55989992,7b844a71,1f5c866e,3f4c981f,4cf6f190,fcd4846d,1d83d63b), -S(958627b7,214a7133,55521887,fdff08d4,64c66531,3fffa310,c53e74b,89194aeb,93ec45a8,e0aebea8,378b1c30,974bdcd1,4e7b8983,c8138c7a,cc85fe02,6884a91d), -S(7d0932b,5d8cf465,ae6917d7,450e9b59,da57cefe,dfe6665a,4338cdce,71cc6c11,85c5b8fd,757613c8,8ec6b250,3e15c412,4ef2ce44,91b7eaa6,5d512740,4dfaa142), -S(c8ef9918,55874f19,efdd5720,cfd9e164,ae2b1f14,ee745c4,1ec5cc0a,d776cca3,c0b00173,20111e2b,85faf602,cd01a186,8fdf633a,1b0f3017,682e5d65,3ba29671), -S(8a72c61b,eeeebc65,6cd8acd,8449ebe3,6f21dc8,1ba913c7,742247cc,c8c94bf2,98e7b573,2c18d201,c0faa26f,734d25c9,23411751,b03088ad,1ce102e4,5de36e64), -S(cf0c29b2,ce132664,c7bfc440,9d1188c5,33c8f5c5,643291e8,67a2fde1,6c5fa23f,fb317c50,1b3b354b,18a120e9,2a639dd5,629b2125,ebb8785e,2626ff4b,4f538e02), -S(8c9dc0ee,20f7cd08,e9d1db3b,a4569a43,98c3845f,7d02db0a,cf6f7863,111fb016,445b117b,c7b1a779,e0e9fea9,fcc31141,8aee8428,cc8e8e06,fcd265f2,2424cfcf), -S(650c7470,6f2a4225,eee93622,69d261ae,e18117dd,ae23680d,15c77d70,15f373df,6a4fbe02,e1701051,99828d13,84083d60,5555e2c,56e7799c,b2714216,b77f6591), -S(b0b31e86,19d20877,1235a402,94a884b8,1c83bb44,8db973a7,3783267c,8494b32b,8c5dd1fe,31e86a2,c40c1490,179452da,74fd5350,1ae38c1,1e1fff3e,a33f8cef), -S(a156abe8,279dd440,2762a28e,836050d6,7b782022,2036172f,a1a95984,49c15a96,b85356b6,c165788e,3c02549a,1ea50dfe,c557d7ce,4a9052b2,41deec12,eb08ce50), -S(c2919cf9,924df70c,f1f74e42,6f1fe48,1e4aee25,fa00291a,676f924,69002fa2,19067bc8,50deae06,1ca42c6a,3e252abb,d2c7c6cc,f89c3cfc,a6e7f1c3,a6fe1b90), -S(1aa1c198,d4f76755,ea94d005,b300ad47,238fe1fe,87cc1244,8f2a632d,4c922ecc,85e4e4fe,847c1935,f14d155d,a41ee4c3,f146a4f9,d28211a0,374ad6b3,c350dae9), -S(f1e9af6e,45296823,eb5a1d8d,a41c7904,3b8c1166,30213fcb,84e2418a,e161bba4,211963da,8aeed276,f390d6d3,6b958b36,da23f1c,8705461a,312a7687,bcb9f03), -S(47b98d04,1d7e118b,765fb3bf,5d30f5f1,6ffc7b4b,4745c02f,6bb807ea,e15aa092,d1997492,7099df01,f1d64610,700b9439,83970fb5,d7123922,39d790a2,a116d223), -S(2220fd83,794eb1d3,a1f842dd,9f8f849d,43d58385,25d30d79,9b4684b1,4c5406a,74f2715f,a6b77509,d58892fc,78915244,66b2db2,df099a7c,f7eb9e0c,c4d8d3c3), -S(be01ac86,5eef8b4f,e28e15a8,63c22adb,4607c574,c26d7d81,a5b69ab7,265f7bff,675f334,bb9ba742,445aa758,c142798c,bee1cd39,ebb01b65,eb4ca49c,8911da0a), -S(1e35165,2411e2b1,d491972f,61a42c7d,62c12f0e,25441aac,e4770c9f,254ab47a,ce7b801b,910e9fae,c9288272,18557cf4,73b0b8ff,4296ed2d,6e5cae60,f48fe3), -S(1585747c,d984fb1b,b34e0ed5,9c3c6347,159309c9,1524d316,f570d257,b7c3feda,9b501cda,20fc0f1e,a7df5176,bb6da6c4,585baacf,a08fae17,9d52ced9,c1991b55), -S(33fe24f5,4f24ebfa,152a2e59,c2445f19,f1b4bb7c,636a0e64,eea338a6,5f17e9cd,b65667f,f14ae54c,2c272efd,eb2eb1d7,2f9ff4ac,35430488,30283f2,cdbefc29), -S(783538ba,9f685c0c,f85376e7,dadabaee,527eb0b8,73a04007,9d0a8dae,80fc693f,16e846fc,bdb1fd08,4e7d2521,327457b5,93f42350,80b791fc,e91af5ac,8d35bab5), -S(ac1d5e99,bf673475,9c1118fe,44f0a7aa,1989be05,e117d2b0,d9946510,f932eb38,7a81d87f,aba5a37,9dd319e,793c2a23,e079c7e6,6dc272cb,5d787cb8,2ffdd6fe), -S(f65dc8ab,c670e7f8,753246c8,e5273670,d12a4ef7,a3296de7,3bbeb72b,20093771,6a4cf92a,7243fe41,9c6ded92,d51dc607,7c82ed58,60b98aa6,51614266,f9a2b8b1), -S(bb076bae,e9d21b2f,fa004ce5,e361f8cc,773b2d50,cdeb92bc,5ecca796,f10689a1,121a0fda,f6192c07,b2a734de,9d8b8bf4,609d2722,8b0818e0,a488f83,176303ee), -S(4eef5fb,85174419,7659a95a,dbb4d472,d418a8e1,db93ca1d,af6ba2f6,49ee31c7,91c54af5,7b5fa5ce,8e7c3ecc,f90b2e28,33a969e,e3f5bd30,4808e89,f25dbbed), -S(e3473056,711af387,2bb63d59,c92817fc,16c97b7e,33c1173a,df11633e,2984ce45,816407c5,3d1debd3,ade1d781,d46f8b03,2aa5bc05,e3c1bcee,5213fd50,c39b6d17), -S(f2356e97,555be224,cac10a3a,c6061ffb,8a67a77e,1d97f011,f86e7594,2ba2665c,8f5dbff4,a6ad3bba,ca27c595,e2d1eb67,e0f752da,817f2e1,5e27b9f2,d6b955e), -S(1c1682e8,1a4c6d19,dd01945a,34f096cc,1854dfa7,fe42af9a,b523f7fe,cc20b8d2,a610ef90,190b3390,97de87df,10d01c94,4a76610,6d8c7736,87d2b863,621ee297), -S(53b1dc92,d540faa9,c67410a0,901871ee,eb96beb,6809aa96,545b02af,e2cff0da,2132487a,616b4084,c2dddd4b,fba075b7,66607859,4d328d39,55c16060,249b1f23), -S(36623f66,417edc01,c4a43dfc,e97573b3,f14cd858,a6fbb2e2,54ff1df8,21dbde93,88cdd6c0,b3872cf5,9921d376,9eca93f3,d5985f2b,ce62d132,18de4cb7,f6ebc27f), -S(195345f,132c5c5,4f6e1bb8,52f1f76a,a7ca147c,e347b5ac,fada9fc2,f90d3592,2fb7f1d0,23f0fd8e,9ae691aa,3eff2832,4e6b4390,e42d7129,246f14a2,902797e4), -S(ef5badac,2143e60b,adab5ccc,a05f222d,426e0768,44e6edfa,4eba747c,8ccdc909,afdbceb1,62ee5237,f55ba6,71395f2f,e4429a2d,6d0c007a,30caf51,a53b29bf), -S(3c3dbd83,bc2088fa,65a9cc99,95ae0fcd,8a065e1e,9b8bfd2f,7c3a76e9,72305688,336470b4,54fad342,fc51cc10,6a88d82f,6a8ee961,46aeae6e,19e9086e,79325072), -S(1da4f2e4,af97ce25,1fb180e2,c529fe17,c30b318b,53c3b252,53d8feab,21b0a0d0,861cf8ca,7dced920,1e59735d,11d39947,fba5dd1f,dd507a99,a882ba26,6e468ff4), -S(d5bc320c,8618b30f,a9305bad,b6b1ce9a,f5fd055e,843891a0,b0d2fdc1,5fc51f54,cc8ce071,7cda58db,25628843,780d083,625d103c,daddba16,ba751ac4,5e3f281), -S(f5b3f6d2,9939f586,2943067e,361a7333,ef49ca55,70df45ee,e716ac43,cdcc4e16,7e522add,4cf6d92a,8b77292c,b522dcd2,1a456120,4b0abb2b,614351ac,ca1fe517), -S(e27f83a0,f2b76455,1e24d358,d39b946d,63dea7e8,5cee08cd,13762d43,a3b05654,fc5375a,cbc0c518,bf3fc169,3170f204,67ddde21,7db88535,74b6bd8f,4c677f16), -S(196b36ea,4d552f6c,eaa9f749,fb5ea209,92cbce07,f1cea121,9318acbc,7c87ba82,17eed0d5,1f7500af,3f11217b,b703a51a,bde3772d,d4bbbbf,1438af15,334c61c2), -S(cac69e96,84328713,e06a135a,ce0f0fdc,1812eafe,fa499993,980d2895,5804a635,f02fa499,9a54c238,4bef1f2b,89795b76,3d3e526f,aa1081f0,189b4488,1d5828b5), -S(1e1f25b3,d43317e0,623f07f8,3fb09946,6ecf2381,ab348284,8670a30c,2ac734aa,c096a239,3dd1ca24,12eb4637,1d6c3200,a5992f17,3e6203a2,4313f000,62076e8a), -S(77c7da51,12a668c1,666b3c79,966a9299,a033ec4b,976e1fdc,15d62ae,96021cff,6f3f728,9eb1ff33,e80a7c09,134cd880,9860f9d,8805c8de,e194f868,4852abbe), -S(8aa11355,a8c1444c,c1d2cd12,d613e6f,1145e417,d11d9e4f,d13442be,d7e23aec,52533b3b,1024e982,725f77e2,50e785a4,97e253a4,f816eca9,2ff20ffd,7dd733d7), -S(3f504f0b,647cbb41,74adbcdf,2d226689,5871107c,68e12cc9,dc30058,4302b841,22a53436,688d17ff,feac444a,b5ccc64a,f82b802,da8beee2,db623b1e,fcaead50), -S(3f02019c,4692ac29,5fed5e1e,5190269f,92a689c8,adaa9e24,2a1ae01b,d23fd952,704f03b1,c7c03308,70a6dd6f,60fe12a5,cd711511,41ed831d,b6e5194b,e3de6026), -S(d33fd654,d7164cb3,a1a40172,28559c54,25630cbe,e34c6c01,8a8757d9,6eae7980,fbe58168,87bf57ea,b89bd0ca,3effb305,7b8d5369,dd4f90cc,279bb613,49d2faf0), -S(fa3439f4,bb63e36b,48056dec,109e7ec8,51944d8e,d7ac278d,23e21415,7902725a,b427d74b,88806fdd,fbda126b,38ca725b,fa61c855,5118fee3,d4e1f586,e888feb7), -S(f5c58687,a83c7896,3c021e40,e25fb197,82d422ba,7df59a1a,4f56bf83,49b19e2f,6b94698f,3f286993,ad8bf70f,5ab72ab,12059f8f,bc4f7c09,e624854c,3b76624a), -S(18e582ca,88939bf7,16ec8462,91d1ac36,a39319ba,546ba6e3,b224d6e7,3b0b30ae,6d091b7c,69143704,eab7ed7e,deba296c,26688d08,7d36d70c,8540c23f,ba98b8cf), -S(a2ded3a8,b327cef6,84785264,5b9ac68f,8e43f035,fcf00da0,da97e6bc,6d36db68,31b2764,36139115,1852a944,179c86d0,955faa17,da85281f,af02b71d,ea120dfc), -S(da61911,1341a038,fc286fa6,704307a6,11cb4c2f,9f6bb51c,da89901d,cb1e0f2e,30cdc05d,69e3434c,4cf06c35,f852b6cb,e0edc7d0,a9ee2daf,d793d2f2,b2d522ad), -S(9fa4c9d5,103b0cff,2cf01cc0,65c7afcd,b02a0a9,72da4418,63cc30fb,572f2008,401b410e,397b98f7,5948ff7f,babf6c33,9b1e88ac,77455bd,9045e7f,a5489e74), -S(952c5289,fe18f7b0,40f8ab3,17bdb63,fcb610c1,a6b3a4ae,4a98c1b3,2f1af628,66fcb4fd,2d347e9,fe40e378,d3bec17f,94bfeca9,faa84789,98f24294,d3fd905f), -S(5372941d,bedf216d,2d79656d,db0afa6c,8fcff27d,7464cc2b,a53a6bef,ac01f020,79bc84c2,33f106e8,96a1130e,a841b690,ed5e6b7b,f1e1c8aa,d833fa56,5fd4678c), -S(a4d5e6a9,b72da410,ec56d24,c01ae684,fd8e029e,713f9a1e,22c660d3,30bccf99,f08fde87,df365268,226f68a4,52acdf64,23f31856,9435740,9fa06d4,564cdff8), -S(e6dad981,9b3cba07,1465007d,4b4b5343,9d548033,4896c86c,bbede7d,54c0ab97,9e43f1bd,949e54e1,57a4adde,61217640,f798775f,193cef6a,db369c88,3e784d6e), -S(dc666af6,71aa7218,bac55351,ee12b736,8a29a026,19ec4f94,b9de8b80,eb3232a,3786e989,c684d01f,a4b5ff5c,3b0619a2,d39b6543,4ff0dfcf,24b59966,9d7dc874), -S(2e730ff0,401bb59,6dbbf02b,d9fd4d3f,eb3f6f3f,51a2ba53,d77ca83f,a2acd02a,9c508012,5904059f,bffee85b,8fce1438,fd761f52,86f1d798,512c47a2,d96ffce9), -S(9824c6d3,9ae02d8d,3b59290f,99c1d183,1d5bf401,15d6834d,799c0827,853d0090,2062d562,bca410cc,3b5fd22e,497d8078,6bd1a94e,d7734a66,a5a3495,77c406f9), -S(b10e2769,8f6a9e66,65b330e5,4b52093d,caa4f57a,19cc314d,eeb2452e,60f05cff,a9729153,e267d4a0,5859a9ff,3ab88628,47f3c117,d6ae757e,a19246b5,448a20a2), -S(d8817793,68ca0437,c780b0dc,51db1f46,ba5ec6a7,566b3579,e157a421,eaa04c4e,94da7eef,255630a1,820abe8b,7d8bce00,dbe5c467,89a53be7,2698c4ae,925d1576), -S(5151b8af,bd8b69c6,e42db2e1,5876fe3c,2da5c340,e17b52bb,93170bb3,5351bc95,122d0316,55d770a2,4b493484,8fc1777,de9a0f1,a5d9ada7,df678e09,591c30c9), -S(6cd1c141,67feba0e,406e12a,2bd012b1,7dbfd03e,9bacc6c0,6fd6455c,76cc0c5c,131f4150,f7ead6e6,35e93fb2,e672cd73,7f8093a6,c27cdad4,ea4e7c75,5c2ed702), -S(e83f8bfa,b679258f,67bdaa95,5cde03e9,bfe4126,a0eb89e5,abfb072c,cf536043,a9fd9d4e,e5eb9d90,5d8a3665,73d423f5,deb868b1,7433af16,28fda09a,406dea8e), -S(afe4206c,ec19b5a0,77683c63,a4164360,54be1122,db0c0bf6,6e564087,c6ea2670,15db0d5f,75b53b77,52af9b90,288dd9a5,a26f556b,37adadad,adaf558c,587b9e5a), -S(73428153,102d29e6,6f006910,5116c7cc,ca8b93dd,fe1c257e,9e5003df,ff139d47,7fc6eba1,465f201,3d234be,a022ca08,7b981add,a5ebcbb,8704bd26,750303b), -S(424143db,9fefd615,c6a97e1e,c59c3338,f7f4be7a,def4133d,747b7677,b0227e85,f7dce798,10cbb1be,3e1a91f4,9d490b63,aa740517,3a84d96,b37867b,635f68bf), -S(1d2bcb78,17bb2cca,b5c7e058,be33a598,122758cd,92075f20,24a7bd83,7f8dcd80,363fadf,e771b3bc,46aa7a6,cba5191,3b4d04bd,e673615d,8550822d,d351319e), -S(5cfdd130,bb671192,e4edeb41,96008cf7,4ac47279,ea94487,5962bdfe,bb1f4326,9a6cb3e2,925e75b6,264eaaf6,4f56fdd8,c0f4c5d,65cafcec,5d9cb110,5900cc24), -S(52495f7e,1853e084,272d6b77,72dd19f1,4f874952,ea08afa6,6ac16764,9664904d,2bdb6597,99a1822d,9801701c,98646cb,37a1f6f4,cd503720,79c23c4e,872e3d4f), -S(d82e59b1,18786ae4,a6b227df,3f231216,f33d2e1d,b0adf12e,a515c9ce,83ee1bfd,772bb140,7f180791,25d23c04,558cfa84,9f0b716a,c0863361,819623ce,7af2e437), -S(f6dbc260,90822790,e71f8657,22df2bb5,71eb625d,ccc23d3,c61fcba1,b9b96776,c23aa922,ea7ac2fb,c88a860,cfc3d7d6,a8c4f599,59c1c3c8,aadc88e5,aca1a54e), -S(aa7b6845,88c07567,a634b1f8,2425a085,6956955d,e532e905,d6017ca,5ebfdc1e,6ce07cde,1c60de7a,ee80355a,258dae5d,25960af9,be9edd3e,dc234e57,7fba0eab), -S(68065f44,466294b3,ad7e6225,24de08ec,b910693,308f8d73,847827b4,b4318656,c6e68f0f,2e9859f1,a2d9aace,ff9b4c52,4329b8d6,12233991,900d3e23,59804555), -S(c3d14307,5a223701,4ab61635,db180a64,162901b0,cf175010,d55129ac,168b76eb,5bdeba38,2f747cb3,50844858,b161fd5e,3aa8e7d6,873cdcc0,1702d527,9c691172), -S(3a1b6c2b,145a2f30,88e3cd41,6d2a0b8f,60cf8d2b,b3960c40,9637e5d8,a316f514,d724b2e4,c1c2aa15,9b85c32,684fa380,8af93d3b,c6a9d647,bce39a85,2f568fd2), -S(d2520145,c4d27a54,ed6de50b,30fead1c,ec602c4f,a74e3ef6,31f6b88,23e68bef,7cca310f,d966d423,b7285d7d,f4d5a3fd,fb4ad29e,94e69eb6,2a60a9b4,c666be46), -S(d01ff7ec,b4d574f1,56755c8c,fd615a99,83018ab2,35826574,d94cce5a,f78ad3c2,d9d17ed,ea436ffe,fb2f97d3,58485109,3dc64f0f,5bf540ee,c98ceb0a,9cd4743e), -S(5456f76c,a9c7b5c6,42cfcaa,aa0a2dcd,883ecf8a,626786b4,4735e700,fca5111c,6b3e05a8,6ffa85d9,8b9e4eb0,72ff60a0,df87c298,c2da5a31,d2af1c8b,54b91381), -S(14542249,652e33a5,6283676b,223c3055,56196b3e,21e48607,2652f7d8,ce598e9,64e9dc13,6b8020e,d590ff06,8702f99f,91c42596,b7091969,e34f2f5,2e0cb5de), -S(26d85587,4888c76a,96a6dae2,26a6f985,6fb5b9fd,b4ded1f5,a8f843c6,7346f307,d1c71339,d7be6c76,f1a8b0c4,f047ec71,519bcb05,a25ce054,afcfda6e,19971cae), -S(7f8e7eca,e0257e79,ab2c04b6,dc045ca,363c307a,4b04ba70,c5c6272e,23acf215,fe96da11,f16d1171,9f91a666,23cc326c,57d3d453,8639377d,c6b79b63,56ff6ef), -S(4ff72771,ccd75c6,2ac827b4,e800e580,e6e4681,208d64d1,11c93258,2d188154,94e87e31,b2907d44,ee02e947,65ee5da6,f2bfd7b2,9808bfdf,dbd2825d,1b3d6c77), -S(afd475d0,8946f556,81284fd3,fbbf67fe,6989497a,481543c9,1d4f4254,75aa8d94,669a72c9,a8d0918b,a1e787a7,5b505f26,d002b417,f156d888,5ac02ff,bd29a920), -S(f5c11fa1,2912b0ca,e4d680ed,55ea126b,3c260a2e,b8fb10ef,ca21ad7e,65591590,7406281a,a8744da6,eddeeaa9,274c0591,fac0dd0b,3d7c3df7,e0f65c7f,a712680c), -S(ec9b680d,bdfb2a2b,fbd04bf7,cdbe820b,7975563f,6f0f6646,72236c66,17aed40a,851c69e1,99b77fe5,f16c4c2c,4bea6771,1a23afc1,569a8bf3,c91e4133,a8324e53), -S(1f73cd5b,34444b1f,d7287750,c213d5d0,17a8fb49,da9cc3f5,9ee30939,dedf9c0a,792fa236,514d0a6b,218b312c,c5b614dd,cf0a2960,ca13660e,f696d80a,b7faee90), -S(7b0013d7,a6c967ef,e1006cc4,3fb177e7,81cd4021,223ba083,50db6ad9,1e949e06,a2f8fa6d,b6416da5,d0b68bb1,c1ddb47e,8081a063,1422c72d,2bcd7b46,d2576a60), -S(14ee47f5,539c7a7d,acad832,1197c83,7daac6b8,6ba7a828,84cbf45c,ca70391e,7902e477,28ed6a07,80fdc510,c792103c,e4bc215e,390c3894,1a3fe0f9,582f62c), -S(fd75aac4,8e5cf9cd,9e14e7e4,6e980ccc,1a3948f7,41e0ba93,25f6d490,1d15d9dc,b544f9c9,febd77a0,89980585,9ce52db8,e1847db9,dd4a7857,6a8a9210,fb61d2be), -S(93aa7a40,c03e4e7,d605b8b0,3ac2a378,122fee87,9395aafb,4698d35d,8f7f4690,db2859ba,b6d5c89e,2fc4b68,1488ea1d,8d8905f4,a44af57d,3ef9f937,4872013a), -S(20a027b8,79a10933,519a97b1,72d77389,5b8722c4,ddc4603e,40319107,1ed4cbad,4fc480e9,fb55854a,f12077cc,dce038f9,3ec1f3ec,6a37d7fc,ec03b204,8cf9deae), -S(e0e26a0,862f4ca,96084cd9,bacbf501,31da0f20,1f3e4a21,f41f5ff4,853a41ea,e78c00f7,3dc8200,cc43d04f,6105e189,387fb1f1,47f39d71,f562d7b1,19c0f591), -S(fe7f03f7,b6633a8c,e514e801,bd9b3b6b,c4bd7790,69915720,8d49b513,8d5c6be4,74db79fc,180cfda0,c17ab6a7,74d73d28,3c9119b6,d85f3a97,d32389b0,102c052), -S(92b2bff4,c74df07,3cc3a258,fd4fc56,88f1eeda,1908036d,c0606994,92e3fb6e,f92ac36e,f10ac585,3e64a67,5e8e26d,b3cbaa8c,1670ff,ba060f19,bbf04fff), -S(fbfdc0c,41238a0b,ea6e3c4a,b09453c,2afb281a,4cfb5cf7,97f3f473,b02717cc,bce0f212,9d3407fb,c5541dfa,7d266788,72343f8d,748b7b3c,8c0cabd0,78378f85), -S(8dbba484,d9bd416a,f1e18a30,6f42c73a,cc15c5e8,49049c98,612a9d64,f8c99539,670200f4,96e34f9b,50601a49,32200d7,1d79e69,b7889f8d,ca45b13a,cd9cc7e3), -S(44193861,6c2332c3,1d35f82a,b35b515a,1cb3d754,3f83f5c8,63f809f,739448fe,ea559711,904549f4,b2986865,86467205,58420d27,46efa1c3,2ba002a2,64e84219), -S(acbc7bab,6acc8d2d,abf39739,fe9a560,d225d692,9a1f2e93,3a441173,5b766e64,e9f2c663,4104067f,5707f9c4,6a9a7d6,312bf3f5,6a851e0,d52057d,6bc296bd), -S(e3300502,a870f610,5d7b3c68,f26d4ae,bae2b4f1,2a893d74,768a6b8a,c66573af,558f537a,8838b676,121a9d0c,c62d862a,4224348c,1a982c37,6be1a255,a57caae8), -S(fc34afa3,8d658fc4,8d420c47,651057b1,3eec6863,2d3c3a22,bd83580e,3a6f8b82,96a3436d,228bb25a,fc274c5d,7f5da6e6,fcab6b6b,72ee98d3,fc293ef2,ed523154), -S(5e1cddfb,a73e3534,c0409da7,af922c43,7f9dc2fd,6f573ee6,918de501,90e448e,4b1adfe8,406274fd,6c1a3ec0,68568d0c,78132b3d,efe3a9f4,fb23a725,a4f89251), -S(d307c67b,cbcca4dc,89c680ef,9bfb7421,d2283fcf,90a07bfb,95c50cdc,f36deba6,254f92ef,5734f448,24ac8020,89f84bf2,b7e8967a,8afbc2f0,e01bea62,b4a90b73), -S(f4977bc0,e8f81cf,753a2b58,65b512c0,6916b53b,1a0116fc,a5528e2d,aba2f2c0,49fc2c15,8cf226a8,5099bc97,97b2eba9,9516ab90,1e39d462,3adb96f,c44e6c99), -S(e70cf22a,9099028d,96239342,bc94619,e266a53e,6df63d23,fb317879,cc547382,9ee3689e,f7eba3e0,f8715242,5ca1bcbf,fac4d337,ac4afb59,107788d8,6f0f61a7), -S(130fd05c,ea863c62,15aa8789,2d5e293d,3493ad4d,5f526a06,b33c4675,e02393b8,75c9776b,feafd1ea,252aea1e,5f8c8,9224ae3f,39c5ab98,98395468,6f45cb68)}, -{S(1b8462eb,1ccdf7b2,b8372f2f,cec1f479,ab07c09f,cb26d6c3,965ec73,4d654f81,62f6755,b4a7891d,55de6427,fbc37d33,e4eea418,a2c04392,a3d11807,ccc9025), -S(deb66785,6c4683c6,ad7c39e5,deb1b8d9,722ecffb,f431fa34,9dceab3f,698f738e,bae7261c,368ee55b,137b913b,8bfbbd07,de4600fd,7a071287,47c31531,924942f4), -S(75ae3c34,5cc1bc11,46c5f13f,a1144759,d39c4d20,4a8f2f0e,bf3c313f,707d49aa,82a5a9b2,2743788,938a0b76,eeba99dd,f85eb5bd,f7ab8eb5,5f6e5334,a00438de), -S(49bd4e57,c59dc8c,c4cfb0fd,83c5944c,3591eab8,1ae90f87,a8d30725,1904fcf8,66e76d62,610cae77,38976214,20955dd7,95e47715,3bde0ae7,491927df,bf2b1c75), -S(5f3c96aa,a71c774b,754f616c,5eaca0ce,f9d82264,7dfc7c2,ce38ac7c,d7429748,8c72e7a2,b7371046,94ce5e77,521ad47e,2fe5cfd3,10cbcec2,febdd977,9872ace8), -S(43d8f72d,fecd31ae,91eaea66,a7b96a25,2c05c3dd,8d7afd20,d64644c6,cad460fb,d6a28b23,50f5a7c4,cc8233c6,85c87875,9134923,55cd3532,f888fb79,10342509), -S(cae9a205,19cb6e40,ed8c6774,7e7c52fb,5c57f1e1,56ac6f32,9f1538ef,6971e888,959e5c41,344ff293,3387c680,54c03756,1f3b6a97,a75a3119,da25debe,7acbe4c6), -S(5f96d7c7,a8409a4c,d4afd355,1139ee0d,ae63bf99,2580cffe,fd5f7497,2bed3d26,972b40e2,83dce233,190e8961,310d854c,db5d4805,e045b4ea,29414909,592b589), -S(2ed0f7d5,a0281d46,61159e80,3cd6bcd,61b1a37e,16aa6801,bbfe526b,9978bb8a,8a6d62e1,2376a282,e62b21df,238ffbad,a055c342,db073e86,1107ac9f,2f2149e0), -S(167b0b4b,c6a4c17d,9f3a2813,87bb277d,fa30bf1b,f35db9f4,b521cc53,dd479a18,32d48b8c,535a49e0,4c412b05,7e000117,271dbe4,5b7bcaa4,87a857f,b723fb31), -S(358af81a,b1352729,f824fe1b,40eab58b,23298fed,82dcbeec,1ec3ba91,21438fb2,b5bada2b,3906f17a,5f882cb0,460252d9,b11c221c,1d316d79,c21dfa73,174c9cbe), -S(ce544020,abc6a8f5,4d911c49,4d0fe111,bba24b6d,7b5f43c2,7f307c1e,1c2a36ea,2d34bffb,416ce2fa,21db1ce3,b6a97aba,29d7a45,29081849,45df56b9,ebe8351a), -S(6057a2d0,11320781,132b5de2,48ad5fc0,d0b69de4,2587220f,2de808da,e61906d9,df0510ae,96a02157,bccc84db,32204888,277d22e4,76160682,65171c77,4766ab23), -S(4eae969d,c9ca79fe,8f61dfa0,e6f3525b,12a3602d,feda122e,1109e0dd,43ae07c2,7763de53,9abc7599,75f289ec,92866fcc,486b1b47,40ea9761,60aa37f8,f7fc142f), -S(a698bc22,7cbd5730,452aa9af,2cfb600f,425d27ed,716cbe96,603d3280,df046c52,c91312c0,7492188e,bf054f37,e20b68b8,9e135946,7180a505,389da7df,7d45326a), -S(52fdf09,1413d6d3,1f64df21,17d35360,16323b0c,e93c66d,257157e6,2e2f8197,d00868d1,b08ac819,9c4e0215,a0beeab,76a543c2,6e3bd1d1,67709cf7,ce2fa4b8), -S(c19e6f2f,98a0f54f,4f61eaab,7b4477b0,ddbe2577,7e82e836,d8b71e97,9782461b,65855134,75c8676b,210c29d3,89d30beb,dfcfb798,6841fae4,56e7b800,e2193d15), -S(7cf919ab,a90c3572,bd41f673,b63d761f,60f28dca,8b3846bb,dfb13545,1ba52fd2,d474c2b7,d6e83e20,12866c01,21f17fe8,e6b36237,45d162e8,4003f04b,808f82d0), -S(455e9205,4d052a0c,9e0a86ba,83ed7fdb,b2b0c06c,eb05b995,13f6ac0e,75f149fb,12b026df,332040e5,8e2f92ea,be60e016,cc8941e5,d7972217,dba58548,f1079657), -S(e066bfb0,1239eaf6,7599d76d,befab533,9542c16f,6b150dff,c96a0eb2,bb0b1622,a8f1743b,b307f660,6ef6485d,aacd5b36,93354863,1d287b83,11eaf53,77df9ea9), -S(f4844f56,52f6b97,fae41a88,3e433286,a0895daf,4929fa51,8aa5040,da2b79eb,a6c86fa6,5c02cc6d,25b6cd86,473eabb4,95d28ae5,b71061dd,8da877d4,9ada9ecc), -S(111d3003,b086df80,114ca249,993e9a56,43980184,66ddbe4c,adc919b4,d58e60d2,ffada7e9,bf38ffd1,19cb0568,da7c8354,ace0f714,6ba144e7,90b1fe26,5e97f82e), -S(4a556e10,ebe25839,9bc4c3e3,8f4e1c1a,7a1500ce,44c38a1d,94e7b516,18ba3b83,6bd865e0,2d756729,c7560a7e,5422f19b,2f9e5007,f7c31d2f,3ef8cf86,7eb83373), -S(10b0a6b2,dc05613a,c436d0a0,9b082c01,8197ebc4,f106ecae,feb40113,1021a9a,6d6ef39b,33023000,5d68215,aa46ef26,b88d6e9,73b21752,a2bbc055,5c88dd31), -S(a0666545,df775bd2,83a6237d,8b8a7357,7c6bf0f7,5ddae3d6,4e65d3a7,90c69336,e61fd87,f43a927c,a5817c6d,20edc6d6,c69e6667,8765be4c,dd260eee,6a7dd5e4), -S(a593c02b,d899107b,6c71aaac,f7314f36,a594c892,32f5dad6,15601ce2,de916170,52fda077,3ba509f4,a1eea11b,6d11824,83a7c16e,b4227d27,fa844657,cdc21d86), -S(46d914c6,a68981b6,99e46e4c,56a6c482,f9ca55f5,4618cffa,5446e93d,f11495a7,bf913796,9dc92ac3,7d52b941,e6199412,117c49dc,8c05df05,95b7721b,66ed1d30), -S(7882d56f,8e53e827,1d51c0c3,49d2afa6,d632fe6e,344a0e4e,c467ee9d,7399b953,345ace50,4127be13,989c4d7,38f00271,a3ea7d8,720ee6fb,82de9c1e,3873f95e), -S(78c6fc9e,571e02b8,f8bde2f7,9540fef,452fcf4e,2b6e7649,3748f594,aa4d6cb7,e7f5a947,b486be05,ad3b9b02,1834b360,ed8bbc78,6013f58c,dca02885,bc8f36ad), -S(562b2b02,741d8c65,6f457bad,56d7bc25,75ed4ced,46577b52,d8b35deb,e8a7504a,17169453,9746549d,1674a55c,2bea12c2,56074f42,91783f5a,59b92eed,768f4095), -S(81f3c319,ff4e12bf,9b7cadc1,75712278,eb9b9275,87df662e,a72fd92c,7d79232f,eb6ce068,131ac2c1,c31a19ab,9aae0633,ee184235,62065a31,59d978cc,43523b6), -S(8ad3bbb4,dbabc2ea,222d818c,6680c029,b0a11a15,7c175165,69a2729c,c4ba1608,65c3812f,9f645537,fc6cd8a8,94279c10,5eabceb,dcd21eaa,dae4784f,69db467a), -S(19bbdb50,a8ce9bc6,5dfd3006,3508bc23,528b3e3,e0615529,1ec0ff71,6a6b708c,75f8a65d,a25c9020,e1b3e26,929e67dc,9edbe8cb,7ce44e29,a3c2be40,50c3370), -S(8866249d,46d790ae,276930f0,8bfd2047,658cda45,ace08344,5d254413,502369b,41547dc4,2fc37c54,11d65d1c,83df2e5c,31285530,15b51106,155d7549,5e04e711), -S(b18db2b4,15471fbd,38648770,8075b1a,7244af47,5a4099cb,ecfddd0f,18bde801,1a2c7d97,23352c93,373919b,a28bfddc,1af8d2b5,953a7da8,2706027f,e802b77), -S(dcd6a63c,70380948,dff9993e,b163a6b2,54625677,5981c03d,16b7b46c,f0b05bd3,2db2651a,e5adc2ef,f2277b6a,d59fa0e6,d6975fc8,14c0c4c8,192301b4,63fc8969), -S(c66261f0,3bc15a7e,2b7ec26a,9ff9ad3b,ccd7a005,b7f9eb0f,f14dc9ea,64b66a24,975f18c,8eed73e0,c2873945,2fec446e,eeaaf732,c3406add,efbbba5c,8ce72236), -S(1ccedbbb,6705448d,9f5a6271,51bdc2cd,e4f57a4b,ac283514,3de7f244,b3fe2593,d58f089f,588979b,a8dd5e1e,e1f2b1fa,26ed488a,9b7ff553,4d4296ba,c768f3db), -S(fa89b801,ff0cadcf,e45d5e9b,b9d76769,a4a8c293,c4d7dee5,eb3b889,ecacec83,fc82e286,1e786cf5,854d69e8,e3c09ac0,4d584273,27f9691,33cc0087,cf7d3a3), -S(ba9e6bfe,2167dc7c,e2cca3a0,bd90050,6b4c5ed5,a65b6799,38850e1,e983c307,8076fb0e,e4b3bd10,5826a6a4,eaecdc6,198cb674,f62ab20a,dc8495ef,9c69df52), -S(dbffd22c,abad0651,673f6018,a4ec19cb,33e25609,5170c06f,b37aeef6,8a7cf6fa,532a4a76,56c364fc,72e4e3b7,b0bf6fa1,9c7c526f,89cbb49f,8e8ed85e,e85dbb48), -S(470174ee,d0a5ced0,3136015b,581f9e97,bbf2b486,6bc855a4,7f4447ef,c2465628,f6347774,94972ae4,90748fbc,631fa000,5c3c9b2e,60072fd9,fdaade69,ef0f039f), -S(e965ab4c,e7b53fa9,e47a278f,18ec2338,5bc8ac5b,ebd90260,340637c8,31585369,ccd9d755,9b80ff65,ee866c71,44abb0e0,3fa30c1,91bb8593,da54840a,cb2a9d95), -S(f4ed2efb,fbec7f8c,54de593,80958b35,e3e4f3dc,1af445b2,a491b41b,256ecba8,b23b37a,9c4287f1,392eee8d,50d8d406,cab40679,a66e0d40,544aa304,aecb9c2), -S(3d911698,27693d14,3b0d458c,427cd698,eeac19a7,8f64d68e,9cb43c49,5421d915,be75c3e1,fcd657fc,59806fc6,bf1df70d,59e44b4d,6d217c8,417d20ed,f4560432), -S(c4589f51,1ed541c4,c4872619,726e7381,a9566548,4e8f0c16,33cf55a5,61b4f33a,c31f26d2,48c2687c,e119bdcb,1aec287a,2f7e25bb,5b3b1ce5,3af33dd0,9a92508d), -S(b3ac12f6,f45d31,b1d6f44a,7d042406,c04ba3ba,ae68fa43,f8200717,b3fd7c90,d04d1b06,ea0f072c,daef4212,89667b3e,effd1f8c,3b4c4f94,ada534cc,552e6d1f), -S(73ed49b7,9a7ecacf,6dc8ef7e,663111dd,40351718,d3289287,7131f8,53fb3b73,e25b70d1,c9d605ca,571754fd,6b5b0317,c7454773,9f71c39a,9069431c,1c755161), -S(d0cdd56c,984d2f4d,6f5068e9,27801a78,9de020dd,32c70cd6,eefe8dd6,aff910a3,35152fe2,70b7bad4,f0d151cc,6ac69412,5b7dcaa7,c757ac32,3562dd8,45362494), -S(adc7e82f,bf52b914,cb3e3c4f,c1d96ee8,7c1a9b5,3a449587,962aa19b,b03967a0,4883619c,7be39873,9be896b3,b1fd6f9b,c62ca121,198bf71d,85e918e0,7ac115e6), -S(a204d702,1a346020,ab978bd7,78ac1df3,bfffb831,3699c3cb,64a118d4,da7f607b,18a0827,bd9da5f4,35ba7ebb,3c4f198c,3f5c3313,fc6f6e0c,f796e51e,3c2e7d5d), -S(8a6abcb0,2aa24acd,71168ace,c4aa3aea,1485f04b,afffc1f8,7ef9a059,d5996ee0,9979410b,afa6de0d,42852883,e13e84e2,e62db36a,6c2a4967,f8e30a8e,11775e5), -S(144704f7,f1ddfdf3,2e270958,99e0f74d,467b09e1,ef388d1d,954b6817,3cfdc2e2,60e0c043,c4bf6051,e09960ee,d7a156c6,5e66e9d5,c19d8b0b,b8ec9edc,6c3cb3a1), -S(4ba11b29,7cf62910,4d7bf384,d87bd0a3,2315170,61e58d80,600fd7a4,b8e93ef9,fd7b0cc8,5c9de5c2,184fd95b,d04d1d34,4c376f52,e9329f31,98ef2fe6,21fc6ad1), -S(4609bd3a,6d606aad,f372a731,9f88211e,31f8e187,d3d0f7d7,ee418817,13540066,62d5d099,88f99333,e309b519,93c17132,45ff5435,8c29403d,8cec5c58,ef4450d1), -S(66e02b23,5399ad24,6d898a63,6e9f968c,b8abf79a,d976df4d,962219b,ab01997e,80a6f6d2,ee813cd6,bed0685e,d42c926e,d59f3067,59a409d0,3529d474,92acdea0), -S(aa668419,1ce4a14f,450077de,e4588ff4,7565c821,7d7e7628,8a2fabf2,7ac7f1fc,e9c1eaf2,4b00ea7e,34f65672,4db33d21,efadb2d3,7ab90d09,e067a286,a75c200), -S(b4680ca9,f0d4eaf3,36cce2e,aa281eea,c522d87b,ac51995b,6893984b,7351daf4,212a1992,b7af5e9b,3d538c81,193bdd3f,61e24271,fecdec72,f1359bb2,95882590), -S(f682edbe,4cf0c8cd,ca5bbfde,4b1263b1,90a1dd5e,e8ea718d,7f01b892,1f170741,ef891402,e5598b01,295f1e5b,48bc1039,375e920d,550cb552,7bab7160,1ccba576), -S(a40a6aa,b4ac57e9,d3b861e5,2b70d28a,5fa6b9ee,1e1f7776,37397f04,6eacbfdf,12957e43,31a5c6c0,18d0c987,78723fec,e16182ee,480b8cfb,6506ca0f,70603294), -S(53b2aa09,23cf3866,61c0271,7b8302c7,4807fb5f,31641a8,e5c4135f,1e6bf439,d4eed7c9,8b265069,533cbbe5,a6be5182,9d79989a,9df82e71,61c3d45e,f0ff3e06), -S(2644109,54ff1fc9,34ac41a6,5b7cf7f3,d66a0976,999b3a90,bc2c4c0d,de3c4ccb,be2fbecc,c71068c6,4b692e1d,6ecfca5d,14271c40,d6713ca9,323eabde,cc7dc588), -S(2e63233a,4146d344,6ed628f7,a0fd277b,435a9d81,21a2dbdb,43dc38db,69189e91,f0d3d6bc,13ee5049,ff2deee1,a13d1e4,eb8a579b,965a86c4,1a0cad1,8569494b), -S(bf0107ed,190729a4,3e130ff7,5cb99a3c,b13392b8,7fd01e32,ae9ec3e2,a0a93e97,eb2023f5,76a06d93,27cfd3ac,c6ba3d5c,ba3ce673,f84d7666,bd2f3f0a,edb63b9e), -S(c22f151b,c978953a,f3a1fb0a,cd1f7255,b5923e6d,c5aa4c26,53fd2109,3b493171,fd3e46,cf4c66f9,c66c5075,313aa519,538b3df9,f2660554,8b407515,502ae877), -S(b99e5b3e,e44391f4,dc3654a0,86abd389,51c8d8ca,ead1ed8e,ccc1b7e7,5b5a4cf2,74b4fa80,bb4579c8,643299b5,5478ce5e,9566c1d8,98eb10b7,200e8854,6a20eafa), -S(b1734d6a,7d8e19b0,10479c2,49ec6806,9d42ffab,e8265d6,f5fffc06,fc1243fe,bed2333,91c587d3,8710f320,1e74fd1,5816ac9c,2eb70bd2,e182cdf5,986b550b), -S(c6c97574,dae3b2dd,9bd060fa,b0515853,b2043ab0,4e58993e,98aea78a,f5678b19,3127c67f,dcf8cfcc,f4b1ee2b,17abd614,ecda39d2,3baa99b2,53ea3c80,74f9b433), -S(14d32f30,f9268e0d,98452de3,4adadf46,928457cb,423b1d95,a58c9f27,eee95150,ba73964,1ac3088a,2285a4af,c63467f,9efeca29,5ba61418,f6d15a68,1d7b12f3), -S(fb71dc00,dbcacc94,39fc4949,ed18b7be,45cf50dd,8dd68c18,b0855344,fae8395b,789b4500,3add70d0,cffc34e7,5c348033,30965e66,b10e0b7c,eaa21f5b,782ed574), -S(97978bd0,2696dd07,408e4a82,c5e7394e,6379e3d6,314658d6,a37e302d,218c6ea,852fb297,591996a7,f1db1402,5ccbe65,9819dadb,647d28be,5f891bbf,e96d3b57), -S(22d18ae4,56cde12e,451f800,f61edc6c,e05a0fe1,91afbcb0,8dffc101,400ff240,4506e9ae,7b87bc3a,9e9eb106,f3a4bb3b,9adf5144,6389db40,5d6e3e53,22874552), -S(263a0e17,1c1271f5,82ccdb1b,5643b400,94f18e82,e8e2a67a,79ed2cbe,c8d7450c,3cf4ff5c,f9b9a42,74650323,88b5083e,676d0ab,45ab061b,9de8d16e,a5f63e84), -S(1fe94ed9,eb72bdbe,9ab19dd4,abdaf994,7e700451,eae8acd6,ab2a31e1,d97a9ab6,f87b6fcf,e01b375,244b1550,77054488,ed835f5d,3c0d27f1,5f150199,40b3a153), -S(65ab4ff,32bdc4ab,953e8983,11ff56d,2648904c,a6ff30ad,3e013c6,f6b46783,45106115,7e3c8b0f,8d362ab7,2de710b,833cb381,bff4d243,32d6532a,1e76cfd0), -S(eae54dac,dcda8825,45912080,6504fd39,a2237e5b,904c3b62,4c960fb3,ec235cb,790f33b6,6cf0a163,160eec2,4f43c321,31fcbe88,696956bb,8b355eb4,b00093b9), -S(5122f262,72e25078,a9c989a7,cb0bc781,47f0be89,6efc65ab,67369af6,8b1b8f41,612aafd3,a2f791b6,5d62a52a,202c58d2,8979e4d9,a856d589,ec45f514,4b7e80a5), -S(9884b4e6,5bddf06c,c3b0be07,108c4880,f2c9f4d5,58b2781,61e57f29,e257aec5,5d4c8435,c7b7a514,929307a4,ceddaea9,ff551c0d,faa2bcb0,77c68755,4f7b4dd4), -S(4dfcae95,4a4e92a,37dc6d8a,3e503359,4b193f66,6adda287,603499a5,f55f53fc,7aa5ee13,952a1572,bfb85bb1,20e0d2bd,1a3dc28c,b87f01b1,8f817b31,c143d58d), -S(bf8f8ea3,d37eee45,78cfcc3a,6f173097,abc2582,22128787,be7557ce,df4f9a48,8fc5aec7,129e9a05,3c6c4654,4559ba34,f0395264,f01ec35c,1eb11a4c,3fad198a), -S(7d9294a5,f462db4e,5e69ac86,427ab556,818a73c,dbc2133f,f6575f43,312d6c8a,d7bb697e,1498984c,d489469d,f4a4214a,4571406c,35b5e88c,f1d11b48,65fb8b3d), -S(54b0b84,e6ae338b,65d832bf,f820195e,932d4e60,24307c96,a8aa8132,53639c9d,330ee890,4596ceb7,28749302,7c8a0163,cd3a52a5,69d41a75,3c099b50,e92a1289), -S(a3331196,8e97db37,c774e6c1,52d5ff75,8552ce30,80d7b9be,5d34f7fd,1d41726d,644016ad,988a499a,70b31577,dbaa6505,7e50a5ed,1cd4fe0a,db31bb50,c9a7e0a), -S(35e2d742,79bbf8e9,80338f27,fff504d1,640cf5ca,30241d06,d388df5a,5d792652,f88cd405,d779b791,f875ed77,8bc92665,359def46,a903d5fc,8052fed9,9390c0a8), -S(e1d851e9,15812c98,a2d176dc,7443342b,3812052f,c2ae183,c8c3aa0e,662c549d,e225ed92,a1d91ee4,2f191b55,f15c9aca,fc379519,ab0507d2,df2019c2,369ae46b), -S(6e99db31,e3f54cb7,cc6e8640,dfc62b01,471ca8d6,35d788a8,e6d0c79f,8de9efa7,176e8bab,4340883a,8380b53b,1e981376,d7f3535d,41429177,bb3a0187,3cf78d6e), -S(ccb520f3,2c671c00,56cfe1fa,17eab66e,7744b2d7,9b5919b4,47a55ef9,bed0d96b,b8a3016c,fa65d9c8,23671498,46379fe9,2f4e74e9,6487420c,38494701,efd9c809), -S(c5e531d5,49e65f4,254541cc,84bfd39d,2279d7c7,98abefc8,cc2cbc17,2e6ca6,4e1c664b,8bec2ecd,7d56db93,66f6a582,2fc70bb6,70c4d3c1,90b76bd4,9a825995), -S(a132f569,c7cab520,d127fd99,9c06d4e6,4a7fa953,9711e1bd,9eea72f6,78430c7f,a81cbf89,b67534a2,4f5ee9ef,8bf5d134,90f73f78,63b3964a,8a81b5af,e44fe664), -S(59242d2b,9279ac93,4a7c99d7,dba4e033,7ba5b199,29a6fa2c,24766c20,71b3c5b3,8824c16f,71126e9d,6bb56bef,7c5e37c6,760c70db,de4b7dc9,e29afbd0,a8d09b42), -S(a8cb72b3,2435a4b5,5687ed9f,bbdd2860,9e96ddad,dfb7c44,d49f528a,f8ba5f57,e8ea8408,eca95aed,f2a6509f,663956e8,e7ced42d,12900677,c86a4b86,ec0b40e4), -S(58888104,903c52df,fd26b72d,4671642e,c06b2efa,44ebb727,e6ca2d1d,616d12af,387e465c,9559e35a,124d6501,715e295a,3d95668b,35335db8,678e48ab,7fe0ff1d), -S(6cddcea5,a0bb7220,f206cbc3,b6ac999d,47f0d2d,728038fc,3b86fa8,61f4069f,724dc303,13aed0f1,ecee0d8,f696c1ae,d00ccd02,90df311b,8611ae43,3664b31d), -S(283557b9,3698a99d,c64643f3,d302454,841eff33,dc110d24,a00467fa,1d9064cd,715b038e,1147a84,8ad45111,8eeea2d2,66cfdad2,e829932c,fce6872e,a99c2486), -S(3f88dd31,95aa10f8,fba82e6d,9d26cf4f,f2ca855b,75bab7d1,c1305654,ccdc8cd9,99ee6e45,76a0773,a8e0a241,a40b073d,78f98b03,33292f75,650a7eb8,bf55fc88), -S(4f0d20cc,acaa4fdc,972e40d1,90ccfb52,c635c438,353d2fd3,47ea675,ad966fff,ab378bf9,c5560914,e5c423d6,f28ee794,eccd664b,fa78a18e,b8f096e9,c7c68bae), -S(4c4f2110,8d32ad06,d60eccbd,238495e,268d2545,bfc5f17f,cdf7a1ca,37c96639,7edf3b15,346f21ec,b3a271a4,bf70813e,c9a4e4db,169b6f36,1d5d48c3,16d7594b), -S(1ba8777b,218e104e,c0908ea,b9ca48d,9145b8c2,a3a0b6ff,95146883,3077f40e,dd385247,7de05b80,6df645a7,646b1c32,90f78fc9,4eab711b,433c915e,462c52fb), -S(4cda5560,ef56756c,f73fdfbf,3799e8a1,f744f497,bab91815,eddbba86,b404e33e,92e1efd3,eedd500c,f4668d78,f4283cf7,eecd6c6e,979980a2,ac8389c0,779862c6), -S(ffd11b85,884b2330,e21d2077,336fd518,a337a931,15fcf6d5,d843b002,dd225ea2,6ab2c275,4d0e514c,bdbc6e24,f3e2f019,8b73b3ee,d267224a,705e0421,4f449d60), -S(fe4a2c46,15b9b000,d871bc7c,af5e6672,a574a165,e544b8d8,bba978ba,ac80bfca,cd15b01c,1ac4e6b1,25b00112,c04d20fe,3afcd997,541f3955,ad60030e,413cb650), -S(c070d79e,dea4a095,a054e026,1c748411,19b7280f,d5cc922b,c2b092a1,f211257d,f7b93b3a,4fdc7bf6,d90ba7c9,56831153,7948d110,a9cff253,f783f075,6c569e90), -S(7820e29b,8a7615ef,44f0639a,2924958a,4b132f73,9e67d58f,ed93f540,934df025,cbbd3f25,b03c0542,5109d5c7,5a409a18,7c117e73,4ba624,3ae7e085,322df8a2), -S(12b4cc3a,ca603277,32fa5c6d,4ffe02b5,eed489c3,9ea67f67,fac3ad66,a20309c9,9ed214d1,4217b11d,324a1c6b,d6edec3f,6dddbe48,2e238376,d3b74a0c,12de2695), -S(bacc8392,e6770551,38b13942,ce2412cf,6e22f959,9f8bd91b,d4855234,d0972261,91263e47,63785808,6c645df6,9b36a64a,8c6a07ab,fdf28a88,6893cb91,4c5428a0), -S(8bf48d87,419b4741,e461ad8,650f2e5e,c93c1e42,cd75e307,c60e8655,8560d576,c38c0513,88d64e1,cb9f430b,5357ce64,c4aa4379,3494485c,4c23e07,dda82bef), -S(c6217853,f15a6675,aab3b7e5,703ff725,eaf68bf0,60dd45dc,c2c209b5,b6255d22,3b5e1d4a,3b04bc6c,665e4ad1,a3a7587,b53f5fce,6db4aba,bcd01f3a,53b342af), -S(ff04846d,7a1309a2,5bcc043b,3a129275,1c5659da,e1377bff,f0a4f52f,78d57c03,5906a77c,f9c5116e,b2bcfbb2,330f12a0,277b211,7605020b,218af50a,b50a8eb9), -S(9d6031d0,7a4005ca,5badc057,34171110,341aa446,37bd5260,9e3c052c,a7833a3d,c505366e,18f920ee,382b6d0,5c71641a,9164c7a7,685bbdd8,6159d981,6990d5e7), -S(328fc8fb,4cfe884a,d6f8807f,5af7f09b,852cdb4a,8d12d6e9,e0a83e62,ef124cd4,ccb846d5,9e5ebc6a,5f753bcf,91ff3e4e,917afd7b,ef3ec9e0,81c302f7,d0302523), -S(6d15ad00,8a21f27a,50545edf,f6259ffc,50b7b42f,6b66daa8,274ccd4f,9968d758,44cf472a,6a9a5bdb,bebc470d,33936503,2823d19b,62f59c50,880443aa,bac08782), -S(a406569a,df5772a6,e881b5de,48a4240e,680b7e48,6487b3f0,6bc10a62,f930154,5378b0d2,df6a717e,b90a9d48,aa9728bc,5fa45468,c997a990,f51aa988,67bf6d5e), -S(a481763,b51b1851,c99f906e,280e425b,833ed883,14b8f84b,ecf5661a,369d345a,95088d19,330668b6,44bd68cc,a7048e4e,da96fa6a,365c1279,47eca0d6,29fb338e), -S(5600b96a,6e0056a5,12160020,7115b198,8ff3fb06,538d6580,f3ba0b57,a9490fe0,a09d1644,f0d14ad1,73b117ea,cfe1f992,2bec2bb0,a8f92f8e,4588e985,4566f88d), -S(95e9d301,fea78bf6,fdd7210,16c7b890,fdf22b85,54870d4a,520756ec,b8d56414,dc2df8b2,6edf5d4d,faf1291,cf2fa41c,d26090a7,499bf36e,a7c5ffee,bf404236), -S(a154b8fa,adc62ff2,ef26641e,4467cb6f,3506662b,8e452518,1832d6f9,145d00d,2cd50f3c,62a43b4a,9bc0c6d8,72efbcb0,c8407e82,39d69ed,40ad56c9,ae3ca73c), -S(f5f28107,77bc1bb3,10c02f60,88a2252d,ac3c3855,78909551,c4602b84,fbeab69a,c23e586c,731e84c6,5a5a0f19,308fce27,ba3fedbd,3980cad0,389e9ede,c1fe6c6b), -S(64be52da,6082fd6b,9f909950,d8887a73,f614cb5a,8e867fdb,3768a0a4,a958c699,4f6792f6,f65ee798,77ca9ddd,3bd4dbf3,3675f059,6d5cfb85,bbd8070e,6f29031b), -S(26d9c5c4,1803962a,f242b042,2fa73750,12c91a17,b6848ab5,af4e9335,43bc8388,f6703950,633edc7a,482f9651,9b638fb0,337b7bb4,dbe6ad24,6a47294c,7f26896a), -S(c1efc973,50a488e8,467d1fd9,ac679eb2,ba011aea,412d7857,e3d2cc0c,19dd2395,c58649ca,c665691f,2fdfdb68,49ef2ac3,4d0bfdce,3927ff52,7a9e3d41,3d8b57fc), -S(dfcc4a7e,5a0ccc7c,f0f76c4c,fa92f075,791a2b05,92f25384,72256905,c08ad084,de18f9bb,28b017aa,474296e4,8ca2765c,8c4eab13,bb4815f,744694e7,697d1618), -S(a44e0a8f,9591b5ab,a051559b,b64ac3d1,ff8177b3,790103b8,db7e4597,6fa991dc,61c41b5e,30cbc23d,e632808c,76bec591,9ad4f050,251e9355,80d9e14d,7116a878), -S(5f094928,fa4652a3,616fc7c0,25b6e244,37d02298,1b2611c6,51265578,daca0cbf,e6599733,a9d0e424,43d3effd,7993510f,15a5369f,6d4521f5,72a85f9b,db7699cd), -S(f9b59ee6,86af9c75,5bb9a4e0,8b15c93c,a787497,ae30a437,bac76831,6f57a535,77f0686a,2ff851a0,e94f28a2,57f05cb0,fe6cc480,39789850,e3f2c7f8,c03f5836), -S(f81d0108,f446165e,46460e5e,5c89d66f,f2dc8528,f19191e3,e75e5d9b,105c0a82,daaf0ce9,7b104214,942efc9d,ab807966,e321dab,d757649b,c1e294fe,4146a6dc), -S(fdafb234,9f9f169e,aac0d2b1,9fa4e2ee,a60ca31,3c544e39,246732c5,61e6d8b7,2b7038f4,9497fc7e,3e73bc8,dd262dd6,9ddefb45,f2bab8c0,770a5515,a5ab1097), -S(bec0f91,eeba7855,9df639aa,6a46201d,9ce07885,85be6bd6,1594c722,79586935,bff92e25,93b8cb1b,a80bf5ca,da923777,56cc1d41,92011377,4f73d461,8b2ad402), -S(41d616f,b05d2050,6a8303ec,e130c5d8,6d27322c,552a248f,2c0dfcc7,1006fc74,1f121fc3,55b81e7e,43523765,80cc3c41,d50e09fe,18dbc40d,a1c75732,5884c42c), -S(e483af0b,fd8affa,423005f8,3d25933f,d2a0c79a,3d020523,5fbae421,51dc626b,31895405,c1d359cc,9b0e5170,b93773d7,39d32681,de3aa9d6,ee635e9d,28abc9a0), -S(65afd96,3c02dd8c,f09867bf,7eadf306,b9dc6146,5b45e138,e20b0a07,570157c5,1034ac39,8fd3318f,44823b33,a140e57b,db8f9cdd,ace4fd8b,33967abd,304e56bd), -S(71aeec22,61b38f9d,1148bc27,7653b51b,7fe98d61,bb3c33fc,b417653d,fb7ac3b6,8344e611,348f222a,cb3c3e12,6a9dc0db,5375d4fa,c1cef432,6008e601,ba2e8c78), -S(ce4a2466,34fb2994,e0af9fc5,a5e8c612,acc30331,81534c0a,640d5fd9,c9b9d208,ca006505,98096923,9973c2b1,c82c6ff9,848232bb,81851f33,cc773721,a97ad669), -S(2bcbcbee,977d3ba,74c81f1a,b1c6eba1,3cc5e48,fa8d9623,35b8ae4c,84fac6f3,bf89907a,8ec4a9c0,44aa6f40,be9e2bf4,a100a64d,3d046c7a,416c9f8f,151db3fe), -S(a745a5c8,3c8fb696,4552ab95,df609910,46074f8,e7381440,e565464,6fb7480c,9b1494bc,ed6598dd,958ffe63,8fb3c73a,d773407a,372db5d8,3504197b,79f3751b), -S(9e0a17e0,33391d78,d168760c,3a31e3ae,f1cbfea,6e13f848,be89b691,11330dae,29bb981c,388aef6d,60461505,53e81a4b,98464956,a69c9494,efd62227,6e0cb5fa), -S(986ffa05,749bb4f8,3a1a76a9,3b972776,e98f87ff,fc66343e,965345a8,608e4411,daf77d3d,5bf42c92,c51f96ce,e78c1436,50cde8d0,11458939,833387ec,993775c9), -S(62720ce,5863fca0,c4723eeb,9f80600f,9a751974,f3c22c61,4bd8ad01,e92234b,f7f18595,97529732,e497344,b7ebb71c,ce51125,78b0bd68,8f2f6b9e,726f7d3d), -S(e60ece6e,c7745cfe,69a17710,c473fb69,9fd6ba1f,1af4493f,2926684,c9740ed,50d14444,a9092465,93dd08d8,3b8df343,5ff98525,907f04bb,343ac295,d8823836), -S(159be1b0,f7579ff1,ae272047,a1c8a9af,2c38354,1ab19a6c,ef7396fb,4c5351f,2ca76b1,a87755df,61682152,d0379ba9,3054049,1f91f57d,1ee1e081,602aa289), -S(79c9c14d,1997643b,44eb981e,1b89a7ff,a6511b81,9539d1eb,ef5dd46f,4c6fb033,2b9b88c0,3dd3e006,638edeb7,1560343c,1a9dff51,b12c891d,dda7f67d,140f1ec0), -S(610f1c50,8012918f,d60ca30,13369bcf,c4bfd56f,abfe39cb,2206e5dd,59827150,85f62af7,722b89e7,6de3ab17,368615c2,9ce6980,4c397580,d48f6f12,5bfbf022), -S(ee26f4b9,9a2285b4,80bde15d,83dd201c,24dfa7,b8be93a,c7ea3bbb,9e46bd88,129379bd,2daa2b99,906b2643,90eecfd9,78b033a0,fc550fe3,b41e1c9c,97671b1e), -S(b9b51c7f,2bae970f,2acc2d8b,fa88b9b2,15ad5289,b92d1f04,92c44804,7e3ca7cb,c5242210,e779cf4f,1f06e9b4,ec92ae71,9a08805c,a16689fc,15b01ee8,d3585a64), -S(1e7530f,dfa5dbd0,7ecbf05e,4c8fc7f2,a44bd3eb,ddc01d27,d83dd25c,c5d9e136,7857a6f6,6d7027fb,b602d8ff,f63ffe5,bae66c9e,ef23b198,bf65e7e8,3fc66d70), -S(f498545a,1008241b,d815e282,d3fd807d,ec8f331c,83669c34,ba126814,56f22037,998291ad,71473cd5,37ce4f16,7bfef603,c144df31,31769e3b,8f5a89c3,a3274584), -S(cba20c40,5a4297b8,2a6b7756,8512c2e4,26e67465,c420e109,b506a37a,9a177d12,81fc17cc,d2363087,ec9c61cd,7b3bd9d,580e280b,354fff37,b43e2ef8,78c338a2), -S(ad4522e7,87c3436b,3406f8c9,3d7f01ed,92c4d319,11644cbc,41c9e103,e8813041,6dea578b,a468d78d,478f3e6f,6233b227,686fe0f8,19ee352a,cab182a4,ec2307cf), -S(e60c27ec,f8dddf6,27ef1c4,e4f84fef,ec2825a1,c57d8a68,dd1283c8,4bc5547a,a807871f,f74ceef0,f647bed6,fe8c2182,e9581f35,465b9c1e,445806c3,428d98b2), -S(9aa982f,b4fa514e,c8f5e08f,447883f1,e49c720,58b6d1a1,d3c3c12f,acb22a64,20886051,e999d3c,f51206a3,165690cf,9d86367f,cea7491,599ba8c1,36ffb70b), -S(607de32b,6c74e540,55de8743,150e931c,6234d65,991e4630,d3e854d,34ff1469,f58fe81d,4f583242,7e8a481a,8b51bc5e,b379ee2,15888e13,fbc770d1,9421b5f4), -S(f980f137,30c560fb,bb4f6db4,c6de3516,2063a618,e1708e27,2f19b23e,af0f3b03,5b7842b0,3ea2cc6b,4d640ace,f6721fec,afefe70a,3729785b,6c2619d0,5162d5cc), -S(c85ae74c,7fdecb1b,52287522,d3c51a3c,4711711,82d089db,1a01e117,706da488,58f96a54,8b03a13a,d15fa656,e67bdee4,ac1ab1bb,d3b91b97,dd35cedc,96d315be), -S(4bb491bb,c05786fb,ad1d2081,2d23529e,5bdc2846,a344f44e,9b914f30,93cc347a,6cdefe1e,abb3ce02,bd3c4c7c,9b384ec8,701d36cf,643e99d2,5c4163b2,a35cdf04), -S(c1eed40e,ff0e2b5,c58ed098,feaa9ff2,7b9e96d7,ddefc1b2,53aaa2ff,ae450542,eb9b0434,e62e2ff9,10ba0dab,8074c85f,9a3bafd1,e6ed1ddb,e158edaa,3b5bfd51), -S(4bef4127,d6566ba9,33881d05,55fdf018,3c47772c,822dbc63,3e6fa336,d06e1c41,1c163ba4,9bcfdcfe,a99702d2,d9bd19db,bfa67409,f4d3777,531beefb,68ec5e3f), -S(3268e230,6eb8d65b,a528db9e,fbc05d6a,1ff35ec9,d4f0bc57,700610d,c9ea902d,126d5546,12de71f,93be584d,38fdb65e,7deccb12,9a5e4e81,b12746a9,cae2cb2e), -S(c4dbf5f8,7b30af00,ee576ad8,3c20f079,cac5eab0,3faf5df7,4d72d9cb,2226861a,badcd32a,d809ae9,7942bfac,a00be66c,80c6c1b8,4b8c7dfe,2473bb53,5bb4e625), -S(8c919ec9,22d79e15,4f1f63b3,5f04db1a,aac7fd2f,911e75c8,b7918baa,a13914ba,dda36a1e,5ada8eac,4aaa28d,6f0285cd,d0011fd5,c46b0e09,1d8dbb77,8b0deee2), -S(1d8b86c1,70366e16,d3c33bb8,247bbf09,cd04fac2,3d9d3b6b,d0fac9aa,3274efa6,ee9196b8,dd6a3e74,697e8834,5f9575c0,80601ba9,d02b9583,260caf8,e342fd3f), -S(ed400eae,debff33f,922353f2,323788c5,29c933b0,e269c091,3f84986b,6e4c564a,35bb3b89,8427ee01,df168a7d,6be85ae0,71c45003,df37b369,2c52499c,85669874), -S(11e79bc0,1c5472e3,3325e3c0,606b6f46,defbf951,2ffdf9dc,8b59294e,e7c03057,e3a588ea,ad8da56,47d42b0c,f314ee96,dc900c9b,5d7fe6e8,a38298f,84812c5b), -S(24a18d50,18273c95,aac1dec9,6d443b92,b980b7d7,d88ef70a,f4b728f,ee718b82,c7bc851d,3e0200ce,16dcf3a2,15bd5322,d9057c9b,df00fc1c,1b0f63ec,fe231826), -S(8349d4a2,fd0937da,1c85e03,c56f01b6,4c0422f6,bdf90415,d9c4ea7e,2bb5873,1557cc42,fb57f4fd,4de5fde7,e4655cb7,fa42452e,1664b328,425bfab7,63ba891b), -S(515c3896,cdf651aa,99e6099e,2d07f0c9,df039a30,c820c6fd,1665b70e,16fb6e07,2001400b,48447b12,391cd2f7,497e1f57,c948e093,6b981cbb,4a414adb,ac928ca5), -S(91251dd4,5a829e00,4c17cbfc,3238de56,c16e8d37,46536392,d5d05134,3cc12279,21748cf4,95c962cf,d28958cd,306536c1,84f8b822,7cc4dfb3,4a8f370,316cabae), -S(659f2b85,6db07ff8,1f10c48f,356acead,cbeeb169,5022f3aa,1e9920b7,896fe684,b7ef27c4,615ae55a,aa576c7,c92bb571,1dcabcff,1bb05c82,359ec59d,a34f53a3), -S(b82012f0,8c209d40,ad21a839,797cac55,728805c6,f139ad02,893cb9e7,3fd334d,76c80c95,ab38d674,715a6f6e,24978fe,5dbc08f3,530a4a44,904226e4,cbe8a808), -S(e6e4fb7e,8e7a946,62ba3dcf,1802903c,fc2cd961,634311a5,dcceb49d,9277e80b,93dcfc61,127c2afc,76a6e097,9033db34,51a95413,a07bed1e,9548d435,88e68add), -S(1e717f27,98ca7da1,268d6bc9,97c01261,6263a807,3874505f,5fad1adc,a56ade71,3093703b,69edc134,20907623,70572119,ff0e9729,a22689dc,8e421ac3,52f4a3ff), -S(8d6c2b05,ea5b29d4,b02706d2,40a989ae,2c3c8b02,c31cfb88,6453cdf1,c33bbcf3,1e27c8a7,25bba645,48236dff,79370ae6,2949c58d,37eac4af,e5977a93,e5ea9394), -S(ef9d932f,d19aa7df,89e6e21e,542bc530,28937f47,7029ff26,45582736,6f207c46,b45714aa,d344a62c,c9348d78,ed4f0684,7424718,784e8ee3,d9b1f857,4758fd29), -S(34932c61,bdd68dac,7957c957,2d4881fe,9e5933fe,65e6c3d5,6f74f7b0,2bd152e7,fd963edc,eb7607ad,a47f716,a5e8564,797c9862,14a1df3a,c6c3e502,86e75fda), -S(ba182aab,ad4a9b4f,3ee47796,3e8c0233,9b416f42,6b4403bd,6087ef5a,f4ad7a5b,178fc05a,35ada525,943ed04b,fa7b10cf,c69f9edb,63dbc72e,5bf8303f,97626792), -S(a5eb1644,c585ede2,59297d94,4ed41664,a4f95c78,239344f0,e6a66020,467e41c6,b04cc4e9,20e643cf,ba8b8dc1,5e4b76bb,575cf1dc,d05a8016,85211ed1,6a98bd20), -S(59ba1e2b,40959a57,a0b41dc2,f7ef4520,6dce83bd,da582f57,e03338ce,cae060c0,2c92f4af,ee3dfed8,3a910194,e548fa54,d4f07bb8,90386017,7394d707,4a979aaa), -S(3f0ff5c7,dacb5106,782f6527,ca891038,da40fe10,7866e49d,106ce243,3b88c962,3f02265f,4dabeb7d,18618e1d,a97700b9,f416e34b,e93da65d,1969eee5,baeb9dc1), -S(4d767b01,8160b297,3cf4152,110ef381,453dcb5e,30af00d9,5bf79971,6656f41,b2c8dbdf,fae8b792,d3a89c51,fd841fac,108e443d,e50376a0,9b4686a0,e03716eb), -S(b3a13e43,1451f086,c6ada2b5,dc38b059,73e014d2,bdb42157,88046d32,efb7cf74,2a0e4560,4cb507c8,6d6e6,686e9b2,9aece6ae,3fb5d3b,7f5f01ad,a8a65493), -S(cd90b032,a7ecd8c3,f1f2bcba,a523feb1,3790cb6b,1573cb0b,1e468417,e52236de,6ff50c7d,354a3008,7907d056,fdb0a4bd,2c34b649,f0f486b5,a366a60b,7d01043), -S(5d12d03e,cef954b,a35e82d0,918cc576,cc8713d5,e77631ab,ab79a0d0,a428fb04,bdfa4678,77f9a637,7bb86a8c,b36d886c,fe09659e,887ee49b,2018720f,6ee35d89), -S(2dc4f368,62d4ff1a,11246119,81a09c25,ecad53d2,e34fbe1,b708695d,7dfcb380,5aca4c06,e92c9327,8d5e29b2,e7af1e5e,f71ac624,ad1977f8,396dd6cb,b676efef), -S(5f1c640f,aae3885a,af679e2d,a3a73b4d,68c3b64b,e7321aa,ec0e802a,66262d54,704c3b72,eacbda85,f425cb4a,6e6632b3,e65963a8,7b26ed9d,770f3a7,81941c90), -S(8cd7d6fc,522eb467,3a366222,5157ce21,805f7f40,3fc2810a,a7678242,3559f2d1,397ddb0b,d0dfddac,bdf8826a,12666f70,d8ad9fe7,f96f040a,fe55e265,bef932f4), -S(b635c8ed,9b7b1858,86c5f75a,d524e877,c4f2cc11,a3ea63b3,7140b044,fb50e692,6c61f48e,a0cc779d,cf746f4d,7b6dcb6f,ca562bb8,5fe244ed,244e720a,648ac131), -S(e0edc56e,e22db179,fb5203aa,2aedb0f3,9f8cd83e,6a1f7449,e33a317e,97b29dab,d3b29f04,818245cd,eb6b3661,8d6c5e3b,384da6a8,aaa60818,ad56cb95,1ecb59a7), -S(f261ce,b12747ce,1b529cac,1d607525,5d48f813,4d1730,32735be6,72db7df8,6c72a777,69cd260b,b78c912,f0bf461a,4d059704,7c1de47a,23a2421d,ba26caed), -S(b6154355,f2b11b93,b69924b5,b450b026,ae63ba72,777c82b5,99d1d0a0,cab223f0,59fb58be,3295345d,abdeb091,8e93d412,c3c5bb1c,b7527ed4,adae9e72,1b4aca0a), -S(74cc74a5,aa36ad6d,42f82135,908b9414,2842819f,9f7b5c89,d2337ebf,af11751f,df890e41,b3253de2,c594c78,18ff0c7f,6637a8f,fd0e13c9,21a512dc,35fb8022), -S(227bf422,28b51fc7,9d090902,a842e78b,a7138a2c,666459d0,16061c08,d6947e82,1abddc56,c5fe3211,7783b52,68f5629c,7ef2a463,40af1fa6,f4edd22f,c9ac684f), -S(31a79a7c,3f1478bb,88ccf5e1,3a220685,845c390c,378c02ba,ddf099b7,7a2905df,a04ad9ec,4b5693be,7aeaf419,2f5c28ab,6ea03c2e,8db116de,7eb055a0,6c6f4a6e), -S(d1b1f29c,bdf6d9db,3d73f74c,df7dd879,14e00b0d,de6c9733,cf7c497a,a355176e,82c6aa29,4caaf404,a5411644,fdb115c2,3c6525ef,f4dcdc90,53d0eff5,6addb107), -S(57bc432c,9fba6e62,35ace8da,4e44721c,a87b44fd,fcb7bebf,610275b8,49b4031a,a75f94ad,19e9a3a3,a0395f4c,403114ee,aa12553e,e168a80d,6610147a,f5c3152), -S(a7c2839b,1c0b8975,2b85211a,e7532018,ebe5f0d2,fee8f053,e6666a9f,9449ab7e,cd2892ed,2bb40ea7,656492d8,40386e97,86919d81,dba6497f,e6f81e9f,ec8b2160), -S(909c4cfd,e85e5958,9384bd4b,6f780b6b,bde85dcb,fe36d8f9,a3f26a93,4c88ee15,f78b72da,b2531fcf,ea9cd085,c17b4375,4263ede6,8dabbaa8,6ecab23c,9475ecba), -S(cb98a258,98e877fa,3ec0d9b6,a1e6dd7e,477b8f7b,716c97b3,1e48709f,de7a3d15,ba6fb66d,502143bb,cc54472e,df00389c,998c8274,cbe8f997,66c90d67,bcc5fd1b), -S(bf5bc69e,81d7b4aa,e4137ab2,6b701fad,a86c6d1d,fd163e6c,4e57844f,3b55e84b,c87360c7,406eecc5,51697719,4eaa7102,1de0afdb,3198a9c1,9253975f,970df761), -S(2457fbbc,767f4fdb,2b5f6194,ca8cdfb6,fd1da59,19e2314c,d809e2e8,6913424a,910877a2,f7707fc6,7b9d3bd7,6408f162,f04c826c,cda46652,cc54415c,30d77518), -S(625e48ad,44703721,c1934642,d72b6989,94550c74,44589f46,33ea8580,e4c20d5c,ef31188d,c127c8b3,67c6b981,241d8627,5125bbc0,dbf46261,4f9b5fd,a54914f1), -S(3d4f45d0,8a28cb71,aafda05c,50a7f534,5b007f6e,ceeeac7,20cadd68,c04748bf,932ceed2,ae007aa3,469323de,fd7e7dc6,deb77872,85e48e79,bfc21cb9,a7bb8397), -S(49f9290a,55e6c9fd,ffe96742,43198574,d81c5b82,1148e5b4,339d7877,ea070de3,f7e61b91,ce217ba2,bd387b4b,8c01e956,3ff155e1,4c8bf553,7ebd16bf,b48cb0be), -S(feffa5b7,78a277de,ae68ff40,9c00b7d4,d6b78b57,b71ac08,f43a5e92,35ce62ac,b90defad,a94dc21b,ce8e7580,dc79073,b4152c6b,441da59b,d904cf6,76219d8a), -S(7b42826,344499b4,5fe3cb54,b8391820,54166846,7806a48a,6221c88c,b0831099,68c5e981,4889f320,cd2818cd,5443063a,4f85429a,5e335f5c,e4731a59,da2ccefc), -S(a2bb3900,e42c4bf4,91aee9a0,bf73bee9,c73a2245,a94e40eb,2f02a32c,760fd29c,6eea2aaa,ef457edc,357c3b54,547ff6b0,8e12f076,2d8a368d,7a9e65d2,d122b65d), -S(ecbf9e55,3bd020a8,196e0b6e,63e8f568,a60bed0,5fb7dfb7,7af48065,ed4c838b,e2be7677,9e7a57c4,3961af37,aeb7a8f1,80070633,617800ec,a407cb5,3ab63313), -S(9d2ad029,2217200c,e3a22d2,62cbc071,9e5fead,6683ed43,8594250b,44e60b3d,7addb679,81dc9504,8b2d98b8,6a4ea72f,faeb5185,f804514d,cd18888e,77acc88f), -S(8cae4651,91c4432c,9c6abb61,438b06e3,d3277b61,177917bd,8fd024b3,353d413b,5615256e,793c6b8f,d96930f6,96d0aedf,4320104f,fe3c7a3b,c7025232,9a10b1d6), -S(2151ca1a,c8b07208,2f765333,42ef886,4a7c9d95,f23e1074,9fc3ff85,bece3336,3a27fdf0,97569b0,52dce8ba,7f22d2e1,325b06b7,ada607d0,7241ad7c,4282e4d9), -S(f6d4679a,a02e074e,3f0ca3a7,95cf91d6,de2b9cdb,d0bbc86a,8e2d14e5,cb4a8908,eb16065b,ab9cbd11,2f30440a,d4540ce8,eb043035,a653e4c3,c8531375,81965fd5), -S(8f8a299b,ade7c13a,2b6ba6b6,f7aedaaf,c36a31c7,bb9c49a,43778c64,b72be2f7,8371703c,b338cad9,acd6db9d,6a840bc1,4bb65328,793ac715,55743a90,f053cf1b), -S(9310f8b4,73347c50,32840e4d,6cb2eea1,a334dc03,b1ac2364,cc0bcf95,e0bb21ac,134d020d,6c2b528f,6e96a9f6,6feddd58,1f4f0ff5,50673620,cac44f57,de0c36c5), -S(a4dfe64b,5f55c497,ec42842a,d2bce748,18f9ae70,cfa521de,255487f5,6d51685b,20b5c707,d8bca7f1,b5d29b42,c6eeb116,6c96eeb2,4201fcb,352e82c7,663164b1), -S(2b880bf6,9a83cf4d,c6138225,733f51d5,ce5b6a12,95b98bfd,e2929b6a,ee5d3863,c21b7e23,b84dfd91,eadf0b14,9649fc10,872c39c7,13b80b81,1d989673,6492a870), -S(300f1400,fad4b0cc,b20fe64d,d9b50202,1105edec,f0bfb8d7,7a1c9f70,73ce546d,166d9e75,ea9a6b8b,cfea2f18,bdf4110,664ffcc8,be29b91f,80d92907,e322a546), -S(7bf49311,d51f9499,6511d0a,70f65466,aaf6cb24,1666b76a,4e821e03,e47cba37,ef25f85f,6dfefb08,c367eef0,c8433f6,8a775f00,464c4f6d,dc3fcc49,7d6189bd), -S(b20cddfd,6f4c3b4a,d9b9ee4a,353d0ed9,9163cb55,83bb526f,63ed9d53,9359249d,b38097ca,9e0203ad,3214819b,b8f4cf79,afe6ac29,cb33c670,2f3cd462,d635ed12), -S(98296e3,83c9984a,b9c06a3b,2daafeb7,32696ecb,af1fdb8,b1d94df5,9149ff2e,fe25c8d8,a72b6b0,17ce8c63,31c3cf1d,dff0ff98,e2db364e,7ce3e642,d3ff7843), -S(ae3c27b0,e32887e6,568abdc0,711409b2,2030dc6,2bb9a2e9,739b5edb,fe4b1a1b,a8513f4b,57f9dc76,5feec2f0,1d7d3ba1,235387b9,132303f4,54fdbaa1,d04fdd73), -S(e0afc1dc,ead8b23d,5956639,5d312ce6,36716e03,e39f3cef,d2d9a5c9,f959dca9,a3a1e6bb,b7fc2373,76484862,e15d89df,8a617e56,b2d61f18,3b79e7d3,d2fd5223), -S(526bc9c6,798711f5,461862f,817b94a3,d66f30a7,bc2aaae6,1da54b76,69004cf1,542349a9,7ace4d08,1022da51,ca2c412f,7c0cc951,62d0c1ef,22d04191,18643b95), -S(dd2a8d3c,8f8bff64,f5acf9fd,6b0d613e,9b149bf9,7c26fd29,41b0c2be,b5419450,6e88162f,acac6dfd,5174d61d,2aa755a4,cd73c440,4b5a83bf,bb79aedd,b7213cd0), -S(d76bccc2,f4079bb7,dbd605ef,ec78a6d5,f3e8c655,c9b38f07,dbff4013,6d80faeb,8776727f,5caa4d38,ba1a3ea0,4a01ede6,5098e470,914806a5,1889399e,c0daa412), -S(afd6332f,27f0bd9a,ea917732,8bf60bfa,4b80f3b5,82319e26,c0fdb22b,dc4b9faf,9595fb29,a8f6df8e,f0b93ace,8f92bee6,f36edc,60b19d6c,968d4177,6582aa52), -S(fb3a199e,1d5f3237,79afbd79,246c465b,98823ca,2851b64e,79aeb1fd,8f90d920,bfea973f,41bf4aa2,f1cc94ac,58e00da9,e4fe46f4,e1d0bd0d,183b8e84,87a959), -S(c4fd8c80,1ef65e97,614bddd9,ef5aac03,3023f7f,1ebfd7be,27f3c4e1,60b14097,2689b9d4,e244e9c7,64b783af,ce2ec314,8ece5372,76c122d2,2fa5d995,9ed94723), -S(6e171334,b59b4989,e2ae6185,54f6c349,26fa1cb1,e7e8b064,61f8535d,cf8f69bc,8064d981,17637f61,72daa8bb,c4604068,624bb0f4,9555f73b,beea8ac2,77e2b54c), -S(e1509f15,8688d157,973361de,6297142d,237535a7,a6b8f64c,c982393e,ff91d6d9,3087adbe,df20cb0c,488b1f61,f12b7e82,f6a36f8e,34a8c1ab,22d71261,d5c2c40d), -S(1235ab12,23b4d47b,e3e5fc37,6b3986cb,941884a9,37d81e1f,991f3fa6,8e529a25,7dd787bf,f7cbb123,e814eeca,45435af1,e2f32c25,8a7081c6,b66088bb,8e560b44), -S(9d70541b,e7995deb,7c9ae87a,b2f085d7,fb458494,f6c4845d,5c8c013f,a7d4a9d5,b1b6c09f,f12d7ed3,9c1af481,3ad135b4,dd0561c4,5a16d111,9bd696f3,e4cdb757), -S(8649ad0c,d9fe1177,8651ed9e,3c2123f9,8ed3b0df,f0afa4ee,adab9fbc,85680dd4,cbb0f8d8,4bc474da,bd1a0b7c,d397e1f9,d9acd111,5847ea54,9018f290,9594fecf), -S(fbae2b84,7685902f,b1473523,2b13f16a,c03d8366,32294d7a,6e214acf,8f8a4e1f,f3fa3a7e,d6cf4375,1f10050f,35a5252e,3c6a20fc,c3d8ef8c,cd393ba6,413f5fed), -S(635dd021,ef74d3d6,762503f6,924c24a5,32c626d3,75ec0d9,279b0086,bff11281,d2eff50e,b28be98e,192dabc3,8b5a605a,639b665b,17fdfc3e,4f339aa0,33d971e0), -S(99ee1d87,4c97c493,f8942a93,8bfbd578,63f8ddd6,387f716,3fd2a454,fd43bd99,81b96b6f,8d06086c,34407f7f,14e2ea21,2fab454f,131da461,7ca88bdd,4026278e), -S(77447295,aa56c62e,d8722ce0,522c58e5,5356d40f,b657ed65,663499ff,289f757b,f60ac045,15811b93,837a0819,f59d6fa0,c1f709cd,2ab128c6,95716590,43373251), -S(b006dc27,bcf879f,92b86d6b,ca0092a1,d848e98d,de52fb72,80081952,34857183,aba7308a,3686ec32,a0a2eac7,47f69f1d,74f9b7f1,60cdb4f2,f8eba9d6,2a9255), -S(41680159,8de643ad,326c6e46,3bd51cac,8c52020b,feb7ca44,6a9c0820,c02cec4b,ad11cf30,5bf184a0,3965085e,42a95721,6a64d9d7,38d9cd09,1dc3a8bf,2ec3b65d), -S(a4e68433,cb81a8c,148b8b3b,473dba7d,c9a1e44e,8e7d804a,519005ae,5c1b7d9c,89668932,7c597505,cd1f0e06,4273e574,85556724,3d257fcc,e0baa643,b38b15f3), -S(3f9b53e,587b01bf,a04a685b,c7d30db7,4f0d748e,44eff028,19192e28,6bf49016,6b927f7a,910f0057,d19f4604,140c7aae,b81563b9,f4c54ac6,6427e50d,11309e81), -S(6833273e,f2629ed1,d95ced8e,e776bcf4,24bc1a5d,284d54c7,d2c3b634,1ec209d3,25607f55,82f7bf1f,4ab5cc2e,c883ede9,8523b751,9d392230,5d98fa5,41e741b6), -S(c7be699,289a091,3021e2b2,eee75322,8cd18703,cbfa7db3,d1d5f0ad,f6d506fd,e5d016f4,2932d594,ddf556d3,399ffd46,c0b677cb,8fd59340,234c9b7a,349cf213), -S(6ef0d7f6,1803acfe,aa62b4e1,cf238e5f,398f0adf,228629b0,65e7c2c3,fa12e589,628336db,78881419,3026db69,2ed2aba8,ebbeda93,fb4f3903,bb8b2e8e,839eb7), -S(ff83fd15,dca2a55d,2ecfdb97,83ca9595,fac1f440,4b1e96e6,dd3abf90,ac857e69,f061ce87,8640d2dc,5fa4428f,75ff93,14216b92,fc1ffc72,29931d8e,f51c494), -S(f445bc67,47a3b7b0,fe56e4a2,db1aa71d,d042b6a,7b09cfe4,bb28c0f1,bc636587,a79a976b,7c857356,2d6131fb,e8476e13,6b6b0863,b8a464df,8e57da25,fcebedea), -S(37f88df9,22775959,94f77586,72cd5894,71c468f2,e6d3e424,45404b16,ab7b9e76,509ebf24,7f83ca08,71fd94f4,b178310d,4fc62bcb,27b256de,22092893,ff3415e8), -S(fc6ed464,1f548b62,a25062db,6b4c9d18,4d5b4b69,ec9fe4a4,db269646,331f6d12,cd384884,28427b19,4c77395,1373fa66,2ca1c771,2cf7b8a2,51c5049e,5d89bd27), -S(675eaecc,5c441173,b405dcb6,256c95cc,70c6ae38,3ba69053,ac02539f,7b6df001,4c275003,664b1f98,98bde64a,6f1b366a,2856a30f,c39fc84b,b6f2d94d,8435c76d), -S(81d9496b,3d892b9f,c4e0b98a,25c157e5,331d6d19,2a7b27f2,e52d2685,3b633395,4b9714a,e69680,649209da,eaa9734c,c611e98f,9bf19099,6f514022,aa2ef5fe), -S(5c6760d7,dbe3dd8f,26bce0a3,a160c8e0,63de688c,e2227bd6,e890e45e,5205076a,f539524e,a8cb2036,bd6ad2b2,3738222d,fe38823,9f03ef10,dfb9d223,407ba175), -S(6c47b5c2,889c17bb,e9f4c1d4,c930a975,6f74423f,7ae9105e,1dac216f,5aec8d3d,55eb547b,d3d60c79,c585b602,dd0f86cd,7d3895e5,b5bb3d13,a44b90c1,edd6c978), -S(da9ab6b0,4a4d3b27,31130717,aeec1123,b21eec88,ae16d3a5,547c1acf,664a264c,87a44739,396a75a8,1f0c542d,2760a2db,944aa850,f61e2fd2,e44c840a,a222a193), -S(cbfc9815,ae28411f,d7056e72,3a4d3fd3,a026d293,f8741154,d9db4ab6,a0147f41,71ed4ca1,e6702d7c,bdd28e8d,9fd41f6a,3879e88,dde652ef,9c639f13,f183d172), -S(2629d332,e3e1ad22,35420ff8,f94d7775,f2385186,a0559166,2aec35f1,623ede43,8e9cccb7,bd6f76d9,d76f89e6,3d8ff895,306028ba,6bc4ddbd,de26f81b,3eb172d0), -S(47ecfa1d,c1e01ed6,111e7ffe,fb44d552,e7a72e76,228914c7,72a80468,634edfc5,c7f3a761,3cc68070,7a1e9778,b0deec89,fc0cf226,14e16e84,4b661766,e6f6b6b), -S(c9fbd01f,ef8da054,7e5f2fd9,c5bc59c5,3e3f191a,7abc3cf8,df5e7c07,ea2adcbd,ba3c6b49,b5b9fc1e,4f433f14,b1a98e5,e20d2448,7fb234f4,9384e610,2035196a), -S(c179921f,24e2539c,9f90d7a0,37d8bce9,bc2741f9,4d7a78fa,a0212d66,f66a0d96,59b573b,9e9425b6,a0232e87,2d0998f2,b1815f68,a2c1ed5b,7bb5bcb2,b4d737d2), -S(a37a89fa,5001ec92,9a93291e,8506c5f9,b669603f,eb3ee27b,5e487113,1ad82cf5,a208d652,6666e930,964ddde0,737c6af2,900b2f0b,5018d814,904e71e5,8f8a0e86), -S(32323c29,2f98e042,abd15506,423514f5,4ea4070c,da493f93,10d1514c,a1895df6,ef273d5e,56e5ada7,2c872483,10180661,a0fd697b,5aad3faa,4cfd1915,fd749ff)}, -{S(6ae991de,18418b49,160194f,a735eb72,c299b987,1981a4f9,aa717ad2,bcdcf13,7ee8011a,40f384f2,e50add2d,97005173,2787cc7c,89dafb66,301bc94d,24b913f), -S(6fe08b32,ab3b1553,14f229e1,138bb09,a3eb4f6d,6629e4b5,903e122e,7ac2917a,4e4e077e,76ab6d54,97c1fd8a,441772b4,36f350ae,ba1863ea,d1fdd05d,f80e6e78), -S(f5ef51f9,13e10480,9a020bc5,37db3a90,3f3e3410,71bec65b,1cea5343,d43cf884,7ac5f6fc,a749b09e,9dafba18,c16bc969,e3d63971,195b92c0,fa8356ea,3419aba1), -S(2e03f430,51968210,a7dc64b9,612b25e1,cdd167d7,f6e39466,9762ad15,571ad471,f063dbe1,3f537e48,1b249a5,67fbe709,ed80c68d,cf8d4e82,53038d90,e67f1de8), -S(8244571a,ded2fff,1a4c9c1c,f3ea152b,d7852596,3e84b90d,6a3dd929,6e0ad9e5,ab14dd92,be3556b5,63cd396e,d8cb103d,cbacfd7,825faddb,1ebe6e3c,9a2e1180), -S(5fa7cf3,ad236db9,db9df632,e7a172f5,fb5396f3,c4df9bdb,d557a3ac,68a97f46,3339f27a,7a6231d5,3e732557,9ab22f3b,49dc29e3,75e08289,b816e6eb,a3ff3128), -S(5bcc702,f5f4a8dd,3f3dd519,371baa04,85b1284e,8bb539df,d8b89401,7206a943,5426221b,2e3fb26b,858a3f27,3d7b67cd,30b7c2b1,b881c285,cb29515e,59b92e8d), -S(96a96f3,79c8dcc7,f87865e5,9023dc63,95224251,12d98ce9,59b610a6,eb7ef515,bd61d338,c84a70e3,545bd8f0,aa0113e7,93f25c8d,d78ec0b9,d5b98d9e,81e16e82), -S(7e491776,5cfb89ff,edc43a8a,c998da5d,cab4bdcb,3b1d6f58,9def4de0,4b976609,7271e990,b7031b00,a990ae0c,86d893e9,915a84e8,d071a235,95054301,d0874199), -S(f9b8be29,8b5cfcec,62e0777e,d916c7d1,371b4627,9d141280,fb8a2767,1af02c8e,c6bb3293,3e77471a,5157f009,58917cb9,4cf77b81,7dc1b2da,d465dd49,711b552b), -S(9f1889b7,720ab815,e6a026e,67be852,980a9609,9e34d570,e1c2a2c8,55a2f54f,9786d89c,4fc1e09a,3bb81830,92df472b,5c1212f0,4ef05a27,dbe9d0a8,75d5e1f5), -S(fc53a56,52d4c07f,3a4af93a,e88cb4ca,5db66818,ab2c874d,63fe59d5,eaeccd32,bdbd9a97,f57136da,8f8dba2d,f34e5d3e,e1dbf1d5,ef27f,11c2c45b,98ef2d38), -S(96a3ced8,ba47f6dd,48a6b320,d88221a0,a5e36c5a,55938018,2dffd1d,3c3c4d00,ee4272ed,b244f95f,54b68c62,2e3d09,b96c7aac,fe77e9af,600a227e,8ec5299d), -S(5d552446,cb8e1882,2aab5aae,676fb3ad,b44eab09,ce665918,6fa6ef31,6f081e9c,723cc3ea,2bb559d8,da986b40,263f5551,25127091,3dbea220,f79711ca,638f77fe), -S(2bd7f7c4,8be5446,86e5a48a,d663345f,bebf198e,d7a6dcfb,da278054,f86d8e0b,584ba0a4,d2cf2664,e9d99d7d,a513b3a,5c06639,5fbc2edb,9259a51d,aa500e88), -S(1caecfd6,26d39493,a2ae68ff,f7af4b05,2373e9e6,8461d254,f9b6d651,9e92ff6a,cfa0c927,ff9814cd,b2af3cf7,4ab5e514,70d70a66,9fe1f353,b0a92182,86bb183e), -S(31ac3e18,ba88bbe9,21fd4834,f9f63ff7,aae351e1,61874ff4,2f8281e3,cd7cfbe9,61d0002c,110f2a2e,19c1b720,a85798e9,e8be1124,c68854f8,b73d6674,4cccd7a7), -S(19bc479b,1637b2cb,2e700f3a,f06b4361,ba1f5d9,7d1e5099,6bbff88b,6dfdabf7,9a59b4c7,deb3ab08,fa5e9e02,4d8bfc2a,a35b15a4,6cd99a08,9fbb0f3a,8770d0dd), -S(c1915003,caa74b8b,51576d17,de53e4bf,c5cc63bf,9c29f847,4981e180,a71fa0b6,cc93116e,500ceae,f045aad5,d9d7a863,392a3534,694d55bb,1aa69cd3,895c7819), -S(ba105ccb,b1c32d83,a57eeda4,2a9bb748,d36370ad,805ba1d0,647bdc8a,1e84a968,76adb37e,53b8bf0e,368a1a87,9a74b6f1,33116144,47134766,27f2df12,602e6377), -S(892f8edd,23341050,7540f11c,9f0ef107,99099081,dbf9e4eb,9bac01e4,94b8ad05,f0451f12,42bf423d,37afc17,74af91cd,7593062d,f22712a1,dc109b7e,f5b81141), -S(389df091,4b0f71f9,70416ec7,1388a464,c0d3d4e2,2c2e111f,f5bbc5f7,d3618bae,e12e51e7,f27256f2,3e8f8935,677aec3c,7c8f4950,712039cd,afa521f1,a88a1f46), -S(383fc7f,86bc9c65,f831c676,2885ba75,25a72886,5d6e91fb,b3ad1a53,d4e64f3,c58d161c,6a14470a,a7be7467,576a3bd9,67d7c944,ae26cced,74089773,b344b2b9), -S(cc4e9f78,9aa3fd5c,eda60c2a,44a55779,1ef31b72,8687ab18,7012ed4a,616fc628,7aaeb0fe,1a94b6c6,4c033c77,3a1fe878,b9b54559,9af6eb4c,a9e79540,faa7ef34), -S(dcf7dcdd,938028ed,f92c5797,6c3faabb,1f2b155b,59a0389f,fe1735c5,ba658aa2,2a008b2c,29290f2d,b64ba559,3c905c4f,46cdae06,ae2b687f,af0b5b91,5422d5ae), -S(75125b5e,f968db84,df6d0253,5108e0cf,df3dd50c,8ca63618,9521475,c02b26df,f6bb520,f8178541,ed169ecd,42a62d42,57ba7d3d,aeba4ad5,e979c8ec,19cf935b), -S(24f1af66,45831b37,bf80d0e7,e6185dd7,51f09e9e,5a71cf,ed350b8d,2c5834ed,2e04d2f1,b0b5d468,b4cab2dd,f0b18467,f8b78304,2b2f5cb0,49d7920c,695f3551), -S(75024c77,150ccf3f,dc677f59,118b4d6b,8749d514,256c1641,e7f70e36,5d99fcee,d36fe19f,442c7739,cc65d1d8,c7ba5479,57aaf055,38497cb8,dab1ba24,d92bae95), -S(4b0b4d7a,51b5307d,69b366af,9a621e30,258b3a3f,affd9a47,52a4a14e,562fbcf3,dffaa5b0,7133dda3,3586df1e,400412d7,6da55cd2,a978e8df,88e23415,9ca43127), -S(83c377f9,13afe5f5,21bb2550,b0a38343,5956fd13,e62e46e,75e77d96,ca2ae791,db64f4d6,6acf0537,f9d60b6b,28ad8e1a,cd9b414b,8f60968c,62a263b3,c8fe5138), -S(271acbdd,71cf48c5,e5048853,3cd6a1f,a49eb8fa,428f05ba,6d7314cb,d128c387,ccf83cf6,2d001c59,a5e6b531,ff40833,4a2b2421,aa75feed,d9ba7878,67323b6), -S(4d41e719,e003cbf7,f3c26d31,139ae98b,a0a24623,f8b86c94,6edb2bc3,1be3983f,2e052d70,6348b402,40e8da52,3b5b3011,a79451ce,41222416,ef040d76,c64a8caf), -S(2599981e,e5b9ec6d,c5da028,1f5ef995,abc78520,32951d1d,6356009f,f482a96c,9560bc0,aa47102e,1488f45f,90797862,3fd9e54c,7467d600,abfc389c,459e5136), -S(eb82b86d,84989f3,68c8fff5,5f801f88,f351e43c,80f145d,4aa7020f,ff057090,62d44ad5,d42a796a,373724b9,f583d57a,d8c19d6f,36f215cb,1c20ed12,320a60c8), -S(8637f2ae,f77485ab,a2871d48,a4f4296a,c84f6afc,b51cef62,b1f22e6c,4cc4b05c,43ba306c,7d6a184b,774e46c3,94c404da,b2acb796,ba239786,d85b5fcc,2c304436), -S(ee462322,f2f44e1f,96643d7d,bbdfe53f,ad268a49,c9a582b3,828bcd2c,e471c1b9,910ec3fc,b9e4479f,2a6d332e,4f809556,1c69f6ee,812b3097,2812079,ebf87cf7), -S(4dcb9320,6a69600f,6d327bb,624d9ec6,24e6d98b,a758922b,b102d159,e6c1c206,da85a8b3,de7b2e,51ddb90b,99f30c7a,70f1bf23,e2c90b47,eac6fe0f,b0d8f514), -S(a1373c2,d15ac2af,2c496399,1db04165,28c74259,6d9d81bc,8004b80f,a68b1405,b7a13e6b,9255caf3,ca4daf3d,21b5739f,65d1e7c,74330404,24911fdb,4e8815da), -S(fbd0d0eb,5a93c0e7,4627e83d,c483b873,96eace6f,fb75acf,ac743e1d,c7a1aa92,bdc310cc,3f420fda,28012f75,e6db4431,d2032990,d4d09a6e,7fb70fa2,fe1344b2), -S(39d9552e,136794bd,76b864ce,d929f2f3,ed4b1b2a,e15b4c9b,485179c6,1d78a846,1565f88f,f2a5c23f,c2110572,c61ba868,9035cac8,ebbc7e8,367c37a,a22308f3), -S(b92576b2,def0f8cb,e13ec334,93e2af06,f2ebf949,332fd038,689dbe3,70700e57,3d7b8497,523e3901,719145,6e908d62,63f752e8,ad2adbfe,13b6267a,ddc415aa), -S(70806f30,e3a407f2,78d59553,fa3fbf72,d5129209,75e703cb,5080627,f30b3d09,c190bf85,9f43553c,6ccacf0d,e33359f4,87b3c406,ea07d424,981d94cf,9e542976), -S(591c877d,6e4c5d56,95152fb9,b809fb97,41a46e0,446b996c,14d201a7,4705914a,b9dc4a1b,e049f291,5c1e6c13,abf19e36,f6560138,9d7bb630,c853b122,9aa70174), -S(f7f3bc9c,fde746d4,fa47131c,195200ff,53c05c09,af87413d,84e9f7f1,feee671a,70a925f9,5b6477a9,f0a6dfca,b49c214f,c219cdd2,213555aa,ea49419d,33f8334a), -S(9505f06b,3a9fa87e,ae289c2e,f4217b73,edb72175,7aa4d7b3,b681b09e,2f651749,231dc38,d5d63d14,4ba84942,67e1e798,973f632f,8ccc09d8,be747810,851c8962), -S(e33e547a,9987dfb7,ae681cc7,1cbc82da,4f3a3a57,972c2b5,10c09548,6c25c04f,55b7c3af,2b3b2684,6ad280e6,51dd817d,b99b856f,409492ca,4f1bffdf,d3fbb232), -S(7bc182cc,598f9281,74fd434d,9b5c2006,e52e864a,90b0b1bc,1634639a,68e8249,2810d2c3,4bff6211,63b09ebe,e77ec622,ad045f21,f9c103c,99089b2a,f0e8f7ca), -S(83dcd3d4,8a18e1e7,353f9b0,76b7ddbb,ddc371d7,7e3d56c2,3741dc5e,c5686edc,8c297536,c3b02d6c,f059db38,791e08b8,2ed1d82a,8cd03186,d2a0054c,862fb085), -S(d4b08924,b8e71bd9,6ca26c62,9c712e61,dc17a48e,bc07e6bd,116d2898,25aa42c9,c1fdad3,1e85fdcc,2f2a0a63,7308c8a4,ef3b31e,a81fce26,21e98cf8,cda3b25c), -S(1b42a702,16d7cf97,de70f734,37a36d38,10f670f4,6a34f585,f9593c50,c6976,f29bd13b,79a7e65,f4f7f94,53b920f,5c751b6,a067d288,82e62b40,7b9858d5), -S(c61413f0,7bcd6eff,ec818025,f792d8da,3643c869,4bf3d582,9a1813d3,cf38beca,68f603d3,db4d751f,ab0823b7,ed050c40,787b003d,6f6e001a,52e3ff8a,71ac0999), -S(5e90173e,8be185b2,16b0066,aa39a73a,350eeac6,e49b4cf0,546bd57b,50ceb215,455ceebe,31e6c3ae,388624ae,fa2e7a1b,fc0c4950,12c43803,c4eaee31,d17122d8), -S(7d0b2da1,8d6416c3,d47bc493,5e409ff7,6b437874,911347a6,3f8add69,8e25c6d9,da9f27bb,82034ba0,64c54a6c,13609188,584f9014,cfeba572,760b23c1,fcea509d), -S(611b1c17,117e25fb,dd62f458,7daa0258,8d9143de,e2bb133d,34377c3c,28778daf,cf1732c0,6de82698,c2531c96,eba3edbb,23aa6586,372cefc5,bb49831c,4c00df80), -S(b43dde41,96f3bca9,ade881f0,5878d347,812abf24,b1a8bb19,9a4a1d76,2f5e243d,1af78af3,acd73de3,dd2a28ea,50b4940d,284d501c,4d39dc3c,8d9220d9,37aa2e67), -S(ba0cf8a,74235782,f251649c,5f6e53e3,6eff1062,fc51f65a,c2a8c83c,e89f4eaa,58e47b3c,467342bd,4202b54,752ada79,a7356f88,92efe201,201af87e,fccde55c), -S(db06d4e4,ca9b1ce0,6d59cf88,da187b77,5e9568f1,da33b398,c682b8a3,ad9e88c7,418daca8,a8e4d3af,edd2de9b,868ac424,6faec0b8,f0b1edfa,e0e9667c,1f3adc1d), -S(8a46cba2,7263af84,80c9ea35,ce8757b7,9ecd15f5,e938f41,aa7d4abd,5c3ce006,6f28398c,eaa2d168,7e6c8427,730ca15a,19965098,7c7338c5,e40798d9,82fc016), -S(705d7e03,b5f0cea4,3720c73b,d6b4ff3e,26d2f8b,cb2f5ffe,6f5f65af,63e4fcd0,4a41f717,baffb579,b769e3a4,ba976687,4727c132,9a30bd62,61df3d91,1472ef9c), -S(e6ed0125,6af3d738,84d8fa5b,361be34,9e2506f6,88b772ed,eadc5c33,98233012,90c4ee9b,aca8162e,2b58406,83a7de20,fb181b92,da81df99,e612e122,8c8e520c), -S(95cb73bf,29e8d04c,a2bca75a,5925ded6,327e6128,e6db16b2,2847ed49,d3ed169f,b4e84fdf,526e060f,7b3d73f3,f534d669,3537babf,3b1ae0b4,c65dc8d5,11917b77), -S(aad1e800,1abd18dc,4d929c2b,c2d59b8e,23c90d56,7b0af36b,2e4bce1d,ea2ee299,a27daf61,acc02936,835d5742,74c875a2,57796038,de289d27,d97bea15,a9d6be93), -S(969303e0,75cf2eb9,551f93e9,43c5512,71bd1a29,b26feda4,cdb603a5,7e333fd7,a8800641,44578fb4,cf16d1fe,3970df68,708e2a10,79547510,f63ca035,616b2f5), -S(6aa570e3,de1b51a0,67e33350,cfb337de,23ce7af1,be879ccd,2b2a4dcc,db1ae9e,98a5f5d9,79cfde0,30fd1ec8,718d2b74,d33639e1,80d31134,85c607ae,d871f166), -S(4e469241,842ab69a,93bc6844,1b6036,578a22e3,c2902da6,1cfde122,962197f8,cc7ba90c,a290de88,e980f50f,bee59f67,ec227323,1db05d3,f11b4e72,34080cdc), -S(772efb55,d4044423,ddf466cc,925548eb,b2525458,e24bdac5,7edc33f1,2cd64bf,df73e64,818bd4e,c7abd07b,24afa4b9,8be7aee1,d115d936,8f4d0fd4,7f40876b), -S(a594e20e,62db69af,4afdd0f2,5a735906,75446d5a,71574bc2,12bf9f24,cfe879a9,1b2fc870,e5f74b0a,994e1d0c,de8ef9a2,74e6b49e,185f9251,417154a2,4f2163ba), -S(c133d96,a51cba90,3afcbeba,40ea594f,3e39a106,8d0a9898,7df1ebe7,4c38d3e5,5cd8c400,989efe10,295ac89b,8891e0cc,be15247d,61ba04d0,4ea018b4,d0fa51da), -S(3ea10966,fca290dc,b77c85c8,232ab56b,afc1dfdf,78628736,9a696fb8,92e67998,798174a7,b4729cd5,67ed639c,9debebde,1538411,94e99adf,f51c4866,990396af), -S(8f0fb3b9,85565632,8207c0b3,e1528802,310d222a,9246e686,6030f9f3,14472152,4fe2daa,d16d75c3,ea219295,661ff8b6,ad9f73a8,b06ba105,80f7f6e2,6661eca9), -S(fc22c901,b93809ac,21e1a89c,8e02093,92e19fe0,8f83d82a,733dae3e,16236a9c,8db62408,8fc9adc3,39de5f57,5377bb32,e3a1ed8,2731b18f,1ecf4beb,914bd42e), -S(7afb17fe,1a4a5e3a,eba9dc9d,c5e178ac,ab9e76f0,d3efdf96,181b1fdd,eb81544,bfbdba94,c3e5d27a,547db3c4,83a09847,3e5c118b,9fb961b4,e78a40ab,84ab18db), -S(38420ae6,13e0eef0,2cf9c567,b0bc28b0,59035e0f,d5df3fe2,d117eae7,27b7eef1,6e21e249,1c6a6f88,e2c96c1f,76a9238e,82cdd6ca,6e9ab090,56e0c1c6,4ccf808e), -S(6b3e232f,1b22dabe,e22f618e,c1a002f,f6aec9fb,361175b3,fe2d48ce,ee724e8f,2530c6c6,8062ea89,24e6a793,6b1e582b,1e630c0b,fa207505,76a6fc24,5e01a516), -S(8f4f70ae,5fc21122,275f1265,520e68a5,e2fb605c,bc3f17df,4ef48133,1d4d3e24,236bd0c4,ef445db6,9a0bd1f7,7ce38360,137d602c,58f8b70f,395e65b3,8b1f18ec), -S(333fedbc,e4a9064a,cdabf1d6,57d5df7f,86114a67,28bad2c3,29a2bbc0,b7e822da,ca491209,173bac98,fab92935,ca8dba42,2583bca4,b7e62ac0,3f805ee5,5f1301a0), -S(d00cbc99,3a9c2c65,b24bfeeb,f596ac8,c925c51c,e5211f32,74145c16,138708a6,5349ca5f,be59a8c8,4ea300,391efa3f,54b3344b,d708412b,a9e6b0ed,8deb8b04), -S(968af2b6,58020db3,e8297d90,c36911c5,786f1d50,7246b35f,86da1cea,f46efc83,453866b4,f19d5268,3ed07612,57bce4a3,173b2c58,280927dd,ccdcbc47,75cda533), -S(fa0adb79,476bea48,8926e659,c8687e14,b769c88a,3a1c1ba3,f11981c0,6934ff7c,37cf240e,ff3a6514,fd7ba90e,687ad6cf,3152f1f7,6d23b8c2,9bc1198a,bc5176ce), -S(7c4a3b6b,3b9c44f0,4f4aaab0,9604066c,3cddd61,996e259,43757c5,a9832392,36a13d10,9ee60811,aca0b269,d42dcb47,aaa0f7e1,7158fdad,50f07e6b,e11289da), -S(9c4dae1c,c6162f5b,e66bf6b3,53b50a45,d1f400db,aff1dbfa,779a94ef,ce7ae0af,2513117,efac13eb,cff70674,b3a9d27,31db473f,e198c3af,59ee1753,f4be8411), -S(c66c125,a04037f5,dbdc4254,70b16cb2,b6318a14,bcd69f85,44ed7eae,346edf13,288a0477,4c2bf346,115235b0,5f921d9a,566c32dc,67755557,a550690e,42b115e6), -S(42f5a4f7,54d8eb34,62c8da57,9550267a,9d73626f,257d21a0,486c043,58c5cc60,fd89e17d,67a052c6,71af223,2337ebd6,16e13b7b,72480373,3fc3a29c,4ecfd240), -S(725051b,43e3107e,2321405b,4f974469,be69f90c,a961e352,7bb8490f,f8d8c7ac,a143d4c0,46ca1288,97633b98,7a6bd28a,81f035a5,e1f49626,1aaad65a,7f68d1cf), -S(358d4f1a,1b94b0c0,9237f4d3,8d7afc79,f1dc3b1a,fae46a67,1a386ea6,ce6b81ff,b8caefa3,86daa463,93097bcf,526d84e,3666a231,97f3804f,3d976ae4,63fa65e3), -S(749bb6b,e9d272e8,8452ec3f,ec83ca71,c15471c0,608a4326,7355497b,27ffc67a,79d588b3,cc607639,4f410d13,c3cab3f7,e635d10b,44e9b242,583b75a2,62136cc8), -S(e5e8cc0c,a1910688,cdf89e82,da4f7a2d,265f63e3,247e5e3d,39d46fee,b00aeff0,89d4d528,60689061,aaaa4c03,469979ef,4c734119,4181ea99,2398691e,29235eb2), -S(62341395,d066f441,60e08ca7,5a9329f3,7581a8da,fb78ff99,1336faf2,407418ad,63930988,431f129f,5933918,e5d23e7d,8249267a,8f0dfbdd,7945e34f,e9e24959), -S(1a4900e6,95118e4d,9f956e99,2f868c3c,dfe8580c,64776298,13da88ce,fc9f8aa9,53bd8fd4,953510f2,72b67737,5b6179e3,e02e12b8,dcd930c8,de94e400,225aace2), -S(b0303fc5,8c1944e8,a84d9bf3,f2102f50,2bad6105,afbe8a37,b09025ea,6bbcace0,d9a29c66,1af8a54d,7b115f8b,52b834d7,e7c2afe8,c7308d61,4e64aaae,3f0708bb), -S(4b51c846,44955e86,9cdf575b,b8796773,d70ec44e,fee77957,c342d491,aac8ae0d,32480851,7180afa0,2d786a90,172ee8c5,75a5113e,ecbff5ea,444ec3e4,143a8d48), -S(c0d19125,b3fea060,45c1b2b2,4febd77d,e3a59da,4b8a8c0c,910189dc,b38d0228,3bed5e0c,e1a5c537,1d56cead,8c2975e0,f420ad89,f0308ae2,95a0c9e1,fd88d10a), -S(8bc96490,25ecb626,131c81f4,c522427b,7f8c22d0,90fd225,ab8bbc7b,50792500,5d2a60f1,591a151c,f0fb3a68,709e1050,21b9148c,5120a79d,100bd319,aad0479e), -S(4acec462,c6566ae9,c17ee177,61822b5b,5ca04619,30270d8,d5b3d342,5e9daace,82832a6c,ed0fcebb,3f40ba27,6e964981,cc0ccbb7,e2a1bffe,6e10014b,c563b12a), -S(6e7b6406,8e3d11de,ee7ccf55,1cf5a34b,168c3f29,d013a5d6,153fca63,2789ea72,72fb451c,f696060a,a82a14ad,1ae636a7,e0f338b3,8aade7a7,fd2599f5,270b55a5), -S(d24b42a7,40563303,25ec4fe3,11ceb35e,68d6b158,689a7434,4cb65ce8,2fbe5104,b4ac12ff,acc676cb,49d5bf0a,7e0a4167,a2460dc6,1b833e,f26083bc,6c7f9523), -S(5ed0083d,2205815c,576c2207,780d9159,7e985b26,9581da3a,2d60f088,1aaec692,2b7ec860,7d94d1d1,7dc3d67f,caa6f499,e3476f8a,d76ae00e,1a981455,85654267), -S(3a2fd05f,4ef9d7cc,6939dbea,a389521,9b1474f2,6fe8cfd4,a2337771,66ee418,5d04893e,6bfaef9a,ee8b9abc,347f3875,2c8cd5d6,d43da92e,be05777e,1b44e546), -S(a0e5e214,53858d31,7aef7152,aff56438,b425914c,d42dc2a2,61415381,30d13374,8ae28cb9,fee0271b,98fcbdf1,66dc9cb6,f0d2ec0,b1e34161,ab8513f1,597e2b9c), -S(ef690072,4a54168b,eabd6285,8c85ed24,2a4c5b04,c4c419,f3586e2a,3ee2a463,49f17e53,7324d9ec,c7feff8e,2f3e437c,d0b01d79,d92189b7,9b35793b,b367fb28), -S(fe22736e,9be9865b,5c1f61c2,a236bdc4,ce37b650,9312cf44,8b536adf,5017f096,bd67d013,5ac42683,e83239de,93f3b7bd,f1d9da45,a7754bb5,f363f501,c3059e8a), -S(4ac35582,84269d4b,cd98bb27,a708700a,5df4e4e5,8fa93963,f6108432,2e0ba4b,91e43c02,ff39da29,289d4c66,6f58133a,5e7ebdd0,1593c7d0,833bc064,d75b876), -S(1bbfb3c,d5ab0755,96cbd99a,cdec6872,4c30a3ef,92162b30,9df08974,30d378d2,b0d34d68,1907625c,726aa90f,d363ca7a,711518c8,831724ab,bd24f082,9b71a9cb), -S(34417402,cc02a6af,129cd0a,d85f6a46,5367b90,baaef255,22622c04,ffa8e389,664ad84a,dc6e21b9,aa5cfc66,fcec0744,dc0e052,3571b1d7,7bc9bf86,f5233003), -S(5e6773cd,613df09,d818af9,cb13955c,f1159616,dc08482e,2737ef50,f3cc34a4,203fda8a,74f49604,b41226a5,40204452,3619c4fd,1c42c8e,1e4c8543,4ba2593e), -S(21f0fd84,1c01cbfd,9998d5be,f2d19830,6623598b,4c6dccd5,28d4f2b9,b0e0715e,ff00f77b,605f8e47,97ecfdfa,9ec4cde4,a9dc3479,3d571f4e,7f9f8bdf,e80b8707), -S(c1ac43d4,7fbdeb41,85536fd2,37aebc3e,b9faf3db,e2155814,e16f93e9,edfa131a,6785367a,1ead47c8,2d143984,c2de38ef,f3689414,14472eb6,8c1fec2c,2b4216ab), -S(c2fcf122,56b2e49d,36e880ba,16f27ec1,adf9779,82679dd5,4ae962ce,62f29057,580b1989,62da6793,9673a54d,41a45486,a80eae55,2de79bf7,9fb63d79,432ca48e), -S(92455df8,c253c53b,6dd44872,9c2c39ee,8f68b260,bb7511f4,b33a5c65,c756d016,c2258438,3f4d24e2,4bb0394f,b05e6a64,552b9e11,7c1b4ce7,a8c59669,b2244916), -S(7e953554,4a105bc9,77ddb025,8fe7f4d8,63142198,98c07b21,8d4c6696,314fa885,320addf1,d0f0021b,5bd67519,881777e6,2bf762a1,2430b17,2f67edf3,edb7acd4), -S(2d57c338,1abbb97a,bc9bdaf5,6ad542c4,4e3aa5a6,2f2da2a9,8c368eb3,506534e2,bc0e3a81,318ce176,c206eb31,cbffe043,8597eb9a,e2c505bc,2c21ec47,2fadfe51), -S(68ff7b53,b4e3dd0e,a24f4edb,c9fedd72,b904075,8ba87e0f,96cc6a1e,4d1d3e5a,7f3974cc,ad1b83dd,9d29847f,d61fb706,f47b1b19,a2993a6a,f885db9f,ff6a168d), -S(2e340edf,431b9efa,cd54eebf,22a4e79e,9ce9de59,b5e306e3,821ceab6,5b11f576,3a5ed040,679e77f,754ad7c5,5de92610,9c863dec,3fca56ea,85dfe104,af228f0b), -S(aee71663,94e2d18,353824d9,2558046,c15052cf,e3e317ac,baa142a,e503c712,6dd9272f,877f5aa1,88c43f4a,d63ecb63,7bce5836,b0b4efde,f980c2d9,778d7375), -S(cf33b265,604c4e51,40350795,baa4d4d4,baa1b136,1bcf63c5,29d5f7de,3ffab739,113390b3,abebded2,667e169,61da10d3,50a3cb23,e2c2aac0,7e72689e,f933b396), -S(367b235c,b5393994,9a034a1,ad476a0f,a3995777,5f933dfb,4493f518,f8ca0843,e5b1242d,c9341bf5,20e7a524,75587bdf,cd571cf0,bc85b390,aa6e4578,69c4c4ee), -S(b133aef6,30e9ff4f,59ce6ab,299eb6ed,ec1ec4d9,5e4e4c6,f37bae90,e80827cc,a9e4f652,cd9aa9f6,31c42224,ddd8c24a,d6f2c8ef,26102aa3,5585d90a,758cc5df), -S(5cc2d108,17007002,9a3a6158,fea4b6c8,3ebd500c,eda5e63b,55e287c6,36d48dad,dc988502,2c2cf16d,6c54d4cd,c5a8d7be,8396f9f0,e78564bd,7bf1f822,bc13540d), -S(2434c516,40c358ab,961964f,62741de3,373bed5a,1db16197,c79209ee,46838156,3376a3f1,8f4998d1,beb23159,143f505c,dd98a0ad,225e7e3c,cea17dec,7d8867b8), -S(5b115d9,e1997333,7f74ee7b,1ab9b177,5f9334c0,6f3815cb,b987619f,e4fc35f1,29afba83,76be4407,d06a8518,3ad236b9,7b967f2b,1ba1bc6,8bcf3a98,f1d36c18), -S(a4c7426d,8bc73763,a0ed12e9,2086bf9a,3f271e21,ca158feb,d6247cda,400ef88d,7beb9c9a,efd02fd4,57e4824e,1f24c058,ad367ab0,d1dac794,58f93031,8cde173), -S(f08ad354,3be27960,41315205,670378a8,9444f336,b1e62681,d1baeb26,f356ab51,24a5ef2a,21eda2af,4b567efe,3c339bc8,1c651b02,25e4fcff,612cbf8a,f17f3401), -S(9c649e1f,c78c4805,7cad2a42,fc8feb93,b93a5c8,a4e0fe3a,3d9c5931,e2e659c4,469afeb1,bf91db88,e49e4142,207cb5f6,1f601dbc,376a3918,77e2566e,eb5f9ac1), -S(5477d1fc,48669d0f,52a4f666,5b599a3,9671f30b,888a1edd,16c4a3ff,b35b0d7e,7fe541c1,b7859b99,528da7c7,ff50c02b,3698958a,b4e96576,684701a4,10b13e3d), -S(33dac142,9de66b17,60ca63c6,887ab053,f315e77a,42fa8091,42d24834,39792355,6fa0d16d,6213a2c,82026d06,57fa1c7c,8cdaa11e,4a92057e,845525d2,ab9401ad), -S(cb80339a,c6d42daa,cf7c1f6a,90074528,6861340d,a9cbf449,4accf827,15ef15a,3f0135a9,3d3d4fa6,80a4837d,e42c9e12,c28130cb,60b9866f,d5ca9f7,2ec484fa), -S(bd7b0bae,e55f28ae,4882cb87,a98c4fd7,bf2957c2,58cc22a7,9505be2d,5c071933,ae3be725,47e45dff,31f4e5b4,c1bfb425,551dbeb7,4d5ba887,376999bf,cc0dd376), -S(654dd97f,29655a8e,12ffd72a,76ca7a91,ae596e9e,2e2e6d05,48157b93,86ae65c6,a6a721c1,5714573e,8cf00d5e,5cdf8169,e363c5dd,fe6e76c0,c26a3dce,f267f031), -S(346dfb52,da33d501,d55d018,70c7603f,d70785ee,1e3029ed,4295ea6d,19d5523d,8728cf28,d307c488,c0acfc1b,53785bc,cfd84e3c,2340dac8,e84db9e7,6739cbdd), -S(4b22265d,70f13fd6,aac7059c,c7f3c363,7200338,28a20412,2168b772,330d73a9,965982ae,f3d121f1,12b4e1a3,a31ba940,ce702a77,1e743498,5ef4624e,ac13f9aa), -S(2336f680,86bccccc,679bc8d9,1c42bdbb,944300fa,fae9aa51,3a5245ca,5f0fcdbf,b0442c58,74e041e1,acf43400,7547ffd5,fc71d5ac,934fce04,65065e07,9b13d8c), -S(9566b5ab,2ca85589,565a2245,cbc04256,5b26b333,b089878a,393f464b,4405922a,2b6ce7e5,b22b9411,a46a012a,6745dd5,6ba35d7b,3304c686,50eeab44,d245886f), -S(e5722284,b8d280b3,a4ea8413,7cb6d8f5,e7107ed7,c1e46b4c,38adceea,8323d731,83492274,77d6d6e9,f19a2166,4fba0027,7c30529f,5025b6b0,6a10160b,bbf941f6), -S(4efc3d78,d30e4d41,e6d7e04f,d65c7f4d,abf51048,922ea858,ced39ac,ff7ba548,d3f3b5e2,3ab945a3,95ead15c,ea221d86,44bc737a,f894d374,f7379309,1f18f893), -S(268b193e,718e2c07,3cb4205a,c1dea8ac,f12b73da,fc17eaf5,b3dd7f74,f9492e16,6f1e00f7,35e4c6a9,a16b0a5e,5ba280e2,20760b4a,691caa82,d959c412,5fe739b), -S(d31e56df,6a0d1e5a,f6ba93d,63a02d6e,a91a6008,8cc6a7b1,ef6240bb,83ca59ea,3693fa09,ac433b64,424162ae,bff3e0ce,b926c036,37266c07,ab6590e5,b269913e), -S(c5103c0d,6b6995f2,94e1418a,21492951,caeb4adf,edadf140,4481e674,247c54eb,7832f84c,f94d55a5,ee865d46,605e708f,a4ed1879,a1bbea67,d01140,e3aca110), -S(f95cdafa,b5578ef8,6f37e978,476c08c6,6e3167ab,73a802b4,a24d855f,39b7e9be,77ae964e,d8a3b05b,8f8a7005,1cc20b99,71a4d78,74dc40a0,e2cab2a9,c662d445), -S(b4b9e827,faacdf2f,6503b903,171fdef2,7398c819,3776d2ca,7d1b4268,e65afbea,c0143786,244ec5e5,a166996e,194dfb2f,54152030,e1bf2fd5,2d33fc43,7f955ca6), -S(9169df6c,e6c940af,8dd672f4,5babdb0e,332b8082,f06ea004,1555b1bf,d269a328,be066e6c,26a18e22,8de12272,a374d17a,307708c0,f05f5846,3ba9a55d,dcede1d3), -S(4ebeebd7,c1b60e42,d40be032,570beb3c,6671ccf5,b7f1f10a,b094da51,7dfb6971,8b8d6022,5b57789d,c91f02ec,81e25d4d,69d85c88,809f202d,2a998460,95361653), -S(8e96e051,f8d7bee2,30209f26,ebbe1f74,1db4bb35,363dcd1b,bc33ffc2,b7c0869b,ccde36d4,c67f2f29,5241fcd9,a85f2e18,c322def8,dd785c2b,232e1da0,3c9dd27d), -S(61b8b1f1,d92213e1,38673287,79bcd83,7f06b24c,331e5dfd,76d91df4,54d6a42,93b65197,a22442e4,5ee12c2c,345afe10,aaefd03a,ad45dc32,98fcf810,914d0d47), -S(3e94ab30,2d01ac20,9b0e8e4a,d7329066,ab3a32c6,b0d8160d,9e2a7b64,8b625563,85ee61a8,643d08b0,a5eb2f82,7ef70bbb,99ca044c,af4338ba,24774e81,b6fecf4c), -S(dc4ae75d,78831a0d,ac87cab5,7c6fed74,500cf2e4,1fdb8afe,7f95e81e,730b9b5b,5daa7147,1fd50e65,9a9845d2,9535f0eb,55f787c9,ac1b595e,da2fb170,b59f17f7), -S(b56007de,d2b04196,b5398832,df12ec62,7d4b188d,beb5f09e,a3cf87c,c414f252,88d29752,eec1e71f,3c72609d,f5a60e31,f485262,b87d575e,83d9070f,b72c0ae0), -S(5d5389c,741446c,1cb8ddcd,48c67a41,580dcf2e,93257012,97a8b8bc,fd20d4d,e79b258a,57ebb0fb,26f08771,d63cc6b7,6d1cf981,124cb3da,28405aa,9217c698), -S(13037858,1413a8e0,9460dd66,18cc50da,f8e93b44,f0c0245d,58950892,1d61c1ff,5374f786,906892b,77d3cac9,df04a393,f17824b3,8a9a8b47,c5adc73,2a7fa51c), -S(d20a183b,1e003892,f65937ab,a19153a9,5c637bd1,8fb1fa93,4d258555,36e334d,c1a3efc7,c1b2c14c,6176dc68,9ecc273c,fc7250bf,d059ab0,fcb068e2,7cb70741), -S(585aee85,4d5fce99,fa00d575,6922e529,abf77d52,3322bb68,7e7d3cec,b28109b,e7f5ea62,cd4e12e3,c2b43ddd,a1f7638,ebd5a2bc,362b087b,6839b13c,ebfc5cfe), -S(1b20bed,29cc0082,5a6fa7f,d1c8fdbe,13cc853f,f240129f,16df04e9,a04e1f1e,daeb1a97,17f5bf42,4972b4b9,ede42db4,7fd36247,173c0e5,b53a6994,8ab01980), -S(c9a9e323,c531bebd,84548b4f,ffe78967,a08b6399,67788ff0,4953a1e8,8c7febeb,d64b4ed8,eda75c40,66c26902,944d2744,503f6017,b8e80940,55adcc7e,b34306ab), -S(6c551219,2ecadfca,bd79055e,d4e45f98,ab4f3a96,15e3b7ce,138f6266,d0ff245d,56aa876d,efa4593d,d1140d14,19f5465c,8a826859,af6a3eef,e2013c60,330df086), -S(e242ab32,5fc71bde,da7da19,686cb1f7,93f38e81,fbb555be,db874200,8ce81571,c56f2ed3,20f7827,cbe76177,e61486b4,cf15a555,816ca48,3a72867f,f27c4ef9), -S(7ab15e09,4b5af61e,3f5b7397,f89f1711,e3c55005,1202b76e,b351cb1d,91998741,27856f9,a77ad2fb,adfd70c5,7099d4b5,8b162f6b,daa3f3e,59f312d4,d46535af), -S(e55d8d3,77e84b5f,626cc6f6,7d1d0a62,44c72dd3,78206816,35c30d95,f7541cad,e78f840c,f8056853,3824602c,3f7aaacd,2de98757,2edda9ae,37da985b,60e1b690), -S(e9a09a03,9b0a0130,f0b8667c,6d7abca4,b3e5c143,d0126565,1fca6216,c2128771,4207a863,dc05cef4,6bc6bb9c,975485f,7c9f876f,3bce673f,f160d714,bc151e90), -S(e2bfd72f,f1af92f9,33ebd08b,d6b70cb6,c1346895,9a0bed0d,7cdae7e1,65135325,afca8d06,74918152,56a53af,b0dab50,91752e09,b44fdb4,cdce07c4,89b00045), -S(656da8b6,83b95ef1,e20bc36d,e64f4dab,7c1ed8b9,261548e0,93e75d5d,525b1bfe,d12b0be8,d382a555,a71143e1,cd0942ad,9f97e771,90bd6a24,5f473204,5d867bad), -S(e5e3168c,51734cb9,c08d9035,d592b821,a6a479b7,61000156,974a8eea,2f2bb902,63661750,8782dc9c,d4271732,68661c76,d2b8bbfd,9d49c7c3,88df9360,e6ea1fba), -S(6676fa5,dbcbc713,920d915a,13d01972,82457d37,514492,f90798f1,dfbffaa1,3005bd04,4d06ff3e,4f06310b,2927b621,2a82becf,5111a825,dadd6e13,bc3fbb66), -S(4f89f4f,523a53c9,ee9571ec,33bd8768,2f620c7c,8257a844,355d87bb,7f6f0d48,131e3f25,cfc2881d,833bfb59,d917d7ea,af2a7336,ee8944e8,6c4a48d5,10d9254b), -S(9f541512,a0f7a48e,a37bdb58,dfd9e627,e775e862,5b8552df,88e5f595,c68cc80c,a8b36ed1,2ae8c2ec,fbea6d33,6903522d,714ce9,3792759e,678f4643,f880b461), -S(777387eb,9e9c70ba,dc94b9c8,f0fb411,ea6017c4,faec6aff,f6d04105,c031e4cf,6bf663b7,ddfbcb36,f833320f,7098c928,22f9b993,3de32c0b,be60b66d,61f94795), -S(b27524e2,ec594848,fc757dc7,762c6396,9938d53,4f90a0bc,78178192,e9bd94e4,f8c944cb,dfe215c,32886c9d,1149dccf,c05a78da,ab759161,22182569,a5858454), -S(c67fb320,4716820b,37dfc400,cf2e934f,4080c4b3,b092d261,b2bb88a4,5136fa41,a3f61aa1,ccd741c,f36e4b6b,1a05896f,3805089a,26961cae,ffd2f70c,b0b2df3b), -S(f4ec97c8,d8a5af0e,d8d71cf9,5450aef6,66a29847,e395d60,7c17e50,68ea9be4,4376c5ae,10e31637,7b1d3ad4,6d224dca,8a83cdc,4e78a9e1,1286b4d6,2c39495f), -S(101fb524,eac89b59,10337c27,48673b30,e24fe7c4,f9beaf75,69861984,d14243b8,d56cb44,6d9d050b,69b986b5,adc3a710,774698b8,72236af7,d4758d29,dafb1fc0), -S(3baa0ce7,feffb71e,31c935b6,ed2018d1,e2a1a694,963f0878,354d2826,17008749,c010829e,aba91b9c,ea31b88e,aa90fef9,3059bc35,aa2c11d6,4cbbf40d,bed2271), -S(3be18f6d,9c8609d5,8b595b57,1ec6084c,650ef42b,9511e1c8,8c879aa3,ad70c65e,84182bf8,9db24dd2,46eea18,639b98ec,b62f8b93,5ce1df3b,f71d93fd,ee3c031b), -S(4249cb66,d532dcd,406767d2,7af9e7e6,2a7e46d2,4a140a4,b01b155f,5712f3a1,e4b5a468,f71ed053,a060130d,e40662de,fa3a87c8,509dffc7,83c7b2de,93c89817), -S(75688f6a,8599ef01,1c89b06c,132dd184,b4485af6,b3410f20,fc2368a0,1df9fae5,830648be,b36c9c8a,8ccd1096,3f2da3e9,e4f03d0a,75b13325,80601da2,3d572a05), -S(c0b7cfea,412fff9e,92e31b33,7e133041,c81946c5,603a3ec4,3f92fbda,bb56f8b8,63a13e2d,9a06506d,dc65bc20,67afbed0,ef0cf722,e75c17e9,14c0ac03,d50ec0e0), -S(777f64d1,c65275fd,6b266e39,5a0eaf3e,df51bf38,336f6651,1140f475,dfed8bfe,d75139e9,ac863e6a,35b495f7,6ca5c554,21fe88af,24cae574,95456046,503f4286), -S(3e7e7c7c,c7cf5612,f44c42bc,51f3243b,20bf280a,8b75e7ea,e52ce30e,2fd80657,e64e815c,fbb6f263,eeb0a21,8fdff95b,19eb8cad,f3d582b8,8847b7ea,7b9460f3), -S(8795ef69,b029ff93,5e9e0e84,5490ebcf,18728b6d,f25152e8,d315292b,d834cc69,86b984af,49c56711,20630233,f30bc4b5,e460ca18,8e4a86cf,5d5badbc,bfed2e3b), -S(f5b01cfd,59a22134,85fa7eb4,d9a7def6,d16b258f,2bdf581e,e22c28be,9dd8ac3f,95696481,42941826,38a4da0b,57f393d7,65e3a9bf,dab06592,87905d1f,5323109e), -S(9453d039,9e8dfc00,763b254f,905acd5d,60b109db,6830d8a,f062f339,a38f553f,59293f71,ea51b918,334593e9,3dedf34d,9dd0c453,2b5c9b35,edf046d9,5137f38e), -S(40011ac,573a375d,7815fb09,8bfab10,89cfd5fe,7fa87734,c257a9a8,9acbe65f,40f2e596,436bfd24,bd88bf33,1e711828,56478565,93e0250a,d7b87b6b,72b5af13), -S(7e0cdca5,50430cc,404cc9e4,e60bcbdd,6611c175,1cf50670,fe19271a,4db4aedf,812709e0,1e5f03f0,dd94e208,992db41c,4bbe8cdc,fe0f0e0d,bcdcd77b,d95cff63), -S(9c60fd1d,675457f6,4fb43af1,3f25173c,f64833b1,48867172,5e1f76e7,3e3f0da5,11d7e0b9,41c428c6,c0fcd00c,fdc4e252,1084a6f7,ae780845,bafafdd3,30a21e24), -S(7251e853,65bccdd8,a493ef77,f22c347c,964b0827,20c84195,5bd367a0,c2eeb752,8df2d302,e0f90ae1,68e84163,d4081a9,b93d0421,52a45bb0,17635904,8efa67f0), -S(da466345,6e03c943,972bfbb1,5b2cd45c,83fde8b1,e22371ae,8c248431,151a6198,6659dead,d0e6dc6c,15721fa8,c00b1aab,6676fd3f,c5f6a834,9ddb4114,b5c45e18), -S(666b5d13,8d5b8169,256009fd,ab4911db,2ac9ea0c,ea7b707c,60196819,6a2dc816,d7486d1c,d50eb54d,22be8156,caa92197,3614604a,1a5c72a3,836d362a,d0973fe8), -S(48f24f6f,e112c070,21c45eb4,59f5624e,e65de1f,ea3638aa,b8b849e6,175805e4,5d2df55d,bce84e37,1a13d26e,f04f3a99,38a9dc58,c78c6c18,4e72aa8e,2ce03287), -S(3518acd8,23ac4b6f,d50f8691,90d14f76,ba22bdb,8e0c5e49,8949468a,30eb3230,e3c92847,a0fe393e,83e101ec,f1b45ba,763c725b,684811db,d2ae402d,a31a7467), -S(105b1aeb,5c85edd9,ad72a0af,cd04ed48,feb975ec,62ef031d,9b0bc668,795b717e,dfb18689,75b80da7,110cc6c5,c845e9d6,6b8358a6,2382825c,2e6c914f,54b473ff), -S(f156d5c7,f15e5276,a9f673df,590b93e8,348407e7,9f6c096c,73b658a0,a630ee70,9d9bc235,b54fc94a,4d34c33c,fa843c,1c67a074,c679b0da,64b44358,14ab5fd3), -S(eedbc38d,d0da0095,a1df4b97,2add48af,a97f2e92,bce8bf67,5ff3c134,73e5c3ac,116d4b18,5a00d9a6,b858d82a,39192f4a,a4e6f305,b2d695b2,e054557f,b895ae0a), -S(14b54fd2,cf799482,ce31b76f,474055c4,60647893,d6b46894,15676c32,3a413a18,5c700720,c08b7a19,7672fbfc,cc7b5223,6b0664dd,f9fd3df5,aaf66e88,f50824b), -S(ede2af57,9ebec635,d93ccd2,1fa74e69,d8bcb14f,d82ef9a3,570bde8,3f6e7f3,e5b817e2,3af1ee7a,38a3cd2e,41b2cf98,c2d4356f,c40dec19,b899d219,e01f9121), -S(6aeec3f4,90b048a2,cf210738,f14d7324,5ff190ae,72234576,e825f5e9,20641002,acd9b1cb,1fd56468,6da61382,cf9d66e4,1fa00c16,d886c9fe,9aee6d13,d1812054), -S(a0df5ad4,8b909123,e0de90b0,669fcfc6,f0e10d0c,28746ac,a260ce19,a678c8e6,3897d22b,fb2ebbd3,e87d6948,cfbaebee,95adda8d,f0654dac,d409dd51,669c7eb9), -S(d924dce5,a68819c,6e840326,5ec20b56,553d596e,78020430,5ffa6d5,736f5317,fa262ae2,f1be924a,18a41181,f417d16e,9013d50,c56a5eec,47244a3a,fe69122d), -S(98add9e1,45dc7541,4271c971,4d6219e5,436e479b,998a4b6c,36ca3a6c,90645ca9,34997501,ea07f7b4,2aa4b6b0,7387104b,4f20c0c9,dc1dc82a,8c2ba093,900741b1), -S(c42f3e37,2cc9cf46,3d76c4bd,e29481af,dddf3040,340baa94,6bf84220,7f9a70bb,5a1ec58,e4038781,3e9ca00e,9c53358f,7d777fcd,4f18b5f0,dd81b9c2,3bb3a059), -S(e940c5e4,1931a103,a4feef73,7e95a12f,346c3855,7a3a7ff5,dec89ffa,ec1c3ffa,5556a9de,d0a5e7be,5440ab2e,3850f718,438ab153,aae411e9,c31d1012,15705dbb), -S(35b105f5,7ababd24,19f00161,262a6a8d,2738239d,418f8f68,8c57fdc1,c8b3afc4,97e93b99,7664d080,f9236d16,38fb8457,28f812ca,9b0d47d0,545058e5,513b722d), -S(15ddbc98,b22840aa,bf698e42,3eabfb3,8f32af95,2969eb06,c24c9901,8b9428a9,33404fd3,2ef62c0,db440774,7fa7f70f,d681c4d5,e042c48b,1c7918b7,75f13514), -S(a00a5eab,1517bcbf,d377402c,d2721d3c,f493d100,3602e251,8882d426,fa69ebab,68f8d86,2708fcea,4022308c,2e391f76,9cd4e128,495aab01,dcb63473,4334760d), -S(7350c15b,8afddef1,4c173893,bf5892f1,6047769a,278c85cf,20ddcc91,125a632f,3bb33254,e5ab2964,f6f401b5,685ae429,7a33b887,99fc9861,75da7e3a,7abcaf51), -S(7d92d2f0,981424aa,6d651cd3,fc1cf104,2f24e71a,29cf49dc,c4aead32,2771f6df,f4f49d9f,f1905e01,f8de9679,b1bec436,ec0bd68b,b24e8041,89d369e,e1a46e5c), -S(2c10719d,6122c4be,8f1ccdd6,d520211d,aceb2e9d,fbba02d5,6c0fb1a8,5b3a44f4,558fb689,90788971,2e5fdb,7bf12431,3ca1e6a7,e8117d3b,8e53ee5e,b7162eb0), -S(5b271fe6,10767158,ef07e835,54e5cb7c,d39fec5a,defb93ae,122bf5f2,44758a61,d82aae85,70af5248,f1e4b784,26a491a2,d5c33c22,c65165af,de42b288,60f097e0), -S(1c3bfc2b,cac4ef22,9f946221,6f03fbb,b2d27e25,9c2e1cd5,c410db50,74be14f5,f3ee7b94,e8c24dfe,abd78d0d,737b89e,962cca9b,8fd47978,c6573e51,2811b857), -S(d43a0bc4,638e36db,c0068609,b7f761de,44303303,de7189f7,99bf611b,dfa1b233,f8877c1f,6ccb955,6e9b182,379600d6,db4bd0e3,83c76dd,42941e24,bf8fe041), -S(2e4d8eed,3e9d1d99,2f08882b,348fff52,913c9a6c,177bc71c,236d92c7,6634dea3,1e994080,635d8ef7,a6401aad,679ad721,56b81cf8,7959935c,dea463d0,b74e96ca), -S(4cdba5c9,d5fe043b,c99da326,9cd6248f,3ecde544,cf617a5,b8c73e47,cf539c92,2527e4b3,ad0bf862,f94b567a,21020d72,92def1d,8e19211a,35f78ad9,dbf72269), -S(477033f6,5abb16a1,7e4b80da,f81537ea,eb39891,d8a2f0a1,5577b1f,999a6473,c986f8d1,3b17239b,e64224e1,b0316573,18c536d7,b00d6f2e,a462848a,389c47e2), -S(2cd55c4e,e05a9e18,9ae326d8,741db193,eeb4b356,78334c1a,48453f56,4452cb72,d9186792,86ede279,dc4fa812,9bfdc308,b887bed3,1b9b4512,1b15c552,ce4f89d6), -S(c2efc599,bf13c184,7906d679,16182ff9,d98cc345,d306975b,a5285330,75925f94,9e6fcff2,981370d,4f4ee530,ab1ecc8d,4f807572,bbdeb533,6157a096,613f267c), -S(4804058a,88482ff1,bc0c27dd,31f53072,f166b89,abfec728,ac77b832,ce24387,ed62ddb0,9c4ad5e8,473c443d,ee624287,e85398a8,dc08ddb2,8ad5b4f5,4e0b990), -S(6c3264eb,7f4d3f1e,5c0c614c,cd8f77ee,a23f77c8,a22d6679,467269e6,a13353f0,158750fe,28339ea1,ccdd2147,466824e0,9c44df45,21b2b47f,540d4f9d,9b57c2a0), -S(5a2e10de,52c3e589,4f7e9807,cb5d75c6,7b8fb61b,6c161f18,661b7bc7,486f1f5,dc191e64,c33a0aa4,7a771ca8,8aec0c33,8ffde81e,3b8025dd,61314acb,e11b4739), -S(57c4ac9a,c559aeab,da34371d,c0088bce,768cc4d1,6423c8f4,daa3ecba,571e79df,5beef57b,97435345,db22f84a,36b0f1c6,7d42b246,32336304,f1f4cc6b,325f7028), -S(46b350d8,326546e9,93e85952,f4fa1b5e,4ff93d4b,2afaa5a1,5ceb2e66,fcc12665,852b0e65,a3864018,62f9bbb7,f284b4b7,e04ddcf1,dafdc616,5b7d2303,395531db), -S(66556fbc,632cd7fc,e3a8d768,b96de7ab,fcd0a7e4,e3db320b,19e9d971,97326d46,45275512,50aede32,9b6713ef,eada1372,69465b72,cc720404,aaad34b6,fcc5c2b6), -S(24e2b12a,798506aa,68b50881,1c555a5d,80984736,5a4e6f7f,b27c863f,8cbd2bb0,fb9aa79c,d205955d,4e9da24f,4798f930,2933fe7e,1cc01024,c08c9fbd,7fdae7d), -S(fb51fa7e,c8d846f1,fde26c,6c14c479,38059646,aead5a8b,7bbb05e1,a5bc12fb,6ca2fac0,20cf7c16,d360d37f,eea72322,edf5b824,3cc3daa7,f0e91a81,dc2f7aef), -S(4613ed89,ffb65026,f0481095,553fd5af,929a13c8,4013bf28,9005aca4,e8e0dc94,ba837762,a2e6c17,4cd4912f,3662991a,ec910c29,8033122b,63396def,5de2cebd), -S(222473ff,f87dfc87,403467bf,9b0f12f4,2014772a,68457462,401933,f6192499,58aab7bd,8e58d310,1849b3fd,96a2b6db,8eab6ac3,d29f9ddb,d2866980,14774839), -S(5e751a2f,988fab02,b974604,b4177076,81dc7332,a2d268a0,4586f231,300552bd,2d466152,4180a713,f6b40571,29bef9b7,bcbc0372,aefb4b07,8707725a,f31d029f), -S(3c94835,bf940014,e0c589b,3df40cc,a53c20e4,f0aab085,d8a79c26,fdb95b24,4cc1349e,212b1111,50ff06b6,927d701,9387e4d9,4d6bc1c,aa0ba14e,57f97414), -S(9fb3ea60,26b6b1d2,d56e6caf,19fea2d9,a2386ed6,65aceeed,aa66c5dc,f8fb51c2,8f90ecc0,87c300e9,3df10082,a3e461af,88bc0746,41e0a85e,4981988c,c539d096), -S(49c1f091,dc031e1f,a14b5417,3831ad26,438e85fc,407faaad,c634a0c3,8d956cf5,6656b7ba,7a5658dd,a78ae1de,74944332,22c36abc,d7272146,80a64a8f,1135e455), -S(eea69d66,68446656,45231f81,f27dff32,83667f37,4dccc3be,5bf12a42,c446e112,821403bc,f618e100,42c45de2,3262f7f9,b23dfda9,9a5532a7,fc6aef36,868eeefb), -S(c251be6c,5c73933d,90bb741b,e87c8b27,909b9efb,b40c70c2,3b1b5db1,956518b3,68f543dc,872f7f37,b8ece85f,acf3c670,bb2e6f00,7df413b0,5416919b,57aeb60c), -S(b1ef747a,4df39c35,4e67f27f,97b150e8,6e138cdd,70846ca7,3479819d,98cf4cd6,7afefc25,a30d6879,45f2b471,20b50b83,eb58b682,b61dc4bc,72c4e368,4f3c01ac), -S(9cb0d6c5,2094f1e6,ff84549e,32ba4260,a93baf84,cbb9516c,68c25c6,4b67feac,3e8e7ebc,1958e60b,cb4159,16f7c903,d63effeb,4955a11f,cb470ff2,e8935665), -S(d11f3d4d,6b18bc42,1692b7be,40589b49,b909ff2d,5659a058,4bf3af1a,7be76be8,cb42df3b,630010d9,fb48f12,e7ab607d,6fa1f829,1543b68b,5e959478,ffb6a8ba), -S(ff6a9171,de273646,9d0c0b0c,5e7829c9,3aaa1ac7,e63a63a5,fa2788b9,888025fb,335b0b06,411d6e6d,7c6d69e8,4a900f80,5077bc7a,248f2d24,2df2c517,a9bc0cc6), -S(655dd8ac,aa0cc2d4,b9543d3a,1c0baaf2,a76f7b41,caba22e7,47c1976c,deb15707,a726eb12,44c2af81,d6b5abaa,c9c117ac,75f2f6c5,c550915f,e005da5c,efcf746f), -S(4ade0988,d4c2b0c8,e303dc20,88a86aef,b2893fc1,80c410bf,d9467bee,a785e3c7,7c2358bc,74de92a5,18d38766,d13d5d4c,2a0d551f,62996105,bc59024b,147406ce), -S(9430a2f7,6f2bd12f,54d885be,3172f512,5282e84b,ab5c6bf6,7120a6bc,1e070db1,e8087617,943aa433,55684564,53d91a84,4a06fdf4,6a587c14,a2695c54,ccc3894c), -S(72b9e511,c78cc26e,f9498e38,9a15ebde,cad6bb3d,ab08462f,f6f19966,d75ae882,3a8345d9,1a0b1a37,405ea7ec,cc427785,607b84d9,d64adb42,5cda786a,fc68fb33), -S(4615999e,29a4f947,83617d0e,2847ad26,f79bca3,b3cdf3e,6a40e6af,f778fd65,5146f8c6,85b10eb,abf0ee65,145d468e,ed4ce176,705b3ee2,cf8e2f66,d3c739f7), -S(bdcee951,41a500c4,8452f5e1,3833dca2,45f94f83,80ee6574,7197610c,5ccb4558,479b3308,fd9ae072,9f97d0ba,622bfd1f,71c30774,c9be1bc7,b6141278,3e649631), -S(8a52a750,7dfa334a,1e285c5d,8c4d6963,5c3f78a4,79cdde18,d057d0ff,9bed97c,d4f40b1b,dadec733,5c264caf,e8c6d0cc,6f7d40d2,6a5d56d8,6a86b392,97f10477), -S(69387f5e,1d2b3fed,1b033614,25486ad,6ecfd3f6,eb85d8e,fc272adf,6d154915,8a72e294,2be10088,f16b74b7,4327ac02,1aea149,84a25458,55edef5,2e5404db), -S(7a8b4d6,982cdce4,c066b721,ca2730aa,5705a43c,84ce54ec,cd184ea5,53bc1099,f4460a0f,62bacaef,67238243,ee850509,d346752c,4a93f59a,5939daab,a654e215), -S(7a32ba53,a2f6c968,56adb025,10d9036,27e945c7,51108465,c88b42ff,e96442a2,213af901,378b30a2,5272dbf8,9b847fa8,32e3657c,1e5af5f3,d49ddb88,f7c9d701), -S(97388117,9d476881,84a6c968,e96316dd,4933780c,1c5b55ad,78c0de2e,aafaca0c,ab2d23f2,13ec96fc,856e6dd6,c73d10b7,5a0e1c5b,b901ecb3,79dc7544,5dcbc672), -S(500491bb,8e971056,380ba6f1,a02b619e,763aaf4a,bd07f9cf,50f86dba,61833354,ad296ee5,b4c32ef9,728c1924,562c0fac,9360a6d0,16f2651e,16f4c49e,ab35e600), -S(1c9c2015,bd266fdc,fa123aea,45428d07,eebbadb5,2fa10d83,7b4a831b,4ff086f9,73b714a5,71eba339,c58d8449,4637092e,9d44ce29,cf039427,de75b540,97916fe8), -S(5a4361bf,44a082c4,4e87d4c3,4173c910,8a3ece47,ccf3d3de,f933e9c2,fe649df7,184372c2,fe0b659d,57ee278c,f3aaa9f9,c6f3e45f,28c8ffad,54730dea,4df0bc95), -S(f6ed8161,c49f7ac4,931d90f8,fe41a400,367d8ab0,ec23b0c5,74886906,86f11eda,6c24c798,f1d88a2a,e2c7b32b,867e930a,41f425b1,ba59b01b,f971306b,a0b6093f), -S(ba392129,6be5773e,a8b509a,408b556c,deb7953d,a5165db8,d52516d5,36cfcf01,4cf094a4,9c06691,bd11a7d1,864ca452,29e91f2a,60b1cf0d,d9bf1162,901cd89b), -S(eb96dc04,ea36d6a,43823477,d4b6e3d4,a89da427,7d959962,3f31afac,49159203,17ce0e2d,6fdf1ec7,3808ff72,aa9d1fba,5038b698,c3f72214,9db254d0,98b714f0), -S(5ee66f18,669dc60d,a3c7074d,c853c51,21f6c584,bfe5c2d0,949d73a3,24714f52,238d8d46,f4143d4c,e7c74edc,78d1fab0,a42e7593,7c340504,e259dedf,4b462433), -S(71979eda,cc7fa635,91767e7a,57f8a1ff,eed003db,8083c41c,ed252c52,438b1e11,94e75e9d,4f3bf3ce,5ed2e8ef,9056d3ad,bdc9f9d2,4e51edbc,9f2b2bb5,90077c18), -S(7a301d3c,f6f6407d,8e62d5c2,4afb8ddf,744c2bc8,d2d219d2,8d912585,51c23351,3578a307,3dd4766f,319d6a8b,190b8a8c,a85ea7ed,1c54918f,73293b5b,5964652e), -S(8b76e056,31f5ec6e,33cc1267,9b49d9b1,16e8e06e,b3ebf91a,a3f239e9,8b188c42,9f0f4f92,a43cdc9f,f1d5b031,44586266,9b65d7dd,707de8d6,23dd8fa4,62c2d96f), -S(7de9be01,b8ee5708,9fa0dbfd,69757649,4d9d2eae,756bb9a5,f9deedfb,d55a6019,8947c62a,fd4a1e7e,dd70af94,f09aa2ac,aa1c43ac,745cd75f,dd1618fd,49251a4d), -S(d0766e37,769689c2,b55a3839,968e1eca,58824760,716c100a,29746728,4f6254c6,fe00274c,f3274a8a,8c529570,8b122d9c,a226fe8a,843920e8,a17f5468,ee2b0870), -S(61e74942,91821765,e144ef34,37c24dfa,80857029,35fdb2b1,511eebc0,324e9523,a641a75d,8917abc1,fb36b5c3,beaa84d0,b4230817,2337f50d,78b71b52,f4373524), -S(a726ab19,5125f8ec,e8cd1952,2facdfa6,2994c4d0,712251a9,8efd73cc,213773bc,2064d5d0,ee2b5cb4,5567701e,a3015c35,f3718700,af2aee6a,22202325,1fe65afb)}, -{S(64850a04,76870a44,2cfa57e0,4e4707f7,eccc5e99,12dbcb07,3b457317,717f5686,7c5facd2,91a6defb,a1837cb9,3bcbd0f5,bc37572e,68ccb2a0,c062a155,46656fcc), -S(fc479625,fda0067e,a75631e9,c79999b6,dbcaf7b,e1b69d64,a75b08aa,f3ac871b,d550323e,54200c9c,393139aa,b8bf3526,45520bf0,d90f6ed1,5187682a,79515de3), -S(a39b8f47,efba84d7,1b781439,f8c144fc,9b637215,26aa6b68,b55d6a59,137dc291,56c6dc,511a8494,b86f9669,504985ef,e88789b2,83e58916,24b9455b,d656cd39), -S(172d5d5,21edbd11,beb288d3,4ee78e86,a1059bb0,5d781bd6,d9589f23,46eb7833,5251dd9,10553e2,d1476e70,c6d2cfc2,397ea7f1,210e54df,d2f61425,60bfe73f), -S(e5f972b2,d1723e8,8bc6ca8b,ed3ec1a6,fce0e6ec,fb13cb86,efd61e13,24d4c41f,2e072ff7,ea3c48c,8653c0c6,595c2c27,d7953185,4e3e1b6c,8c1e7cd3,bdbf9ca), -S(f586c6c5,44cb108c,edd7cb15,6ea36607,d411d162,730170da,51ba1c39,a1e33241,dd5425c4,3f49fcc3,c92753bd,dbfc4de7,f7ad4511,f8b720fe,b07449d8,8919888e), -S(e324072c,8d3b5516,1c32264c,e2287b41,eb8edab8,356250d,b958c37e,555de216,4bb37975,35b72127,6ef1e62d,82608300,9c04b2b7,24655acb,c2d3a06c,ac55e7cc), -S(1b76872f,cf8f2297,ed95552b,17bba313,5dafb896,7f2a7229,faf4a4af,fd416fa6,8c389799,32b146ef,87aff36e,4d6e1891,a2acf7ab,2f362302,d13e34cd,7a34adaa), -S(797e7051,903abbe1,9735f94e,acdefaec,2f2c8c60,13a6ebb,d06a4234,14820bf2,ffbf5cd4,19e47bda,cf59491e,55d3a3dd,97d35b8c,1b824c79,955ff91c,81269563), -S(e3e22849,a67edc06,10662641,d5975a4,ce59650f,e9ced88d,4865d63f,e0ad948d,551b701f,fadbb47e,ad4ad324,ebb01c12,c5ba2ab3,754c9762,cc840bd5,569897b0), -S(50e49072,aa2ff6ed,2c8705af,1ef1b703,903194f0,2c91c0c6,5fdd46e1,2a01e887,b55bdda1,e98db862,6a283c64,e1e813b2,20e26556,921eb4bb,b72894c9,27be1c7a), -S(d1b0abc1,e1164bc5,277353b9,84856cb9,1c55735d,9d475ae8,8cc743ad,b0462739,cf712d30,edf88915,373be307,e1f7e73a,244a8610,e7c6718d,112cc414,4058bda6), -S(62fecfbb,c1532096,583a588e,cd7b390a,7fae6e93,a675d14b,4bc99ba2,546d5573,ccdd7145,780cfa94,7e4f20e6,1729ec09,6ba6d28c,c2a53ca0,65d060f6,1fd9028a), -S(192e0299,75cab01a,5f5a8428,ca2c283e,1b300925,ceac8290,1e134c8f,97698d79,55f467bd,8d0db18f,cb4c8b72,2784ee99,8127067e,bd1314a4,22c063a,4755b817), -S(eb5a94ca,29e28ddb,11907c63,fbf8fee4,e1677ab7,205c5539,b0b3675b,f5fb9b8,6e9bb010,1fdb591c,c65702b2,cbb16061,cc7b8698,bb693c28,e09e853a,fc00ca), -S(4cff025b,579f9c57,c78bff07,115b7268,39a20ce8,f893e5b7,eeb310a9,c738c67b,d1531ff1,a839c908,97afac4,256b35f8,5bb31903,3e8f8e69,b2a9c13a,ff6be9c2), -S(bb5f423c,77da9a2b,540812b0,1e899dd4,a100bf59,46bd9818,ed4c2e6f,103be9ba,d4851c37,afaf40d6,68de6a6c,3a1d9209,f0fdcd0e,98310455,61210c7f,a1a797dc), -S(86066254,59e38927,b90d60b2,f9594e27,5e509366,f5678d35,133bb9a1,ad4b3262,40900453,bd36c557,10f5c8ac,492186fc,f5caa74d,12c69b2b,c28dad4,9e83e690), -S(81d52fd2,14f2d1dc,c386ab9e,5fdfa5e2,99d57284,7f55917f,4468bec3,812cd638,8b131ad8,2f24d27b,87e73419,bdd9d41d,795b9466,9268a11d,c8b87e01,7665f2fd), -S(7cbb1f2f,47f57e0d,20be44ab,2427feb6,18bc6b82,6e5f4909,51e1927b,bc596ccc,bb587bfa,d416ef29,aa36ff38,1f448f46,fb2fc0d0,a87e5170,8313715f,30cf3d25), -S(3c6e6b89,2e897388,157d3565,95ad59b4,334394ac,b33a3a24,7c455d90,a4dff784,b79d7d85,2b62e00c,c340cb8a,d42b489a,bc372022,75563918,fc9b81b2,a1b58b14), -S(dcad5a44,4c6ed0ba,2206a2ac,92e2f0ea,6c5fdf7f,28dc6bd4,7a6a48b1,d32d7e2c,6300d599,63fb36c8,f0d3109d,161ba1d2,9f718697,6694a11a,63377075,b944ba19), -S(c8515e28,b0f7d1cf,6e3829f,8d0d43d1,cb382299,1f781962,b265b268,c09a0aee,f33e0699,9385890,5520fcd8,f06123bd,3429dbdd,cdad22f5,3e80d951,b620c70b), -S(d1f81565,ebea70fc,6ee132b3,79e11725,4e4f84ad,50e04282,ec23afb0,8e24ab,38bfa250,6628029b,721a11a2,4af41f28,7a4f20d6,87a3c4c3,815deffd,bea92642), -S(79c02a3d,93cbfd75,2dc01fd8,a4d83626,2505eb13,92f4800,965086e1,51cea673,aeb43c57,458510ef,202aa9f2,b904fb34,6350d4cd,ae8faa3,d246feee,8da21571), -S(b476ddcc,6a6f785,b1b8637a,a22b1984,30574567,1bce6b36,ed3738d1,8c1c5f88,e71abebf,e2019b3e,99b27560,d4ea4ef0,6d52d300,14c462b8,1daa5a77,3ba73176), -S(937b753c,2d7cd681,b1e48b4,4236aa73,96968213,b57c5af2,3d48b0d7,cf64523a,2d88bb55,e67d4ef,adbae06f,5f93288,2562b9f5,99b50523,e6e05cec,fb7baccb), -S(7e719005,dc42e572,471177bf,80cf531,d31daba6,f2015664,d46c4df3,ee9840ed,80f9dba9,6a495938,74704313,613e3bba,70ef8e1e,83f2063c,566d2791,d79148aa), -S(70d04693,54db73e3,780a4413,804f7cc6,ca1849f6,158c1b7a,9eded185,8071e826,ff96b0e5,4692693d,774e01d7,5776190e,7caab3d6,72cbc1b6,1623e87d,f0f96936), -S(83bbd70b,f2794adc,7bddc8a,ab107e14,d5cc19a2,eedb59c7,71ba622a,53e2a603,eb92141,5fc3f2d,b96bde24,1d68e314,244c9a0f,42e455f6,3b8c09fa,fe3533b4), -S(8f8ffbca,72942dd0,94b208b1,12ba36bc,c324dcc1,dee4de01,ad8dc8fc,ed4f84a,58fc0a62,a5c20df9,e0de3aaf,3944c907,d7c6db11,4976df5,e38ce452,e1901894), -S(7d5fd589,955a3b87,4bec2638,19faa133,9d03ce58,2a64eb4d,643c42c2,95ab2c7b,deed7974,2d442ed3,d70ac86f,ee47bf20,9a8ec7bc,9d9a98b8,b02ff4e,a857db32), -S(19e47a2,323d5a26,fa5c13a2,78ceca70,e46bf5e8,d9d0e22d,f228c15c,8fe4656b,bb439d24,789f26f8,6e5b25df,b40a9cb9,6b3272b4,d85e4a04,e6651443,e1e41706), -S(75708952,9fdc2d9e,ab85a24d,d06a7c29,252cfa04,f2686d19,9fd04ef4,ecd0d304,c7f53395,8aaaec4,ff6e97a3,19ecf7bd,a53a3034,ab504c6,f02ccb24,2a04475d), -S(30f6959f,468add62,636c1bb2,18c2794d,5eb2d907,3b7449b9,eb5c1f7e,a5c1b016,6fe05738,e8ff7b1a,d8527ea,b8ac47b5,35c61dfb,efda4279,382e8dc2,52893c92), -S(7640da0f,4ddf3448,dd21cab9,257e6f87,304afe2d,fef9d58c,93c2de41,e9a7ddf,f1cb4a24,f553505,a660a219,6baf3485,6e8d21b3,6f661a0,baf2aec6,36805c22), -S(1db0050d,dbcb4f6d,e716dcb9,a3a54079,3a8fae5c,53c630ea,aad1dd66,f195226b,50562f14,6f5c2949,3f9e2efb,d64e2907,f7845673,4b7ddf2f,977e46d8,42cb6bb4), -S(2b5a8ca6,f1d94ed4,d68460c,ebf90aea,7506d3ff,9c71de28,908d05ca,eaf08d0e,6cac6a6e,6b8fe9bf,c733259e,7b4a7715,5a15ca6c,94a42a54,be686849,61a8e064), -S(eac0ed60,87593dbd,3c88510a,c27123af,9fc926e1,4a829f01,9fa24686,1b0f9279,5599829e,ba8e5cd6,253cc3c3,8ddd5a30,7e2e38a8,2da09504,4cde7e55,3dcfafae), -S(495c0e20,51615bf,278ecd84,508ae728,72a7e82f,88cbd992,20f2e370,1d46f9ed,ed5a3c18,27e3474b,c04b6684,bc754cf5,b8014720,145ae8b0,fc24c6f,9297b394), -S(c74debae,32533089,35ad9c23,cc038b95,f3f15965,c46dd3d6,df61b482,ba65cd43,9f82e190,4ab044e8,ad645a7a,b27e0f79,e45bb7d0,9755441e,80d463bc,b25ad4db), -S(c6d4d1bb,4b396ba4,a4393403,ced9a8de,59931eaa,beae1f2d,55c1373,77455ec4,c51f605f,101f038b,913300a8,9ad96bd6,d5e60dcd,d7702ff3,357ee1fc,6ca5b45c), -S(a0f35ff7,dfce08fe,6335cabd,c642c2f7,9a4b6e1a,c95df6a3,b4694bfe,91abd1d0,fdec4844,90ba4281,b78267da,b6dd63c6,ad0ec964,96c42407,32834ebf,b9c822a3), -S(ee231095,46b51ef2,547bcadf,14d57e1a,f4682dae,4611b67c,8d99ee4d,ab912004,dee04daf,3adb4d76,485f8e5f,bf9a2231,5e4bcb96,faf63f67,da257c4,5645d797), -S(77fb6478,1d1ceb38,ed04147b,92e46668,bc47fc0c,73c6e677,a56c9fe8,89772810,ae42f6b7,d26702d7,44c3e867,6750cc7e,224e799b,857b6c68,52936846,6a9c35f4), -S(dd205a7c,9a4901ef,3439a05b,56968951,269c8618,ba1638cf,b9949f98,d84ef11e,8a7da4f9,8a628f46,ca39d902,5e994404,dc6d09ba,8cc2d199,47936454,c024a73c), -S(d4225a81,af1ad205,d1ff1555,cd15df81,d82d75e2,7d8b6a37,a7615c32,ffb932e8,3902c36d,7530add6,a88c6e6e,e426434,b9728690,c6476d33,cdca32a7,eee99fe5), -S(237d87d4,2ab0b9bc,ad29bf03,f754d98e,535a3a2b,6a184929,ce65e18e,17eed134,bd7e8be2,8a125d86,adf47552,aaa6a474,797aa641,94edaf12,56b86a9,5057e480), -S(eb9d15a8,76dff407,4ffe6ce7,c430e797,ffcdd291,34b6f737,b2f07cb3,7f2dc8d,8d975595,aa7790dd,d531e7df,77dac484,948d4ac9,3cd1e4bc,d3b7d9f0,4dcbd431), -S(ab6ffcf,2681db28,7a99226e,3fea18e3,5abec631,898d7038,19c4721a,ae341e5c,a93ae653,4ab9ed9e,e2f50552,cce4ae57,1ab80473,38da0fdd,6a203f18,4c4bed0c), -S(28b7ccc5,53c5665a,1daa0150,102a7eab,8d6db154,b575d2c2,33d2ee1e,6fb2231d,a5eea545,a89579fe,ceb2af8c,e67304c1,f1cf936,91ed7b0,4e461c3f,72863921), -S(db7e3299,5ecaadc1,e94ce255,2c04cafc,c10e3ac0,a88edae4,bcdf941d,6a913b60,8d2cc29c,5a23d74a,76d39caf,fc026a0d,58af12be,9202f250,da8e7b6d,f6a701a4), -S(a030b7c8,169eda5d,ccbe9258,30ce03e0,aa89fca3,654e70ba,f9d9cf08,bb2a95fe,4a16e85,3c8efe30,46443cc0,12646aa6,fa030141,1a0b6f70,dafd1cf0,61ef977d), -S(580150e3,ea63bcfe,13b1202a,b31043b,4d581eb2,86b0d985,116d8b06,3a087325,c4dffb1a,4f7190,9807e070,fbd85774,194d7d2,99f203d6,4470f9a8,b8a3c245), -S(d23c6b7d,4c455c41,edf6a923,33fb1b66,43fb00a7,f5f9e0ff,9d96cbc9,af10e6d0,56a494f3,91b77cf4,3a16f72c,2084c3f4,7332893f,de676cb4,3ae527de,eea4835), -S(91a4fdd,eafdc6fe,5630351c,a1d3270f,3040e70d,7c2ff55b,2af7e256,ba853510,59b05210,6c8d327b,24cad438,891bd72a,1b71ac8a,15c9970,334453a1,a8926055), -S(f297dae9,fce4fd6b,decd1c54,72f86b6e,499a6f01,2468477e,316a689e,62c5d5cf,6a8561c6,6cf1c950,9fd21b39,d27e71b,984ef01e,b8c1fbe0,d14a76f,4153f1f4), -S(c8bce284,4cec327b,83e979c8,1c7bb30d,4f5ec633,d64269fa,8bc33ca5,aa4b72e5,71b4a02,e529b17b,6550455d,e5f6db29,59b59cf3,7fb45e24,ab69098a,a71f6bc6), -S(18650112,b904e937,5074377d,ab19db9,88771616,b47c5e90,93e16eff,8d237969,c464be51,dda23669,ef352ed1,e8eda746,3ee2c9b,f56bc33d,7ef464b5,f96c7b82), -S(58e1d8fd,c85f3d28,829cd90f,f968e826,7ccb6aa0,ec8d7002,d78d77a3,76573d48,b76e4320,40359597,60056ac8,6f953e46,6c335207,6e56422d,28d6dade,f7280826), -S(87ca9444,942ca103,5bd010e8,f89ad6da,7158a16b,f5a7774d,84ad7e2b,91130d27,f14dc3ad,8f102cdd,6e192f9e,604293e8,c80211e4,a6b6e78e,fc8e7343,84352a0e), -S(ae61aef7,e240b692,ecb12ea2,b568158e,8da85c8,1c902d79,db82aa8b,747ddf5f,8fa838ed,7248894,6ae75ef7,b4809546,7bcbf668,9e5bb460,2f711f17,6501d3e7), -S(5a91a937,f5a36f44,4a25053a,2bf2a374,aa6118b4,d7f18ffa,1b641977,d761564d,8d2be259,bc22caee,3d0694ac,b70f4a0e,7b7f8edc,b2418486,9613e0f2,7b2e2fd7), -S(8342a29f,f3739b81,f77918ff,d5a74f20,efd76175,6456eab0,aba2af96,b95b1488,5e1280f,3fe41f14,3da73a56,c11df7cd,69f596df,f98204e6,75ec2601,7f7f25ab), -S(bfd9e9d8,dfaa3fa7,a1bac396,45ae27d7,e0a2d2,aa4022e4,6df8d408,eb06c3c2,5ab07b07,1acf15ab,186836fc,29fea177,2c6ab202,a72bbae1,78c4dd8a,7566d025), -S(ae6c6419,ad0fa0e6,56fba661,834b5f49,2299c610,be8f60b9,815f4775,7ea4d9f2,95e9e9dd,ffc81a1c,112d5f3d,d59a298e,6a3fbdc9,c5fa9c00,37394081,e9f965eb), -S(12212918,77ab7009,96eceb7a,b7ae5b7b,822e92b3,e99e0308,481a9936,c3568143,b40c8be9,16637b33,b428f521,b5c4395,6096dcb4,2504bfcb,5780d42e,984f4474), -S(4cb67c85,5964d298,667173a3,3f3bbfe4,5d2f1e07,72eb26ba,95fa961b,41728597,de8164b5,2af252e0,464eefc5,7a65868b,1e0d16cd,f9c5ee7c,7f13ef2b,1f555cc6), -S(b882a78e,a897c609,29c13dbe,b0d15fa8,3b36d895,9ca15b43,d8c8ebfc,cd2592f0,13a114f0,8bc83d53,103a7327,b92e2289,d18b6cbb,39a9571,16b19c8b,77a714fc), -S(7f77196b,483fa953,39b28b5e,464f42fe,e3ee50fb,3384e401,ae7e5a63,70544479,d66bc424,8370ffcd,445f1aa5,38dcb965,68f51a62,4babede2,3f59ad63,8dfbfe36), -S(d04af491,28f406c0,26c8228b,a270962a,7c45c5eb,51c3cbb6,856c8cf8,d2da8959,c354ae41,f03b906f,74b9c259,5a675bfc,7d6389b7,1c181e6b,1b0bd779,b9e47d71), -S(20f6bd64,cde466fb,e0ff2436,4f9d02a1,d7ad2a92,3bafafc,67a1a154,f1a572df,13dff561,a14d7143,369d74fa,c7872c6e,f57d1e78,b0211f57,ad9a2363,19ee4f4), -S(2ae2e2e9,b53d8788,5889bebb,7cb25669,e75ff2ee,ba305324,a2473937,1826365c,6e52daae,1c2a50af,dc37b1ef,22782d72,7a10f128,225eb816,9b813970,fc14c68), -S(2b50215b,7f3489e,c313d5a,14389c02,1c72b1f9,68ab37ab,d9f4896c,6014808e,50069279,8b2a2226,defcafdc,8a8bdd38,dd7c9a13,f5a2157a,4d0942ba,5453a859), -S(d4bb3a0e,7dd530e4,ae3bcc5f,4001686b,ccdc81d7,6c79c131,288bc2cb,76c72717,9c58063,898cd752,23187ac1,d446c8db,c2918fc4,632c1bb4,2278c0c4,48e97d19), -S(82cec682,b714ec75,6d3348f3,da10fe60,885c790,99822f33,d7811cf8,6077284c,c1f14f0e,670e1bc1,ab604e11,8f3c2827,7c86ecc3,79e97e39,6776594f,b4750f6f), -S(b08b799,5cb8527b,c4c976ac,a6675f03,a82cff9f,309eef60,e78ca418,71486c5a,70df1520,c27367ce,53499421,35fd0daf,ba7df181,f66aff88,b83e12f4,f1b57411), -S(44541703,b3f11462,fc2ffc79,b28237fb,3f6d8611,44c66891,e9cefbd5,7f75cd9,e9b53337,162c5629,eabf13c7,f0433cdf,dc41bd64,9238b810,96d2c8f0,77a5f165), -S(5726f775,b5164bc8,9fa8dd60,267615b8,d5aa1be8,540ce3c9,23271a65,8dfde543,31777af1,58e103b7,db7750cf,37f42dcd,6a155880,7f5d426d,1075d8f5,9a83c9b0), -S(c9993bd,7368efbb,c20b1082,354fcece,b072a3dc,a5fb5e68,73bdc8cb,94ca2b98,3a6b4c46,73d3756b,76d0ad69,701af08b,3f4bd359,3c5ddb40,94eb9c25,776063b6), -S(8b12af05,efe4bafd,bab8b73d,830db99e,c3212e17,bf2f1245,86d821da,82a11b9f,32eb833d,79e92f26,6bfe6840,ecfecdd7,ce000f89,14326697,562372db,66d36ffa), -S(c7986b3a,f4992e69,24363fca,fa8b681c,4cf60003,beecc0ed,af312080,d9329f04,a8a72ac2,f76dddac,faae1172,82965c24,d8710ad5,1a1a5863,5dc2778f,22ca0774), -S(b571af4c,b8fd57c6,2ce4b52e,8a38305e,b3c2b5f7,1cba5931,6dcbe676,3a219f07,4c028e68,9d95d4c6,b974fc05,e7a3a264,b1410fa3,2be80588,32986d4e,fc9976c), -S(412a3d77,6113d30f,fdb4ac2d,1be60a3b,bf93fbde,c837fcd1,d23fe917,811fe6d5,d8dccd67,8856db2d,c698ad2f,269aed7a,3c1255de,590c8208,b8611153,f18faba3), -S(33e955e,9aec13d0,c4b8a61d,455f784a,4d22fd0,f935d7e4,69a88dc5,44c89426,668a62cc,9b903539,a26d8de2,44310f07,d8304b7d,2ec1f4fe,35251b82,220c0cf7), -S(c7cb9ff6,4e7c8dd0,4d05f9dd,a7f106c8,a9841fa7,1cd25eb0,2866a34a,74ddc670,d436d69f,c42c21bd,b64250f,19a15191,bc228b35,37469444,717f4c52,a4e9bfb2), -S(9b6fab7f,f701e6ee,efebb2d9,3c4432e0,826560d9,8aa5b0d6,cbc31c5d,190768e5,f01de8fd,bce677f5,5602113b,90853f6,da7f8029,beba0c02,d20b599d,5646d773), -S(48e25e2a,cfad81b1,315385f,25c958a3,26c425a4,9d75c2b2,1a0233f5,9a830525,83a6accf,d0d149d2,b5dbf766,2bcb0bf8,d725753d,50615657,2a0807fd,882a4d6f), -S(14690774,db72e162,667b9033,be102fb4,f1fd648c,858dfc31,a8b17513,74bc9792,d919061e,6c624203,1f0641f5,bfd7466b,ac55d890,a3b1175,12a4517c,af9a6cc3), -S(941b1555,4838a75e,7762a4d8,fca39187,bfcaa3fc,9869df23,93d6c77a,2b956d18,348db67e,845f7133,aaeecf17,ab75960a,954d0d2b,41ea5e15,be098ff,c4a43d09), -S(487eef1e,77bb13e4,821fc8ab,c9f4448f,672d09fe,5fdefd84,2a9931c,477ae38d,eae4bebb,e06b75c4,b6d37238,faf0237f,5b035c2b,cb084825,93053964,33bc4b53), -S(8896a835,37276df4,40f3be94,41267b4f,4160fbfd,51e3f01a,f675387f,362b0ef4,feb71411,db1429f3,5391993b,e461df0d,c3beba79,4b1b90e,cfdb9338,80e5373e), -S(c6f6f864,baa97e54,69407b28,bdb459db,d1af42b7,19da64db,ba274ab1,58da440b,db83cf5d,feb196dc,5023736,c43c1d46,d6ddba7a,44805f36,69f639e8,f2759a33), -S(c901d3e9,1f590c4d,547b5715,dfb1a61d,f898215c,2be28af4,a4d9d229,7852c00,821c673e,77517338,da3617ec,53213d08,9f695c29,2a5ce31,c60a377,428db6ea), -S(19707c8c,3a276dd0,a54e9cd0,b241f54c,470b508c,ae773fdf,20810696,f9eda3e4,1d8832f7,92db5867,73f1d260,39877814,411f502b,899282ee,ff205495,f04d2119), -S(e197c27f,cb20bca5,6c593eb8,7d677048,5b70596d,4f35c504,acc18bbc,49a54230,85995a28,27b2715f,ce2a682,b727e7a0,4c25f412,407bb99,20cf55a,f756027e), -S(5bcb759b,56bda507,23e45cec,4689f03e,d04ce46,497f2409,1c5a93b,3799ff1d,b068ae2a,47e605f7,f9005545,a563ae91,2f841713,15ee191b,d81e0d58,6d68ee9c), -S(2acdf086,f613c0fe,1299e13c,47568fe4,701f5831,1f515c74,32ebbc0f,cb0c5dd5,2496967f,5f3aa9a,352cac15,d3fe9880,a862925,45a2bb5d,7600c1a3,ccdb6374), -S(268c185f,5d0d2fe3,1c1e2850,b3c80f09,f896134f,5f410524,8edbbd5e,bca357b5,2e81765,ab1c4336,6f782895,35a39076,b8501008,41c574df,d6d25b29,707feff2), -S(b6de69ac,f84f7cf7,48d50a05,dea4faa8,9655ad2c,98846edb,e166e2ef,de4483df,3c377b81,ffa03daf,823a5da,e0d4cb27,77b585be,d5fdb889,62c3a3b8,709ddc9a), -S(bc71d28c,ecd81488,5a76720e,da59deb5,f6d4cdb0,36b2bbb1,2e566d58,2843bd07,501055b,52ddb633,74bbefa0,62ee294f,ced29ac7,4398a634,b629532a,3f50f1da), -S(9091a40c,3a3bb70d,d28cb8c3,ade93,910b783c,40b4a2d4,a48facfe,50c524b7,c1bfb69,3ab9ef96,9eaded97,57ed9621,92344389,e62f6c9e,47c51d8f,b75c1436), -S(46a3e416,8ca5d225,1e01eef9,6cc422f3,da56a59,81fd11df,4ba87e88,ebe6486e,e3630232,96c0efaf,f93b3d4d,2367ea73,3d776180,d98abc44,94d1032f,f49dedef), -S(869daf22,c0978d91,20595281,569f2a43,b3afd058,9e2f29dc,c0644dda,fd26ab6d,58f2ff45,bef8eb75,244e93bc,93d58778,c7a1adc8,c2599c04,635009cd,12f8a6f2), -S(1247ffaa,76f92f50,2e4408b3,2d373f38,79a93634,ced87989,c3f666ef,ffdcb366,8dc9de29,3267dfe5,1966ab2,9462d5c7,d81c205c,536c6eeb,4f2246e1,1848fafb), -S(e25575ff,bf62e7d7,aa64255f,8ad222d7,4ce23ab0,934a3c,cbb80d92,7fd98272,c6c749cc,320892c0,31b3ca54,3920afec,90217d17,5397b6f1,1ea201fe,414c1d24), -S(d02c3fc1,68bba27b,ac38bb2a,4fc7ea99,66e8da54,75f9dd9,fa131fb,d2862057,d24c229e,85b30ff8,80b87f6b,ca145250,f4f72907,ec33f51,94c2f8f4,13a8932), -S(28c4002f,5f1fcfd8,d9e13789,d2527f5b,d2788649,72d5b12c,37dc5c13,b0ab243f,259617c3,7c84d212,2ea7b4c1,33118fb9,9cfdbbcc,db707ec,e99b37ac,12380123), -S(a4d02f63,3f6edcc9,88970f4f,e8b0e639,d07cf277,1a6173d2,1e54594f,65b21770,236c19a0,4bfb2a49,98c776b3,2a2dc4cf,7e91293b,4bdb7d4b,a0ed62a,64683bb), -S(f28f22c1,c3ef5444,fd373435,23e97c40,5d3d19f7,21ee5bd4,53087e95,3d2d006f,fca3f966,a264a422,3e861dee,c5844b99,8f245a11,48301797,db141374,128ae075), -S(7ec145c9,7f1bccdf,ab49ef42,1feaa816,e7a6efeb,ca371e4a,29b7950c,ce8b10e4,a278eb3e,1e9b6d14,52f60e3,5ead3083,114ec862,53101724,442482f6,4fe7f997), -S(66a1296f,f7700439,3305a768,bc9712b9,c6a8b79a,a4211d82,900f39de,3cad406f,968f1ac8,70766942,67d06a0d,655279aa,6110ccf7,7ae73873,4a0f4ced,2848d887), -S(f9e2f7bb,6fb1c6fa,760ded51,d465ef1d,b1207d97,660a360a,34be4dda,c5ccf177,48df22b6,c18fdd1e,213d5a1f,a70084df,2419d324,6811f90f,efc5bf8f,24f25e6), -S(f19fcd39,2cffecc4,4f0a9849,6c0920b2,11ca3208,ab312a84,a87bcee6,f6d5f6e,df36cb00,33f564cf,c2e1397e,5d38e21e,460b019c,9bb86ad8,6d4b9e01,53528261), -S(da3bbf50,f63c674,245af2dd,ad0dbf7,7644d069,bfad635a,f6065c52,f6b4b1f,e6babe9a,281a2a99,92b0f5e2,a1377416,e6d143a6,a2de5cd7,dc91eeb5,b3d0c4f9), -S(d5bb7b31,cf5345b7,8c6c0f9d,bf94bada,3d917dbe,2ba7bbf0,f65b2be5,eada38e1,e8103661,6c69aec4,31c7260c,731a471,e236e453,dd0733f1,8e5d1204,bcfabe61), -S(b1129318,36da4fa4,23ae1331,b1adc768,f1460e0e,22331fc1,4cebcd25,85d40d7c,9f8b7276,27200133,b69adb10,ba95989c,22fbb25b,723dfd60,7d1f4815,293e0856), -S(5bd95654,67d6794b,fae7bae9,df0cc02b,a0dc7ccd,cc5d98dd,5ef33d01,99c10f41,867b8536,363dbb08,234d6be3,d8b25a4a,7caf5044,2546d3ed,8f9d6d95,dd279619), -S(cab5c72e,7561a912,25cb65eb,edefc6b5,2e36caa,5551a749,7ac30cb3,149e6b55,f88e4081,3a6336ff,82cd632d,53590df5,32e3967e,37ea5aa2,bef69000,7c683996), -S(f3198dc6,d55fef1a,9273d311,b0365422,ae4a4c9a,2d2e94aa,1c4d081b,2bf138a2,aa2554e2,8ad481c0,d8376221,d15c3937,13f0553c,97b4f8cd,7b341c5c,72b4123), -S(900f4005,d4af3591,a1f518d8,2cfebf0c,e11f6a0c,8ab82367,337293dd,c823d8e,dd729fa5,d0fadbb8,c294306a,e0e2dcbf,9def32a1,1d58ce37,cd318e85,63cbc99e), -S(10f24db1,481336d3,25716449,c08795f6,efd8e3,f49fd445,cd5dfaaa,58a7ca05,ebdfa0b2,75c6fa7d,79751a4,e66b8a0b,f92852ae,bd108f19,a6feb9e4,9a49d936), -S(4babe89,ec5350a0,2ff673e,2b6fbda9,a1e826f7,ef060396,af08bfcb,8da15719,8415f595,ba1d8e7c,e287fcf5,bf386432,5a5a965a,a5ded5ff,4f9e85cc,8a287228), -S(212b485f,e7f39183,1605bbba,6b32cd0a,e3dbef40,a52d1adc,91362a0b,1fc783df,91a67656,9eabb6ad,dd13a646,c07b5ae0,f93c942d,6be6e96d,3d79ba89,5a1ef56d), -S(4aa0d59b,d8feec6b,507dedcb,eeb3feda,ea98fa96,4cd72734,811a72ca,d1f4fdc5,3d487788,3608eea2,dcb5fce9,dc5d25ab,d9bdfc41,ccdf7391,7cde90ca,ea6fde61), -S(dbad6aa7,b7e547ee,8c97e30,d6653c8b,9bf7c37e,679f8ec9,b74ceb24,2ef65c33,3d39eb67,c276c7c4,24b1e367,e71de6eb,dd32e624,b957cdfa,35081b53,510ffb4a), -S(e0495f52,49e4394c,27d9f2e5,e01c59d2,dcffc868,e4be4ce5,1fb114d9,4607901b,e77ab12d,732e11b8,c32a18c3,9c8931b5,f780f62f,7ce0685f,3d921e96,7d21de3c), -S(aef97af4,f923b5e2,3245ae92,9a0baaab,6c14d1e3,bcfaca45,a7c6dd20,58c6e2cb,83e51238,a46575b9,183635eb,cae26493,25acd694,8c04b911,d05c0e53,dd9c61cb), -S(831ebde4,2fa1913b,f4e036ea,73c22b97,916a61db,73918efe,4f94da72,e714235d,60c29914,c09663f5,e6af5b6f,e3b8da4,80a179ef,70da6c98,8ac12a75,10162124), -S(e4db4221,e7ab4db7,e473572,ec6034b3,96537815,2d1d8bdf,e3ceed44,2f24dd2e,359b878,b5bd2f,53f9a275,384f727b,634894fe,a772d1d2,72568a4a,a4d83d50), -S(2f144d89,972800e9,e0ef550f,da814390,9a106ae5,6b2b9dd,cd0f6855,1d824570,269e925b,ab060ccf,84d4c79f,56a557cc,f476b477,9e73a4b3,872875ee,26388dc2), -S(b3638ed0,d52b3292,f7b953b9,7f6df07d,8d1d5c3d,487261a8,8c25a2af,9a13cbeb,54fa96f6,8f475bd6,5515942d,b8d6f208,99bac252,b042394c,fc73a7a2,adae3113), -S(48c7ecfd,5dc8eb51,7827fddb,2430b600,ccc29edf,906b3db,be5151f2,590e56bf,85e43f35,7d9f46ba,8e5a8903,a75d6d36,bcaaea65,1666b1c9,b7e7dc72,487906d7), -S(963dda96,74cd2b15,84c677c6,dd6d91c0,c968d541,1941f5e5,9a2747bb,4f6a69fd,5ae7f7ad,fb515e1f,7790b789,8d2f801b,b764de6a,f5c33fe9,c54ce712,e4c23a1a), -S(6a3c5404,e22a666b,77396b5e,5827643f,ccf4e3e1,7b8b7c8b,6ad35fc9,ae21b1a2,780c9b96,5220c67c,3c8f8e0d,fe57f1df,67ad445d,4c2f0c41,483d9a32,d558206f), -S(14c13d08,209e5619,df06c33e,ee8289d9,628d4ca6,141fd46a,aab75be7,25a79c15,7acdf79d,b5722728,cceb5416,18c1555,4d833aa2,cba5be7c,5b56ed26,7c323bbf), -S(5c83e244,4ef9d09b,d8d648c4,37af0180,a376173d,4b6a23c9,1791d211,f4ba0973,8a041c51,d8001b77,8cfdab74,ebcea960,414269c8,50e52776,61da8c55,2f06d765), -S(824300c2,d17d63cb,131d489f,63c914d6,75120933,667be49d,e0950587,13cd17cc,94cfb246,f97bf2d6,e9de7b17,fbbe864a,521614e5,1cf6eff0,9f949657,f60c522), -S(691f9af2,1a0e7506,f16acfdf,ef22fb51,fa16e068,86d4ce5a,82bfd069,7fed7406,33d1d8da,91b28358,913089ff,dd0dfe0b,1cf5c3ca,1b4acb43,5223e353,5be8af3), -S(a0014691,2dd02b0,bf8533d7,60cb656a,eaa87ef6,93959f13,df81028c,82025aec,644e45ac,2729f6ee,22388317,a18381db,e1675a35,23ab2820,87afb9d1,48f777f7), -S(7c8f565f,228c2015,f1624956,146fa45c,945f6bea,b69e1b9,bc8401dc,f95d3331,2491f474,81df8eee,6b97f82b,48506dcc,fbdba731,44dc6e9b,29a1606b,22bff452), -S(bae86f26,301c873d,2f5cb288,7b2dad60,161410e4,db4b1a49,6477c58c,4817c582,65eeade1,cdb0ca0,14d50596,6549039c,a0c6e43b,4514de9b,fc222c93,180a7bbd), -S(aecd8a88,4bc42d87,b1c49637,ee23c3a,364c04b7,c16ec871,11c9b447,81116c69,fbe871f6,bc384cea,b894b0e5,837a6da0,98f8ab45,72b82a15,b7e7a058,7d93350a), -S(51388726,2e51e2d8,9c5f4ca4,7a6d2aee,3ec63b6,7ee5515d,4bfbdd82,6318278a,319c5fbb,2cc90ee1,3b3c980,3f2ccdf6,18d9f3f7,d09cde94,12779499,9ca87b3c), -S(29826f1a,27d4f62c,9f891a35,82ede6c7,163bdd5e,22f10325,6eea348d,cc4f5cf8,3f473cd2,9041dc75,6afcedde,34fdd6b2,82e3ebc2,baa2948e,774965a5,6d5c6b5e), -S(2d36c3b8,f293d2c7,80792a15,89895cb5,9b33d8ad,362469af,5777f0e0,225f2941,bf0f3c33,6ab29ad0,1bb693bc,249cad79,63aab00,97beb92f,ff1d4dc1,cf1885ca), -S(b7f1fe36,faf18532,34cbaef9,a45d47fd,26a6cd9d,2cbb6424,7f0757ce,3bc0338f,f86de831,ea68826f,925a8401,5ebffdcc,dad4fbc6,9d32b264,767ab067,c7b1b6b8), -S(d254e76c,41359c6f,521a898b,d55ab42,208b583b,59761c54,e9dbab37,fef84285,d504c24d,7955bf0,2bdfc187,bc8eefc2,42b65db7,43e9439e,3f5204e2,9cec288e), -S(88bdb44c,6999ca3c,8d3e8fa7,61f343e,7a9a5f15,577e514e,809af06b,354b8971,c7cab922,69bb008f,cfb1dd08,b6576959,e0593f76,b5aa45b7,899b305f,e432cc7b), -S(94f19750,6ae279c,772b1c5d,17146012,cf8582b1,973c140b,7aeb0bf9,3cd21ef7,1e9acd37,9e7f2dd5,a6df7a9f,f4b757e3,369aff72,341ba963,fd984259,6c615de), -S(f5b2f65a,16322443,a4ed65d8,7fa21983,25f2d3b5,523cfc11,39f676d0,8953680b,7f6c8197,cd730769,2eb466af,8c63e35b,1d4eb84,fc83d22d,d5d1217d,10e06ee0), -S(58e85669,c5f76dff,9b5f601e,3d1a15d2,c022a5c1,389dc15c,81657f8f,e3eb1be7,4fd07587,429bb7ce,3903f7fc,f3356282,24e17eb3,e256fbb1,32f1fcd1,e1048f05), -S(29bfb3d9,d116ab87,407376b0,f8fc607a,ba8a9da1,803479e8,a7ca8fd8,ce96a822,de56238d,93995238,bc6c4b94,f03823d4,a7b690a5,24d01e06,374ddf4a,2e5589b6), -S(78e32283,983fa295,f6fec0cf,e34ee0fd,83541350,e50d5948,8760279b,dd54cc28,8ce8f6fc,d58a5330,595cb9de,eaa7472d,9cc02c4,c7dad678,74af6,e4a20f34), -S(f70d3534,ef29e626,84b84023,2e69e806,740b20ad,ea957ba4,41cc06ae,cdd4ce39,5cb415c4,7812684f,971026ae,21f8d1dd,377d7c27,a91f8d49,90c96adc,2d570c36), -S(4dffc775,38cad4f1,2e87a8ea,44ea868f,ec9ecb0a,a79d26aa,6db46522,7244f006,7afc7426,9d4a76db,2c243eb5,a89735d7,2d91305c,2d44acae,335fc4ec,7cd5f81c), -S(3fc601db,563c119f,9c3fcc60,1005f3d,63c92315,5bd786,9092cafc,237c6c15,4ce31449,bb975d34,5898d06e,6d2e463f,e8e84835,7bde361e,eca2c999,6982735c), -S(7a74384a,d0423c88,4ca797f5,1d62a152,4064db4,c0b5c925,47739139,5bd9219c,2b9c87e9,53965eb0,d5708dec,58a5d0c7,d698e51b,b6d2d45a,b174c9c3,4eba7f76), -S(76dbd3a0,2ca25871,609eace1,6ae2f814,8b256a09,8cd74d21,ae6b0344,16d542f1,c95914e0,5971f888,61800a05,ac946af0,99e0758d,78cfd058,9347ddd,8000bdec), -S(ed159060,2d63fe28,5b88813d,a6930f49,65dd3290,759b677d,ceb9b213,2340475e,894e82dd,1415a206,f3cbe2b7,3b7043b7,1adff71b,58b74c6b,2297ba54,2e1cccd1), -S(74fc673f,4a41d30b,d3ca4b63,b850d23b,8e1b5f2,6c37fdbf,12a83b9e,9c896ee5,8d341f30,c67403fa,e23b7502,91c35064,ffdde04e,ea52b3aa,3003b169,68f1c95e), -S(78c78ab7,5bf6ae8e,d7836957,e8258a33,b88b9cf3,53feac8,e3a8abe,59307600,95c6d9a1,3c9b637e,35c301d5,78534af5,777dde51,6396b017,6155927f,11db8880), -S(4d694817,ad756fe4,2cc21193,d4e707d8,ec458304,291db1bc,c38dc6c0,52f11194,869b495f,49bda0df,b0b12c00,e19c7cf2,14e457ce,66cc8e6,d93c5db2,7a91e1), -S(ac23df67,801e05c7,d283aa5f,ee2dc366,b02517d3,559123f8,d093de6,a9d61a10,e7e7d4a2,1bd85ae8,c88aa4a1,c5cf91b5,6fc2ec00,f54d6ff7,89e10103,7ceefad1), -S(10c1e9db,43b60e88,379b2ee6,566a53a,3341c12e,8d5d6490,ec5ae5d8,eceb1675,2fa61b2e,26557d26,f496ac8b,aab81dd7,16983978,35abd7e4,4d5b11a8,8d7f3558), -S(55ac4cab,1aa3465b,584aa94d,bdcb9eb9,3cff7159,f8a139a4,2504bb27,bb618854,cbe23bc3,8c553ad8,fc9fa619,b96b5de5,90463240,944d2906,41a14b56,cbb28844), -S(4afd69f4,caedff00,601225ac,9bdb192e,6c17fb45,62a28164,15929e64,249da79d,d08702a1,95f9abfb,47296d6,c24981c5,db62e8f2,96ebabc1,1b4b1612,c9478a55), -S(d70b4279,b68e2135,844a45b1,814f1c74,7eb8a5cd,100a6d8,8b12cc79,bc98c9aa,2728845c,c3e20846,a7088f35,9a08add2,4997be96,1327b54,a26ebb1f,95641efb), -S(ab6bf873,7d0321cb,bd2548e8,b81e8070,ad449761,af21a945,9ce2e17e,bba82bec,49bdc2a4,8bc574a6,9577cc51,91267c5a,85fdf00f,ecc5c538,688dcd86,f9d039d6), -S(2e01933c,1462cfd,b8c6f180,c7d633e,1b684ec9,a3011aff,573ac22a,aabff3da,f7c0c7a3,36e576dd,96b83111,9e3bc370,3b94ff45,d50306cb,4acdf9f7,d8126ec6), -S(9ce6a2c5,cd9dda93,2fd291fd,30e8e846,63720189,4a70fb34,9361bcab,263b4e18,f1d503d,592be1ea,98ec3218,8e61ed8b,c2c94e76,5d42c72d,4fd404a3,83412251), -S(626aa071,a774d04a,bfe7cd21,448392e4,a5a3d2da,a2e53dc0,93fd8cee,78f82bdb,a666518c,7dcbef4f,a0915a66,ce331a4d,46867af4,3966c81d,ad9d2dd2,43d30fa5), -S(a6fd685d,4ceae2b2,e1de2177,dae1ba3c,41822896,22270c76,74118916,1b51ea7a,73c90eef,ee517cf1,4f4afdf3,b0f58c8,b66ff7f8,c59a83f8,49b9153e,e29a5ac9), -S(ffc5a16e,cd27880a,bf5f1931,ba61fd51,57396ea1,1630577e,b5e12eb1,e9fd9826,90abe5e5,e312ce4b,14c6548f,bbe2095c,4e146bf7,c25d4022,c017242e,2b057afa), -S(848ee3ab,8e9bb2e0,745ca530,a6231a00,7a41d685,466bf798,9ef900ca,18407854,e1b0d35d,9f44e0d6,b1c8b148,ae5efecf,320bec28,32aaad80,5e1c7812,993afc41), -S(28d833af,476daeac,27559042,f7e352f3,4aa2f30f,b7ffaef4,26e41e28,d11971fd,d0a0338d,57c2f186,c4faaa78,eb13e931,8f8f6d7e,1472ae68,40668e17,94d31802), -S(40579821,9bc06e48,88b1056e,270b19c2,4ef1278a,d415d3,47c7865f,98bcc237,cc9ce014,f853d620,83e18c0a,2fd36b0e,9eb7d265,b711fd5c,6d3f809c,b86f34d4), -S(98470fbe,636eeb22,7b6d425a,d7077b31,9384ad8b,9327d1e7,139a33a7,cf5765e8,92d4c695,5837771e,9d69826b,1445f09f,bc610387,d23a90a9,773113d1,78d471ba), -S(a9d28158,a84ea778,63c7dd75,5bdc6b60,3d6a0d6a,7cf88e9a,b649fb32,44aac2c0,5d628cd5,38824a6e,25477bea,12962465,dbe281d0,bb7f5db2,78bfca90,e5d812e6), -S(7dea83c9,13fa2478,fb03c1f,459cf002,98adbc39,4dedcea1,c90dc05d,5a56ae02,19306ca3,7f768ad5,9e70ea0d,c811adf1,a1e593eb,42bd8d9e,de0c0673,afc1260e), -S(2ab32555,3df0405e,e5576b5e,9965e488,dfccd677,63b03dfd,ef3255c6,7000ce2b,4fbd0086,10d10040,af8a6e80,a1525d88,d8e44ca2,6a1ca8a7,d6eedd35,c5d26ef4), -S(d59e876,ada6de89,fa87dbdd,43b2db0a,e1c1ed01,cb0a5d3b,5fc5cdec,ea52d069,b7923636,a2c5d928,7722673f,f759ec4d,3dbe9484,b470e14f,e28030e2,f37c3bd0), -S(8a69a111,7bdf0752,13f53f00,1101c594,2d2932ac,789c9b7b,15a57640,c679082d,5ef32f62,103c59,8ce35443,5c26f1f1,9ab21ae4,ee8e4350,60aa910a,99fe1633), -S(1aee31cf,451a516b,24f43cd3,71a1b93a,6a04bb09,74f73855,1120c6a9,d27d4546,f6767dda,c1204f16,e31cab5f,ae5b9357,4a2d8b47,b3dc3229,95c0afcb,c4271d7c), -S(7fcc179a,9a2ab1fb,10f03d6,1e936985,91ac91f2,f49ac834,e583f991,365efa71,c69dda71,c28efe20,3ebdb28d,70d0718a,9da3aa5,255c7c60,6f355961,3841ea7b), -S(bf75127f,46e4e90b,3bb81277,13641056,c75f78eb,3717425d,54df396d,9c021a21,640e202d,c28d9d72,c6d1575e,9d672c57,d64610e9,93983585,10eaba8,61fa86b0), -S(4c1248b6,27e5cbd3,5f93deea,44070e7e,bd5b78d,97f27961,53cb63c0,c18feea6,15e12929,f7b6b8df,bce226f4,6f2c73e,7d473833,18fe05a1,1f8ff01f,5d42dbf3), -S(584bab22,79395635,883c483e,abf11ac9,6e97bdd6,b9a0fffa,f30b9062,37520da6,2e7e69df,570afb7c,a3e594fa,7b23d00a,2f8a7e64,c02cebd7,3fe718ea,458891bc), -S(68ae6eb8,fbb41532,aa8e8801,e7c1334f,571ef1f3,92ad014f,9637bb46,b18ada9,aab3337d,550f07a7,20285869,72781c30,4bcc2d81,ecff0fc9,c27fd09,5c41b1df), -S(21d7d1df,17e3c1f8,65ee8c63,f16b0e60,c074501,334a601e,eaa803bc,2b1db846,b6c847d9,a4992f60,c9dd1898,708be183,41f4999,a5803b4e,7c2a5677,d3def3af), -S(63b70ee3,eac6f6db,36b273f2,2f919be2,6146d19b,bfa217e0,a3389ca1,f131b6fe,38accbc1,28b57d42,ab2ae5ab,21997cb3,5bfb42d0,71059542,6867fe83,14df95d), -S(6981f1e5,ce35b49e,b511612b,22ba76db,5884e2e8,819832d0,1859e993,84d6e8d5,7261f896,810a30d8,53cc24ae,40f3f36f,78826bd2,49141d57,6b9bd900,678e0b79), -S(e30c73e,fcbfb24c,882df876,b878b5db,31f0a78f,2e476d3f,850f6b2c,e1d3d548,5821f7f9,7a2e568c,f0f03bbd,c5e43e2c,ffb1a55a,4d6d4855,49f7b6eb,f9a6817a), -S(e95e8d30,316e97ca,70e8d602,89c5a43d,1c698beb,f40e1ce6,87d0d017,7e922f4a,cb161116,c64f6a66,7fa6500,294fdfe1,f5f27cf8,de2213c8,97c55144,2a70137), -S(f0062921,2603da15,6e315036,ebd10c56,477eb7e7,5239f2d8,a4fec336,9e956c38,4086b08e,a3d16b48,a0cf712f,54a7547d,e732233,69030526,c10ba827,eb85793d), -S(ee8526b6,a932b82a,c4645a4c,c5200e91,ac1a8ca9,eccecd29,1c83cb02,bf69ec6f,d5f40396,4f593b1f,d6b130db,65a45c32,241be6c7,d0faa091,bf8f0d5c,41bc41a2), -S(6209df6f,a66fb907,70c68cf8,81b0494e,7c31ef69,38fab171,cef2156a,740ce435,ed1a499d,5d7712ac,dcc39dd5,512aa71,4af5fb36,f53c789c,7eb53d10,7ab415bb), -S(f1f7899f,7a0cf14f,4ed384e8,e55bd6d,8ef0cfe9,895bea58,ab80715f,7bfb6fb1,679f0e59,705f87f6,b23a008d,69c9e145,c44637e7,69326445,68c9dfd2,631a0e32), -S(ecaabf0f,890fb84,a23e6b2b,11822f6c,62ddefda,7def3d2a,816ea029,2d24d93e,b5450b41,29c8ebcd,f3aa0def,bf091346,6ceab1d,874000cc,527e071b,6e3c420b), -S(42220ae9,3b056efb,66349955,402c6b93,31706ce,c5ac1916,494e523f,10959fa,8272973b,a0c30376,a3ad6d38,f007e1de,c9f74fad,f6621d6c,cccd7f55,f9293477), -S(a5b1cb9d,ffbe6c9e,152304e3,c195ab6,1904fa5b,661b097f,6838e33,fcefb7e4,f933eb70,32b9723f,250b861f,1c2881d4,fa118f20,2f16d0e9,bf41844c,4bb6936e), -S(dc460969,258cbf33,c327b9d3,3927b18b,eeb2f2b6,db477491,fe1b0f8,bfb274ed,383db155,3ec0da85,62038810,653c06f1,f573065,4ec029b6,1eac7f75,85bc7ddb), -S(546afcc3,d5e1002e,f7531c4d,40284782,7690f7aa,a9b7aa65,80070700,9642647d,ea4c5ed6,31cb86c3,c7710671,dc26249,13fed4ef,e2bb56dd,fa4f21f3,478ec442), -S(707533d0,61c5c4ed,387e30d6,69ddc3c1,de0162d5,48c11cd2,8daeeebb,6fd8eeb2,a8f2c219,eeea9182,16a5722d,b9fc3f44,a8cae2c8,8e9632b6,dc9350fa,6d6f08ab), -S(4480b923,babe395f,9b21ded4,d7f3ddc2,b9044ed1,379ff4a1,f417bcb4,ea1a1bcc,14ca822b,e0cffe91,42fb177f,712b5c65,6e650c55,24bbaecf,26450356,c7dfd4e7), -S(484a7a43,c88ccc85,9bd81923,a0faf130,f44e45dc,cc43545a,9f7f18c,184efda9,8b79382,3ab0435d,6422fdcc,8a3272b0,1b326ae3,4ef2992,65693070,45fc2388), -S(df247ee8,1936fb3e,9a4da6f,ad000c85,f7c83171,45097f9,ab4b94f,a2c8e1f9,4955c099,d857520c,633c0b75,731c6286,7b5d43fb,506dfea7,9800ccda,9a4962ab), -S(95a936d7,c83a5b13,e0bf865c,22155aa6,71d8f86a,3c518cfb,58e73ccd,f23a141a,be6ed058,5bee36b8,9f2d8921,58bca498,f87675c1,9342df09,f23d62b,64a6533c), -S(89e0cab0,118c0f6a,58b22a3d,fb66fc48,b19c059b,6b5e2958,6c7f7487,61c65b2,cb77eec3,d806dee7,b11c5552,16dcb2a1,2c00233d,2461887b,6897618d,e8c4b0a8), -S(64ac2ffd,67fe55e9,5d82b26a,a88aafbe,5ecd6b25,12226ef0,e6503aa6,a3fb4ecd,41bdf623,644d265e,be30bc86,13a6f084,a44f1dfd,a6f1ee8e,16d84e4a,fc51d66a), -S(60e0f0fd,99be1c5a,43866b76,a7ea8890,a7077135,43bf4299,e25ff15e,e35d87a6,4ef82895,b158d4ea,d8ed02cb,82e8ecf1,df795d20,b3692951,a431ec81,78479c22), -S(49f0734c,8b89d8fd,2b349b48,2d5b32f3,b7d5e68d,532f76d9,753503ff,de2a3caa,4e1c2858,9b22009a,2b4d143d,94fe44a9,5697540a,48a2fad9,100110c3,ca0b9548), -S(ea29d84f,41a54da5,f0d9f7cb,ad239ff8,91395e85,5cf2c86e,e00257ee,325993f6,a0bd6636,dad5c1d7,8d65e18f,c36b00d0,96d9379f,1e650fb9,cd072b0,224d0f4d), -S(92edd00,f9dd358c,6622bb73,ba4f4760,de3e5727,2cde54bf,a8a6d0c7,bc205f56,eacc8aa9,b85829fe,391ae7b2,a747c122,625b408a,c97f1d46,cd0c8891,eb0d4eda), -S(29811533,8b09ec4,583d1702,5a0b0bf6,b8a322f1,76fc46f2,49430c74,84b7b6ac,f7332c0,3b3c5c4e,bf5bfd9c,1e87d668,8347b315,7f0acc43,591310fc,5792ca4d), -S(b5a4aaf6,8a97958,86540199,cad47d9f,86cc478c,ec43a24a,84722a13,4dd6d20,bafca1a,5c9d99f6,3c986ac5,9e432a49,7c8e5683,331ca708,4326978e,1db66f8a), -S(4e249e10,981f8ee8,b3f0e5e6,c2e67de9,ffc811ee,6d9776b,4cabdaa0,98a8b430,955965e1,7ea5d179,4b293db0,b750a649,429833a2,7c317a24,654806cb,5ab7d709), -S(1d10268d,abf2f72c,2769dad1,dda70fe,879c650c,8ed3b285,8583cddc,cc02ffd7,7d31408e,499940ca,8e88fb4f,1aeadace,fbd288cc,c35699ab,8484be00,1acec27f), -S(3540f96e,fe965c34,dc608016,61bbba18,386b20e2,ccf75f8,a0fd6e62,65b8e62,b0d0399e,35c5c376,7773a848,34cdeb8a,cc7ff651,ab6e2575,1ce81e9f,628bedf2), -S(b1e45c76,35de0135,21274840,8f06efac,4550291,d3151239,f8272640,b7354cfb,aeff7dc0,665692d1,6fe0d607,c996ea0,8134b150,317df1c4,afe97cf9,3630c3ce), -S(9fddcd30,734ef7be,aab9c040,f1ad782f,5a67427d,e457f107,b2935caa,d52ea1fb,5c89b6b,36e26147,38599d97,2f4ceafc,d3dedc7f,79e482d4,478e4cec,b7c4016f), -S(17a4abe3,99579c3d,8504a0fb,427e521d,f6034e48,115dc864,b8ba4385,63d692e6,df5128f7,aea1f8c7,214db822,4738dd89,24e08023,36fcfa9f,d4a49a8e,c09056ca), -S(a7d67392,27d93a67,e7eac9b4,2f1583e5,633c7877,56ba7b01,a983d8b4,d4cd181d,1f10081,e72a50fe,b95b829a,d5c36349,be13e45c,f9722108,8ad78dd0,c7b5d9a9), -S(87b2dfbc,e4301a3e,311d8c9d,23c8bcf4,950f8fb3,8481689f,905d6bc9,be1db1ca,4dc9f93c,c4c25853,93f10a45,31c6cb0c,9607170,49192ea0,9ad09810,3c078463), -S(d2fb6a94,adc47e9a,e68ee0ef,24a1ec07,742f3307,36916c3b,8409de8a,2b546ab,eb44e5d3,970cb849,a797bdbb,438bfd0e,6e6dcd64,83bb11f9,10be2dde,978b7e1), -S(7dd84bf8,c7070b5b,d258da10,e62146b1,b5408b62,d7154cd0,45ca4cd8,81623bc7,cf07575c,a02b6ea3,ef2d4cf2,9ad42689,4b30f1f3,689f6a82,31c63515,6633fa1e), -S(b13fb14f,8fb7bd9d,c2a26c80,aac1ad3a,3d10116f,6ec1a7a6,888bfeba,acefda26,b5314ee,2048c766,af47c814,592c3d42,b143ef88,3470eabb,9629c4c3,5fd70d27), -S(b58f21e4,4061132d,75843ebf,74126a4e,25def37e,1f30759c,1c1d461f,95c29dad,737399d8,b9490cdc,7c0a18ce,3d33d340,c2cf7fbd,78a1564e,1115306b,247feb38), -S(10d3dc81,14156a53,f58cbedf,207026ed,6c74f52c,e62cc0dd,68189a6a,bd577fdc,fc4b7c5b,1f1288aa,698032bb,7b8ba84a,10819479,c616c00b,145f9996,8a4588e9), -S(3890baec,2d7505eb,ab767f3c,8b6ada03,3505a329,791920e5,acd55a6a,ccff5fd,a5ced26c,24fb642c,64d292e,2696aa5f,fbb234b0,3d695e83,50f5b101,6074ef8e), -S(3344cd50,af1eae91,f94eb7b1,168737d,fc8d936a,1fbaa3cf,14e9bac9,9c85dd49,b844c82d,1ef06c70,e7795dba,ae1f1e32,f8ecbe2,6c7d295c,b96433b8,161a0fb5), -S(968d92d4,5b6c2adf,376324ca,2feee09,9715b56b,6038a3c3,c51182b9,a2ecfba2,3e014876,6e32cb,5a1ba838,a5d3c64,f954c3ca,a6d481b4,3c660974,92e39d4c), -S(3f7a1811,751e8bfa,2740371f,27e823aa,c2a23c07,d1f5892b,ac2132b4,c8be745,5d475208,6cad8b6,58cee187,f692309c,4c01f335,c4a561e6,6099ff83,18cbad88), -S(2e5d840d,5e808361,799353bd,a2edef2c,4e686735,f8161382,7f98d94a,a4a4a522,859d0019,a0d7619d,89025f7a,6273d98,25acd521,ecbecb75,195bbac1,6d1124fb), -S(5536c7c2,e29de995,e3ad73d1,6d525d3c,5646a96b,fa931bab,5b96dd,ece62eb7,710b162,6d690586,15e54f97,828f7dc5,527b20a,3273e318,5fe9c64f,86ccc206), -S(d29f9ce6,d0758df,c4025af,7097b53c,163493ba,5e16d5d1,d66414e9,a75fa6a0,af5fd2ab,36975272,bd4eb8f4,83e37b01,9772cabd,fe863c46,53a38906,450cd77), -S(8fda2d0c,79aaee8,fbbf2e24,c9e2a98,e37651f,117df59a,b9c37d62,a4538ca0,dc0fd47,aea5d11f,c64a0aaa,d0a2953a,2762878d,6608d513,8b911d40,e679f238), -S(2e17903f,6b00a556,a3492c2f,cf52ed69,58a53715,950c3cb3,f99ddda7,fec950ae,73c72ce7,6644e080,a0fa570f,32d4bf41,ceb500bc,c328aee2,a9c2b22d,56419e5e), -S(c5ec2ed,9ea6c3fe,5d6021f7,bd475c33,3899edbb,7562d91f,4d0028ff,7a07709,7015d790,a6c3f25e,b9cb4bed,f3bcca04,740daf14,da1d3008,463a8f28,6bcad698), -S(b8deae8b,299a5a56,24dc2931,c9d4b63a,361ba102,c5e4e2d1,fdc17262,e10ea72b,40e8ac66,b37a8bda,5d30e794,977b3d40,d2af7b0c,276ad346,a0c10273,359fe18d), -S(66e4daa2,5442fd81,500071ec,51a2843f,ff19b706,8a8a387c,744f295,6282ca65,16a75c2d,bd9d5317,e2b2094a,a85c95ff,87bf3c9e,39101a0c,1bc743a3,70b09380), -S(237df4c7,cc475cfe,7936c17b,dcbddde8,61f37e34,93e4f3da,40d9466d,eb2c675d,170fa5e6,156a8c60,ced37da4,c929fe15,e6d8c691,ff99850d,bdfa8844,38968873), -S(3290620f,ee694bac,64b4af07,25beb94b,9bbbd0ba,bd9c7340,9129d1e6,d5d8da43,31455278,5f416fd9,5bae000b,9b5eebab,65575fa6,9a3b6ddc,cc2c5163,455438dc), -S(a8eadd35,4d5ecbc0,cde50b55,c7e21304,7a548291,7d979b32,94fc138c,d9dc4cff,94dc973c,962b25e3,9aa324c5,8f1c9349,9190eae3,8c869896,a0e62dfb,222255f0), -S(14cfbcad,83d44db9,4194e0f1,bc7d8650,c3586ea8,a362e1cf,f044d3e3,8a5a3ead,348713af,acdf1749,bf27a162,9baf1992,2aa62412,ca2e84ae,85046366,95acbec), -S(99df52dc,8f8daeab,5bf8a48f,fb8c4368,7f4ea8e2,b7feb3bb,fdd6e1ee,59bcda5f,3c6a421b,d7631546,d3fea7fb,6370e823,999c6a58,c8d4f60a,6362e590,c6114825), -S(4c420d8d,7d734ff8,220d9335,ede52153,4673dcb2,c4af920a,aaa691d4,777e0e61,4ec2028b,811fee0e,8937dc37,9961ef93,d7a04147,72a2a45,1e3f64f6,ec5c37d1), -S(485b4e1b,e755e864,ba0b7505,20ef3fcf,a58e2fe5,5b6f736a,6122ad9c,160a6ad6,56adef3a,b8d325c5,c4b30910,cc7a85a0,5a326195,a39a3681,2838d5c7,e3dce17d), -S(8d698df,4acae452,26ee02c6,18c04d33,4e11ec3,f0ec73b0,6365b46d,2e61e478,bebc1c0d,285eb1c6,bd132d29,5786198b,57650a92,f6eb951,a99bfafe,b06454ad), -S(d0d4db9c,4f9b50c0,dd8612c5,43b9d535,8027c081,cf27986e,cc4326db,16526a12,43bdadb1,b7e56e62,2f10f5d8,169a3198,30523f7,908a679f,1c78bf26,6c699c53), -S(b4aaa39d,50e18cfa,743e307d,8ad30f88,3f8a86d6,9f040d03,de008e10,b66b8060,ebce9bf6,8be9bc73,29e1ce4f,ae1a904b,2e1613a2,a45c8095,ed8e346a,6a1bb53e), -S(28e6c590,5af1bcb,f3a81492,37011af4,2e46ac15,fbe0f2f7,a19ba76f,e7104f98,82ba4bc5,4b20238,12256511,b1335079,b21e97d9,7698ffeb,723605e9,c200fe67), -S(b002b5d4,2a2089b9,fac121e8,eea8e240,2ac5b8dd,77f8fb6f,68b59c2e,f2b45182,7eb16bec,99d2249e,22f89e48,11c51324,99f2b7f,e6df592f,7ebf0fae,36130449), -S(36e9cd9,8d1335ab,90d58af9,83f7736b,e317c3c5,c1f0d702,d43c32cc,916719be,df8a57d0,19c19da2,8fa517fa,749f6cd9,21e19b53,dd97e255,1eae0b93,fa6dcdd9), -S(f89c103a,bccc8040,3684beb0,ea56ba57,b447442f,bf3fe918,b25be9de,9bbb225c,7fb1eec7,855ff2dc,9029e712,ce0b619,a6809a7c,3068acd0,1d275dc4,41a55847), -S(5f164591,cc718471,7f23615c,ac67d055,268bcde1,bad2e211,7e235699,4074767e,99aa6bc3,3979f79c,9765a053,66c82dbe,6c067ae,539065a2,4ae37579,4c5a0eda)}, -{S(92133195,a4fd0c59,7e0cf65e,8ce1d939,e333f7a8,441523aa,31e339e1,2ae51e8d,556a388,7a7d579e,87de7f49,8c54bf24,2ca4b8a2,8b959e21,ceec4555,b8fabccf), -S(e3b58edf,cbd6615a,dde1978a,30160514,80e9a335,1ba66cd2,a4e939d4,f4cce6dc,8d493750,a60f61fa,ed9f680d,fa8ac946,d765ab2,1925675,d535e60,b124b12e), -S(d7dc081e,9409bf1,ae46ffa3,5f9eae76,8a92faf3,4a670d76,487b4334,50c2959a,77737006,f0021115,9c81a55,b58da8f5,5f056493,6d319eb3,9fa1a9f2,9ffe1696), -S(ad4d72d6,768dabac,d7c40d1e,b88d5978,46e2f335,8721b980,f1f4b16c,bdcbd829,151a1ed3,ed7f999c,ab836e2c,665212b6,fa08a716,35ee1061,d650735a,3020f89d), -S(325cc8a0,c03e6d53,acebdc12,265ce043,13d69ef,ae00b17d,84df58e0,a3005759,2effa974,b24c0972,84f2cb82,b48c7460,3268ef06,a117aa4f,66d080bb,20ac77ff), -S(38e08a95,fa799d10,23d33d41,e5f305a7,eed9cf69,5151099e,cab0dd40,861b094,3e2c225c,e2c7d8f4,cd27e9bc,50015cb,3714e4e3,2feea2dc,3d275a24,997b7c08), -S(d477d862,f7572311,73fc315a,35342791,319b0185,4acc9ded,6bc71fbe,ac866aa2,c869f5b1,cb084021,d2379b27,d4e5dd7,5e88ecab,765a1808,4664ee8b,74b23bc8), -S(56a5b347,f304a6e1,13dd27ac,3ad1260e,8e65265c,31a95f8e,6d58a893,d2afed47,43c3a208,c6965fb3,397ad3a5,3d335b11,647af4cc,9ca1f4b3,1dd7cc3d,f11b4b22), -S(7755d5e8,bb6c946e,d5a9bd6c,1d3f1675,b0bfa137,3f69f92b,8f0f64a9,baa72e69,1126edd,f0f0d7d7,18128faf,3a988899,a7e2caaa,901e92b2,312f2658,f24bd0a8), -S(f010342e,3b068db4,79325185,ee3198d4,1cfd61ae,e1f2fc3b,e9552b30,ad5a1767,132b3929,a59718e9,addcd814,99ea1f69,941bb18e,f26b3ac1,50b9324a,eaa58001), -S(1f994727,6e3ef21c,2eee65a4,38fb451e,bc87028d,31ff0769,f9935095,efd3e347,425ebd7d,4d6a6a1a,1b32ecab,7be89b36,1f333206,e1526523,991542d7,b23cdf81), -S(eb0a70b7,ca8a1289,e57b3a86,9f21adeb,1ad77d21,9ab64d0,10716f91,3c5fd2b9,dc03531,46af152d,b78813a,bc402c76,93baece4,e57cf68c,ea05b6b1,ca6be07e), -S(b46e930e,36eba93,11248490,4fe0504,91cac0e8,5caa4d76,f35384d8,24f8637c,8f2e844a,29cb90b5,580b74b5,b16f07bd,87385834,23b61485,e3336286,1817c92d), -S(bdf5b431,db844804,70eb3188,6380085d,76c89d00,7bad9990,f28a4e04,e1bad223,9b71ff3b,8f13cd83,b493c150,67d91f38,6341cba7,5f711276,bf768f3e,229c1e55), -S(a4aec29f,3aba4188,e6c73e04,14e8c538,e482491b,6d1d01e6,9801c580,fdefe920,135980f3,b38cddff,e9f7c0d4,87f1b44c,c83c393e,9fe3f8c5,ef6d7840,85a11013), -S(4664f7d4,58ed1845,33ff308f,6389282e,ee336d05,28dee862,2ad54d31,9d1bd536,d774ea2c,9346db82,edef5940,264d2f47,da810925,ec1492dc,5f3c5887,e0015f58), -S(1732bd76,99c1b718,654ca447,5a9851f0,f46bc444,541239fc,54b9b053,e6cd8d61,db1d259d,15dc772b,608957e3,cf32f7e9,b076ec05,3be1305e,c2b8c9d9,7aedf5fd), -S(8e33f8a1,22c90484,7303d6ab,d80fb29,ff84bb43,eec9ded3,fb643482,82f9d4e8,5d1b2f19,30758a1f,d35d3993,598db1e1,d8514855,c23ab82f,245abb78,77f0eaaa), -S(4d96af74,6c067b61,3dc07f73,7eded3f5,da106daa,8910d37d,f9d8beac,962ea02d,74939d7e,c345a59e,567f8046,bb400efb,54107096,8fa45412,c327e10b,3db50b1), -S(478f6fda,3e82c5f1,d65caf64,f80a8341,54428fa0,90dd3833,c2a58cfa,dce5d32,1cb8ecf6,2f7cd442,8b9b3f6c,b33a42b2,bd7c8a94,26e35886,4e1a73d4,65294226), -S(9f7b432f,c89b4f8c,98966a60,34ac0218,d02cd505,f888dba0,55688463,687164b,9d18be19,871f002a,b4518835,9730000f,15446136,f8803657,51987e10,571e681a), -S(c3d1eeba,d935773a,7f30d379,4e5405bd,6bbb9990,26d3d745,78294c0d,c32a5e2e,8857248c,674c01f,4124bb99,3d5b261,def62594,7facb651,f6bb5385,2f5e5674), -S(40a419f9,180b3e76,dddd489d,eadefab3,b3a53abf,8898e5c1,63221606,d7384ed2,53f5382b,a73b7d00,a5afb12c,9345afbe,9c5e5134,cbfe1d9e,81bf3b59,4dfd6b95), -S(ef7cf180,fac500e4,32a70987,989efd6d,d527ddef,779cd09c,589b7e19,747b5572,7b540c7,c2a008f1,8d5ac610,96743cc1,56e87270,5aa2dba8,ac891ea8,bd6b755d), -S(402422a6,8b33b370,aa5f4d57,3a92aad9,acc9be9,2e304de2,73aba72a,d2a8c4b8,351e81b4,4a250b81,5abd8a73,f23ba0fd,a624970a,59076ed2,99667c52,6f63e7cc), -S(1b101d88,9f802cba,396dffef,4eed336d,24138432,12d21fd1,dfd56765,befab1de,b51691ae,f6589bf9,f1d47e2a,c29b6e95,ba600e4,17e48801,aa8c1c36,fac8dcfa), -S(1e82a9b2,4458de28,97110749,dc63f744,94dbc6e2,1085afbd,15c9317c,e3b0bdb,72ff3c57,cf1c18f,64127651,2959762a,83a77db7,2f7b261a,67b1f64a,bad69db), -S(3e5f2f47,a3b6e9f1,69d67e79,39ddb4a6,3ff4d6b,e85e7855,9eebb19c,ba5dcd88,208bd01e,5ace2579,5ddbf6,b57ea49f,aac3aea0,ab3160c3,62e1436c,c545c7bb), -S(e0aba818,cf81f784,ad2656b8,1576ab4b,91a4d0ef,1145b359,393b2bf7,5e798cb3,52f41c6f,3f49e3d7,8031c7cc,c2d4197f,51d53167,7a2b3034,20f2750d,f85dfef6), -S(115d9e1,1d6ae4e3,7a28e641,4704361c,f6422288,a3044b19,7dcfb54f,e76293dd,81c06f64,28931504,21f74c52,64adc217,9c9839d0,9e2ad42,8680b289,64d7f8b4), -S(b742c7f5,60adf44d,a8ad0f43,30c110df,488fc072,c6029911,bb60196,6098f26b,f683d248,d6ad0724,2d1187ea,109f89e4,b231331d,5867a009,26496d34,e7fc2b7d), -S(d8d686f9,2d5b3e5a,90a6b33b,f6e22fc4,e4dff29c,c8e2abcb,cc03d1d2,89d8ac,817b0c58,8e768884,6570da24,12d4dbae,c1649e4,e87b15f8,fb6ca41a,dc90ef8b), -S(a2792c2d,f53b4f8,c4d8da47,1117e7c2,19891016,14e6f8f3,cd40e74a,1f079bd4,bcd3c49e,fced8a89,c5a22469,8360d91,e55c7752,b3c0b798,ffeea98b,373bbec4), -S(2aa4ede7,9b0e39e2,2108d839,a1a3a280,e69cd9da,3ecfc71a,b3ff89ee,f921feb5,8568355d,eb149d39,8d4ba4f3,bd1a36d4,d7e0320f,8b3d8c6a,c81479d6,702c5841), -S(ab965917,6927e9dc,20ef1e6c,60349cda,947dbe9b,79dd2402,f5fead7c,509c56eb,2cc227d2,68174216,abc20792,12eda585,2a91aa1b,e5e141d2,a510a165,405fd059), -S(4103c008,71a071b7,f628d6cb,123c0c9b,2c91fc19,e52e747c,a35846cc,71a9baa3,8aa4e7d9,ee8493a4,ad092826,1377f4e1,397597b4,f63dee00,cf379bc6,92ba589c), -S(972734a8,6a5fc831,6745ab81,5487dabc,51dc150d,4747ee8c,b96de185,4552d1e8,64341946,6c2ae001,49ea0ee4,9dc92692,9ff80e7a,649bd30b,89030606,319a6fa2), -S(9405e5ea,569e492c,883a5035,ba768b83,79fbd706,bb4171af,b0a7480,7069c796,ebab6dbc,4dc6195c,f0fc9b24,82cf324e,3b00fbf7,c4773677,2f55c2cb,60109c6c), -S(c9152518,b43e2f9e,7565f8f0,322eade9,83c5bddf,dc85a120,8b18c6d4,b53e2cff,33a5001d,26ba5f94,19602e75,a0cd39c,c6cc7648,ab9338c6,a796f68b,250f8bf7), -S(1069e550,becc5618,5bf3b627,9e70db17,5c2b98ec,8796dbc4,ebb393c3,95fc23c,cfcd8ae6,b94cfe4a,b3856627,4896faea,ac4db81f,3137c2f4,d14bcffe,26255ffa), -S(e1d567cc,7a7e3b86,ddfe4143,ddd5ebda,41e731fa,68e84445,3494507d,642aef46,7c6355da,fcf15ddf,8b143c1d,542ac5f3,da67225c,d1eeefba,ed24eb41,698af892), -S(b12d2da5,72556701,4915f7a0,f19d0483,452626f6,d03c4829,9bd2fa9a,633d2ca3,5b3af65c,1ee45b4,51a1be81,db8654e9,62b81470,2f162b9,5b02bd2d,313da49b), -S(b8bf7426,e023d1f8,bbdcf2c8,cf0d1ca,3bc14c46,c25ad34e,30e37538,222aebb2,20311608,cca061d4,7daf2293,ef087cb7,bafdbf51,b6fe17f0,f2c676b5,596120b0), -S(30e2ab2b,4d4416f1,56eae97b,15df3e89,8313bedc,39e224e,2875def3,45ebf7e1,a9a5c2f5,bab83663,463a5ac2,38d34f2d,942f0864,9f013068,d5fb43e4,3aa9cac0), -S(b51a0245,335f2b69,ba346bca,6e262ae,e3bb9483,2c4a76e2,cf1b0a43,24398a06,381aebe5,9c57447e,e48a5615,2b8c1ae2,36e1216a,eab9fcf9,f4608c3b,d5c1bed5), -S(16ff6ff9,ea6268bf,fa04d0d7,697f08c4,1717ce6e,6956c14c,bb1e7088,32ded621,a30c4501,a9791b68,15d4fd1b,9b6c943d,8af81feb,b995457b,34640389,eb312a), -S(75a9b34b,80f56b8f,843fe73f,f0a522b6,b32941cb,a892948,be3a649,ab644ada,55c90f2d,e8ddccf5,a896fedf,bd1676ff,11e537ec,fec1e99c,3d880705,93794d9b), -S(e3d207b,fce3af45,7c93e30e,fa54e879,dc00b005,481775c9,1d2195d8,3c0be4b2,ea97b4fe,989166bc,eb7485d8,50829a7a,ce306586,a34f812c,5f30353,9f46702d), -S(4c133100,4af7bfb,d9b25296,64c16012,aa5d2000,167c5ec0,4560c44d,5f424139,4a68e2be,d1509b05,9839d1bb,1e96e953,cb655fa1,1da92569,8edbd940,5758296d), -S(cf6da6f4,eadc1ed2,c4e5c161,541cd6d7,6c3187e,2ca791b8,2fb20f9c,4f8bcb0b,c9fab960,ef26fed,75259616,ae18156b,3e5c7ab8,73a08a65,cd199de7,f743a492), -S(70348438,bfb71d5c,c0ad51d6,d6dd5b01,1694c9a6,d759ac00,72c1f3f7,8e6064a7,1c825ebe,cdf3f546,c731df,c03a7bfa,8101f864,b8428461,36beb2fa,a1d5a916), -S(505ffdd9,f57bb5fc,1e32c035,6bb7f655,793f3aa8,1d34ae77,68a0fcab,73aff902,7ae3363e,36fdebc4,f5d91f39,cb92dc58,a772741,c0191eb8,ab95575b,ac32bb79), -S(a3f102b7,1312ca94,748f0364,1f3e15b3,bb41d1c8,8bb9ea8d,b51b4c9b,4fdc659a,1b1506f7,ed9bb787,7e65f94f,97b400c9,bdaeb208,5944d4aa,c70906b6,6b8e85f1), -S(21f0e0cc,35288167,6cf5df32,fb7f1d9e,962366d0,ed994a35,5e95d68a,1ae73664,13b8d4ee,c089cfe8,ce0fee41,67f25dd5,bc165cbe,c178e80b,d4d7b57b,b0f26f85), -S(6cdead78,97b40a6f,ab7c0e79,66f930f,ef8a2ea0,f8b8e20d,6c832aa0,6476da10,aee696ac,24106a15,2350a75c,aa45a230,c55e3eba,413e2251,719ed8e4,9bbedce9), -S(ac3d60b1,c5f1d942,17c4165d,45efe2eb,889917c4,8a9e650c,e2528893,ea23d48f,791c1b86,6e072f43,78221fc5,b62c5c97,4a601a97,57f130c,787a3401,8bea3f6d), -S(74b31ac4,5ed0eb87,36380b35,e711c93a,1ada56d3,f4d878b5,ca04033a,2673e0a0,818c0254,b96ed496,29724ffd,cf71501c,f37d57eb,93df690a,4c7fce70,a100fea), -S(b4ede440,f1561150,4e25aaf5,e415030b,3542680f,45697539,6c91c85d,aeaf2be5,92ac0c65,d90063ad,793e78a5,6e94211,392b5a72,f417fc5f,d1763228,4ec2cd5f), -S(b629a62,2434ce88,6f7e340d,d3fdb0f6,b36f06d7,cf4657ac,aa189793,5e46c413,f927a57b,8eb72443,bf2a04c7,65ba56f6,4c9aaaab,f28fce4f,aa1fc964,2b8452bd), -S(2536ca07,e67d4bd1,2a3e0c56,77e0b83b,35f03ef4,392efbb5,9a08106f,5e7468a8,4eec6714,c83fc9a5,5bede8b4,206affe6,68d84316,b88f65c3,a7b1b002,9cb23d94), -S(30a68c11,93764521,b72d251b,dafd608c,eaec6052,89ca2a40,b3bca114,117667f2,4a79cf91,e5938ae2,31516a5,a6198cf1,531c9824,1eff5f2f,519a9038,76c21b6), -S(aaf6b23f,bc200102,ed92dd61,a8a853a0,7298b004,7699d43b,ee706ba2,15daf366,e9a15558,d984695f,fdfdce2f,5add6499,644c1d91,79e910b3,2d8f5cd9,6df9a78a), -S(aba17c14,424f27b7,324bd29f,b3a232c4,670b56bd,71013ea0,14942d40,c55cfdd9,5c0265a1,963f3679,f4bb7e7a,60919df0,860adc26,b0fc502d,830c81b3,d8000999), -S(7dd28211,82eff020,ff58a4f3,393c6fd,516b52a,9f78b823,9ba92f08,6fe30fef,6893b183,1c0402ef,c162c99,87efe669,58e9256a,54cc4048,aefb5ff0,989ed93c), -S(822f080b,76a98334,55635b09,2fee11c0,4abd6018,73b83f82,fa761d68,5fefbaf1,fba007cc,b611b2e7,37ce918a,ff26efcf,92a17d1c,4e90849f,ce058397,4128de69), -S(e47aa72,50e27d84,ab7e2e8c,a566424e,646640f6,c1b458df,3eaacf89,2982253d,e2a109ea,5e1854ea,951edeb0,bb8dec1a,8adb05ef,515b0bcc,40774196,222a0e09), -S(6fb6cc,902df4a,34a517ac,5feb8d78,33607701,1d5522c9,9654dfa5,ab5f4872,6efd6a0b,f55f98d,9a1872ec,8a4102c0,e7272e62,9eb6e10d,de6f5b80,aa4bc44b), -S(2cf349e,34205e69,79ba5a1,83032a05,76b5fb8a,961636cc,4d1e0cc2,82158ce9,b75d36f5,94df0de8,6cfcbcb4,b4ac7b97,fd4b711,b48f132f,961b0642,a123cf1), -S(9cb540d2,f8cc21ca,d4fb1b,7e2529,389f6a2b,ac1a71ca,d73f5152,483017f5,65bb5abd,91d3c759,924314d6,f9925b47,87413c2f,1023a6b7,8a7bb65e,d43a48e5), -S(b008d6d,24acd10e,aa0f129,58045da6,4a858f30,44b47e6a,1caa37c3,3ad7efeb,808a3f6,12773a98,59342b25,e479b2d5,d28a8c1c,b2597f7f,72fa0e9f,8eab294a), -S(24bef8fb,9a3465bc,63868e5a,74293e70,3eac939f,99bc1fe0,8263e324,96a171da,efe5e06,9018bce2,bb92fcf4,29efe63d,1d624acf,d732fd47,f6b82c81,db028f36), -S(338b7660,385e3d4,65d5cf89,12473b94,3d1cc1d6,98a07910,8a3745f5,de300277,6c419d49,f3df4dd4,b87178e4,3bc2e9d4,9a76c1a,262d9d0c,bda141da,78fcad0d), -S(a53c790d,d8756046,8446a40a,cfe6f890,21f64328,8d4bf979,99a5fa9f,51f4bc22,444ecb6d,fe9cf442,d34b643b,94bb73d8,7fd9d5b6,87907c62,68425c57,e43e1158), -S(185852e,f02e1aee,10d6054c,796ec263,a33076db,26a997f7,2ef01fc0,ea6ece3f,1b8ccf90,fc573d34,b0733ffe,f10c1346,2190860a,f3e79c16,863a3fcc,add7394f), -S(5894b2d5,476f40ad,765bc171,2bc9426a,df05dd54,31b0d89e,b164258f,d5ec603a,27bcb2fe,ef2d1ae1,e2024ee4,b62e6d77,9d4930c2,3badf2e3,84241d74,cab8beb4), -S(56f1ebc0,345c7d51,c0e58f2c,5e4414c3,a264da18,73e1e898,e3e7d526,777b77ba,1066de15,7ef9ad2b,a07dff34,7d430525,528812c0,2593c14d,a0d0a7ad,73cd1d93), -S(5a271684,5903bd72,89629f8e,c8b99ded,6e20cbb2,9d20001f,9aaef99b,c6e21ac4,1b32158,4e2273d1,4f9f2fd3,9f5b5813,526577b5,af221538,91feefff,ff1a86eb), -S(7cae9233,8cc38ef9,a84e10e8,2281463e,303f8b0,44eeb9b7,fff51d2f,5ad8c8ba,69855baa,a2516e72,7a516081,821f2f68,988a50aa,eb9aac08,e2cd5e74,f2aed0e0), -S(31659ab6,1bd1376e,e989ced2,7d22ef10,d6e48cee,5ed1563c,646f00ae,5f7049ec,2634891c,bf30a25b,fc710d57,9b0e2795,dc2175d,5c7552dc,c0bc350c,cb240797), -S(e007de0f,96522c6,52f49b68,ac817746,27981ecb,72f70b80,25a4ba,efbb871e,6cb6eff3,dc6c9c4a,424be741,f6769eb,f325f749,b12cd512,d6d82ce1,e142b12f), -S(5c67fa0a,604b6b0c,19997329,aaabb82a,926b595,32e10f64,7c519cd7,139aa06c,7b5e99c2,9c49b426,e1df9233,d0fecd34,ba5e2c75,e6bb2b2f,8397c00,18d77b71), -S(40f1a163,f1046ce2,3d46cafa,30c3f1ce,a0b21da9,5af03f72,e7e8e006,7f070563,efeccb57,6a86a01,4ae4273c,fde8a661,3850ea8b,658aaee9,d3058ae8,9df8fba9), -S(bc34a35b,303f885d,d3d2f32d,81f81b84,fd283478,16d56674,89750253,9abe723e,79e3b04e,e93470a3,5c8848e9,30e3a963,77fc0704,5a0fcf62,f41f5610,1b6cc670), -S(49695da5,ff006373,2e59e24c,6c2b8b57,b081dbc6,8438395,282c555,ae9545d6,197f0bca,b2bae828,669a3505,e1790b60,134eb70a,aa85c7b6,82210c4,f6f2a024), -S(cb73405d,957090b,9eef27db,62657d6a,ec058e08,e9e51513,a63780a7,15c3c77f,80ef26d1,deb10417,a2a430ba,4501a722,8eee85de,c40c863b,a88ac3e4,814fc645), -S(40f1a629,1a37fba5,a9992ce7,a9af16d3,ca57625d,1e72c218,bdb71efa,d6ff819d,fef17320,d4f318f1,e6536f75,c104e7b7,fd5d23c7,efa0ac05,5ab28aa8,9861c05b), -S(adcedea0,47371dd9,95c2d169,e84df39,7b91b051,aef5ca5f,e759afe5,e30fb54a,986f4ab9,dcb46d,676076f5,46ae4f8f,55393422,95d33c0a,d4177ac5,bade6dce), -S(56f92765,41af201c,3e9f428,e7e23b50,7dfc84f5,b36e40ba,41f1f3eb,610d9e0a,c1b9bc04,c9e7412c,c8f6efaf,c4c8ff7a,59b76a40,d2717a5,ac6d9270,12ed62ba), -S(208efb63,23799f9d,a69aae92,d7921ab2,31ba1d9,1b5d17db,f6f061dc,30395e6e,4765abc8,177f4765,810c0fca,a125d72f,aeee8889,637b169,6d843d97,51e0e5c0), -S(271893d6,a36b984,878c40ec,45459e3d,932920f6,257af8a8,a5a11b9e,43a111fb,80ce0758,847df058,1c7d4db,6c62eda1,c41e3b3d,33d6f2ab,2efa949c,36c0fe0a), -S(a6ec4e2f,4937a358,91153a45,254e22a8,dd5b812c,1333500,321a62b5,af4be98e,db55a35e,575d81d1,41da4bcb,12a5813,65c12f37,f8ff0164,feb847e0,e49dd86a), -S(1f5a1cf3,8c4ddaac,d12deac4,efcb280c,6d6cbac3,901fecaa,a64d570e,9ebc68d,12c7fda6,5997f8e2,b4b85d96,9d9ee069,1d084761,25a221e7,cbea891f,6993153b), -S(bf41a276,99dc209f,79c80dcf,a5812086,38c7409d,cbf4b842,21869806,e445303e,d375e246,a1bab103,3a89c999,ab89d82b,7bc50961,ee500c52,4fb6eadb,f4e04104), -S(8375c69c,bb4249be,77bfcb40,8ae97e2c,db6cef39,7e265ec3,85987a60,6b83d8b9,3d6e1864,8f105178,7817858d,791938e3,7b6d8f98,ef9f627a,789574ab,c5bde6c3), -S(4872571a,c44368c0,2d0ebbbd,a82ecdf5,b451d428,f3f9f848,28046f01,19d8c41f,3ac201f4,cbaaa772,c7afd2f,1d942d29,2a0c705,90da811e,789b7aad,ab49a7f), -S(2c24eb5c,124db868,235f333f,c3453e49,5dbe9215,5b6de64e,ffcdaaaa,4be86b86,6f520dcf,35dcea5f,86edd00b,7b7e4903,6e414e2b,f643ece9,e22431ee,9b3a9d29), -S(aa70abed,8c5e973b,a21a038f,37d36ab7,61b0da01,636e9cc1,67cf95e6,78c07330,b4367401,7226b35b,1def07e8,c02b272b,8975ab77,7e8d7c31,10a78db9,94fcac34), -S(ab317750,1b5a627f,45a57b2b,38bff161,aa8869d3,a034a5fe,35289a60,e5056b0d,783adc21,9b1c0173,9977568f,234a3cf,4f05e91c,cf07fee9,71bb55f0,e379ceab), -S(d8ae6ebc,fde52d4d,c482acfc,ef231d62,637f4bde,71c32ad6,8205ab30,9d66c013,f75f1efc,2883bce6,ce06d01,1dd86796,77ef971f,22a1b5ee,1c08a3b0,2ecf9cf8), -S(949dc802,f4d797b3,b5f40cd6,a5b3bbd9,c98e579b,7a4bbc20,2770e4c2,f737c1dc,a1d1dff4,7b86235d,b16a88a4,59596ac6,6634bfcf,ff92736a,7b7aa081,2c10ef89), -S(8b0fa15d,59e05495,47dfd98f,5366571b,91355f8c,c54d78b1,b50ac4bf,ed31e633,4b0215f2,65267379,10855e46,1d8abeb2,71c7baff,170667f1,962c0954,6480baed), -S(98707fae,93b85fb,23f0fc23,c953ed7e,68fdb5d5,c7d29c5c,1b130193,400f3a47,bda56a3a,97c9d049,78bb228f,2aa3b6af,59fbf9a4,b0ea2f29,48304fe7,47a654a9), -S(df34cdd9,cc111a99,66690fc9,a79cd621,66075104,dbc40423,69a817cd,8e94500c,29ef5a11,91ae6c3a,f9b959e2,423523e6,5a32e254,c924a416,a41361f7,df7c4351), -S(c23fd61,b07e8fb6,a528733b,f4ab486a,292901,eb4f6af1,2b940af9,49e80811,a749fc6,7f340cc4,71056f0a,ee59e08b,ecfd98b3,cc978477,1eac93fe,1e2831a8), -S(d8be2fba,6d2970be,cf3fca6d,3f3ce70b,a4eb5e19,61f07223,c60853d0,bdd99e21,b03144b7,7e6161a1,a35a01f5,2474872,6ec44cbb,cff5daa8,53de1524,3d5d7c48), -S(beab3690,382f0fbf,e1ae999b,1c12a04b,f421e94b,ddbe0d78,a287c8f7,9de0a903,91168177,fa3af115,e75a4e5c,b399c136,41793138,4d22a85f,982840a7,89d59082), -S(72b16aa2,6df7b6e,9b6381f6,8f3e153f,da872dd7,16c91f66,d04539d4,bd8182b6,73ff3867,2b5b7008,6db53e27,2d7e2969,c6522666,cb544607,52aa6bd,f6a6a28b), -S(b25f6e67,169d5375,3b3c0e43,a8a1dc67,33ced5b4,95902ebb,4187277f,cb754f9f,88657428,cb2e98d7,8ca80ab3,a52cb043,cc50bda,3e0d477f,b12aa478,dad14016), -S(c5d724e2,1eeff913,fd3bdef5,10c963e,77fe49e0,18890a24,fa2832c3,a8b61905,f06907d3,ac8982cf,63eee75b,b9ba739d,e80b819,32a3e978,a3702a9f,256e9f9c), -S(c2ebd113,ad286a61,fd8bb092,ec4025da,67a1606e,31e023ad,f0f7d8c6,e18b5e61,f5a5e5c,defff7ca,722b9fae,e7182953,3191ccdd,cdee5536,f2ae31a4,48c6918b), -S(d6e1a1,62047343,aec39c67,65f07f2e,d0bd1b14,256370dc,2c90bf11,7b54a82a,75864f87,9f5bc30e,afbcd624,71816e3e,fe9c3aec,ae631dac,e0cc99f9,702f7ddb), -S(bc4fc591,c3869b15,8401713a,e545061b,94675162,8757ff17,a52d200,f6f490fb,8188af48,51cdafbb,a85fc8d5,5129dbaf,53642f19,c0ad555a,8385b0a5,c82860e0), -S(1748e74f,610d6d00,f299527e,9f09b30f,271371d8,7cea2ce5,e092416e,7823bc5,5ab591e7,4cbe7756,9fba9944,b84d8f60,268d4824,f73a05a4,9103817e,5c15960c), -S(cd5827ff,853b6997,b3aed60f,829c5fa1,5a6c8482,f4ab123,eff27af0,3e145f6e,3e7863ce,b6101b67,243b1c22,73824acc,212d9123,882310c,970c6f4,9936cbd9), -S(d61d636d,1d5db74,1cfea51b,59d7b870,4566c733,e8bfd023,a152fe0f,bcbe9c95,fb94fda6,36a9c976,2cd6e1ee,81bf6fbd,a5f033ae,1ff7db06,3c31b045,5674e021), -S(2363f1d0,735814c2,8ae1c637,ba838c00,601cf14,d99dfbbb,a1e0f45c,75c62726,f340d59b,44924783,85235374,729d4773,365943bb,21c78b65,c8d7a8a3,f1de05da), -S(45013f55,3e53c6a9,aba8d265,696ba61f,45e15c9b,b69a578d,57a2559a,cc7441e7,ea2ef736,8dd1868c,34b6a65b,6f451f6b,3342d2d7,f90fa2be,93ccacbd,6e6f5d0d), -S(8fd98d99,6bda42ab,ecc672d2,521921a,4c838e9d,760f0f06,25523dfd,2dad54c9,ce29f650,a59a61a9,5955f9c7,c4e1505d,5d795caa,4cd5f81c,290175d0,4e48cc97), -S(d9af8b8b,3ce2f4b1,70979639,db524cdf,a68797a0,dffeae55,e0bb9e60,9ddacef6,898eecd4,5ad6bf9d,55e2e658,2387fc69,d1acffe6,8603ff56,68a06597,bb0186fc), -S(f3b40480,1e1588bf,fbb524ca,9dae6d88,c96634f5,aa163adf,ccd9fd9b,dc78d8d0,4951b9c9,31a7f009,92c808a0,cd7d6c66,fd6dc868,1836c577,d61b3783,39decd99), -S(feeb0e91,e310b9e1,b8c68885,b6c1c728,31a6c29b,f93a733e,c8c86b43,2f576b27,c43851c8,46c3ba4f,6b84f039,6cd4e20b,3a8d492b,57970b8f,2df52534,ba1fa2a5), -S(8aa75b71,79cd7941,1c45f803,e0e76c01,59972566,b24d7566,3fcd1a17,8a0af8c7,f050d1a6,fc082a7b,6c342cc1,f7221042,373dce2a,2b055638,c49c5900,85b97fed), -S(44e9ea01,b7f3058e,f878a57e,8a9ed638,b6fb5730,aca25b8b,e92ea856,611e3b78,e28955c5,2a5ec160,185a29a2,28b587a6,6ab207ad,70236a25,35d0df67,44b48d7b), -S(7533e418,ad594d1,2cfee794,8894a09a,1e440b6d,335d9019,78416aec,5be9915e,312b4709,605c94fc,1215e513,ec13d2c8,e04cb150,bfed209,e848e247,485b4f5e), -S(682d72b9,e5ac04d8,23d7f275,ced51d52,6f8441bf,2b290c40,1e31e6d2,91392bd9,96a37870,6c3e7c3b,ecb70,dcf3aa02,902bb466,9db00db1,39a5e8da,1cb7e749), -S(79aa4b03,a9cfbe13,b7a9bafb,2e170b87,7dc29832,ae4c33a4,6a4e8957,ad2fff11,403a3f70,b165471b,b120e22d,a78d964a,f40b6712,1535d44f,769ef4ea,ab0827cd), -S(73f36ec8,1fd92ef2,f7a7974e,9bfabd08,2e8af24a,4589336c,9f9d72f4,e903f164,9e351dfe,ae961e77,8f617b33,4faa021e,db206599,84ce85e1,53b3eb24,bf155584), -S(c765b554,2a70148d,ca6cb008,12364451,236cb8b6,f2f389da,8325d283,1385555d,c7010bcc,54c1cdff,8cb53644,59916a7e,90dd5c52,e5ec450e,5bffd621,352f9aca), -S(e3b41ae1,42c61c16,b798aeed,8fd85c8a,1ce8bda4,c7378511,b595b1d2,1ca13278,319a4f8b,b36842cc,b4bca0d1,f30970d1,491f1191,b96bdab8,c460230b,4d79ad87), -S(e12d6ec1,6db77af0,2f6487ad,2e07348f,f09e0db4,61b65a48,51381bbd,c0adc704,8d5eb2d,5dd04fd0,a0a62c1,4dfde904,9345fab1,22b9fa08,d54ba78d,fd362179), -S(222174f1,9fd39456,30239a89,1555950e,c10fa208,fb2699ca,311a383e,a92fbd6a,47681f6e,517eb688,c1c5e6ce,ede55387,d6073d3d,3e838121,1324e7a4,e7a9919d), -S(91686e4d,30b99146,e67f23bc,5d0c2e56,571fbc55,2bde35a3,33360ec2,8664ca33,49792737,7b52d9d3,7fa3f737,898895f2,dc6b5cd,e83c034,8876451d,671134e6), -S(ddd308d,5e6de51f,4618dc3d,5ac91e2f,bf449a6e,3e613d47,5419a018,bc88f5ff,9956918,ba5f5ac8,cc155ab,c617cef3,3173fb42,c3c2ae46,e4ecdbee,9bfd4379), -S(ed320f14,1431b13d,b683a4ec,e2b82554,b32f8c8e,fa626ba8,dc9769ef,f5aec648,90d63300,1b6feaca,db963593,ed87f370,63f58a93,1712d88d,62ea3cbe,1ad502ee), -S(4a6fc424,aa5a3dc8,5e3922ff,bb25593b,a74202bd,c8a3aefb,495bd516,54fdd47d,8f32c810,59df5968,8c96d558,64df667,b1e17252,4f48fd10,801297df,325d0370), -S(409c3ad0,16237b76,e4f61caf,16788c4b,f8b8f994,f82435e1,c808a7f8,e88a0e1d,3a2a5354,b0e8d2d6,4be8004a,287e27c7,ea1d1b8e,d6b7e542,4ffe878,de81dc8f), -S(54cd117,bcb57ddf,67ad286e,fcf49489,5e5351de,95011a8f,2887967c,a2d89b3c,c4967891,b75792b6,ec631929,8ee79bd7,79f499c4,7282805,dd4270ce,672e3c12), -S(f31e127d,fc904fcf,9f38aa19,e3d797d6,83cab4c5,a36be0d7,73e69267,785775ea,1c57ef59,42b1046e,1ae1b2f7,d20f3330,1441baac,eee11a40,905315be,165caa10), -S(a0260e45,b9fb584b,1a82262,cc07a5a9,67dfa2fd,f3e7d748,705d87c8,f46d4b65,8e519cb1,1c634aec,67f682a5,72a93009,a11e91bc,e7182c47,19af78f3,bc171806), -S(f8613bdb,882250c8,8f755bd3,86e31331,8cfb410a,ceffd9cf,7b148ed1,c19b6ddb,aa36adc,3d036a3e,4188eba7,321845bf,26350925,392a9a2a,763e6d5c,da3264b9), -S(9cb8fddc,93df0048,eb5919fd,52e29385,597238f1,d7eae596,583727e7,439c0de7,c9f3d25,5cdeb940,c8cbeed9,92ae5bfe,f9be9d7,d81b32e8,a2948d2d,7014db9d), -S(4543a84d,5dda5cd6,af28086f,ec4b916f,9ba8ddb8,d6c1a4d4,f1e242ef,805cd5c7,5ab700d1,a4a4052,a137778,f5691683,824c6596,44f4b206,4f1f58af,9fbb34be), -S(a33279ff,9fa4e088,13d36e4e,e6be8892,7bc36723,cea3ae92,c059a7b2,cc7392c,b47fd3e,8dd3edd,384f98f2,572d6020,21289abd,b05a0d38,58f0c557,15542fe5), -S(2831c5ae,a01f60f5,55763206,9b0e11b5,e88c01c8,7dc81d6b,c4da8497,f8d34d26,4557f90f,2bed0c05,87bd7ea6,92db50b0,dc12c8ba,a9ffdc0f,972e0e8,9481682f), -S(f8b84c2b,18aeb807,5c001f20,e55fb13c,bff76b0b,fe7defe6,9d985f32,abef4127,46258945,3a074620,df7352ef,cb5efcde,23982c5f,3e706272,52cdfa82,6b2c127e), -S(c47328e2,8dca9f9a,ad9dd5ec,1c9e5038,f362a491,46c39de2,dfc6eaa6,32602264,4e0d731c,834a4a3b,6bd5b3d8,66c1ad,1afb3627,c641fc29,6c1adf2,13d6b313), -S(24980a0,6f177e94,7b00373f,1b7985d9,88d6f715,3647090a,31efc04a,a6fff347,62d80bb6,a4841b41,4d6c8ee,bf626629,2b2a505,15fc158a,7d00d470,63efdc1b), -S(c1c03eaa,ac9c665e,cc4081d,fad9bb3e,a8f38453,c4dd54eb,885d198b,5cb9fae4,ca769550,165fbd81,96af4fd0,82ac3a42,5bf75be1,312f7d05,f5cfa9dd,d20c89ef), -S(14cdaa50,b4ec0bc9,5f609133,4698395a,c204fce2,62fe04ac,5f010826,cefaa818,52008b61,3f289f96,1298c773,2938e44d,2607b5ef,8ceef7fd,8f89566e,5c5d4ff8), -S(9914f9d5,f45c50c5,fc4c11d6,d2aa2751,29880d53,7c0a3618,17577886,abce07a6,a4d71a54,3e5bb9e0,664bc22f,86c146ee,3077764a,fb5a0017,41405ad1,50098d84), -S(5ba84c73,de6b3cd0,df8aff3f,c907de14,b73d21ff,dd0236ee,1eb6e83c,b22cb97d,759c472e,55b3c84c,5a677fcc,19dd56dc,14f88be4,4df9b18d,c0395648,487ec1eb), -S(5f0ebbee,3d20d7b,bdf0681b,ec525604,e95ab69c,166a5ed5,a3b38790,7e2a1c76,2ebf4d70,652ab5ac,a932d68f,7687f284,8be58123,701e6e78,1995a10f,c49a0c32), -S(ac1b8b80,3d168f58,f7498d84,d771ab77,2af1c5dc,fce17fe0,f024409d,5a3735b1,57232c98,5f2b2947,82fa66f3,5cfaa879,36bf2fe5,7cc16e43,3f2ecc1b,508329), -S(ffb18dc7,4644086e,51a6ed2b,b6756b36,69cc9e05,e1599ed7,5678437b,816f8656,3dc8b95e,213dc14f,4ae4576e,80a07ee6,5893720a,62f3d45f,bbdf2946,9febfaec), -S(f80b44bb,1a268d50,66b0aa33,6f0cce05,ac025e05,6bb167cc,c3ee3256,31782edb,10d80583,d4288202,a1c7c543,90373965,bc67191,948c4833,1c629f29,2abf2c02), -S(20131423,d27cc837,a520a922,f5638314,11a73ca1,ce7b5442,c557a341,c0fbbab2,7b6757db,16d6c286,44143884,b76fb2c2,8a2a0811,5cd88e7c,c07b72d3,b91a3967), -S(92343611,cf9abf9d,76291f5,7e00c0c4,868d9f28,50e24c85,3f302c90,4a3fb0fd,1190d25c,b8e776fb,931f47ee,25ebb7ee,7dd032ec,c30bcd5b,d48e1049,6ac9062f), -S(27a0148b,39981959,2ad43fd,bdf913ab,26e98ff2,8bb5d33,d74eef9,c07c49a3,b8322dde,2f0aa07f,c3c95e85,88ffc410,5c18e236,7d71c7ce,e8287e33,80addb88), -S(b336155a,ad266dbb,a52bf3fc,e3b681d0,2f1bd72f,2a3b020e,d1a34e76,62fe00b9,bb997d81,4c915336,117026c8,f0f7baf0,a4a3d63d,13477748,ca4b5228,b32adbf6), -S(27752e08,63b8dc92,c4e63ed4,d2acf880,365ccdd0,f83d3ff7,ed62fa2,a6a4bf9a,a67b60d0,81dca9b4,ccc6a192,4a6f4734,16af822c,c939ae01,dfa88ce3,6d4c851e), -S(c9d2dac6,93e0f9dc,7124c6f,7c256b8f,f99a1436,8ccdd33,6cc9f421,e1b1d474,a3ecf256,9ec4e99b,e04cbcb3,af36851e,44d4f91f,b945e59d,7c76e3f2,288c32d4), -S(ef56ff2d,e27a5853,64a397a8,88204405,680b00a7,6c4943b5,1ad02915,a321be5d,1b2c1be4,5f2f67d0,6cd9851a,9c6f12d5,d4dc7fe3,27031b01,76cebc1e,bf8674df), -S(1abbb10b,d34154f2,d28928e9,6f2719a1,d6674ac8,5c078e2a,bf6167e6,6723d972,7bcbd8e,4c01c5a9,68696956,c4359776,e5ce3cf6,a7faef11,7cb7fb3d,19613de8), -S(e51bf6f7,73d2b22d,4dd57e4d,79bafbd4,94f9d6f8,65baa712,97d8596d,dd5b9c83,e7a565f,d8f0a273,3bb72c84,1d283e0f,d6cd1738,af58f6c2,80a31873,9f70d9a1), -S(f61e0619,2acddda5,309a29e2,43b3f597,5b52914f,5e7ab14b,45047d3,76530c93,60bb1329,705d072a,12cbd305,35ed2f9,b530e967,45e34ede,885ca32b,ff0dcb1e), -S(f91f0469,da8630ab,2134c23a,e892ee57,78327bb5,2b2eeca6,11719330,ff163b8c,c216fc14,88bcc308,e4cc5df9,42b1df51,92c2ab24,e0e6630c,38735932,f941f7b2), -S(c6ce13aa,ecbbdc54,6124e467,e5e8f966,a5cdc609,8e2c77b,37ee82bb,df5da173,eacbe9f4,9e21a930,99b08a1d,1e5e8887,f3cb59f0,b9c79e5a,1e26545f,879893ed), -S(522cdbdf,20b56337,e5062b1d,24c8c347,6335e380,4aede233,daba113f,3a174101,b8be6e5,3dbc2cf0,4373ff88,79a4d847,70255e9a,1c9e46cf,44dc14a5,91f6f659), -S(4fec5311,496a5626,341f22fd,b72d4078,109f6656,347c4a0a,6ffc2757,683f50b5,71235dd1,4aa58ab3,6a5fdbe5,71be3f,c76e68ba,9cc32ff4,95bd2166,b6c88737), -S(ece25d,92d12386,1b8b7a20,79548c7f,71f05bc4,5b37fd63,46f14cd3,8d03cb46,ee6c9e60,d7dd08cb,f3fddf35,547ccecc,5d7c95fb,8de3bebd,f77c529b,317f3b60), -S(b160e499,105c9f7c,5582071c,fcdadffd,bc3be684,74158120,50fe69bb,e090df53,702fb302,77470032,3af31e37,aff2075c,201841b,f8ff4589,fd1faf45,b265e3a3), -S(f578953b,a3e785d0,ff9a0c6a,a4f1c1b0,718024c,c40832b6,fec24024,dc65c23d,46391a1d,9a0eb7cc,40b43b3e,6f234ec4,da5d174c,fc22ac49,13d94c2f,87fae285), -S(43fb3e79,fc0b7a1e,a12e3aa2,78fce929,46f1e368,ec23d157,4ac404c9,347a2468,fb902d9a,1f4fd892,6f622169,b7a9792c,d6cf9071,e0efe86b,cebb9274,be62537e), -S(322b8b20,a86183b1,47e01e7a,1a204e57,b5261b6,3d0cd615,5716c2ba,2b7ab42b,dd36d5e4,82e4ffc7,f16ffba8,dd409cb3,217fb763,35810059,a8bf3534,116dfde1), -S(cc54be01,33ecd8c1,c3bc6031,b8e9d0ef,e5483bf8,23c604f4,464cfb5f,d3bcafb,588f4d9a,561f0951,9fbb5f07,1f0f75c7,530caef3,fda4b815,bdbc39f3,9a93e3b), -S(64ca8dec,26f3a2e0,11929ed,22074fee,f9b9ac00,296ec54b,87fb54b7,184ec668,d1465642,dbea26c1,391cc7ee,4380983b,55a54f6c,6886348,dd394b4f,9fd8056f), -S(3bf7a76d,281c908d,4e9b096a,38b432a,2aac8b63,9fd69561,18dc54f5,8f563cad,2867389,d516089e,d6e21add,199ac238,c239743d,e4355602,14e9e570,c060f268), -S(e3e6ae01,7b23ecfb,acaf4c15,b3068e5e,3c1b7b0e,808dec28,15646d59,3f84b011,88ca8e0d,a307bf72,7aeac25b,49fe536b,213d4815,7d229cbf,3944867a,6d90753b), -S(9569f3ae,b8258e4e,98e2243f,da75fb1,ef74c3b1,58f89f42,8ad3f884,7b40bb6e,751c6fae,979806ba,fb81187c,69cdcafa,e13b4657,1785741f,c10bbd3a,71b8f7ad), -S(f66297ec,a2526513,42662205,286620a9,a2a30926,4023e1f9,98c5ba95,702e3bee,9193d0bb,b677a6ed,68be4f01,8c7c3810,23cd7190,bc7be65a,67e633bf,236262d4), -S(d867329a,1e6f65b1,7b6d1bdd,23c847fd,3cfcde18,e0527696,b282dcee,3944094c,8f31fc4e,43597152,ae9e6749,c16b4873,c678b55e,19375d71,228bba75,39182518), -S(356ac12a,743ae734,81328cd,a8469f86,e0e50107,6bb67e21,e77b2f24,8b4d8bda,585efea5,d6bf41cb,fdff2ae9,9b3c8ed8,cc3d6381,bf5593ed,4efc09c6,f3c4739d), -S(c6d16443,5641ccce,bf033261,510529a9,8d5886af,35248aff,ed516ce0,e8a0cb57,3f9d4a08,cc77b5,32f8ed9,e401fc4d,39f59876,41503c46,42077c9,57bd474e), -S(cd895ed0,d1aae7b8,ede22bea,b3d39045,a3e6ce5e,cd8ac7d8,4b74ba17,ab2a67ee,1e1ad565,2d0eec45,4f9c6801,358b05c0,fa96e34b,796a293a,a2f986b6,a920e6a4), -S(1779a75e,51a56cd0,b433fd5d,5b138c9f,6d42fe24,676daadd,7f0865a5,c58c7d97,ed7e5245,445fc6b9,33032805,b4d6c02a,beb7caa7,b6a4f51d,534f2181,d7a9812c), -S(5c1cd955,73d0ffe4,1d06ef6b,a3aa6f16,f275525e,15e89142,cbd043ad,901bffa9,489f6af9,1798dc67,c71159f,44f4b3cb,b3ba9cca,bd9af2bc,a2fa6e1e,d693c7fe), -S(637d236d,8d9dc670,1d78f88c,acef91be,a05092e,44e2ab08,2f057ce9,ccdf1011,8dd1883d,303dd21b,6de832f4,fab06158,ae9a7043,b6fc026f,88d6981f,46476547), -S(c3c046a6,d0ba702f,72f3e1d3,d7af46e5,5ba2581a,b1efbe36,ed20b96f,326afb97,d9d3d813,88bfbf02,9662d022,ce0fcf38,c5442a6b,426a852a,ac443f4c,c0b940da), -S(f224c5cc,249f2879,92d6ad0f,c9556628,b8565431,b0778364,44521b76,1e220e71,4aa9dfa6,99c5eff1,209ad9d8,9c26df9b,4a7942f8,607d9f86,deacc85d,65637dc6), -S(50c0ce65,6f95aa63,946b66a8,da465882,19b856b8,8f2cd78b,5d85040c,feb19a05,b8529304,9cc46692,b2ee676b,d39b6c7c,d2f465c,f4ededd7,6e7f8655,654c18c), -S(925757f7,d66b084e,61fc08a5,cb96d115,86f94c5a,5979d09c,ca34a07c,44133c5,66691d64,5dc5db51,bec2c2e1,e398fa11,84209850,99ccb6f3,e6467406,256f768), -S(a1a7a197,c8067535,df3ff670,2363c366,988b3630,7b63ddec,a48e5c7,35a5338f,4936dcc1,b186ad2c,7f0bfcb6,7792337f,561a378,e8508206,46e2d8ff,21296856), -S(54ba4a9a,877fe4e6,baed26e7,307ff40a,ee662d57,7a48828f,eacb9bea,cb7b614e,696eb116,b1508f7,547463dc,a93cf778,1a4842f3,d7b120ac,89cb0799,5b06bf15), -S(5af3fea8,2941c9e7,bc3423b3,ffd12df8,2b560441,dc3a2851,9ead7546,898082ac,e33fb5bb,c79b2fab,f1755f54,c56b67f4,c1ed9776,1580cf38,3b603dd1,e6b263b4), -S(f383a835,81e8d9e6,1e9c6d31,8fdfb6db,ffb26137,367885c3,401e1b93,33ad37d6,dc6eb905,bdd1f81d,b27ce843,df578a31,bacbb490,bba9adaf,d0c4cf30,c2e858ef), -S(ea01281b,1aa98a60,5c4a1d9,bae8e45c,a9e67ce0,6eaddab4,4decc473,5a7a51e2,3bb44d94,b07c483d,da7e1f63,eb8dbc9e,4f9e4a59,3ff722bc,816a11a7,ab0c4cd2), -S(e5d489e1,e3d0ddb4,9a1f42a9,e928e2a9,b1a1db09,48a59fc,68452a35,c52fe7e8,90d6cc3d,b30be1da,a8d3742e,bfdff07c,f8bc7c31,a3c4e166,fbd1c3ba,9c6507b2), -S(26133aa9,17fa7770,102a229d,487c56ac,1f531d0d,536043f9,8d25d6b8,ba4bbf0b,57c2eb26,6ce9169f,8b0f0a03,cc9d7b3f,25e1965,91eb66fa,247bb5c4,213ef5f9), -S(447cc951,1e20b173,5cf546e2,809140c1,ad248474,51c101bc,40e0ad44,ce791f12,9031be0f,bdc5de93,5539eb8a,dfbdffbc,b5550e70,613811d,dfc9131e,4550ea6c), -S(76992362,e0ab0d3b,b4ba4552,1197fc18,e355b161,bab8b080,a9b849e6,c32f4ae1,c73b4930,47dad2da,c9eba540,5955da52,94b9a184,fb1dc60f,8cc94d6e,6fb1bec3), -S(e14ce3c5,831c8464,75ea238d,46e8e7d4,ad77f14b,46323bf0,aa48d958,cba69e63,57b2b465,8947875,a26c956e,e8b53d83,2d8a4c10,87170d78,ff751fd,dc82762), -S(76375016,e26cad9c,c194cc1a,fd2a5464,5b5450a3,e93eb3fc,c973db01,d367fad3,f86a87fe,5ad93797,6a96323a,e4261db9,6e176488,3f389165,3aea78a5,a3b3e0ef), -S(99947ad6,27bd282f,60eced69,6a6bc741,e338f2d,b905fb2,85e170e2,9257ef3f,6167d7f0,14605150,2e226f2b,6c8320e,b2338350,9962b6c7,e8945f81,4ce1ea63), -S(a68c11fa,497edb8d,4798408a,f2c0c832,f7f70ac2,45188bd5,df8caaf5,58292b66,1007690,df500ea7,a2e80c7b,78162a27,2b54c93e,1bcaccc7,84218656,8f24f590), -S(559865b4,fb13de16,268fd4d6,f2e4adac,6fbe420d,1c7db6be,cd09cb58,a539edd8,f61bb541,17750264,94d479f,7919c6eb,9198df88,3c195399,f3bbcc5a,5f43b52c), -S(7e88a6ea,d32b58f3,5e76431f,75a0b1c2,848b79e4,8226fe18,60241685,e1e349ab,6b070306,7079d62e,747bb6ea,85d7fdbe,1df8730a,7a62615,28b5b20b,341a5d72), -S(a93b9d40,c0b8cee,3a094e19,a181cbfa,d4ec38ee,f12b3fc8,d8e2fd05,70029b05,8c55292a,a8a4ef7d,4a69ede8,c55dcf57,e0247625,85efa9d0,aa22d6c3,ff070370), -S(26afd318,eff92753,1727fc74,5d3bff1a,9b433c23,475059ed,a6065375,22c0cc49,5f03409f,e8a2e649,7b1deaa2,5c2ad40d,517fc985,2bb306cb,86b0a16e,4448fbd4), -S(c0b61efb,ddac8a75,3f32e885,df07e071,a4250886,4657014d,de4fd9b,aa84be93,c30a6285,e838590b,dff89275,a1f69548,c65d7478,52d57a6a,aef16450,f73569e4), -S(be39b097,6ea0302f,8350a663,1ca366d7,7eb108f,ad8db45c,dd679a5b,68e7657f,4528a809,88d04fa0,b4ddd4f1,10fe8948,ae1f6c37,a13d7a10,81cdb4a3,4b83aa84), -S(267becbc,72ebcef4,95d64c5b,3da4bc2a,3fa2149f,a554bad8,eb20bc47,b43c055e,5c5cf671,4fcc1923,9bba9e52,fc97140c,3037d95f,2aa4b828,2f019854,63e89e38), -S(683e99df,1246557,2b88fac7,914c6b15,a819be55,f7415348,a59aa51a,2f08d99d,e5bf288f,d1a561e6,7b79920a,7cff1563,e22528dc,c0a56996,1e87b84e,98210f18), -S(984d688b,cf2a0f4b,b5972f58,f996d13a,c65ddfd2,35247aac,9c983aa0,ad61bd89,b31672e7,ea2611e0,cd3f9397,3d56b8f1,78ceb2d2,85f15a8c,55a4d514,e8b9296a), -S(a9224213,7882e7a5,5ef1c35d,12a6cea7,c0912746,af66057f,20a9835,5dda38a7,532992e3,630370dc,bb4490c0,76f81e18,b9b20dc1,99b0a557,4c600947,5f05cab), -S(6b6cf051,d4311bc2,6a878a11,f5d755e8,dcfbcec7,ba63180a,6c1a527,90c75f0c,395f012a,fe1f6377,7266f20a,d3f1b47e,552c1e04,fee7cc43,bbc94206,1ade5147), -S(df30d2a,fd1a4145,112b2e25,1943fc1e,3c251d44,f67f583f,793d1f2e,da10e3dd,e6753f83,edcb12f1,e29f688,a555699a,aa361a11,afb94832,32849cb3,33bb66ce), -S(1e09829e,89fe1ef0,54ccb6ac,eb3787b,291ebefb,c4531e5b,765090ad,49e9b4cc,db2bbe7f,57c81824,515191e3,7718c75f,63b6abfc,ea51f397,b4a6cef1,6cb49a58), -S(eae324c0,88d0e213,ea0a5e4d,9fe3cc78,3488bc63,22fc4733,d5a2509a,e9fe9f91,5bd9f44d,bf33e894,7572cd8d,41f7ffe6,47d1e194,b4d27053,4f3da5a2,df55ccde), -S(ea64dfd0,aafda3c,e15d6fd4,d4fd87ca,a050e0e2,9c581b86,dc0ac4d2,9396f1f1,f448858c,36b44a58,fce7d720,b8f577b7,d0888751,2569e473,eba52a94,ffc0b33e), -S(22bdbedf,7b4bbc51,a95efc63,8ddf782c,ef33cccb,b112e866,61e7e47f,4eeb4b3f,5c9703d3,84f23420,3eaf2139,9e2f51ff,c02fda84,570af857,e6d51377,bd837e7d), -S(57f7a357,4787394a,d3577667,99126aac,593d86f,58801919,b1f8ad06,d92f97ad,edcedd28,23618851,ee897866,44846a08,5235a60f,d0e84dc8,7ac22ef8,21cc9bfe), -S(38da2e5a,f6018763,89c3b2de,1101c202,390048ab,5e976c5b,b1d0626e,27b5e684,ad71092d,e3c12d55,496c5fed,739a8007,998bf851,8dcf7937,1e1e5d00,cf05286d), -S(129449ae,79439127,7e336d44,34b40d7f,6e649931,feb5be64,b2e59678,1a9eccb6,b7c99b67,a2e523ed,9b52110f,e5104056,c6410ed7,1c91382,c4e5676a,3f0d568), -S(34d6ee18,c82e63ea,6a795055,4558874,6b93d52b,295b52f4,239cd98d,5250a099,d8a9bccd,2d8e6f2,54c25353,996bccb5,dc2ebc48,ae5e6f55,eb015ace,e111fd9c), -S(d202f4c9,c114ad97,963830d8,1d15018f,ea9fbd1a,37b8b818,3a504b89,5925ff3d,f250110,1abb223e,c3293e06,3dc5d2b9,20b5d0c,ac28ef72,3c3ced74,6ec25def), -S(753d539c,82d24f0f,64fb7e90,fb9553bd,90033df,770d7fb9,aa6255d5,f598f611,340d2ed5,7f4a7d9a,d0f94be0,d7c80fa8,c3d42eac,5536382f,76568caf,ccc86226), -S(a440e28e,e1bb9c91,c03b0664,ffa79f2f,c645433b,59ea44d1,a88c73c6,1536f480,96387729,9824b3a4,d28f1a2,7f8a6f78,60407412,2d06b028,78a31c79,85354247), -S(aa9a9ae3,3ee7de0d,5a1785c1,75bfce5a,2d353344,3c32c5f8,94f7248a,1726a0fe,9063cb03,350e55fb,dec53691,4d1dd16f,34d3631,f7d4a56a,f2c6601e,1eba9482), -S(61b60b17,1d406619,e612c5f0,eeeeee96,a7b02b6b,13333f29,3a67e9bb,996f4dd9,e5093ce6,f9eb8b4,4cc2b835,404ac312,2c62228c,b3f0780c,3d995ffb,f92d1734), -S(7fc18068,b529b15c,86180482,b33b7b7c,12b6cd49,79f46168,58cb6084,c92a8443,49aa8a81,a8d66fe4,b4993097,da735768,a2a64f4d,21993b5f,e6e45f25,7632d775), -S(8ae08ac7,6d8ab6c2,a0eac25a,8bfdd54a,1c383b06,84d99005,5f1cc3fc,ea2ae26c,1b463b39,549f3095,14e22e18,e51c4af6,c3e4f5da,9050b9e7,e1556c2d,9b47c2e1), -S(de680d6b,9e75f2cb,4482e3c6,37b03f25,1873aa93,d4af9641,a3e0efff,d10d10e1,22fde416,c2cbfe77,e27fe7d1,190896e6,64da63c1,f89793d7,1478697d,e5cd9108), -S(6522ca17,8d6fffe3,34a8dc3e,83a7c9e8,566d4d61,aa0de5aa,5623982d,4459f553,cf0033ba,988ca9f4,7afdcff2,abb9a069,62f1622c,2b3744d0,cf7533c7,9e5fd425), -S(bec2be0,2fdd1e26,699cedb6,92c46054,57317b30,3e2ddc2e,bf8c9b12,a55a52e1,f03d1203,e013cac6,5b4fcba9,6ff28834,b6dc8539,d38c8053,4d59b5e3,ec3b45e1), -S(71e3f913,cfda601b,1d9c0d29,82dde7c7,970123a7,a2c9c25c,548995fb,6d28d488,6b30b817,2785c0ee,82eeb3ba,1f3b6f64,95b73a61,990e8532,aec482e,19992f85), -S(901223af,65764264,da7fee9d,fca46c4a,d7ce95f5,1c3d3b59,554853f9,20de36b4,c15ac0c1,69b718c7,9bc06ba8,6bb180e9,f4a45c4,1b09a761,67139e11,c3cf220f), -S(bf0ca457,8cc9c676,e6ccce5d,dd9139ed,ef3e2a92,6d4cb5e1,34db0a96,302ea422,b067b031,4a8cd0d3,427d6e18,6c12d0b7,3eed37a2,b7f197c,e2359dd4,6854456a), -S(8e4ad808,c2fec2de,17595149,4cd176dc,1197c18b,b6d31f18,41501c96,fb96293b,71b0086f,f41aa674,e21802fe,f44ada5d,99b5d7e5,47c60b1a,11c4cbbf,42465e6d), -S(7c682ec,732238ef,d9226ba7,9e3d0a21,d3a23d34,66597af2,4db38989,d06464dd,6a6e89a2,fcc6b55,c9d0562f,2c58819d,b7b59177,fa16eb5b,4f6995bb,64546301), -S(36f96e68,ae6603d3,4da2736e,f76ec4db,645c26c5,cdac2721,29527ac1,9378ae2b,6aee55fd,87741026,362d9c02,1adaf833,1a85623f,d97981d4,d0ef82d0,87e83ed2), -S(3cee56be,a461cbca,53cec614,3453442a,8b7f314a,5a79e004,6ccf2363,7b867ed2,b43ae401,ecd4dd1e,4741fc78,cf1853c2,97352cce,853c50cc,fa4c9699,7b063228), -S(6ebd223,be2b4d8e,6fd3a2e8,cc6d899,9b8f571a,7f5e9905,f45d71b7,7654ba84,9cbcba8,3fce430f,41073a92,a90380e7,73faee19,b2c08150,949708d,f49d23b5), -S(112aada3,f4ae50ea,cfb050b6,52ccb99b,79524b9c,4d7821f4,d67b4fcf,b992e64f,4b4cc764,ecb5698b,328eb0e0,7a242e0e,b69821b2,38231446,964f1f01,b6c59877), -S(54e622ff,ef55ef5a,8bbb46e5,f7a98f9a,4cc577ce,ef87fcc6,40909be4,8b0ae6be,1442f6fb,a55ba6b5,7344b4d5,5555f71b,4e77c10d,442504b1,64f1d948,a38a14fc), -S(247497b8,1e23728,f7dc5d0b,8c450eda,fb6eb9da,7eb90d35,e5939440,8705301f,9a5d529e,f38de912,f5c7f58,56e02285,32c6a6de,702244a8,6bc1990d,6144b46e), -S(720cdf82,bf44e211,b71d6fe7,52ed34b1,c9d7f88e,5c4042aa,b3826812,b45df62a,2a05003e,1b36d9f0,b76e34e7,66feacc6,2ed49573,a3f6414b,f631f32a,9d79817), -S(7b9a28c9,8f5260ba,18db1c61,5656d2ba,3de591b8,90a9cee8,96f60bac,54cba095,8a162ddc,95ca8565,d00530ad,d8d338b4,bd62760e,4f185963,60de82cc,9b543e57), -S(cef8910e,534f2fe1,9228ec86,b903a1fb,e6056a5d,2cf7ddb7,f2dadb23,6e2952e2,deda80a0,305e27b8,e9cec5c3,81015929,202fbbcd,3e84340d,3172e0ed,70666b1e), -S(1203af6d,116f7b3e,4926c3c1,f9002e20,196ab0e0,1c6b2b5f,adb17142,8e2f6ffb,6e7fc524,23e6c744,52d2b6cb,4d659fa6,6e541df5,785cc666,a4779429,7ea3a842), -S(c265725b,f9c43ae8,8ea01292,9d0e3edd,e9bc761c,54316ec3,47adb51a,98eb4590,362a5d1c,9f0ce3b8,9a6c83ac,b30a7e00,ffa5bf70,be1490e3,f1e643ac,3ac65019), -S(5044578f,e3d7c3c5,a70a6a1e,dc6686ef,da027c91,a9bcb7d8,5a14cbff,6e7eb943,18d64743,78e2842,b6704760,d8c68b0f,5caf61d0,37fa4b20,98046c88,8a3e84bc), -S(3d278c7f,c4644246,1b324f0a,f666803e,5e052d5a,80dc0755,9d067d1d,e32acc63,a242e218,d1449f64,20417ab2,41406756,e94d3aa9,f4ea1c40,192015e7,3f3b74f6), -S(e89ac46a,382f58ed,982973b7,6569c95,c23c7ca4,4c893317,ce3c3a0d,934b4c93,f8db1b16,6bca5162,23b6d397,3a7d429,9a99a1f5,1c9e82d9,96e00103,11a9c696), -S(d46d9244,52ed46e3,5868ca93,35c9f14f,158165af,f6a16d0c,f31e90dc,569b8acd,c26880db,bd8c2308,5b2995e5,7a40773d,e692799d,b8680a29,d01fc51d,d92bad21), -S(52b62ffb,6989bfdb,ea671d22,f782c692,aa99daf,f6afb854,a260f6fa,3a5dccd3,75d15e76,a21b03e4,7adf5c27,3953584c,9067450c,343f026f,e0dea126,6d6a4a52), -S(b3db1f2f,9c3e602d,5c32a28e,85079423,3759c3bc,3ebaef4d,485f1e00,817a5f30,cd336cbf,7cff0f29,211b9c6c,3b811eb,1d49dd23,c03d36b1,54b43c71,91dc62db)}, -{S(ae5fb021,e9256cc0,6236d667,b76b9bdf,304a4683,d2916ffe,489cf019,6b4c5683,e768366b,5c8d36b6,18e45550,d57493e2,41fed17d,12627e37,b29b4b74,d3603696), -S(d6f735e7,93f6162d,d540a255,76449ae8,edd46e31,d8f641a6,dda76200,c0d33e4b,7f8721f9,23fecd81,b153eb3c,eb2cc58c,c21f3cce,56a1d750,7f99934c,4ade221c), -S(84254df5,b28af43e,d4aed5f7,4e104d1f,2fb371c0,a2adc7f4,21415ce1,ee836c51,b07204a9,260540d4,8e29fc23,e254f378,a49a2cfe,fa21efa9,a2657342,3be3ffa5), -S(7c329ae8,269aaeee,fc01a25c,d2e9a15e,794c589f,b3ad0c76,d51c8efe,4fed9c87,a31b2006,b54e5b13,1e5f4997,f1eaa866,77aa3073,6f6b808f,249522f6,99373dee), -S(922c5ab9,b3938aec,d8a89bde,ff2a803f,fa6d77bc,d1301d76,3f8aee6f,608c8976,efaad685,6ead7c1d,adeb3f45,988af445,ed6701de,1e063a53,6d8b76c7,64be0ee7), -S(3b3b6d42,b662a8e7,44e218b5,4e8c7ae8,842600d4,dc8ff55b,701ae392,512d2d88,3319f63e,5e72d98e,21b23c40,fba11751,cba6756a,68dbd747,f5ebf054,34f8ea52), -S(7031413,ee20f2a3,c716ba79,39882dd3,74dcd7b3,c4fac819,10b856bf,72edb957,20fdd866,33755d03,5ec21df0,39bd4c33,e4ab4bc3,4adc6e7e,f95c6afb,980daf70), -S(b924bf9c,93d735fa,24f61239,83aa798d,e6745852,cb1202d4,db74ded6,a9ca4d67,c8800807,c30e88ee,6351e5a6,547705b8,e29f87cc,4d7166ea,c719d0e3,3f156cac), -S(d43f2e6d,a0f105eb,e6fa058c,c3e98099,3d878f4c,40791188,80a8c5dd,a775f798,3c681084,a8a466e5,34fe34f0,f533f6bc,7aba722e,37af767d,30519272,4465404), -S(d6fa6f22,5617d2b0,6b35249a,eebdb016,517b7ce8,f2f52051,385ecd1,e987785b,1fb064ba,ee45eb8,b7ee88e5,963e290d,6bca04f5,1edd9623,a94476d9,83d60fba), -S(8584a76f,1b641da2,e3645a14,b9b0beb9,9e43f4d8,40ee16bb,793aaaca,c212f1f2,9d3de317,5cdc70f1,35aa3b81,e8a31154,15a65855,510a1bc7,d980715e,5af76d1e), -S(67f50f74,1508598a,c32fa77,8e7b2ee0,3b24b63d,7a48c12c,5bebfb4f,8af63e2f,f35b00cc,c14cdc2d,a088d8eb,b2b39878,5fa46ed,4ce966c7,8acac1d0,a59430b6), -S(34bac85f,a0bae27,e443336f,c6e6df4d,252e5586,f0dd898a,afdec4c8,8a57239b,756a85d9,71dc0296,8f7124e2,5edd877f,d8554377,4c8dc772,ef22f698,5d741a7a), -S(1d2bf603,120749c8,c802441d,b3021c02,65364a0f,6a162d41,f4dfb347,a425a8f9,4cc35601,ac8bb504,13e3a3ed,9d67a55a,fc5cfb51,d3caa73e,73300b65,9503f351), -S(26b9ca6a,aa72fa3b,68c0c995,52636afb,d0f6e88,e540dfa7,a5955952,af5204ee,b2d6cf87,1e017775,152ec88e,155e7ff2,5c04a631,92df5074,2a5e546b,6e15cd89), -S(7dadd65e,6c658083,e82369a,bfb1745a,fcc94247,54db92f6,3fd00d25,23172d06,655ca6bf,232d8f85,e5d0ed6d,5b4040f3,c34e9589,6be0df98,2c65ac06,ff50d51f), -S(98667128,2950f125,a399c076,d9eff5e3,ab8eb85f,c5a496a8,ae8c740f,cd4853e1,949246a6,b2b17c2f,2ef08455,590d4076,a26c508,6a4043f4,18f2d2d7,2dc42511), -S(efa70ff2,4042d4cc,5215b450,703838fb,d274bec,204df700,72a014b8,33d3bdb3,62fc11bb,bb1a6d7a,b585f05,c5da598a,f59b2148,f31d293f,17280652,c8743380), -S(97ea8025,12bb4141,7a2ba994,8456a498,f66fffb1,69883e3c,970d4c13,834c9f61,87cc181f,6a83fc47,c1ba6e74,38104fe3,1627ca80,6b4efdb3,329c62aa,d5cf9913), -S(1353da1,849ae275,84e55047,e8662ff,2a2361ea,fff847bf,17dd5c8d,52b46942,a380a7c5,2ddb6241,cf7cd12,87cc89d6,96a7b3a9,5a198785,76bc4039,b9a913ba), -S(33329e8f,50855274,5598448a,d07e36d8,85b9eb34,8f67b10b,a8b7d04b,b71edc4,be08cacf,ad6763bf,92864ae,3afebab1,a6b19992,b1f0d9a9,436f42ee,b96c6c90), -S(863827a2,46421930,553387d9,46fc1b4a,7d40549d,dd470f6c,75569887,27fc2747,3fd2c6d0,a9d5a056,95c25ac7,8f7eadca,465176d4,fee49512,72a93d33,5fe7324b), -S(8f2c64ba,637543ac,67a7706f,69ec59da,9528be29,7b1be5e7,ffb4fec0,e16d25af,7cb53924,c47605d0,239add6d,287030e,9e8f33ab,4a36aa56,54f1a729,e3dadca9), -S(8ce26953,8fe8a9dc,ded83d07,717e96a5,c95eeeec,e6af2b92,14ae0811,b315909b,9277f1ea,33861808,36545b6a,f467c0f2,dd96ac04,28ea8a0e,e32db52e,de60207e), -S(44274f51,cab44f1e,3e527e95,e92156fd,1cd2e363,332876d2,d3ce75a8,e96c034d,fc4edd64,5e2fa7fa,3e0a8a60,36af7a5b,80424f09,7203774e,489ad68a,5a0c3b3d), -S(ac9170a2,a320f19e,211c2cae,b827e87,d065a9e3,15e11584,d074c328,b38dff24,5afeef29,a8a03e49,45009c9d,e41d354f,69d8d974,ff0f6b08,d0bdad83,5bb8fb5d), -S(eb21ae48,cc5aad77,7202e145,e7178bac,af1899c4,de96aee6,ef2560e1,a13e898a,5726d1a9,1c897a8,c6594022,e139d2e3,e23047f4,99d107fc,9f3ca9f6,aee95d9b), -S(b6b842c5,bb0ec79c,36c0831c,b87f8eb4,8234618,f5d1b888,678d751d,be61c7de,9dc3deb1,6eee7b4,4f6d29c4,ed170cce,2fc78db1,a5485dd7,85fa6de1,8b9d1838), -S(281f770b,e956f478,26529137,e836d00c,5a5b55c7,4158ff32,79b96ef,7b6f17c7,33e0dd6f,e4610a87,c703f4f1,9a7f2b14,3756ee8f,e3e6fbf1,a36f1d28,88a2a836), -S(3520dd8a,8df2555f,2a404ed2,d2766080,302a38ee,14cad37e,a7c575cc,18334cd8,36000e77,7a789b8b,e3de5ef9,71b345f3,3e08f491,3171df2e,ea41e07a,cddbeb92), -S(4307f2c6,db337087,5e69307f,73fc13bd,eb70f5ba,8651e507,2b58ba8a,5945c07a,198ad388,9d9c5b9d,2e050e69,b8b0ab53,8641f4aa,98204215,5262143f,2e513bbf), -S(3f69e90e,4be15f1b,7a3e0518,d2173143,8fa2d0d5,31617b6b,390cb3bb,6dd3e130,2c2eecb0,fed8c40,a0e158ed,44c94f07,61c5c288,d525f12a,ad927235,cda29dfd), -S(487638fe,525ec3f,fd34fd11,6ea6629d,4c15cf03,fb581c18,2c14e0a5,526e9b99,464c0ab4,eac365db,ba6aa562,2dfab02b,93ddb339,d790f875,f8e98a6b,6dc1677b), -S(9fba06bb,20600712,45795836,ba95a91a,af40c61f,c9c83511,8bc97ea2,1428981a,97930e0b,e2b4fe40,8bb37aaa,afe5b66d,6b8c140a,d4a0b0db,a39abce6,f35bb8bd), -S(fe0b19f0,dd103ec7,cbd3d605,dd1e6230,dd4dfad1,b4dfc2e0,23b8463d,8710a27d,167d8e8b,4595516,1daf03be,99d1dec,383d4c47,247c68c3,8927515b,dd388621), -S(a935d63b,16467a8f,41657e49,2c9f7fb3,c5da37f2,3191955b,7e73882,5bb3d256,7fbcb19,2261cd98,ff7b5087,567c1dc3,635b544c,d9f43d02,8d11a94b,94812623), -S(ad28e247,18f124ca,b1377df9,f3f78fbc,1fd4f8f7,74925d02,2f11f56b,c08bb8f2,e3205a6c,5add373d,4893fd23,84fab0ca,525f87ee,ea5b687a,b1b60550,f090bc1), -S(9fd9c788,2172b1d5,9f2c57b5,746506ea,9483fcf1,5cf51ecc,70fa4a40,841f7e9c,900279b8,566e555a,ad3e1318,dc890ad2,6a0c9e4f,36ee4e01,d3a6b046,7b66f11e), -S(85ab8716,a347ffa4,fa4a9807,6a7a1e4d,8f887dcb,7b758212,5831cee,5fd755cb,ecb83ee,e3ecf915,43460350,39e2097b,ac9f0000,2855ff37,ddbbf6f8,6d2f885), -S(da34dea6,49f6db93,c4edb612,c7872054,d78b9e13,4614502c,e2db2c3f,1445d2a6,d34bd4f3,d65a7b20,79510648,3b41c2ea,5ecab70,5fe961a8,a3844e0e,95b5640), -S(1faf535e,2136c3f0,e5026f42,15ee8d0e,d088dbb9,81ecd469,b5311a1d,c235462e,ac1e6f90,a482e42,c6c4cdf2,d8c33dab,b307c39d,c3745cfa,db24810,94e826c0), -S(d1924ae7,ff945ae6,5c1b41fb,398c257b,cea8bcd1,fe6c6e8f,2bf4118b,c6bc9fbd,33d6d54d,237fdfdc,4536abf4,1bfe6681,173a3b42,5652aa1a,9f605f2,8c2cf834), -S(5e30dd95,dc01b76d,2eb1876a,4d0079e7,4473f4d6,acf88f,4b1a7ade,81ab4a44,5edefb5,959759da,4c39c9b2,8ed669ca,7e96b937,394f8cf9,109d99f2,8ae94e9e), -S(1d1b3ebe,aaf21685,c590efc8,5def9bb8,4b5a6e74,de93b34b,b9b169af,3d1863b6,9c5230b7,c41d8d3b,9512a817,34fd101,9d98856e,b916fc79,2806e377,2a75fc93), -S(b1f84efd,e53a7f4d,4cb66989,876f9521,9922fb16,65dad292,a342ef77,f151a7e,624ba3ee,f1bfd30c,81e905f6,fc9a17a1,1c0cc014,acd9ef0,25620277,3e95e849), -S(88857890,30e21565,c166d64,4b14a4ba,9832f99c,764f34dc,ee2aa79f,60f3b4ba,bddced24,35da5a76,79c207b0,e5713ded,b73cb088,997e2ecd,c9cbfc43,f38bd096), -S(f4b8fdea,a8a4a630,2d59c0a0,b34c2998,a7a72c6e,911cf7be,7adfb44,63d1a213,f78d9aba,e80329e9,f02c4f9e,d1bc524,35114a63,884709a4,99925c8c,d06963f7), -S(7f85e0f3,6a03b7c7,47b9cf89,55aff917,df60dd64,f35e14b0,4e9ba8c1,d647393e,f3b23489,f86e10d9,f9f542f7,49df5ae6,d50f5613,481564f4,b8842869,6e40b72b), -S(b5d3138c,6fee7f5d,68599558,b7f4dad9,948d47af,98abb02e,369fff57,bcb9deda,e0d247f5,2e097751,fd33df86,627cc172,5a26eac5,4a6782e7,7c42cda3,b9262d58), -S(7b13216d,bbb83d60,20b9d45e,5b202538,ff22a2e0,e0358147,22344248,d352f2dd,2eff7c95,77819e9c,aa0a762c,ce70fe9c,f0732917,46a2c8,250b0a86,77563e9c), -S(3a79df59,b1f3ced5,70628491,9aafb365,59c757af,efaddcf2,164dd3f0,73e0b85e,5afd0066,b083d36b,da510974,75d07f24,28ec9d25,5ccf79bf,49e059d,cb637a1e), -S(318610b6,9f525ece,4c7b4c28,14cd0fff,d4729929,56872cbb,3ca350b3,6c0d5aae,8dff9296,62ccc6a3,af202f73,4825ccea,362d64eb,30fc187c,f8db26fb,6ab1ff8b), -S(e411c5bd,ea470bea,188e8e26,f7207bca,4f92c793,ba34c1d2,d1a0ed70,f441d836,d4d40b75,f46aef9a,b17afc53,efdee46b,50217b2c,93058fed,838fb17b,4fc33be1), -S(f363388d,497316bd,bc962af,270c591f,6d5868c9,69a08003,1ca021b2,f218792c,6d29bca1,5716584a,8f13a69d,498ffb53,f37d38ec,d7703e92,d55f2dd7,14b860a), -S(79852af7,34689490,a5e7be06,33f973a4,5f1870c7,aa5912c8,8b121a6,3a6f7aec,ce1bfac3,f472d348,c5186160,e167d840,426a4be3,7a58f56d,ed651eaa,15d14053), -S(353357d8,c93b2dc3,3e091ea4,fdfc99dd,3d235074,1eefd250,70215e03,7ee9f450,85c07a65,6bc1389d,9065abe6,a896d4b7,953aff1d,f918827,dd0b57eb,918e8297), -S(d64e1ec,704e979b,5cd19df,3ea4845d,8161f348,eb9afe89,de1c22ee,6fff6236,6772ac7b,c2224a28,dfad9639,3b9fd942,6f59d6bf,7e4a94d5,4003d24f,6b1cb2f6), -S(4afe8fb,9fff7ac5,3a0a0689,24b5961b,4056f190,27fac3d9,dd493338,180e41ea,efb6bb06,ea3ed1ee,c5e7603b,2cbe1d11,e32a1602,19079b9c,a04f997,8ed42f29), -S(bb42b5e7,a047ca7b,eaa52d7,48c763a,3ccb8ca,38f252db,f131d123,90cefe5c,65f8231e,f9bb6ac,4adcd01e,87b99dc3,b2dd30dc,4163d84,8dc0faab,ae035b87), -S(cc6431cc,e7e4ad45,a0125326,6a8114e8,ac9c6896,56cf6e75,ae8cc4dd,cd810a29,498de8d3,f8194a03,ee8c5db,d1d39826,6e09563f,9d5253c2,a6f5ddbf,cd41dcda), -S(624b81c0,b8f558b6,6b19afbf,76b1b7c2,9ed964a1,b53b6ac,6e58acf3,4c6e4d4c,d8429386,43d28c7f,f0e79a55,801a989b,2c923c36,d84638af,686cc637,2cc3095a), -S(53ad6cd8,b0bd0b5d,2742bd76,65c0d0dc,25234c21,a68fc9fd,da85b2d4,a9efb4d9,d886b54c,9dc40ae,40f57f4d,112da945,46c44b26,8ab08440,d027740,8264d5a), -S(ed7a10a6,9a2a65b7,7f3bfbcf,2d8b2f5,57ce675,5334f13d,615f85b4,7bbaacc4,d9021ae8,e1a0cf99,ba539b6f,52dfa141,ac6d2d48,ff71c1f0,c2cdfba6,845750e6), -S(b07022dc,5d250d6c,1464a03e,538b53f6,72470792,da6bb28a,9eb97664,a9797d9d,6e1dc0e9,2b112d0c,520e3fa3,7e90f7b6,36959a43,15a76833,ad935237,6ce4a96e), -S(f0cc2567,eab35314,d0aa253,681d6319,cb016a81,c6e683b9,51e151a7,98b3ef22,cad6711c,1ae440a4,4f547afe,693d199e,4be0f8d0,6a13e2cd,4127e9fc,c99da815), -S(1a71731f,232ff7a,670c81a5,30b9868f,eb59fde4,6c77a264,7357b84e,51917b2b,1560cb00,13a3bae,23983028,4be74589,ece8016d,8c6a23d2,9b52faa8,e907eebe), -S(b8e1e4c7,461335f9,536fec82,30136f2c,a348baae,bb3a6cda,fc8a3a9,bcf72df4,fe85e36,e956074a,26f56f8e,ca1f4fe2,81b0a682,508ca1c4,d6c3249e,21f48cf4), -S(63eeb2ee,ee187fe0,b80d0c2f,ba2222d,1a763aa4,776b2679,b14bd541,f566bf8,56ead5ac,84ae0964,c728b87c,979557b9,c44c13c7,dfa3b31d,86a7e31,5a920c99), -S(862e7b7f,9bf1cc99,8f0a3cc6,3d873eab,228b3977,8bf3aaba,57ab16f7,32ba9d0c,2d69026e,f29ac9a4,151d9f98,1c4248e3,2c3e4789,72c27811,68fa2c4f,5fce4a28), -S(e0588c62,3f65c421,e12cc7bb,d5842e84,bf46c00b,3ea3c38,9ef98056,6cd1deea,98dc9056,d105607f,569aa79b,6d6b6cd6,1b42f749,4333e255,35c220e3,15f9d939), -S(9a6f0406,7e3743e8,78ba2f1a,4b4aa09e,bb8b5bf5,7058128f,bb0a573b,1c504689,6ad673a6,61c9dc87,15cf81f9,3815b32d,6c47879c,c831c549,5a17749c,80003838), -S(6f4bcc03,ed655fbc,be383009,5fa5a1d3,3d4be203,9380ada7,d53e1ba,248ff68f,91e8f700,44126d04,ac2cb1ca,7650a287,e77b2a9,8cc22e9a,b36b4906,5d03b8c5), -S(66b32a92,23945f66,ba2f7934,43f5e31c,8d0bb858,3fdf9db,6d1861e1,fba5e0ec,74d81838,3c0aa55a,16242a41,3ed5f9e7,6569d041,e668d82d,ff90f6b2,aaa9b9ca), -S(c1acd55e,cc4b6743,3aeb6a4a,6a920dc4,626a4219,d70cec1a,1fa4ad6,87696330,6b14fa02,11b63493,ccaa9c6f,e2c288b5,55a4b851,d6a20682,d7aa7039,6c21b156), -S(2bb86341,deda561c,99dd59b2,dd2392e1,4a5cfbb8,9fd49d9b,a35634dc,3274bc61,3662d431,b4403678,a9d59758,dbb413b4,6b48bccb,f3fc9fba,801fe7fa,8d9da0f7), -S(b94189e1,9fa60eac,7b1eaf49,be80b0f5,511693cb,a0efd3e9,70cc0036,eeaf851b,26ee1cfb,ce3445c3,c217bc5f,5ed12d1c,59367ac1,80b65b91,a52d1d8f,c091c8f5), -S(8cda78cc,fba3d6e7,869ad44d,bb5447cd,718be851,df976c1b,ec65be9d,335ff879,cf2cf6e0,94f20682,505bfc56,8f537acc,b2289003,c87c5cc4,23cfc9a5,f61acf02), -S(eb447748,ca42bb71,71c6183e,6ba0e9,a61360f5,b9b686c9,246295ce,c8dae15e,586d8bb1,4dd7277e,5aefa348,55af5e89,55e56526,df89ba4b,575911e7,59f6cd0d), -S(73beb803,c18a68a3,ee1c945f,6031c646,b08c688,6d5b4999,5641181b,c6ab7b0,5fecd8dd,82e3f515,d7a23cab,26949aee,afb1c1bd,1cdc6853,90f3d081,ffd51157), -S(4c3f9e89,e5cc661a,ed4ac704,f37cac28,42afcf38,2c4d51dc,fcc21761,d87311bf,28547fa6,8c661209,67ba52f1,3a13ce38,33ec41,402cb743,49d82e38,2973f615), -S(3e19b5bc,93c422f0,42a2fccd,1595e7d0,d89a2655,fce95a02,56802460,a3ba5b11,edca8ed3,2758daeb,f2649ad8,80114b84,654c3b72,d7ada177,2b84ea75,ea7079ed), -S(7f4b2fb2,6934a60f,50fb114e,b382e0c3,a432f213,a57124f,6cc23e84,27cfe1fe,d0ac243d,9fa8daa2,90efc550,af03e5c2,59d39ca,de0e8779,d68b5880,c74fc874), -S(daf46145,a53b5aa5,ff26bd5f,e0b1c880,835e04ae,9dc51caa,ab37f168,6e57db0d,6203be50,dc56e59f,adee0012,d1c8f24e,afb8caba,88dbc814,f6c127f9,efbf956c), -S(2b339287,f9760403,6bf7d2a,5dec5ac0,6ed9d23d,c2557b4,f853ecf7,70131ad1,6cfe12b6,fbfad32e,b7b100fb,7abcb7e8,cd990d72,d5e7d10,97ad8a45,bf056c1f), -S(2b42fe3d,6a44b1d6,8077ffd8,d3eb700,96afb615,f70af414,48ba4e88,32791e4f,1a8db3b8,50293439,9d31a512,9272096f,6e913775,ae89656f,da79c425,90ec01aa), -S(36c5c074,76246100,bea82171,713bdf41,3d8ef2b9,5ed50fe0,390a93f7,7756614a,53842c42,37723b9d,24cb4666,9f587f68,fb14601b,f4d7b05f,24f9533,2b6d41ae), -S(6c82d0ad,ccee854e,b8ccf077,4917a92a,4c8f4f1d,da784312,2f317ebf,8e8662bf,be05113c,2fba79a4,14442305,f8773526,3b909e30,95a51853,4f76a666,7be28f3c), -S(5019f59b,48e6cd5b,bb394dcb,3b8798fa,bf13bde6,20916ea3,ee9fb32a,53eb2503,4b2e655e,9a09615,7d64ddba,49d9b337,a84b6b1a,707d8896,93211e51,6829a07), -S(301d16ee,7f980c8f,98056bb0,6ac49906,f2f5f404,f36f4f7a,e1b93d47,6e6640b8,d73660bb,d9bbb41b,8f0cc43d,d203ca79,2f07d10a,a60904e4,8d2e3905,e207ecbd), -S(23078318,53146a67,7e03cade,15e9cb41,d3f516c9,4762abc,8a6d7722,1f5557ba,bd7df729,10f0a43b,74a27c80,5bf3dad4,7751af23,9810d9aa,3f4ebbb5,773732b0), -S(2b91a10c,bc666ed3,e7449d2,bda7793c,d6ddc1e0,59c90e19,b85b80f0,50e2a21f,a9b18e39,5154dce9,d6da961d,dea00c40,c58a9cbb,20d9829e,ed4f246d,e7a4af15), -S(73f25213,23e97715,c726b678,cd8374e2,fa7fa140,ec0f9de4,ca25ca02,277bbb65,8b1ec6ee,85ae17e8,da8f6984,c6d6f2df,fa7d2fd9,440904cb,449c227f,b3bd13f0), -S(b8971801,ac6925f,374a5901,2b19e8f9,f2279479,70d070d2,4e097e04,35b4d196,7329d3f0,23a5d418,68e576f0,39b7ed39,8e0fe209,25f098d9,ffa1c45c,8c805fd4), -S(15a6be8,52035719,da9d99e7,9971035d,bcbcf637,d73a37b0,ed8a0113,7500f8f0,3512f517,b5d07551,2f1e91b5,79ceb942,2b807bd2,6be8c336,c124057c,8f204957), -S(6a814e7,c5267f8,182b46aa,a657ccd7,508a468a,dbd9a8a8,b7ce315,2fc672a5,87013b76,ac1d422c,41c8413e,884feb4,bcb29c4e,4639f65b,1962eec3,25ca0d1b), -S(d5ac8a12,2c4e2e37,4145aa10,d5309658,d5d8dff5,7a246d8f,59a4ffd6,43a48d23,683710d6,6ee30017,a07ad2f9,8c12110d,f794c8b4,d92a89c5,6b509470,ddc737cc), -S(9b2c7eef,f744c46b,6e080539,6abb4dfd,6309458,d65185dd,d72a3c2e,ed301b,866a08de,d9d8598,c90fe692,f195d40e,e7a294bd,13f113be,b32323b9,edb35354), -S(a1d0ca41,dd26772b,303085ea,6514331c,57dbac2d,f7129d3c,94a14b56,64dbd1b1,828b9dae,dba3a32c,e72dce2e,e57cba96,7b3a8001,dcf4694f,4e936cfb,2d195c9a), -S(d775ef1e,c3e03ea0,be8852d5,50d30e2,651f2b6c,1b88cce5,8726d66f,e0f73334,2abd706e,acb8e68b,3a3b096b,4517912c,61fffc4f,8bd6c0af,2ba7affe,f3446c8a), -S(6c4b9a00,8c0cd988,e518536e,6dba0027,60e43d4f,e26e7a00,632db70b,e7701742,79d51a,905d04f5,75067ed4,8b22de92,3c25c98a,f14d2955,dce9021b,9aa9950f), -S(39af331,36455357,e7b4a48e,d74e5b0e,182363c9,aac8ff12,545e7cd4,7af66101,e66eec81,736f055f,7325521f,e349d4e4,3faabfb9,c73f7bf8,7c9a791b,1635f16a), -S(ecd4f3e5,36ec00aa,8b4dcd7a,997cb470,6fc83e55,8635c241,5c03807d,16f6916,479006dc,de668a08,fc4d3bb4,628c8b23,6deaad8e,9f75e99a,93e464db,4bd96a8), -S(d26fe1cf,b13ba752,d76d09d0,1ea6204c,8e90baa3,79ece72b,80e6f7a9,282348b5,db4d5f6b,c63ebd68,44735571,a0f43d81,df9d5661,471a1050,11cf4801,b182d80a), -S(6d00c0ca,7c94bbfb,dcc30c47,1f5622e1,afa13179,8b0fef54,3adb02cb,296faab3,7705f197,bca702e1,3ae1eb4b,ff6d8ad2,80c43085,ae5bc7f7,12fa75a7,aa65e6e4), -S(5a77b624,b3949a1b,16587011,cf9b251f,90428c1b,6f5a371d,f2499c28,92c94982,928036ba,b113a731,65760dc5,70562398,f23d1a53,126ded37,6370178d,37ea3db1), -S(e92f3c46,b854d695,455035b4,fae2d3ff,83ad6f62,5fe9e8f9,fa9f3266,898d063f,9ddd806c,683cdd2b,430677fe,89a7a603,75fa8923,bf72c196,cd0ead02,e1d9fc8f), -S(c9d99f0,47ecc29b,5892fe3a,9a285f23,eb7ea82c,e7ffbe2,2f0596df,14c2f8ef,64c0ead2,269f8833,a7a16d8e,d0c3acc1,56309197,9685467c,f4b47420,1b6e74c8), -S(85359be0,9d8cdce,de34edea,1ae82ecb,51af02ac,8294ac59,868b7972,c114398c,6e6e163,3b8101cd,5d3b4264,26a05f69,3aac26ee,c5da1d7e,75944fcf,710b15ff), -S(a1fb58fd,d1283e1f,86026dfa,4e29ff12,da8d9c7f,d6e75e9,6fb31706,8c9f34ec,9429b8af,a89a0031,ead59b83,a9796219,aa8ecbd0,a7875b79,c9fbdddb,85f1a3bd), -S(8ac4d467,6390b97d,488f7943,5e68c47b,eb7c6cda,f920cfc9,dcd6faa9,593e1185,5cde9d0f,3fd47f0a,65b9d7ad,c415872b,f860e1c4,74471b6,c57d464b,9395ead9), -S(1e1cdc12,96067717,2b3776e1,d61a872d,a65c6a99,33596409,99ac16b8,f836237c,f9fae2b3,49d8e6ca,57911ffa,ba411fc0,f80f45c3,a8ff0bd,ac0d6dfd,1b4fe271), -S(b96841f0,b49538fa,7d14c6c0,2cf08242,d6d21ea7,333ad720,9a0f6156,67f6feb2,fef3827,23554c52,6fc37f41,7baed824,17f163b6,e855af0,51e81cde,bf8a32dd), -S(b42499ab,a8a83591,3be09ac,504c6c47,3214f31e,fbab7573,67936d9e,216fd0f6,a2f6a202,e1a97f1c,cf083e26,c84ee6d,7d57cee2,266246b3,c4b6b56c,5f4d613b), -S(418c2e28,7875dd00,6c5760a1,1c72ec31,f267677,7d27a4f3,fc03cfd6,803d85dd,5e727ed1,a2180e35,4bcfed5b,65eb44d4,f045d3d9,ede9fb67,beba53d3,cf8c9ef7), -S(1aa9e157,cd261a2d,c4a00e7b,d119968f,5bff1084,4cb9c835,62b7218a,3d484fe3,d13b9646,a6f1edb3,777a526f,a48353b4,eb06031e,1a2327cc,99be4b06,836a3bb8), -S(2e865670,19aaaf33,c7833174,333e3f9a,bdd63c7e,d25f0af7,49f2d7f7,a69bf7e7,69da2079,a30f2791,8966aae3,b3b9f8e5,fc150b3e,e71616c7,ca845174,36ee5c24), -S(ef7a8374,943df2f7,5ed67507,df3c1a2f,abe2042f,d66e97f9,4f6e3490,1dba9ce2,6b93d053,481b8395,c77dc3a0,6abb3125,7951ad9d,d9d76190,1e218bee,8bb6b4c7), -S(2d097904,179b400c,165cd596,f57919d2,2d7b0535,8018d528,aad0d3,23583478,9f9a0ecd,6976d6a1,6936816d,95283e18,3e94cfd8,9f384bc8,3573e695,35e15380), -S(35b46f8e,231424a2,314effda,3b610f4,5fcf33cb,799b5db1,6389b880,93ab66eb,5e97fbab,a0b89500,d9dd3e4,2cb68439,ec7eda2d,f1a5d6be,24186be3,212f8648), -S(eaa55e55,c4e410b7,2e599063,f4cc976e,754c43ab,a0df3bae,825a4563,fbd27711,13966980,3ba07091,faaa131,71437472,67a75d15,3f5611db,91d4f27a,80aa6975), -S(310c9ee9,ead99f8b,fe9c711,f93357a,e2639181,176d4a6e,4ac84cb2,2a52d6e8,300e5486,deb90657,dbe417cd,6aae423f,bfb00e5b,b3077fef,b6b8a166,10fbd172), -S(de1383d6,2eb93ae9,81f87d12,7811be58,fc373b38,893f0e7,6a417a82,95b27bef,f86aaacf,8704cab3,f0715f93,3eccc9e8,203396e0,636a55fb,ecf76440,7a2ecbd), -S(f5bfa7a0,28beeef3,1fbd817e,5ef6727d,5b81e76f,179fcae9,f271960a,51eb954f,ec3fc89b,ded5bac4,72d79d7b,19db43fa,ade10bb3,cc43d38c,f38efb3,f9ae9f66), -S(5e67e65,80b858fd,df24ecbe,f0f3100f,4378ffb0,7e382ff,f4761ce9,226d29e7,870a1da5,663f1be1,4cd642fa,d7eae191,d50fc6cc,1146882b,5b6eeec4,f1e80123), -S(68cf070b,60e1778d,7c9a2f66,b6abe3fe,23c2e090,f4c59618,a37eebb8,e7108ea,f09cd61,f52305c8,803a2346,65f76a14,49d2fc53,8a4122cf,8462ec5f,b64652bf), -S(427d23db,3ff49c5f,8e693ed8,d88a9ae6,339105cb,cbe2195b,13f39e46,172abe8e,25f4ab41,24ce76a6,a59cd840,de87daa7,be30fe64,59829f80,2caff723,efab49fd), -S(18c3c0e9,810d5353,7963dea1,820a41ab,3f662b0e,ad0fd5e0,8b07806c,e3bc1110,da91ee74,69e89a86,eb9d4ba5,558d9f77,d3c41201,e0db692b,8f7cb583,da4b41dd), -S(f16661c4,dc6130ec,79c47737,3794193f,7538ca5f,2560ab19,23929a75,ce4a74ca,a225ddd0,d3c3fe76,adb89df3,9987d46e,4b404343,6cb457d6,c3a13583,3b41e05a), -S(e467d2da,4ff404f0,5a1fcab6,631ff889,b8f5809d,64328225,7c228589,cab00ccb,86c1f60,ef5aa2a9,5b262e4c,d539a3cc,6839d704,f20938dd,7b93f958,9f461645), -S(ec69c75,520581c6,4cca16db,acbed064,20df5851,b3b13bcf,299aa02e,4473dc92,7742d8f3,96aeec3c,b27d066a,fb640236,ba38722d,e1ee4d2f,d0c9d810,3dd14d85), -S(21c0f26f,1e5a08e1,3db7581b,86fc8869,f7db1689,c1137223,7305f875,65d3c5db,e799f72e,24aa785e,13de622f,224af49f,ba408dbc,22a935c3,2e3909b1,2da7d775), -S(a49694e1,2feea444,ae028e73,e7c56924,7ae4c7e4,fd7cda34,425aa039,c4c13378,de760a14,58c508ba,f8889c90,35478a55,a8ffdfbb,4ae61802,a364832b,5735b599), -S(1c49af88,e3dfe13c,69e470d5,d8680b17,b2f3094,6e94a5e9,5de05936,d556eb71,3466dec,96cdc49,54957fd0,3bc9376e,7b53b222,ae5f5765,a6645110,c04e8f05), -S(e445bedf,aa503c85,c98cc507,86724a03,d6bda967,ded1752a,3b688844,485c0829,2eb37e04,25589c02,a1531e24,ac1c2df3,497cc81e,3ae51641,cd57db8c,f70f2ae4), -S(1fe3fa90,70496133,c6ebf718,8a076453,91c67d39,6d88f09c,a8244c62,242b494a,35a8b8f1,20503992,20568f9a,c5d0d90d,4a5d1d3c,b9a7c2ea,a17561d8,8d40e61a), -S(658dd6fa,63d1df2d,c9d4045f,c9726e55,2eef2721,90c3c437,29f4a01e,4b775b43,442b482,b77df6c,727f58fb,51331d0c,7604f8c,3da01b77,40f71ba2,f6219bde), -S(57441b8a,6787c3d9,b87b58dc,a66da1e5,32a8e8a,267f8961,fd1fbe3,3859fae0,fb065a85,9675effd,307fba28,226f1276,95f6ee27,389b6959,ea9ef704,ac460e9), -S(432449e2,51582cb8,ac8d232b,901d4796,63198f92,43c1ac42,f66aadfc,a79ece53,d5496156,87c64c16,c2bbf07d,c94e754d,af680ea9,47beb11c,94394c11,a27454af), -S(90db95a2,b17842d5,37c4aeb,42aba933,be6a9cc2,fb23b9,457e35,c2e6a77c,8e10ba44,21a6d262,a4129852,d6f1eab7,2e885bc7,1ccc8b5e,9023e504,2bd751ff), -S(9a7c6aca,93149860,cf4bdb29,fc8dfc1b,84d30bfa,13728f67,ef3bc6b8,1492fdd8,48beecaf,c66ab57f,9e5aa39e,76887725,3ca4a8a9,b464df58,3d86e8a8,f8b126ed), -S(926c02c8,cc70f343,9522fc18,29308f6a,3a1d513b,f632d3a4,cc56f7fd,259de58,229378b2,6e0f48b,de2b0bd9,8364599a,bbd011b9,918e1e55,cd7a0bae,a8cccf2f), -S(264bd086,5bd54674,11b22adc,f02653fb,d483fdac,1682a210,54aa810,9c9cfbb1,75032c4f,a101f117,a042bfbd,5b0fcd3a,3991875a,d3444ca8,5688e3d2,1d2df64d), -S(a2ef67f6,ffacb94b,9f28432,f27bf1b5,ced82580,8c46465a,69e57f01,c070bc1d,2ea53f94,5c1227c7,5eab61e9,a508cbd8,7730d9ae,73831322,80eb90ee,609130e7), -S(940733b7,46fa83a5,4acddd6a,76ed1e31,80daf833,7e014783,93641ce0,3c9a3657,c5a9ddcf,b2202a32,34f736fc,996cb301,9bfea0b0,21988946,8112f5e4,7abe6a11), -S(95e6b0a,eb191afb,10eb0ce8,bcc7c14f,5990a9c,c63da64c,c7bce7ae,1a0d9b48,80698f50,f7ac67c5,4d55911b,cc88d764,83df654e,9873c039,d854d7ae,14a92980), -S(edf7e7dd,e79ad130,1b7c8d7f,ad000004,298a799c,7d08cd94,38b0fecb,cbf5df2c,ae1c98c4,1a7b068,57786d39,169ebf92,ecd60d85,795fe484,707970b5,e7c33fad), -S(f6f75f2b,c0fe2cb7,8be2ef4d,e728e06b,e17f6350,4267de70,1a9dea54,736b804f,11d046f4,efbfef4e,9029f632,e1603dc1,196b710a,32173f07,94dad87c,f8095c84), -S(185ae081,d470ff62,7e73bbdd,3a7fc5d1,df1eb46,733fda26,8e4001ec,fd7b7b94,cf57835c,3a69e46a,5a58ec1a,2c0ff80f,4d8020c4,eef5e1d6,dca1e260,4b2e22de), -S(a93647b6,1342281a,7fa5a92a,48c3379c,4e8fd29d,2113c07a,792e1d75,ec4abde4,b2260a18,e6a05f66,998c3aec,201ea4c1,545ccc98,606d35df,cd671d7e,5b53fc9c), -S(27028628,171d1083,7d713e7,8011a818,81125514,dab8eaf6,846595c,d99cb5e7,99b0fa18,eccaa210,29e5437e,6d561f2c,a5174f49,42ea2f3,b640ceb1,50ceb025), -S(d560c4ed,f442947e,5a99d3,f2f8e519,b61f5243,322aa725,a3a68249,50318281,f403247b,70998349,d5eb3d38,1041616a,ad8697c,6a06643f,8d3b786e,707f12de), -S(b54c07da,a18196e8,33173c51,68d5cf7a,1cde555c,80621501,bfae82bd,2043406e,ee83b25e,300e532c,b09ed563,5b1e1a80,48fcea5c,5b41ed38,97cd2c32,8846b3a7), -S(5e43b2c2,8365005a,fb52b971,ac372448,22ed45b0,9cb6d829,f18fa481,91a5780c,6b3d5dd,951ff60e,4533f783,aab0276f,aab00898,4a4899f4,a31a00fa,a34bc760), -S(3a62aa88,99bf76bc,a23b39dc,d6008d4f,a57e9b1e,3bb69a90,88b77407,49b3ce9e,d83de010,f65c8320,810f7079,8de4f3c9,6e293792,841e7178,d894ff76,135c0951), -S(69ccd9df,9cfe0990,440ff050,7a35ac47,6a0ba786,56c775e2,7677bf59,e5c37594,73a97d37,48f1c24b,6d5c814a,a5829f0c,8589212f,485ffe5d,d86d9868,14bb537a), -S(9b2e9201,51d8b063,95823db7,83e33a7e,e35c092d,265eb440,bcd0a6f9,c9f89c5c,ab125c05,dd565f17,93033058,cc0a0ad1,f6b32ad2,90d129e1,6032c781,ffc2e331), -S(9af6ad84,535f84d9,4d80a592,943c83f8,76360fd4,787ea16,c6f6df4c,b9d92eff,a443e538,895046c2,9cb80270,7777ef63,ee18acb0,fa028a16,d7be8bfa,c0b4e5d0), -S(e7fc44df,cf4eda5e,c982a8a3,1a72d69b,b2b39f83,3dc4e621,bb002fde,2277f4b1,64fa8e8c,f2194013,8caccbe9,8808a47b,bda56376,d9b02ce3,33e36558,365637b4), -S(c820365a,3c6cbff7,273c80b3,f7ae7278,f6f4e282,dca68586,1fd23693,a0dbeaf,adac7864,cca90280,13bb3a68,c3d235d0,dfb3b99f,749b9203,9b03068f,f229310c), -S(3f97b6b9,235afad6,a4cf1eb3,dd3be029,7d67625,ec18972d,62ae4b2,a1b0de3c,a652fa0c,7fc89c54,e11df8e9,7650fae1,7cd51674,dc44be18,26e70b90,12089f2c), -S(74f315a4,d12dba88,1ef5b14,14bea596,ec386f5d,5f6e1dd2,f5e777b,c8c3370f,fc994b03,bd5a0461,9ce52114,4915b7e4,f9380a77,8a15407c,9b8a96d9,e7999c0f), -S(db546b02,795e2435,e8e6ede,3a45fc8a,1cbf311f,d0d9784d,dcd956d4,79d37b40,f16a6c,ab9dfb8f,1374440,86f1e513,79e54030,db4153b2,d2c06602,302ca383), -S(e1ce9f95,c8764028,b707f2bb,ef2b4d0c,88adeb47,f0469924,e2659195,6a53183d,358014fd,987f41cc,8f31856d,25a509f9,d406a68e,82a68fdf,1e1d4afb,99de59d7), -S(38f1e3,e35f77d,76cd5847,9b9b2c92,e90bbb3,d8793cec,509b29cc,c0fe13ed,faaa8e0a,a9a943a2,a5bf0e7f,a2a95079,ead33f72,8e1a3547,e55c6d63,3e908264), -S(143da00,da92138a,609b62da,8e90c19a,44b89be6,3372913,fc8cda65,44740ed7,2d042699,25782d78,8f6d8f4e,7dc63ca,570fb79c,ac2e5691,65a8df5b,38089686), -S(93819e60,23aa61d3,f015f747,d74ff5ce,d3437f2d,9c25d9a4,dd5ee0d,e4bb413b,3496f668,113975c2,4cee563d,5a5fe406,5e68b1d9,afc95e8e,2ebc949b,5779955e), -S(247bdc8f,abbe756b,a35c9f77,2c00836a,51cd8c5a,d2182e56,81f4f79b,2c0fbfd4,39dee166,712fab57,95edba10,8ac84b0,3ac90b43,7e22290f,91f0899,7ac3233), -S(282c681a,c67c8ec0,7c399e8e,a3198c41,a7993d37,b9bc4042,b0226d45,353034ad,8d5fcf2a,d66a9266,788d77f5,5fe4830c,6025c26f,e9468d95,3271d2a5,61634ba0), -S(e0e0229c,b260bfc1,a5979371,5bc7d226,eb9a8989,89edb9cc,5012a2d6,c05657f9,5321fb39,ca241eb2,94c69885,502d8d25,b85e414e,f540b713,e9fdbdde,ec0f50b1), -S(b8e62275,85d52f64,88a76515,e8c62894,7b9b01fa,1a7bcbea,9124dae7,b8a05447,84a564db,e14aa687,4cabdb11,7ccc7e20,706a7a54,c4c23689,4660ea5b,6d0a189), -S(77f3be41,2e08ecdb,b8443431,8e71c69,e6613ec9,bb2ec577,40cf944a,a3e12abe,39b45913,a90e014f,ffae3a15,a3bf44b8,7ac121b9,fadacbe7,19af320b,b9d35124), -S(350833c6,8ceebf3f,b0e5d4a1,749838f8,c60a673b,a7015eac,dd1050f8,eef646c8,ae37f219,cae837b0,bdfd2899,2625868f,3906564a,70ee0b90,92f2b24a,a2631de1), -S(2ee6a70,4c8083c5,3f88dc2a,aa39258f,2833d3f3,600b1a4f,61101e44,bed8d5f,589a8a8a,d8e32dd1,c7e54ad,d2b6952d,62017da2,5e68dda6,aedc696c,77b4dfa6), -S(156af2de,75e81831,2e6eabff,ffb82dc8,b5fc207,4fdd6341,b98597da,b22a6473,dfd13542,36d0407a,e0659ccc,b7eaa304,10bb4afe,4afb4221,4e70909,15d4fb18), -S(396d53f,5a488086,9be37006,e07a4638,496ad4cc,80c7554e,3f4b4939,5ba18d38,a7a6d320,39f05345,f41e2792,77bcefbe,10983280,f56c17bb,943c253d,7c094b0c), -S(15407e62,684b2d9e,4a8f08b2,31010bc,fe42c9e5,f85378f8,904e649,a759c7c0,54ab28eb,1b91562,ad8551f,47f41c96,2516fac3,3af933a0,75c757cc,e381d3dd), -S(80fbd75b,1538f0bb,96f29ebb,3c50682f,de0cd2e,e9615f1a,4b8c1b76,3b2090fa,cc3613a6,8608dc75,97870658,3d478a33,21c3677f,516cf6f0,6fdfc253,3bc0946a), -S(c795f08f,f5458042,f6268079,36fdf08,bda3ab0e,5281fc3c,447df53f,25aecc93,1524dee6,b98b74b6,616509cb,77a2a5da,2871b1cc,78a7b217,3185c187,223b88e5), -S(1c39286d,1aca3eb8,36bd90d4,e46ade42,ba8c0b1e,43523499,ab151e3d,7b331e6b,4f81e790,e66df7af,b4725dac,b506bb73,4c299afd,21dbbfb0,a60055c7,ebf119fb), -S(e778e362,f5f67d32,73c861ab,3cbafbc9,eb03f7c5,e862b5a9,2b7a51fe,26daee5c,1035cc76,9df9e120,7a71a13d,37693edc,19fd6ee9,33fae651,a145cc60,37ccc1dc), -S(d71b5cc5,56ba74aa,a0ab5775,cf0acdee,54e5c48e,5cb08734,6e510e1b,18f9a914,f3c3419e,84b4cf22,31975aac,e31b9b36,9aeb4a3e,e2b2bc6f,feffc3fb,538e8e5), -S(819e3ba3,6f5b1011,64f3e798,764e01af,5838ecd,e6141690,971e562d,a99d0520,da38a00a,838d85cc,f606c440,b941f128,a66b0216,544008b7,a4904094,7d7557c), -S(3c726a07,740912b5,560bca0f,f8d827fc,a9f2b1f7,1596f922,218a95e5,db2c7048,b9e52f48,ee2d0944,3c5c5776,eef02a78,47cdf47c,b83316b2,220fbf00,4b3d72a5), -S(e2b550e7,189f0fcf,a897fe12,245d6912,e6743828,b0ab0d78,9faf3865,d90d1d1,11dbf946,3cefe572,f45a5288,55c2a257,43dbd70c,3db6d012,34821a0b,35ffb115), -S(4cd65ffc,23acbe0d,59471667,44ca1194,f52dfee9,ba532725,508eff79,61130fe9,9af3c41,97fa257d,79fcbe93,145fefb7,96bfb0a0,3914ade3,c1127b41,9e321a28), -S(6fc537e5,4f7bf705,bc4a7a1e,a7cd365e,ec36f190,dd4fc7c1,ec8f5f3c,8dc63c21,d06a12b9,ccf770cc,f8504b97,ae68c61b,1872d500,54db9cfd,76a55c29,58eeff4f), -S(33bdc335,cd76ec99,db66b3f4,d90ad5a7,924f343d,836edcbd,847350a2,10366223,2761ca74,ae8bd215,b74fd37d,9d6527c2,c10406db,fc5932e9,d408c2e0,ef554987), -S(a4ac1b95,e9a8ce4d,da11a1b5,c21401b8,b92d9bc5,f7bbcfda,3b1940cb,cc331dd7,8f630ccf,30f68759,174b4052,8082050,599c29b2,4922c1fc,e4a5952,61c2e239), -S(6f34af2c,86f06702,4f720e5f,89d45fae,f44a8976,2b0bb390,e9a7ee72,fdf07842,785c4f09,d127954d,d6e6dff7,e342bd1f,5540448f,ca390d72,485b2967,b6ef1825), -S(37ef099,8571efbe,bbfc5350,43d0fcf5,758d78cc,3ebf247a,cc7b4f59,480aae80,29a3b2eb,fc41f793,66bbee1a,cc6fffba,76d37631,f10136ea,4a47a18a,d9263c78), -S(3d815c75,6c6d730c,b3d7ca6,de486159,f0035011,851211c8,25bd59f3,624b9056,56e109c3,e6ad3198,48b2e00d,1168806a,f0a22c93,81d8a243,53850c4c,1c486cc1), -S(d3143ac9,845ed52e,961b9fca,faecd1a,ec6e8554,c90357e,ba2317c0,c832730a,f4276188,6db140b,4d9b8b96,1e6555ea,a80dfebc,8d37ddb3,a21e284f,50b1dc73), -S(5b0066c9,221d1b8a,3bf660d3,ef28c3a6,8c611dcf,943824bd,ba4f2a8f,836b03c1,86a24204,f40de381,21be77db,a23a6e3f,5c8ea5eb,7138d218,45d8003,cc8460d8), -S(62461176,e6bc9c4c,77f8636c,3ffcdf24,45ff5c98,935e4b76,1c4e50fe,c00b606d,5431f12e,488bcede,ac9822e9,5797c2c4,5a49167f,6989a6cb,601ed3c2,860c28a3), -S(8efe7f7f,482ab457,4a7e56b7,77a7b5ff,dad6e208,2261b9d6,bfd6c647,c88a757e,ef5e2083,ceaebbb8,aeafa383,d188f30c,7350f484,eec83262,8d9fbabc,522b072f), -S(4dd8e450,5ccb49bc,2ffacdeb,53bad1e0,362df309,5756505b,33eceb64,34ebe715,9f801ac4,243d720c,eab5def4,7a7e6d6e,a051d3b9,783a2b80,aacf087b,b575b58a), -S(3a345a97,85c7db9c,b5661c97,3c739949,c48253c7,bc36ee32,d4d74878,3b0cb734,4bb7a957,d4c8a2c8,e1229e1c,d29af780,ba844bdd,a0251134,5da7fd4d,30223818), -S(d76335f,3e14a6d8,b8d6a87c,7f8d96bf,ee171c24,276feddc,a52f17ec,74cd3ed6,dc2d6c21,590edeb3,a9014b24,fb8a6ffe,e99c0f0b,d8fad1b5,2175f647,d5be53ba), -S(25fb12e6,2e05fa71,57badcc2,ed5c53a0,89a55b1f,4f5b508,f89fee83,b309727d,c73cc2fc,4021d267,7821ac82,f5803218,d4ebb736,6fb22f98,62a98f9d,6e597928), -S(6ec69e2,970df6a6,52e50e1c,2682e39,66e60120,6ac7fd61,12dd1446,47a11783,e9d08d09,1148b329,6a8c7b7,f9e4588,8fdb1179,72e08c56,41908b1d,127b7a87), -S(f72d2f36,35701d5a,a19309f0,12d8c5a3,7ae0784f,699a200a,bca89cad,57b08db6,5081bc4b,16c53997,46f2a35d,e7d59b53,8956b57b,865a99dc,e8bd86b0,259888c8), -S(945fab90,e970531b,766f939a,8c1a5cc3,c43a5c7d,45b96983,ade1d042,13d2e46,d76f827c,1eb775ec,7d5946cc,aab05b62,97173b32,54407669,4bf194c7,c84e612b), -S(fc60b8e4,129df265,9c335842,a099edd6,182acfa5,b74110e7,7880281c,4f582b77,69cc15a6,11c54e60,72db1bc9,9af6d289,f647aa85,95006a83,8b3a91a9,da33557b), -S(a4e41222,f9643671,390a7213,e6d0f5c4,9722d41a,9d0102fd,818f4aa1,6e03f5ec,c1636af0,55a67855,fc6a1827,c9e3e463,88922c7,c769357b,4f4fc4b5,3af2307c), -S(b1749fc4,8c935c8f,f2dbb7a7,2a69524c,83a7d551,88b48ef2,30f0306,a156a002,43efe91d,ee498afb,4f47a4d6,51ce132f,fe1fe875,da143682,c56d936b,dd7dd80f), -S(407b881,6141cf62,b8c87b3c,439290f5,6be1c590,41c847f1,f127c8c,c4b913e0,c3c90c06,afc5bbdd,7c699eca,5ae24594,69735dd9,71bd6b0,e48db6bd,6b77bd8c), -S(b0054fcb,94060a29,f983b713,79ec998e,34e39d5b,c5e0c271,ef48ac4a,e12b3a18,e2b89e84,5aa2f8cd,8ff2d240,72c0491a,81be7ad6,1e8166e5,6619e928,7d37c2fa), -S(4c202cef,fd6b69f2,33efb265,77e327a6,b47e722b,1b8b6477,2372f4fe,7559e5a,1a04446b,e69535eb,3f10d334,38049fbe,e0374b53,54f2f46b,5cc1de16,59c3e726), -S(451ea6f7,c1e9992e,b50c5ee2,90784052,a9974a8a,101da027,753575d5,1f306ef6,ec8cca1e,a21e21b2,cd0fb48e,dd14609f,733b32e5,42cd1c,a1ef2acc,6396cb81), -S(1ae254d6,686a8a2f,135fd775,16de17da,5175a82,aa8599ce,45b1660c,b5f65d78,a2595603,71a24698,626cfd82,7efe6d46,d8c4e31e,1765ca1c,e01ef584,4a5780a8), -S(d358e246,514e986,b0b8a192,53e07db5,5a635c01,85d7f39c,666064ca,cff640ac,d4b34eb9,30620b9f,eb1f94ab,8f88f3c8,8d8a9a5f,4ff35528,df0266f7,d4481c2), -S(fd4af649,5415092b,e61abb8b,ea2827e,3e833f5b,4653a1fe,7e9886bb,ae454b54,9743ed9d,d30ef4ef,31ff9df4,e5d10272,1e5c7609,b539630b,ab555559,88b56965), -S(4286c7fb,d1b785d5,a778f72e,2574bbc4,2912abdd,ebd9f6ba,15bc6c23,c7700cd8,3b0c1d36,2f62cf4d,f5dfdd78,1414fe1a,64a5526,cd36cbed,8e41c740,56525e71), -S(2262acdb,7dce598,ec0b2419,2d761dad,8b413bb2,58444c1c,bebd1693,a1ed597d,c6bde565,87f6e506,4882d86a,6eaf0314,20107b26,9b57dce,e9ba48f4,d9a220ca), -S(b8eba19b,a6057f98,519c319b,cd3566db,8a4a53c2,f3d825fd,9646dae7,13fe7b5c,7bc344ca,fff215eb,cc8f42f6,6b711406,7a00e881,f7e40ae7,253fbba3,bfab8273), -S(d49b8d30,2d8a1c2,ea6e8302,33ec1fe,371cf035,57c2c45f,d0148df3,1a43b11f,6f1052e1,18fd6180,1694b106,8e1d8cea,f72b3e68,ba84d0e8,ad945fb5,156dba1c), -S(56db7750,350da2a5,c6a73239,13f987de,9b4ba04c,9f0c0fa4,67d53abe,129116a3,e4dc5c13,9b72462c,bc5b5200,68d27c73,9599b40,d17c8581,1caa69fe,3a429fa3), -S(1c987244,7d133050,8368960e,7f63a52c,ae56a840,cd19a359,d8e94720,b3f4d54e,9d8d1dab,8efaf90e,f2bbee51,b0e9d369,abc06979,48bdc1d6,efd1c18b,26dd0ec4), -S(e9bfca61,b09d2298,3f1657f1,f303e0ed,f9650830,c3151ccc,eb7cce77,7865568b,6c06c996,48a3a164,a57dadbb,304d9d29,75906d64,89e42292,63d4a86f,b4a82642), -S(52f86eba,9c3ed139,83704865,ad0ec3bb,e54dd2b5,5841fe8b,826da573,213dac7b,59bccd99,a53fb65f,1df73e8f,eb8f4734,67f1d4b2,715745e8,693589b8,d1f24d9c), -S(ac02234a,412dff76,e01f6ff4,a3bab5b5,ff3339a0,4ff3fc70,eac1bdd,f0eb88f3,768d7219,782584c8,e16818a9,f8ce5aa8,18228c2,21a7dfa1,6e9da56a,61227843), -S(c2e5044,2dc773a4,d0c3d1de,d9883be,dcc01c32,c83b2a51,3e946212,8551336c,30063e65,133d1c40,607c2cb1,50f680ac,43195e5a,8ab68add,5ace3977,4242b689), -S(fa02cdca,e19fc987,a7c43acc,77328914,741ac5a0,e150e9bb,cc6aa0ed,9c16287d,ad7e7b78,f566a226,99e27510,2a03ddbb,de7a5e57,58fa52a7,f198dedd,7f27f72b), -S(805110bb,99a2b8ce,a8dfa8fb,e4bfa353,ece63c67,22adb161,9c696d2c,5aa66939,aa0e9a9,df1a2a11,72fbdd30,6ec86d84,e04ec973,79e16505,5273bbda,4fae3c8e), -S(6472c6a5,55be3145,476b3cbc,9f1d5459,be137d1c,c4cf7a11,6d28a722,f1b8960c,d28a0da4,2cc3ce06,fa16e4e4,dab04b2b,eb74d8b7,8b09632,1d02ab86,b92b0afe), -S(a659d5db,dbb45d5c,af7a9893,7f82e6c,c37646f0,34411e20,e361d595,28c4fdd4,d064e26d,ac724089,90947031,27256e35,745ca0c9,696da250,adf2df91,1a3a05a3), -S(882a7c39,56bb7ba3,f3d20df7,d0645bd,b13db6e6,2ba58f31,82ce4efe,2a0846dc,627c82c8,82437a35,1ebc003a,4035af13,63de299a,52924337,a4162a0f,c5bb17b8), -S(5556c236,9f7c003,d5fd2451,8c4be1d0,9b11b2e1,8961522,68e5cdcf,a6282db8,384b8cbf,13d9adbb,7a2fce16,38b71729,aa70d754,37dd7427,8cf98135,bcb0f1ae), -S(f268a877,472c9305,e3c2b193,303c29b0,a6fd2ff0,fb1563eb,ec5d39c0,def431b4,5dd08bbf,c1b8cead,9b45f164,e6323f7,c1bf0b33,bd9ad8e5,c553dfa4,cb42a634), -S(fe3438ef,5cdb0229,2c5d392a,387c38bf,87e453e0,596c5546,aa27940c,7686a90c,5b3baa2f,76647870,95c3453,64f59327,415d6aae,9fce79d5,85222afe,8304b998), -S(51216a9e,54a94c50,f2c2ba07,9548a51c,8345dcf3,b38a7e70,1a3de47c,9d5422fb,1046f888,360c5de2,95d63e16,93463bda,e3714f16,46f74ab7,3b6d68b0,15df71ab), -S(326d2470,700341,9ba6438a,b7ba4498,957e919f,f748590a,130857f6,d46386aa,7e31c242,cc2f3ea7,d5579be1,8e216b8d,9f69e360,c03af079,636bc03d,2090b770), -S(cd5abed8,a071a8c2,4d379611,4d81f490,5e644884,82b2e2b8,3eefbd92,a98947b1,f3d6560f,e10eacaa,9a30cde4,ab852b49,3ef0add2,f6d83db3,5d12b0b6,705292f1), -S(4482b5fa,c39560b7,7550b621,238fd8a9,5252e8f6,25fdc8c8,42382845,8d2e27fa,c1d246d2,145041cb,ef8d3fc3,8b5a1237,fe400256,e4d2588c,ee320733,f6884933), -S(1eb303,74179ee6,76a977a8,76ce0ef9,71ca88b6,615f3729,cab3cefc,6080caa4,a9293fd4,a0a156d5,f8f735cd,a60b9ef2,bc6004b9,efcd12f3,a0f5c16b,5524e421), -S(542685da,a08f407,71cc90b8,bce723cf,d2f6e616,133adcef,7908fbb0,ea29a4e9,df4076d8,44a4d3a1,10126bfa,344fb3a7,79f7455a,a9abc99b,7429eeaa,989b5d44), -S(bf631fa4,5277594b,c425882a,85a361c6,d62c50e,aac20ba7,ebaa596d,d6801a54,69995b4d,f20f336f,44681ef6,6a65b54f,88d43953,6458ee9c,f7657389,94e53bf1), -S(27be809c,5bb70530,ee629628,18a4ea73,540f1e6e,75990926,3269a205,604e7b53,a5bf709a,caba50ab,ad939c56,1abbd0b3,fdafaded,3b82d9af,964727dc,bcba7b3b), -S(40126263,3f3af376,4bdd2a6a,c1c6adb6,fee285fe,1171a29e,af4d71c2,5f03b849,2ffbed36,47815c25,5d5bf7d0,a7f09dfa,8eaf79aa,df9e95ae,57024960,ec98fe8c), -S(a634b11,bf441eff,6ae8eee6,dedba52,6377cb96,e3c36a7b,4ebf02de,42146298,57c555ad,85f0e194,2f9701e9,1227e0f7,42763296,2d0702d9,e81e025c,c411d379), -S(d6130997,fa2259f5,bac49b16,38d224ed,f30786ab,c7321e10,d593b932,27745905,ed5a448b,c2157699,b436efe,6725f8b2,8df8282f,1a588692,41ca7db9,6c66821d), -S(4a313361,bed4a94f,b7d9f1de,a1feaa4d,3d957379,cc24d880,92dc29df,5c503d72,2e4e6930,b8e33e50,d166f862,a4f73520,63470e27,f9d9a3ec,3382d252,e42ee20e), -S(6be34d7b,5aff85f0,e731e6bf,285b2f79,eb241c67,df9aa3aa,c2574e5a,d8b146e6,a9ab3f20,dabd0073,5935255,925676f5,799d14d7,75c896c0,de451057,f0112f5), -S(2e42de88,38560214,228691ae,26a0a26d,fd96cee7,9416439a,e771891,3499898,6ff846c2,72393037,a2d0b2c,da38539f,f8d3a6ae,175fb604,55afab50,8454a419), -S(d65d003a,c979da6d,9e4b077,3ee965a2,f33e512c,5c20a9e7,456fd3d9,fb5b0b6b,fcf12ef7,6fd89385,5ade4bc9,4984d7bc,63406649,d4525f1f,3c9f35a2,6b357f0b), -S(f58d02ec,d136eef,67ec91a2,6fc5097b,74c01db1,911c2685,4941f56c,af6b10b8,14169b8f,aa3a5512,55d3eb4d,25ece18f,d802606d,f1259504,64f79587,518561fa), -S(fd13b1c,d189e832,e3c06cf0,6277474c,3e388979,e0a7e925,1799dc9,a9713b9f,a2838fe5,4a07d539,5392dee5,dc2269c5,9fbb222a,8541f3c0,7fb28cd8,1ac2283f), -S(bdfc6941,424ba1ec,88ecff53,c8da31d1,ee6ac442,c8a1e58f,5171f4fe,b808d41f,a0533200,4e7582cd,a824600c,20864fa9,b8286c7f,2107ff82,9b5c964c,dc4a3531), -S(a390ea29,4096bf15,e953986b,86893c37,e2cd18b3,5a0df983,5be6ba2f,8a5769c3,1b432110,1c37b5b3,147029f7,aec437ab,cbe82b5b,559e9446,a2cd4067,9a9b5b9b), -S(40a61a44,a356f623,968e386e,319bee22,574f2f41,f558cc5c,f8a9b6e2,93db0ea0,745b1083,a9e9e080,365f95ab,31db5c6e,9e38c2f9,62bc4e8e,6a879768,f21998fd), -S(2ab87f5e,83538093,e99e09e,468a0056,5db6e308,2bb072bf,b7f5522a,24977f87,49a22c4d,790450fd,f31f8199,1084676e,7cdafbbb,5656e2d4,bd03621,bf50cf68), -S(656e91bb,156468b,821fc9dd,14c3ee76,ea8016c8,92133d2f,189820a5,81a964c,d8d153b6,870c6ce7,a4db4eb9,bc1f75bf,22f6c3ff,74865118,fabfd336,c7ad73), -S(d2c9e2ed,7cf8c21d,8c078e70,73c8ea8c,88e7169c,abea0a44,5c6c339f,82eca7d2,2db2942f,ee70cb15,56fe1d30,d5bc94a2,3d748e0a,7ce8735f,876e9931,90552a5b), -S(a5301947,cc6e0053,7cbd19ad,db91d854,67ab1bac,1a5e9862,bf46ebe9,a2d14710,c36d3b1,d62195a6,18f5bc12,61680ea8,1000f37,86f3ad28,3f516d16,f45e7cb2), -S(1f61d637,80113793,5cbe0dc5,34042617,932efc37,c3a95ea3,57575ca8,7280269d,24dd91ab,4adfa0ed,9369d30b,70a25b1e,df9b4383,37d83464,7fe064c9,e2ba5de4), -S(14efe93,49750c63,81d61000,4b80c733,204afe5d,223ef3b1,e45bcb6b,177c633,d8e284f0,ee2f4826,9c958271,3caf5364,6361294c,a0aacdd,a9aef70e,8fed2bfc)}, -{S(782d5c9a,d970322e,deff2e7b,57844184,c589a4da,c042fcf3,86c1a9f8,26c1babb,27bba565,405cb392,64762d97,cbaff552,1bc38b20,56afe313,556542d3,f200eb06), -S(1c000fe,9372bdc3,68d4d6df,832c0396,3701cefa,bee1cdc,3965e183,3476f636,1792668,89cb19bf,39633363,98df43b2,9d2eb378,a9a30531,9d33ec1d,a571eeb8), -S(17688e97,d3dd0dff,1f43ced0,af969ed6,d0b53f3b,22c1f1dd,240f4bbb,253770c4,bdab9644,b7047941,f42ce962,4800d25f,54dd194c,6fc74eeb,2e1e9779,3e4890f1), -S(c9e92b0d,e85dde86,8eac6f6d,1eef4b4a,8b25974e,7b77cb,fc210530,b595cdb4,5aa94a9a,7210e6e2,e04dda5c,8250c8af,16bd5081,f2102f6e,a9d09265,8b4c4ac8), -S(c9efbd02,5f6aaad,e30ec696,e5e6739f,ec6e89dd,9bec22ca,cb2a9142,d7bdd284,f32f9e4e,dbaa0a73,135fc5d7,7d2cdcc5,80c357c3,144bfa1f,e05e70e1,c8888744), -S(25cf39cc,ceff3fac,e9ae5cb,e6e6db7a,586f1fb1,8b3c444e,28cb2d19,ba08ef4e,d3b55fe5,3f11624f,f6c25252,4928226d,a82128f2,4649c140,24fb1f17,c9ba9742), -S(262a25d,36253456,cabab430,5be8500b,e2fcf871,1c580d9a,a76202fe,9e97eb39,873e797,bf2adf55,dbb3b0a5,a2480c30,1395cc6e,477f39d3,520e1a1a,6e61440d), -S(3041bc09,6dbe8a9c,9e436f15,bd88954d,b2e1586,5de92c9e,8f8df7f6,456665cc,f17d1d17,e406001e,1aae6cb1,ce4c8889,4a502e40,1a0f7f04,3f8daf4b,a4ed4345), -S(d0fcb1f3,8d32d3c1,5a0d984c,f9eec4de,22e0f400,b93c0343,337f98c1,db2afa4d,de5133d3,f7920fb1,4d34b28e,5058d81e,e9e312a7,17590c98,aa242e98,92f8356d), -S(65f5da86,cd13e857,f41a7016,9e62e05c,628506ef,d1739ea7,5308b75f,510f247c,5e52e176,38b22cfd,8f1f800b,edcf0af2,1efce458,e179da1a,d046e0f9,5afad4b7), -S(a4ae6a21,f07f51e9,cf635714,e0cd35d1,d31fe32f,22d29ffd,16af4bf4,65c859df,41a69d4c,ff1abc12,8831efe6,e410a22d,80790640,5f319692,46fc3bd5,2589c094), -S(d92d5f09,79a47bb2,e995693a,e005c266,54d6260b,85f41806,89407c47,69b2c5fd,1ab29589,87b2e4be,6ed6eaa,fc47a9e7,49349e9d,1eb438c5,735dfb9e,d77f2e8e), -S(f0f136b0,787e1c0a,e43e3c34,66d77cc3,64282ca3,4b686a23,eb30622e,c50644b6,1fe70372,b3047ab5,242190cc,6fbc18a6,4dc0797,d51b2ace,1eb208cd,30625ebd), -S(52cf110,c8a81a1a,f6ecba15,7b6e2748,9fade773,20b22880,ac023ebb,3ba95119,eeb4e114,2762e0d3,42ed393b,c3b01a2b,e7534b34,c7466f91,224519f6,762da31c), -S(dc1f1041,76019cb9,e5ba446,f1601edc,77ff662d,e69a560e,2795243f,e3635bd8,29fff9f1,d8aedf11,5f518298,4b82186c,1c2b8e9c,8d80bf5d,c0a8b0e,9598700c), -S(dac7cde7,dab3d68d,cdecaf9,3b4a1985,ba099d97,eefb84c1,efd5b103,1559bd5a,53940d9e,785b017f,9142dfb4,4157c250,7a8543e2,c52150ee,8ec1910e,caaa36e9), -S(42500318,5ca69e1b,c4413ba8,ed3949c0,bc39ee8d,10b543d,c4035f57,7f46abca,5c187b2c,936e589f,66ecdee7,dbafbd48,b184a1ba,4ee9bf01,f70327f8,7b80f384), -S(1a8728b1,3cf2ef6b,d122df7f,ae11873a,fdc4aaa5,46981212,616f7a35,73fb94bb,3c6e1732,320fa8fb,7bc908a1,93204afa,aa22e138,571bcf1b,b0b31285,2cb76d21), -S(9963b507,f4fdba39,1312782d,35446a4f,a1247315,29a1894e,cfa86138,22206031,1b7feefe,36616571,f904d548,4673322f,4e867016,b60527a0,f0e4ffe5,97b7021d), -S(5f98a8b,93016cee,48a8bac0,6553c0c9,c3f0af5c,4ff969db,237f5669,ae7c4f12,ef144971,69e32124,d0ce4525,c2ad7857,43a62914,ac21c954,a1f0f6c2,4cc2d091), -S(ff4d4fee,875ebc10,fa6db1ab,19941a6f,b934ef14,6b2f7299,cb7ccd74,5c6be029,10b3dcdb,2a753aa7,e2464ce0,b021eabc,3643134b,9acb6f55,955dc471,8a5bf46c), -S(ff159279,11c229ac,f5f0aa9c,67cb98e6,309d16c4,94a95808,91bdc404,e2a1636d,5ae15340,a7e94020,108e0a07,3e775a92,a7eda92c,ceb6af56,cc91ace,e8991e1f), -S(652bcc4e,a1c2f450,10273043,2cdbf01,3e07aa76,7f5d8d00,a48ff9c0,b97d73f3,de96c171,173cfa8e,66174a45,e8899d12,f5ff50e9,481f6310,8293075d,cf5d524b), -S(8d33a9db,ca44ca87,634d52ab,c325f892,14330c84,d6adf84a,3a2e5ab6,ace8089c,6ac0fb1e,2324dfdf,546dfb42,37a523b4,1d8dd5a,81a6c398,2ff14f6b,c68348e0), -S(b7356428,d0f718a5,a999a4b0,cd55332,b812920b,26b5c5a,babf1afb,3c1ef230,60a1a61f,17e4a054,921d9187,30807530,3c0c72f9,1ef469da,743c8a55,cc58f62a), -S(bf32c76c,c733c2dc,85299812,392a2ee6,5b0ce661,93cecfb,ed2ae522,48706aea,961e28d9,a6dfc6e2,3b7a1235,4b9551e5,bd1da617,f8a4d985,467de1dc,bb2b6630), -S(68760c7e,1b0b625c,bfe9533b,fdc4df7,cd0acd04,de4c4e5,cbbda233,4d2394ad,b0ea6bb0,f9c5c9dc,91af54ae,718c3ff7,5bbce1eb,ef353006,3809ab3a,4432978c), -S(abfddef,d56b2944,ba1548f6,dae0e65b,40e19431,b6415380,3558d497,7a373aab,ab40ea01,23588781,882e332c,432177b6,15023347,b76dc121,be5a0a71,f55563f1), -S(73800767,7aa92884,93ace49b,60923a7e,e3adc2de,78c17e28,3ae967f3,72145ad5,fb1552b1,6fa17e4d,1dc2bb35,95b1b1d0,5dc7e48a,ea07fde6,7e6f7c75,f15f5267), -S(50c0bf3c,6e3666c8,a1a69544,90590b43,996e9a75,77c87e0e,5bb8e927,5caa4ec1,d0f80c96,1b75680f,8264fddd,31b52c28,48a769bb,2976d706,b922b46a,277ecc24), -S(879e4cb0,47b3138f,1a5cdd5d,9eab5b47,a9a8b542,83fc488c,f82ab22b,7dbf2f47,5f607d08,bccffc0b,27c2f0f8,f8a80476,52fdc19f,eeb62b02,248447ed,d5743bca), -S(6ebb3735,465dbfcb,32bde807,471e19af,35d5568a,ea6f5286,4a382596,df623bb7,e2801ff0,8e04b574,414d4844,b7b1efe,8741c0f6,4af13080,ef473397,3aa0bdf8), -S(5997354b,9b77dda,f34a9ef8,649904fb,fc8a0223,1e8cf882,7a8309ab,b209f420,d42f55c9,4d8054ad,7dacca4d,8d7553e5,355db690,1df155,5bd07574,25e9580e), -S(41e392d0,456f7aca,f62f8c96,37881d25,8b316bfe,7655ab56,61413f43,4e428f87,20481bd5,36bbd86d,96600911,1da82106,2c55ae0e,b2f12d81,a8b8a1f0,4309af91), -S(5c3514be,60fb6a05,2303b2ff,ccf81ebb,5734ddd9,ff2b485b,429ce68f,3b16ae64,573f787,958b70d6,36565295,b35d9e73,7ee46c3c,d1d1ef0b,e37828bd,eb80e579), -S(de9e95c1,220bcf2c,cc2acf7e,ceab12b8,239f5531,e2c52949,29e30daa,c340ef7,2e20a50c,94476926,ded26edb,72780f78,81f01cf6,bef5b1dd,5051a27f,abc2b181), -S(29922283,6619c2d0,402ff634,ee6fe671,b0afb7ca,cdf4d109,cf98814c,af69adac,ad3f5da2,7b1785c0,b958af5c,7e9e7a85,f6c7002b,3000c25b,f7e82207,fa9ee9d1), -S(82f8b1d4,b50025d,fe960c1c,600eab7,45a25ba0,ee052eae,2f3e56c5,bc236561,97ff7a9a,a3fab00c,54f8bc06,fd59e050,b854f7d0,53dd2df7,1e93d75,60456d29), -S(4b883553,72c3c528,b8edd509,b8eb2b21,92e8504e,da5087a6,d2a3f9ad,256cbeb6,b0ec67df,a34acd1b,a3a68b3f,79962c17,11c0bfbc,3fbed2f3,345cc097,c221aac3), -S(53cfaef7,ff6b8bee,f6264a1f,f4b796b1,a5d3d1e8,471504c8,d6ea5d2a,5362644f,35697dde,1730762a,2692fc5b,1db386bd,1749e07d,a67ef310,47deb9ac,394ab691), -S(c4d4a268,112c2adb,d862b32b,f344af89,4e070db6,2262daf9,244b5c2d,758e1cad,c109c651,2ef251ad,9f9b55b5,10c973e5,dd6b2746,996942ea,7e4de0f7,cd8a18f8), -S(13d63ba,49b043d8,ce6a21a7,929745df,668a2497,5a57895d,704b4f9e,3bbd0aa2,d52dd90d,6e418aa6,afe2037,80870e15,78ce6dfa,c1a73879,490b57e1,c1f06878), -S(4499275a,5e03c1d5,2ee69082,9bd53365,6dc44a6e,6584d2a4,3c27ef78,fa3475a3,4f51bc3f,56fac2ad,3bc36d35,b47bfc56,b3885e3a,9c279c86,83762bff,edc952c3), -S(e526f9ce,24911c8,30311aa,82e8855c,575c9e2c,553f7392,2285fbb6,caee91c3,e56c2c38,28c7432e,20b490e1,3f6c2476,47040253,7b1d851,31690263,a41ced87), -S(723260d9,c31cf302,acafa19d,ac90ded4,18d5945f,e5fe302e,e7fa8e84,b3fb2449,bf7b11aa,b5603f1c,89a8d6d,ecdbc47c,9bc0d229,937cffb0,8e4bb060,d932f6ff), -S(5895fa08,76ae7387,41184045,d088aba1,61be9802,33f8820e,7eb1f9fd,dddbf76e,a4dce1e2,d7a60205,197a8458,d566e8e3,720edaa3,bfc4d946,f798e438,ea3b3c65), -S(c358ae6d,c1565fcb,623c2c2e,a575ad86,388dc893,b9153135,af4e787b,17c64c9,f5a5852e,e3826ec3,e20a0d05,c330338f,f28699e4,ebd749ff,3abfc3de,edb3b97b), -S(efea41f2,599d5357,5314ec4e,7f36b564,1f31802b,ad030d6b,cdf8ef63,4c1491dc,5dd25fd0,45ee4019,c2d22619,e47da1c8,1c4062e0,d6a9bc4d,fb37c6b6,7b9c52ea), -S(8e939129,e1547a83,c73900d5,4adb8bdd,79f98d70,3c9c7689,9a7b3f35,8eada2f4,47b19f53,433c6b75,f8f33cfb,3aa91908,b8acc5a6,a69bb533,711cd84f,f497ca86), -S(e5f3fe2e,ddd45d3c,745baa9,fd812dbc,dad77d5a,aaac44f1,20f92515,53681f79,a450e661,a13cab2d,758eb49f,4e49907c,f9ec8207,bece14e3,e3e80eda,cafcda1b), -S(727ceca1,f1985b59,e3b1abcf,400972e6,87f83e1,ffe30f64,c853c8f6,35f4a3dd,c451b046,44e83ef9,d078367c,3cb44374,ddada9d1,9416ac28,db60a12c,fc526fe9), -S(a98a9e68,da05a375,80c0633e,216d76bf,151a7921,32ecb2a1,c114c001,3fc095b8,26aac75d,f680f14b,ac3cc30c,5c14e782,3b7be308,ff8ec2ed,1551737b,2e213c33), -S(2dc1bed0,a25f6024,3ee2e20b,90158ae7,102b43f2,c781f91,86dc6d8f,768a0ba6,85b6b3d8,509d7c9a,ec12d44e,453456b0,c881212a,3c056d0d,827f5488,f02e581c), -S(90cd9e84,5fc1e7fd,28f28544,8b9459f4,e22be67f,4caeec44,2c96d77,3f6932bf,63c92e01,1cba5199,3311487,7b208922,1cc6a651,b160a049,cd558e90,3ed560e8), -S(7ad554e9,61e1084d,8be77d43,e8aad732,5725a9f8,3ba29da5,6ee8e21c,8d6f15b0,9e13367c,d9b38a18,6b8306e8,714cb709,12619c2b,56953ffa,9c538383,c7b36e3f), -S(e39f4f35,c68f835e,b84acfc5,dd5a9c4a,84263b85,376ee9a7,e72489df,c96fe3e5,3f06c83d,60b5eb27,f6d8ed32,1d38630a,8bf822b0,1eb97f0c,90d2d9ba,c1fe81f1), -S(e732ec5c,6d2c9f2d,17ce26cf,99151e74,31aa7c07,87a9cbf8,65611936,5458124d,51d3e77,e75c44b5,4576bdfe,36cd28c7,9131d0f4,b1cdc356,dad51aa7,253e077a), -S(5cfbff88,130d394b,c0ab5ba4,b79ac89f,f78a2c0,fb3f7f35,bb3b8c60,3eef9596,18aca6d9,58e733bc,12ba085b,bef5173a,6990eab2,59bd6d4e,e3cc7c5c,7bb5516e), -S(69d1998e,3a0be330,a6341161,76adc83b,6d2dc4d1,2b985924,468790b8,25b182c9,5d8435fc,6cb17de7,65b628bd,2609a81c,a4f8d081,337be0d7,89cfd817,583849bb), -S(4fa189e1,1aa8d445,aaac9fe,b8bb0fc3,a615ef8b,5db97120,b231201e,1622d7a1,ae8130c4,164090da,706a5f21,1bd3389c,8a08418b,36c7b248,a9ce1c7d,7f62a175), -S(5b8c0419,17905a9b,7f6683a8,ab52261,bdccab65,9d70db3e,daee62bd,a0647a44,ec7c14a7,ce63910d,4ce729cf,e1c30a22,3c74fb05,eac31e8d,876487f0,cce4bcbd), -S(d8911bb9,9e908660,34a55849,84a7eb49,2f4e2ca1,c1f99d3b,35fe4d58,8813df71,c479c2b3,4d9d5bdc,c82e1f76,c2aff35d,cd71c0a6,fec01808,a0d35ef6,e74631a6), -S(9691f765,417f4841,22baf14e,c65afb44,8337b915,dc85d449,c6101e07,9ec94981,d3f163e1,a69a968a,223e2ba5,145d0dd4,2a8cf4d,baa6d247,4ac5c965,3cdf7049), -S(27299a8f,98275592,39b42976,bbc08787,30025475,79c6eaff,4f959156,61a47ca2,cdbb9fc1,bf25ee54,f5524fe9,c5d70a59,3f849ce6,b9ef2b72,c9d85c57,a0f54974), -S(ba929ab5,abb7da7e,be263049,558e3e68,397811fd,9346890d,ca890f2d,4260a31f,78e7195a,1d6fa4d4,a73d3b25,125b9a70,1346492b,962f3587,7e5b8a40,7b94e610), -S(5d065bee,93ed86be,f4d96ef1,cb1584a3,7723bca0,1c696602,ad27615b,a0eefe84,592a8fed,16b03476,ca7c695f,3e934da7,c9ae43db,6db95bdc,e313ce85,8d6efabc), -S(89c311cc,2cddbba,b5d183af,2d6013ac,f3682f24,7c51a9b6,fda419fc,5620678d,a3c6ff3,9bed892f,5fe084fd,18e7ff3c,4facd6ed,38afc3ba,becbf4e1,67e086da), -S(85d1158b,5ece0b13,97a5d9da,35880f77,fba762cb,58d05c94,ea27a97f,8b84daab,b8cbaf1a,b3f392ab,f70830ad,b7bd69c3,69384f9,4c2f11f1,476ac91d,f171c46c), -S(9905e022,d0d9504f,f9acab48,49be95e6,f95e1c74,f28a8281,7c6e858a,602f65ec,a1552c6e,19467331,f78f6fae,71de8604,504b11f9,66ca5dd9,8788597d,b52b88a2), -S(2cb38e47,c18dda23,10852993,6a668f2e,aa5ddd2,b1acbe2e,8d772c00,18a0b513,6ae910bf,62e0d313,fe326bf1,55e44d88,c85c61f1,35862d96,57237a8b,42310ffc), -S(b98cf874,dc156aeb,f85fe931,af406e75,2e4a7738,bb22db42,5a853949,e152dab8,bfd9ea5f,e8f9fac4,bda888c3,7e37e2e6,73d3262d,8cce54ab,f923fe5b,6afa964), -S(b907808b,678f8eaf,b29d69f4,5f62d8e7,990be642,1f62087e,8002216c,5f75d851,8e01d556,f9ab18ba,711596f5,61294f50,432b429d,5bcf101d,2c7db554,7f2881f9), -S(158c96ad,32e36ffa,1b67a345,a650d15e,e3caa5f8,eb9f391f,f14d04d4,a3299700,f63742a8,a8d39d2f,da081040,748d157,18c9bbc7,f228a768,afabc69a,7897dfd8), -S(cd62d2eb,1ffa09dc,e6d5596e,fd6627f1,a40e1d6,46e58d0a,99fdfda7,1e1d0665,9d0d6f0c,3e02d85,b99b723f,90acfa03,38c1e021,bc8bef01,9fb0deb6,ad41836b), -S(1616a7e,c92bf575,713bf433,e6788774,2ffb6c2f,f9ce2db9,f0df6149,fd7acf66,baf4dcc9,574957eb,aafbc4b9,cf6f913d,198cc26a,d98d9640,364bee25,6c76c22b), -S(e7ef9ff3,6e86908f,8cd68871,838ed08,2873771f,2df1ee9f,a74f8943,f2f46a3e,ed95ed67,65626e66,8cc8860f,b268b28,e9e4784f,4d704af9,3427f645,4f65e081), -S(9d91f868,ddb1beb2,a986d7ab,2e6c8da7,65e2605e,e1cfb07d,f368a30e,239b16eb,55ef3a1a,284bbb2,d73e4fbc,2f92ed35,b332c77a,fb19cc90,ec98d964,dac6f8f9), -S(609af9ec,3804a542,833fc7a5,bffd7bc1,da753dae,2de2e9b8,296b7327,b04da33e,fe876bc1,8fcd4c30,5bee3437,77a27231,c4e1baab,cd0afb37,9469c085,c416c8b7), -S(871a8cce,60560ca5,83896884,9bc3c7d5,3d9dee7d,ba988495,16258f64,23ccce06,2b557be2,d08dd1a6,126c798e,ed1cfe84,340aa979,c38de116,dc01e442,39418023), -S(1475a480,e6da65e5,ff84f5fd,d926f302,6ebada5,6f32c036,c7cc1375,db1df8a4,1e35a8a8,b1c38922,555357d5,69ef412b,dd0338a7,54e58ca8,87d09cd4,7e9fcbee), -S(4e90a94f,cf609448,27b69ac9,7c758057,9aaf77,54e068e9,db68f50f,6d46f68,5a7532b,13f4224,b51542aa,6e94b984,651caf84,37a16c56,1583d227,8099cd22), -S(bf8f311,7c4a9500,8fb70bcc,2442cb8c,bb5be275,f1631dd2,e86edbd6,6e239845,2f8cfd98,1dbed87f,4c51d621,8b308d4,76ee4e60,161509d5,861ff2c0,72a0cfb), -S(ee46cc95,d118b3cb,6c37dd09,31f42988,ed324ceb,9a6cf226,87fdfe13,1bac0cce,4bd94958,867907bb,4823a7dc,9e3deabf,a3ec504f,a4efad0b,146ded5f,3fdc67df), -S(76c7cc03,ca94b2fa,ba2aa8f8,b571d57c,6849461,5aac6385,11e28d0a,4345d4ac,89e964e7,d0c2bdf5,de3be34f,886d6b2,8955cd32,5e92ceb7,b379aed3,b216624f), -S(ee37e6e4,bc5616e,59748645,72e2c350,d43b1f5,fc6c672b,524615fa,e6a5e14f,8b721572,f7fb8c3e,a108c05a,1214ecf0,4443dee3,89fad7e3,86b054f9,1f0c3d5b), -S(e1c7ae02,561bd2f0,1e64844d,ee3df837,eb647df5,db64bae6,96c1312f,d9a0775f,932381c1,1bfe3926,37921d4d,7e1ffc39,8aeb52a5,b113d01e,1b78d0ff,106f4213), -S(6aa0b3e3,98f6f75e,f13994d9,91cdd270,c025c754,67ddc374,9fc530c2,7edbc255,5282fe89,2d97a94a,e4c54bf9,94d9db69,8f629f58,fafcf7a0,e18f85a6,574ecf22), -S(a4c83267,3ea49743,16e3aa95,e5d9ad46,30818d04,58c6783b,5f305e04,71b7e980,10eff981,dff167b0,119286f9,453ec889,a98ab7b9,4acac35e,f8a39745,2df75661), -S(d5b2a546,81726474,55c45c43,a5e900f9,4bdb83e8,8196e3e0,17cbde94,c2f2cfab,d0a76d60,dca26b92,e0a91901,d9b414fb,eb90155c,89ab67c8,351e15e9,da1bc7e7), -S(c7ee2daf,b3d220f,8865a578,6b070507,533d0b2a,3ebf9379,da04c68d,fc5bae5c,ed030df9,e07b915c,ef0dffc3,d2d24cc3,55a0af4c,f6462786,7f322b21,78420cda), -S(1327686a,b3a0cc7e,59a8f6f,c3cfacde,ff6c17d5,9100470b,94f04bec,ba82b09b,1ca32583,151c8774,6a84b527,313c79c9,dee0cb5d,3043f584,6799fd7,abd0d07e), -S(1b245c2a,3e49e7b4,4d35701c,f6b69597,9df760e2,e65df3d2,b16e8a5c,efd065c3,7ded9046,3a7b9073,c30fc599,eb8660b,f3073166,4fd147a7,d5c33903,ec3f046a), -S(d48820d4,c768c172,43727ec1,8b7d4824,ff214bba,1f079eed,828377ee,e386d651,7ccc1a18,5b0018f3,b7911938,21a30185,c18f3586,9d34dddd,4da1f76a,a06ff703), -S(7dcdd09b,ee384bef,55bd4591,82b7560a,aced0ef3,9037a661,317d911,38562054,19b815f7,c2b8370a,e4cbb9a2,facb11ff,b970c050,26ef5aa6,e92713e6,f5cfa3a0), -S(19b26e20,cb023c5d,f474cc3c,12a80528,aaf0150,bd90a19b,9f7578b3,c9624a85,71ef67ed,d954782a,a3fb9bd7,c7b747c9,e9101ab9,2778c401,18c96ddc,d1458273), -S(9dd490d6,f1ae170e,598c17b,3acdd8d6,f50f32fc,9f956bcd,8e2497a1,5af3f29c,e62680d9,4f21d3eb,4ea278d2,66c4bce,ece6c1ab,e6fc068d,ca9d72f1,21bf3903), -S(6f12b9a9,71263232,4c15a533,3726f032,2f634d81,964e0b15,b20dc998,b085998c,34fcccbc,b4177216,24471698,31fe129d,a90ca8d8,d95a62f8,cca5da0b,505d0b3), -S(b011c854,19c89036,77c6023a,bceb8a0e,496c2021,e0448993,87880eed,9f5c2764,afc0603f,aa87d081,5449686,d9ebd182,1f33f675,35d7ab18,5231e8f9,6c5cfd8a), -S(c7ebbba4,5d2c4b92,b71b0e50,3f4c4e99,d9b61fd8,e3bc100,dc3b6b42,53444c10,8c042323,c7a16c9d,32654e6e,240f5c97,901fc2,2f6e0840,de0ad053,7afde378), -S(95d1bb83,27dbe838,bda8e60,7f23f193,f43996bf,5a548270,fd296f9a,7ab93eb0,d15aebdc,f5432a03,3ddbd8e4,42433984,d1726068,634fc49e,ff0dc9be,e843842d), -S(94897726,856037d1,3e009a99,cc799006,388a0eb2,d34541ee,f548ec75,585abb64,7552c109,7343f999,9d97f0a4,ed65910f,f1d7ca9e,542d9b4a,3ecec791,3abc4920), -S(77b0dc2a,158cf2b1,88a98be7,d1b3c1c9,fd9b2c94,a2bdc2f9,c3597e77,e8572823,ff3dee13,5d130bb,c5c12bfd,73f73aae,c510ad84,cc9aee31,f28ba147,e99554f4), -S(47f7ddb,bbba408f,fe233d83,627582bd,a4d8915f,4bb5386e,b0b039e2,ed3706d4,63c6280d,be656fa7,81389b03,1d70ae36,6146f7f6,4fd736a8,8d9edecc,a45d2710), -S(b6561d0d,9673a6b3,4005bf53,20f74c4,acac0fab,d065d10f,8a61d5d5,25145020,dbf3f35a,9bcf58d3,ba3a5534,5229918c,a4461f1,8ae692a8,aeebd8cb,1e66782f), -S(fbff78c9,1c67bd4d,75d62a12,b679a4da,ba352a0c,73ab0d91,96ab06e5,c7e7052c,e2266fba,7e71ecf7,a6862bb5,84b1cc9b,6bef8697,fcba312e,649e836c,fa0fe837), -S(fc7e1250,3b630005,f488c776,9730f43,f5a4848,edaf869b,68bca480,22f85ac7,f8170409,f312edee,fa00b1b9,b62b463a,b7e0ecfc,563bf6f5,543ae7a7,10885247), -S(84f2f115,9fdc3a58,df6a2971,9e2dfd7b,165d1052,4eff49e0,6ee53a9e,6101f30d,50557807,24376a0c,215e44cd,ae1d1dab,619c324f,fcd5e766,89176f71,363d7998), -S(41f89dc6,3cc4169e,e6dd6317,d9aeb671,c5e0f0c4,c29c1621,b9fc1c73,9edb5a14,29d608cf,75a44457,82694ed4,32924d76,79a33233,2e62b4fa,cbad3643,e6ff9e36), -S(2bc495ab,ca4e5879,fa277a14,6c07a2fe,98a07db5,ee5a145a,e042b578,bb4e9c17,87b9ec1a,79d3d68,b822a80e,721238e9,c2a75c2e,aca94cab,2fb731af,f964de60), -S(4b18ea46,1f6468f4,f1f6b709,a00934b4,818032ff,61297f0f,6a4cb057,8cc4cd90,4f491b20,32837a07,171da3d,2acc4191,11eaa82f,db36464e,fa675944,a2c4f986), -S(ecfdc56e,c44009f,1206b7c3,bd3113e3,178e3909,68d6d2f1,cb85ce3b,b951e61b,5085e948,5b4a00bb,9f09efa1,17f83987,6711a043,1c3dd794,611b2c8a,c795229b), -S(6e97a5e4,2e911bba,c5f7ff6e,1c4fa9cb,9d12deac,2c13e8e3,1baa9cd1,3463a8a2,a86f92d4,709c635,f98dcdc2,e93d66cd,a541e49e,aec0ddb0,6b1c90bc,e692ccdb), -S(265226b4,253a201f,bb7db973,5558a4fc,e07c26e4,245e4743,2ab0bb89,e99a804e,51e617ba,10b8b90d,67f565d1,156557af,a967f03b,85400f9,975864c4,f5c2daab), -S(2ad97868,5a488eed,838560e8,b071aa47,565c4bf0,67337584,c20f8cdb,b2534169,8cfd2d8c,4d7bba3a,9d9afcf,2ee1d594,1c3aec8a,8e532e1b,def7e232,b3ae542), -S(457eaad,8c46f083,56a2c593,a65b3d7,74ee3292,bfc812b6,526aff72,8ab2b495,3bc3068b,26008298,5186ef55,7c9c6731,795ff1a7,34657d65,e97dc564,cad5a019), -S(dc83dd36,3ece98e9,636fbabf,96610f56,c74d0518,6ff0658c,e1e96aa2,8a488c7,ffb4642b,9f07e134,a3daae04,a7895645,ac49d6de,7cf95131,a9847514,786b4f76), -S(36962a9d,5731fdd5,379870f2,6562feb8,38f733dc,cbd6726a,41112d3a,c9df3cb4,efa15b5a,bd55c577,82e95c2c,12e54992,d9728e70,31566878,85e19362,8d55af3e), -S(494fa294,b5ac0d72,fc6f7f7,6b7e60d4,f8ec6399,dd1f4465,e57846b7,32210ea8,e0b00b97,71079c11,2a5a6e32,613c5d0e,420d1a5a,3212b52,71d0dbfc,4e6d16a5), -S(4989c175,23783475,36a6fe53,a6f135c,a968484e,f7305e4,f80b6d95,cf41b30,75dd93f7,f04f06b8,88a19ece,4811c5b8,9992825e,9be07f8,c212b660,13cd7017), -S(677e82d2,8b74f3db,73a8230b,98729acd,6b010356,5ba148a5,2438a5c5,436b6fb5,1ad2444d,b7b84e6,c4e2f573,cd2fb644,f3823c6e,81a574dd,bb4777b4,e26ff10), -S(c379002b,e70b8de9,80af55ee,bb05eb6b,ef0beb5a,102e2172,687f85d5,b9984d21,127b0907,fc511741,77cc7f9a,9b36c334,c23d1d72,20267878,391644ad,dbacf331), -S(39b33368,5aa7ef10,fd223b41,3c375334,38d06cf7,5b27ca06,3fd5c8e9,22cca4a7,88aaae58,acc5c41a,807e644f,6cc1bc3f,1f147174,994e0440,ce678f78,d783433c), -S(825be64f,b35ce8ed,85cb6826,79ca7677,5a40bc3c,105828f3,a8b30595,ac3b6b21,976a3b6b,dae0f22a,e33f3d36,7d3fcf21,29f2ac35,e8239df4,553a869f,18650183), -S(47d9d5a8,8bac6136,ecf568dd,ea7ececc,57f26b88,6fdc05d6,4c5b7ae1,113d3a7c,c6863fd7,e05f3e16,c0a47eb,6c2b0581,184b8d8a,550da1e2,370928cf,4d7b2804), -S(bb7576df,abfd677d,6545db2b,69af7d62,20ba17f4,f4ae2881,8ec91a0b,23487df1,b5df0436,9d7227bf,67953da0,ef410f0a,a7cf80c7,4f3c8c89,de6cf1b8,7c65d16), -S(6febeee9,251bea0c,d43eff7a,da9dc5c9,5b86db1e,b0e09bc0,4d34fa4c,4ead4508,df691ae,ac9bda8b,496aa808,949d348,97166b32,3f99c9cd,a851f68c,26a1e39), -S(25fe413a,59744683,ef244175,a8021b6c,62e7c2ef,c6489261,958167e9,10716fb4,8be281f6,2df1bf49,8823c080,69849a84,b1ce138e,2326db32,cccab7e7,8c8a1ab7), -S(1389327f,be427f53,f219b978,4faae37e,8337f5a3,1c377bd3,415596c3,e72bdaf5,fe33fffd,a7bb26f1,34340613,ab692eb3,9a24916f,37b66df3,194ac53d,1f9c1a99), -S(1a3221f,30f9ca00,9e9b3e7,ac40dd45,b7b37b5c,1cff9c34,25cd5375,48f6fa52,7a105b3d,25b763f4,15fc1ff4,b8b3b964,9c1f0317,a6c4fa25,d731a120,562730a3), -S(ece7fa3d,55e6b94,4c6beb50,b6ae339b,69ec8a46,679e11c2,7c703056,4cda225d,68be5c5b,fa975326,e5bd41fe,7187ecd6,b83ba698,ec98a7c8,9c8ff6b,d207d5), -S(9fd0196e,91eba507,74f75e0f,980c4737,ac7ede54,4be0a8e2,c1a852b9,4799d10f,bdf3d80b,fc7ca162,76417e3b,b9caf72a,6e94c84f,c42e8091,d3eefaf1,ea790dfe), -S(db89a9e8,703f23e2,13300b25,f952df32,853691f4,6fa6bade,c7ab775e,21a80fad,504c9ae3,c9a9e7ce,ccad44a,8f97502b,5577db41,510b3e13,8ccfa64c,2fbb0a31), -S(32e762ff,a1b84c7d,c3aff832,a838d555,a9ceea5d,7066ae6a,efbbf96e,5f5c5eeb,ad842a97,ed1f274e,d3bb0460,309ce41b,f7e9cb55,c7bb5d3c,3b2b662,daf4c419), -S(8e7328c9,93fac58c,17d2c9ce,8a3959fb,2c0c8c7f,a4d583a6,c4428f9d,98f5d1ca,b5370e52,815ba519,3fa02e95,d75a7168,e1906ae5,12cbec72,4bcd1a9,b897b8bc), -S(dbb8e270,d516fe0f,470e325c,37707a03,3607ca5f,92c6f2c,97c32f86,1418ecf4,3da4b926,7cab86e1,7bd9442f,f3bf2c41,52aef531,f1d028ed,e801215a,7204fa86), -S(5dd9b4a,bc618666,12cd3344,2d8e068a,fe624850,1cff8c33,87af5881,c3523544,51f5b,a9a010dc,6e5aef1a,138251aa,dd75c5fa,caa222f7,db2d4218,220fbf44), -S(50a74f67,90a95b14,67eaa018,9409ba38,7edc5abb,4f2c408f,5bc6a5cc,6724ecb4,d32f7031,9f9162eb,861255fa,42495a6a,fefc8949,d36150b9,c4d5b066,7b41031e), -S(11721064,55ae2391,2c2e35fd,190ba29,6bf1d580,fc76cfd9,1fcf6a02,e77ac992,158165db,2865,968604f6,3fbd298d,3a079619,a0c161f1,35879f14,5091a41c), -S(570cb8ce,d29b407,f5e4769c,57c42796,b1c0b111,684c5a7b,fe9ecf8a,20b687fe,9826e697,97573a61,26d7cada,c636530,ea747b41,308874b0,a4fa578c,b984814e), -S(5adfd4e9,142a8f6b,1ea6aa3e,14a83fc0,7e1df246,279082e0,36b8e2b7,dcc30637,82314ea,36edc02d,c489c36,c2b0d808,d64167ed,1cb33651,418e3c08,7732c97b), -S(b26f96ee,37d49fc2,e4e76f4d,257197a6,f1c667bb,748fb69c,29d9f033,b94419a9,bcd2178,aafa4409,329d735a,60bf2fb5,60706e87,295c6d7,a7a7e0c9,4b280542), -S(dbbc5fc1,ea84b079,90bd1af4,fd244599,70bff024,835ae3b7,129f6caf,290c4bd7,78612296,2b62b621,6f43f734,eab00121,ba5a5b3b,81090a4c,ebe2cb8a,5a02591f), -S(e4d32dd2,710624c6,94120041,36639e21,708cb3b7,a15682ea,57e80ebe,a13738b9,3aaf833,3a7f31ac,6d6c8b85,e0831fee,3db67209,f35b0362,3b153677,6d7a4098), -S(81c6fed1,b687970b,d3716384,5c35061f,e9edbb33,bbaa609e,53a835b0,c13d6a15,934cc11e,e733fb68,1a575c98,cace3279,7a6fff4d,6bcbed2e,89836fb9,3b83597f), -S(28a654f9,58003817,95793,46ddc440,13c07f78,79c3b247,e52dbe27,97a02852,10de9cc6,571f24a3,6a08fddc,1ed27cd4,a9a0cb11,5d275d99,ceb60676,43773965), -S(532c99ae,cc7305db,5cac0294,e25c0a0e,45e270dd,4f621f2,d1e36ccf,51cb7a48,8ee3619a,61df9f49,84259ab4,744f563a,bbb45462,9eaf0670,5240d67,6b3240dd), -S(de02390a,37ec8a18,2a5891c4,f8041ef0,d548f367,4e8a91be,9e29e0ec,2b822e8,8ae501c4,32e81681,844fac5e,86bcca09,aae6f862,76994d93,7074c1ce,c3a04b33), -S(877916bc,6880f1b9,530af368,1ad44238,dcdb76cb,ef1d3f61,6856566f,bb6da5a8,807bc5e4,5c400875,42804d76,eab0f291,499622b3,dc9a7e81,c1db7839,ebc5a5f6), -S(5980d5f3,4b0c3684,a3381a84,434436fd,e0a0d6ea,1c8f16ff,b8a35793,74c30e9b,9d20e10,5e51e720,95d95766,7f479f61,34051c24,b09c8a2,125fb9c3,6a0b4b7d), -S(5246fb5a,4fb10bd9,c240b274,93abbfd0,e404f444,13f0a126,5d8fae3c,ba805fa9,8aad021b,c7317328,6ab78e8b,3e3cd613,9d881233,d1f62cd0,9a3d6260,88886c7d), -S(9b5ded4e,dd6f9c11,c3e9e760,71a7e257,74d2ea6f,c87412e1,a918f2e0,fe2075fb,80fad92,396c0f77,216187be,66619a53,d6a6ffeb,1ab70ca2,d64b19bf,2b0a95bd), -S(d2d4c183,c4ba3336,2aff6d81,263a5845,b76d1e3e,6f5a0a0c,928a1887,da2b03c7,ea15aeaa,b602f360,f3a7faef,fbf2725a,5838d041,70455d50,6ec5e1bc,ca651b2), -S(222241f9,b3408b3e,a8f7bc96,67ad4928,183557f2,754b3972,d5e938e6,36ea7857,cc2598d9,4621a8e0,3c8b444f,bc6b68e,ea584144,c770d095,b2152891,e6bde708), -S(14cc26c7,c26fa386,e29204a6,99b24119,c8642d24,256e9fa5,407bca7d,4e69c32d,9b125adc,dc2150ec,5181d2b5,5a862dc1,4de72a2b,7a04e912,cb2f6503,24101dfc), -S(292a1480,959eeb3b,468d54ff,2944786e,7702bf4c,8ebdf837,edd65177,1d5a971a,e7355cf3,e1c089b0,9362b68e,83825a25,39c88058,8dd6e1dd,ecae9447,ea4b6388), -S(6c9f4196,a35d0a9,f0517c9b,2c04a420,127140b5,ae9d2274,cd5eeffd,140ce3a,854d6c38,df5604c0,1d65c8f1,9f5e89f7,4c6b1c9c,2756fb9f,8276088c,c39dd80e), -S(fbd63ec5,8b3e0c43,4033ea2d,f4a8cd55,b4b4d24d,d1f8ed5d,6d8b1b6f,a14bf30e,e3770f0e,7b29f62e,9921f8e,2a78d2c3,a62814f,97caf2a8,304a782d,b72c6b50), -S(df91d6e9,b046fc63,d81d94b9,aad17096,a2c7fe88,b95e423d,edaf12a2,4a2edf87,2cde227b,ffa27e95,ded3f142,41d26599,da28da39,16227b43,e665aebc,f67a9fae), -S(b2ff741b,8b5d4cc0,aa987660,59652337,6ac36083,e784a181,63f653c3,667fa2fa,400a34a,e6990fc5,7e268eb9,ed2ee2ff,dcbb27a1,26f0c7a7,937617d7,19e7b0be), -S(d156797b,9de0ad57,41b759ab,38e8f935,d352b464,b01080ce,70e22376,8d6b5e23,b7e64c4d,fb332c98,9d21c2ee,67a5d5cf,d728bc07,9b448283,55d9e6d,4b0fb3b4), -S(a3814ee5,e242a6a4,65ad0681,a0193dcd,16538d6,1087c6de,fd362a8e,671e7ed2,3be12033,59d441ba,d59d88a5,64d03ce0,c67a5d18,4f883388,96f7caa9,e3dc96ca), -S(6aab0cb8,b46728b3,8b78d386,d45122af,c95bb1c9,9298cc77,299f2fd2,b5d72586,fcdcf718,caf0c93d,1f3ec76b,b4060f8e,a3863736,a5d966d7,c617fac6,6f530753), -S(5fc6e596,7b508698,4c99666c,22fc7316,54b700e,55877f73,169241ff,8b759937,57af0c61,76ffb00,626a98f7,ecf72762,9746b0cf,dc8a8914,683cc49a,6d568505), -S(7f3944e2,bcb3cb25,e36c8479,ed51019a,a61b1122,ace99dc4,82ac38a8,580c6d2a,dc039090,54244e0f,6acb6d33,fc4fee58,8e5e25f4,b23cbe55,5a330779,872f2062), -S(5485c8db,86078936,14fb7a19,73651f6e,66ad843d,e92db2f2,c4db2d5a,bb7316f5,ac39c239,b0fda325,44bfe05b,1a4ecfab,7ccb84c5,db2ec999,6d8587f7,d15bb82e), -S(e52b9934,910510fa,3611dba3,8630853,d0cfa8e8,ebd64a2c,7b59bde5,edcedf2a,cea4d745,64e8df98,d47a3ca8,7f1e45e4,728e52df,f383e391,6dca08d1,326a7e38), -S(92b17ef4,fb8f8dd7,e0307a,672b37ee,78e0dfe3,e19c094e,44a50c9d,3ad7faf2,5bd53e68,dbcb4e47,18266085,9d12a34e,943691ee,dd034cb3,1eef8a29,e35b762e), -S(7f8b2952,70f6b2e0,84503f9e,df24fb8b,e91393db,64a90971,5e68b009,aa9c3b6a,c45f0d84,d9407856,19a87d38,296f70d2,41ddf1b3,8f421d12,fd2be1a9,32d2b437), -S(cbb90912,403439ab,8d04714a,1a5ee460,70202e4d,1d7de375,36754bb2,4c8bd2b3,6966ca4f,bedcb6cc,64d72eac,fa1a699d,977dde05,5d2454e2,9deb220f,e2f51c11), -S(7d4ac2b0,6d1810b9,a3e823df,ece821c7,70c90d2e,ed0bc324,9ef1a43d,bfab3043,824fb46d,6afdf15a,7979b032,28588c23,4a9add5,6f512253,780acb93,ed7ff34d), -S(36482902,2ab638a1,df90feb6,c20ed6fa,fa81ddde,87d069d3,7cac4a6f,e92a9b32,af6530a8,1c62e72e,409d1308,d07fb227,63afad97,8e843672,b241ef60,dbb36aa3), -S(73f4eff1,ec95095f,be5d307,8a9f6db2,23e9b874,bb2d077c,c58fbdd1,d03e1f62,d7c0f36,5ab93ff1,999c6f95,d5c6102,47341004,1ed97e8e,9632b845,527078a6), -S(9a88fd12,af0611c4,b07ae62,59767f24,308d1aba,529886ae,6ef7f5ed,22e98ba4,a16e8f50,164ae75d,9712b544,ecdbada7,725c2144,3e8044d9,f3aaec64,367169c8), -S(265e4dac,6139efd6,a7866385,f0bd1cd5,e8bf205f,344ce71d,3c0ce073,766a6619,ded5a75c,ff4de7d5,f33bab64,d000b65c,e5078ff6,c01930dc,17bfc64c,826d103f), -S(6fe39213,baecad17,f8b82f25,d7621cb,3f1b1a07,2333ae38,d2d00a6e,ed8aa1a0,d6b830ed,f36775ef,7cd7c648,180a6edf,be65ab25,7304de39,791733dc,f561172d), -S(671f82c0,ac712083,8cc32fc8,85ae272d,4bc59e46,2dadae48,b4dcf279,707776ae,4aebdeae,2c42a80f,fd433d38,ad4ecab8,9e4dbd3f,d73db0b6,ae72e78,6eb7aac), -S(d83ef3be,4630e5d4,edbc6628,828b40fe,45806e60,83094433,31be3042,814bf4fb,ce89b788,8c93be59,bf0bffa7,adb87c4,a4fbdb78,73de3d04,c62b5a58,18e1ff92), -S(de2df94d,78cf43e4,720da5de,7f08de15,4b271731,8bf450f5,667956d5,596cc60f,61c4585e,3557c10c,8d22671d,8389c508,195b0ea2,e9150ed9,ca93fc53,3892283b), -S(4bf44266,3d4c7de7,872aa7c5,e5ae22a7,30dce19f,78d92abd,1b7e04ae,fa3e5dda,ea831ab3,b59eda4a,8e959003,c4a6266e,d4f691f6,1514dbef,18409b03,5b2a6594), -S(4912c91d,38722c4c,f00aec0c,895980fd,af4c6351,33021e52,ddf0ad4b,89b67f7a,f96d3a36,89e4838b,116b1529,55392373,1be5f0d,30b1d541,6c0b7839,1b24ba5c), -S(8c0bf82b,d2cdc2bb,49b2161f,9f0a528f,79f8f8a8,1b919b70,9fe5a46a,c26d417f,aa98d79c,1869d92d,251d322e,7bac3dc6,5f166c56,28250c29,9be63e4d,ae430dd6), -S(83eea34,4eb8bc40,2f4ee569,1d89214f,dd3ae674,d60cc0ab,9df0fd42,7559e0d7,9d7f5834,fe912c9f,23790306,3aa41b6,33085264,e6621a9b,9e87e151,dcb2562a), -S(754addb5,a1b21e3f,609416e5,5792c265,76b90660,736d0d0e,364aa13e,74b0a699,3145763c,c0d95a33,5e443b3,5dacc8e7,bdb2904f,b868cb27,3a505475,511f3dde), -S(3e513f87,e381efdb,14dc686d,14d85d3c,bf725e63,9d934de5,647823f0,c4eafee3,360be751,d3f097f0,b09c7d0f,1d425cfc,88e400fb,7a0aca3f,9d521e6,e79eb87a), -S(ea4cea76,f7478452,7364965e,546a7356,55d203d,5a92c3fa,336816f4,983fce7,a1b664b,e74b830d,8a49eab0,165e6945,69ce0518,98007000,e8094f92,6b3ba536), -S(eaf39608,61712ea1,88c9a2d0,c025d56d,8b52e59c,ea35f298,41f13759,625dd824,96ff00bb,eef7e8f7,23f2c7bd,7d6c3eb4,16827208,d3a2ca54,d40dbb83,4e13a2d), -S(34d3a7ad,a590d9dc,2547b9c4,b99a2e10,9689320c,61105415,c50879d,4de223c8,49eb6d27,eba087c3,1252084a,d78e187b,89473be1,1032e032,8a944e48,ce0a7bd4), -S(22f0cd6e,9e232e52,d82d70e7,d1ad0df9,3638bea4,8fa0bf16,4ab3c7e6,a1d961ee,66d0990,b57c8e13,4e2818b,910c27b1,7eb33daa,90ad5b2c,427b91e5,51514068), -S(27a48cff,114f4f76,bbce0d83,458a949f,c80b8821,fdcd35c5,b3810fd5,60d179f3,41690918,b0599515,f913db47,37083743,4f62321,72084ad6,7a730af5,b32d25b9), -S(2d845701,6ecda7b1,3a2a72f1,cdf24c12,8f4d85c2,c4b72881,45802bb4,603093a,50f1e7ed,ec9e2dd9,55678abc,e5ea06d,12ff61b9,baeb1d56,79055c32,d8654315), -S(cf2d9ab7,92247125,b0bccfee,f77a5a37,5e796957,75950d0c,af401a12,c8fb9a9f,8839d0a0,850df254,3e77dfb6,cf06f424,dd16c26b,f3aaefbd,aa3cdb5b,d0ad818e), -S(de85e4d3,75463ab0,a198a6a4,1d5f1fe4,c56af2f3,786ab9d3,705f540d,6b5a3770,1ade7a8e,1f9d595d,b67cf482,4c8e11fa,561b3625,4ec5631a,68d73907,8a9d8eb2), -S(c18e2092,299be419,77e40102,c9d4388c,84d602f3,770beca,50c03008,55ea3a66,86b9b3ed,786a570,de95e947,2fb0e61f,ac4aa85e,47792e99,25738e5c,3c4af6da), -S(df9ad184,a9e3b41f,ecbdaa0a,a48e2252,944e0384,538300cc,43f9ce48,6b224422,c4061799,db92d160,de19c4f6,a1280ca1,b62d675d,b7fca41d,ca838bd7,3d082fab), -S(fd846cbf,66ec362e,4d10a783,ba60c734,d9577ddd,18934ef8,81ee755f,d3748a95,d6db4def,d6c742a,e50ff8a4,43336754,d4244a42,a851ff72,7609a016,d0c84d32), -S(5e86fa96,c29e30f0,7b845438,5f39ac6f,43d120fc,df10d891,ef60e2b,141791f9,39f5ad4b,2e86a92f,3b38e286,5d7e1ec9,2782845b,593d1d4e,43ec73b9,2dfd6440), -S(8744ac1c,1b16d65d,daabc8ec,d6cfc40b,109dbd9f,c19e4439,1e2ec486,ad27293c,ab30e186,e4f2f48e,51ffed3e,46dab701,ba78b9af,b6987166,19c642d3,9491f1df), -S(9c4bcac1,c0a0ca58,debc6c0e,71238988,607dcdf1,415045df,83697282,84a31c1e,6467c5b2,32947b2b,30c32a18,174035df,d813d42c,593b37f9,2a8a05c5,52d2b7cd), -S(3766aac7,b9a2ee6,27691923,ef91cdb7,30a24727,2da61421,955ffdb3,5125cb7a,22b7d930,94110a51,ac72dc5,9d2bc66e,45349a1b,90a7c655,4464713e,6d2833b4), -S(e7f2d315,ea0d0f71,be63c896,3c6ba75a,2122e650,fda59f27,b4ee627c,54bdd30f,41cec687,9e6c21cc,99a3aaf7,e4fc75d7,ec163a4c,6aad8a21,22da269e,1e342d80), -S(cf50bffb,bd4aff61,80be7e75,e9004d85,2234fdd0,7b0b3e13,1b883359,7e96f40c,7c9eb80d,7808d937,eb5215a8,4ec4d330,565b2aa2,162fc4c1,b46bdb19,b93fc159), -S(5aab4d81,a4eca88e,e9cc0c20,94ced3ac,912ae932,2834a67,324aca30,956805d2,64d622dd,9afc799a,eb495ad6,dbdf31dc,7156ee66,d8a5e67,c44bf50a,94fac52c), -S(a4f6d781,9dd34aa7,18166000,79d8d7d1,eeb5b971,4549cf3e,a472126e,3cffe8c3,4c87eace,b4e535aa,36ce839c,336fe9f7,d4b0680c,e61fc525,4633d38f,a8c395bc), -S(3ccc6b5f,8188f3b8,b5805bab,c95f08d5,9b803e03,febb6f49,84dab325,1f6ce719,5b4987f1,7f9e2610,e443cb1a,2df24752,72655670,e739f0f4,3ca9c3ab,2a4dbbcb), -S(2d0a94d2,5bee2c99,1d8b312c,251e305a,5f44e1b9,29bde36f,a973e51,2919130e,f9cdc9ee,528a45e1,5d1ad338,db49b3a4,2db74785,d84cd12b,59391140,566636a1), -S(ecfa1649,da1a0bfd,41ffc294,40ad7a91,b6ef0d97,115408e7,3a05f506,e1aaa6e9,7f8a0b16,4b817533,84970c00,3c497414,ae319090,7481fa22,9a920004,8e2783cf), -S(4b97331e,38aa629c,14c37220,b6c3241f,603bcb0b,6b07a66e,c74ad1bd,bdc25d7d,65524ca8,ddb85804,a2111e69,17167d2c,105a58c3,321c27c2,2cc0256d,c30761d9), -S(acfc4bc6,99f3af13,ac70f25c,ed729ef0,866b900a,6c39705a,5e0937ba,fadd2a90,70ca7ebc,923aa022,85f91b19,3c550487,172f2f0a,8f10f0c5,29384cae,20167824), -S(2a984810,805a9eee,d24d1ba5,46825c6f,aea09889,132295c2,b4ec7e64,8db9826e,b56a531d,7fb7e8fa,ef957956,747015be,dc28da96,eccd66c7,c2727529,c2a45ad0), -S(76c6568d,551abc3b,f6102d02,17a440e1,36e80776,135dbe60,7581bad8,2aabb2e8,81e56168,c16473a9,bdadabf8,339c04d1,5d3cc74c,56465bfb,2eb0b2e2,8bd4f82), -S(6476831a,3425f0e,e8ded7b8,be239bf7,7b16d271,eb1d4b36,ba7f692,a2f155fd,90cc74bb,88acd0b,cda7e17c,48056936,9dfa8ba4,ec8d6f85,eebb19ae,f35ce085), -S(b2b49ada,50eeca27,881c3b6b,656df825,3422e3b7,1c145401,e92c5ed8,fa3dc51b,4f3f9fdd,41d2669d,b087ebf9,883f4f9b,383c4241,eb87898f,1e916392,d6838820), -S(75448fb9,5c0162e7,c3892300,bcf070ec,dc49560f,8c0f1665,f0bb081e,dcd12e05,b0b84014,c73db3a5,9963812,d99d6d0,5df7d46a,6a646929,9868d874,6308beb0), -S(643e795c,1c158422,24ccc0f0,97c18b11,dbe1fcbc,df8a4e2a,f234f465,f42cce3f,a067acf3,5c7f2e05,4ee6c40d,1c1f1eb,2850c9f1,8138642f,e6becd29,46e3d604), -S(fa200bc3,6ecefe8e,9e5c82b5,1f380c2d,a14b0478,6329dcde,9dae0546,4d109dec,8c6b6cd6,a676bf1a,c7f43bfa,29d6863d,87740099,d5a06e9a,eae4b885,44d1ecff), -S(851fe9d8,e47b0186,ce001821,59c674d,390e5481,fadf397c,67a2a35f,8cd7b1c8,e6e7b57,cc25bfa,8bb93e2a,f934e154,314dbf3a,37549659,8952de0a,3ae55a71), -S(4e462e9d,d2995148,d0091e2d,94f5660e,a5a994d,6476039d,dc0bd812,cc47ef1a,63c80573,dbba650,5ae95b0e,9c376a2f,78fb0d86,889e0ae8,33e0b823,7932cf00), -S(3e46f7ea,4606f5cb,4a8d7386,bd0fa2e6,89f03985,b9ab7cd3,1baf3cb8,24e928f9,a4d3c20c,9ce14434,2fb14481,41a381f9,fe4263c2,ce955e7f,daef45dd,97c3948a), -S(c650291,432ea873,473dce0b,c34aafbe,24a752,fd54ad97,5da33acd,66c48bca,795e9965,74baf74c,2fdd9e2b,a917f02e,aead569d,9a5069d0,73341203,772ded96), -S(219416d7,52d6258e,c69ad11e,1a2a7552,4b327412,c9431211,7b57d960,d1e23c5a,916c79f5,97ff454f,b93332c3,d0643652,73861c82,68ded6b4,9558d76c,217278da), -S(d97d3e10,8f3eb83a,9dcc03c6,76755f7f,ada5b761,69859e14,bcd4e7c1,56dfd7c8,a2f0cb2a,2fc680a3,79aecd75,1cf7758c,50398624,8381a5dd,ac9c9902,65b18a27), -S(dae2570e,67a3dcf4,ffc0f56f,ae3dd134,479b1e03,8faedb8e,2e84bc1a,3847223f,817af757,125d14f0,c9841d34,f885209e,e2b79522,53663a6a,a3077e2f,43da2c7d), -S(6d2b21e4,33b168,a6eb9eb7,496533fd,b6ec326d,e7fc7556,84547cc1,2c9c3143,9ff9697c,514175f9,6082783a,a2bdefb6,439d6826,af9a61d6,5282884d,4741262), -S(de577780,8bf5caf,428cf519,9487a81d,8fb8a2a5,2bde22fe,2f72598e,3fec4495,8ebe9150,916a70ed,1c6384a5,d133210c,53e205ec,d0ba7a04,5a6434d3,e32df9ed), -S(d04f1378,7bbc4e1f,8b1c548f,4d79fdd2,8a0f8199,49d81b51,3c63ca6d,c5c6d3,5cbcc339,3050eeac,677f8382,8499c8bf,b3d43b1f,5ec98768,ec0a71a8,d81dc3ff), -S(4353b53b,ff906815,d6a58b36,ae02cce,cbaa3fcf,a2bdb5db,7dcad258,4fa18e88,850b08e9,5714b0bd,2fbc8f2a,4ac5980b,ad30ff76,1241a5e5,5a5f01c8,a221fe83), -S(8141ba70,fb997010,1ff2ffd,865ebf7,137340bc,9eaaf3ad,279eefe4,d80953e7,ce0450d3,aeaade42,e4c66c30,2da0fae7,595524e,debbe419,316a1d89,d238ea5b), -S(8676ba13,25c85d1e,af93f424,755d17c6,70d2694d,2d52b890,540f9826,f2a1bfd1,df0c7ba7,8fbc592,46b5fb7e,8f98fb1f,ce1bff80,c23cc2fb,c1caffad,213a51f5), -S(c55ac2c5,1d918713,804abb83,e2109412,4494f614,109f32cc,62148706,98afc8a7,44e56fe6,6aa7b14f,44c6bf3b,1974e6c,dd8c7b61,73fe0067,952f0391,49512132), -S(72738507,f0b3244,e199409e,20eddb8a,8ffe7fa3,18930f45,ff0b1c9e,f7a15b90,ec121c76,e6f5caf4,7912cec8,4ae5c8a5,d5a9311f,a7f383b,d2e8622d,62e6171f), -S(f6a7158b,4dedfd94,6a4ee001,cf55ed08,33a57284,cedc4221,58cda87b,a0e1bbf8,2f37f2db,45ca86fb,b2fb6af4,df82582e,28e1e33d,bea3cefb,906d15e1,e7442f25), -S(8cb36d0f,40f21951,23ab2ace,e1ed08cf,de216970,ef6c6c96,48d79a1e,7760e58d,f397a565,d5eed2cf,427ad4ad,52d5d748,2b87bd97,ce31fb53,ad05cc57,2989819e), -S(c5cc35fd,5575f56f,6c050c24,769f4ae1,c0427e01,b953ddbb,4551ad36,93fa385b,6b5210a1,8e4b1d7b,592cb2ed,d1a66e11,545cd114,8541aaab,cf781d29,77551419), -S(bf3bbf0a,48711b91,74e120e3,b977a572,712271f9,842bab34,db42d1dd,7da678ee,6c711317,4fead9e7,c7fb5ee7,9b8f862,a3af320a,d97cd970,df12c0f3,84a3f3e2), -S(35534e77,c8dc6f7d,425d430b,b5cf4743,f3fed959,73d63a3d,771e5a5a,bf7da645,d22f018b,81b8f8a4,e2d297b6,f233e826,8fdc6168,4166f72e,2d89998b,4124159b), -S(6471c07f,de641ca4,b118958b,8ff9a9b1,27403eca,32a849c4,1b0ae1a1,b2d9ae23,ebb318bf,edcf26de,5d4bf68f,56fb898d,8c2294c4,7097bf9,2f34f3d5,6c535807), -S(9b8d568b,4f2879c2,1bfc95d8,1e97ed73,9bce2444,ad40156,7438ae1c,4b99c2ba,752531b4,92245df6,19251bb5,7071301d,f4a7f681,ce5ea509,18924173,7d00957f), -S(8a8673da,eb675829,cd5f3cb7,2c7434b8,d42c51d4,2fdc7a97,1681f7bf,4fd04e37,f2a66884,bb5ed9eb,f4e16864,3573135f,f65ad9f4,2203250,60b45cbb,1861a000), -S(b5048475,f56c6a46,db949469,2500bf4c,49b226c8,83576872,9524621c,c9807bb9,4727efba,45050af0,50b7847e,f5201101,591b5432,57ca917a,b9e6a210,20036cdc), -S(7d207c2f,40b9b31f,be509744,c325dfe5,c958c56d,92f43a15,511888aa,9deff6ef,4125af38,1e3f9562,64089375,965274a0,30ce04e3,9533b3bc,bc742b21,e6ee3582), -S(f6c8baf6,b2561144,47fd3cf5,a018b31a,846eae1f,a1d8f74e,59f315b3,43182edb,bf8137b,3aada7aa,7d582791,11d5c4fb,970669e7,2c160ed1,da9e1d1,4a2e2bc1), -S(9c67787f,84a714b,89a560f2,b876e92a,f8b2de18,6f8cf416,f5bbcb16,2e59d27,c0262b77,becc9f9d,378051bb,d2705bf0,92fd8a3d,b53cd131,aefc583a,b98e9402), -S(54d474be,7b58457a,929b9a7e,39e97b65,3478eabc,fde384f,681375cd,6896ff47,b8314502,4c1c2aa2,586342a2,f035baf4,ea086434,52ccf444,530b1c06,3e4ceed6), -S(e4dffb62,4132a5ff,6eeb946a,35f98c01,53b607c5,40811043,d1baf243,3bb23467,a580f3e5,d8d8e685,47e0c259,5e9c4d6f,a8616067,b3a437f6,ed43bb7f,a695edab), -S(d572f1e2,8f3eb14a,afe3ece6,585ee6fe,f49fce12,a2adcbde,d5f4a247,97c4a7f2,d9d268fb,2e80049b,b9a26309,69bc1692,c96b2d5b,dccdffc7,93305aa9,7011f88f), -S(bea4242a,5a5eb8a0,6f5c0cae,f38c3b81,4711a7ed,780e607e,10512d32,fb4aba82,601c583f,25936e03,ebc2406c,b248aecb,61f7ba27,894e4f17,46f34aa8,519546b), -S(e3179e2e,b6b92374,9c8f7ed0,40ff053,127a7d78,2da166d0,4639f55b,7cb74459,9a22f3ae,8df42fab,4b3d01ca,527c967c,7cf43f38,6a0d5751,8d47e7de,731b21cf), -S(8a973494,c8cc5c5b,4d8eb9a3,13bc9feb,fe6385d9,27112399,3c78e2e8,a732d4d1,fd2d15c,c9aa5128,c505fe85,786c55ee,aede07b2,94bf2466,d9845d3a,1596d8d5), -S(b87bfc57,7d8decd,3396f6,43200d10,946c0a7,f2d4ef92,4de7741c,e8acd653,62bc1f4,e3c0760f,82d953a,5d02a10,8ab3d0d9,53c463a0,295b063f,77f434ec), -S(aed2bbe,8ea08b0c,fc49c4a,4c92f63,2bebb84e,53027958,5b249cc4,c0ec61a1,76296846,a5391c5a,69df4e6e,44e9718e,622392b6,63a4ddf0,54b9e2e7,11a35bf5), -S(34fcdcb2,655b0405,2758c3ae,4f0bd15,2965dc47,9d7b63c2,b787adf5,6852835c,8b87ed68,30c88383,8eec48f,89a375f1,3a846f3e,ff0e8729,c1ad8e99,32cd4786), -S(f9586aed,be4ac742,2ad3b9f9,b8cece5,a52678b0,5b8ab318,1c6c2412,b470771,231f2be9,7b81431c,12539d6f,d247b4f,3d0dc8d8,15c2cfec,4526ab9f,e9cd6b79), -S(88125579,33848e15,f6c9d813,91e5eea,cf8ecdb2,1f55f4d4,1ff34ad3,a80e093f,d45c6727,c3340e79,a5256df0,41b4d999,e8910869,9620aa9c,bce6c3fd,7c17283), -S(ce1b52c7,f975a37,25f904df,9f602b82,52573170,96d4adc9,8043d35e,6773d354,17b65d8c,cfec6748,2a3c6d62,99dcc47,bfecad81,bfcb7d83,5f216f76,1ff9ba7b), -S(7e6885eb,5c8a5faa,6cd47921,54b2f5fa,4aa292f7,5fb16cbe,87c1ccbc,57501542,16a0e969,a212ae5c,6b4df92f,b3a510c4,c0b9ce27,c4f0f389,e77e4038,8c3cd101), -S(37589935,89c37714,3467b869,c366af1f,2d1566be,1ef950a4,ab1491fa,ed2ce425,2ab4eb91,cd533805,2020300f,b83a46ad,bb846863,6fb2a9c,c1e7c7cb,f3e56799)}, -{S(ebc119d3,8e794efa,85fcbd,5affac35,f73c7428,590ede0f,6365f1ea,87c65b4b,183a9992,3911b1b1,cd9b0fea,3667b6e1,52af7499,8d32beb3,d2ecb91d,af6e8a06), -S(28740562,ba21e3a3,69d80ec9,17b36013,8119b6b6,77b64cef,5f84f278,2fe5b3c2,2298a60,779ec4ae,86f9e0ff,7f981f2b,ea69e782,20927aa3,da793a10,3eb3d307), -S(12f64dcd,310014ae,81a7f6b7,fdcacb7,e8a9ec78,d28531d9,71ef3dad,af946fa,dde0755a,af7081cd,59da7725,e8246e97,2340c01d,eb76dd90,f0890923,54fb2d8c), -S(76134d79,133c485e,87a081c8,ce365757,f3beb361,c764220f,b16c1924,787cdf2e,2a77c2ee,b1cd5181,72101ebd,538d2f0a,10af3190,118da259,e4a53dff,d7a7b0c2), -S(89c5073,fa0877c5,50911355,475c24d4,bf8b8e38,8e9156fa,93021ed6,21429c8,40fe8b47,cdf3690f,63b3af00,efcc2aa4,b29c705,d04044f9,bb910671,b6ca995b), -S(bdcab1d6,157ea793,40f3bd0b,13365b24,b68641af,4e222d7c,b4efd8db,47b8905,b9d78e27,96820c87,850257de,746c6a05,5be5e595,aee8ced1,1dcdbca5,d92c5ed6), -S(da509ebf,2b7dfd80,d00c4c25,4b2e3b1f,df021d5c,cd1874fc,50b24141,2444e666,c3782467,e1606722,a76bbd84,dbdfd6e4,2cc41a10,cf50d921,d1bf916b,24459c50), -S(45da8013,3e8ee0d,f0a456d8,bad2d285,ab401f36,bdd520e3,c66b3d6c,925a17ef,4fd239f7,bb17c84e,3eebf9ee,c352fe82,652af898,f670dc5b,e1b9842d,9e593938), -S(d67ae553,58ac6a9f,cab9bec6,8a423738,bf7340c8,33a51cb3,2528893,24cbb1b8,d0b6ee57,e131ea57,300e228a,e1feaaf,55f1eab9,67a3ba3c,c403bad,b1dc663b), -S(6ab4478c,c8bdf1e8,7bdf566e,c24f4e46,a689459f,b002d0d5,715eb22b,62cbf077,331f13ba,e5be2960,97f8326d,1e4d3147,fc3ca83b,f4b3a4,56ae15cd,83d176b9), -S(e5d02a1a,3bae963e,9410402a,40390ca3,53d53a56,66ec6258,e82510f7,f72cc2c5,80379b63,2b5d4835,170bb358,c9040fe7,fad6b2bf,c7fd26f5,38acb1da,ba357453), -S(39acfbe8,48db640a,c2e7ac,86a1333a,ca94060e,fa88f0fe,f00d6273,74d79293,70ea1445,f7ea5f8,1148f42b,a37b2fb3,fa09f42b,9d2416ef,7fe0bde2,6e1e8f50), -S(1f8ce5d9,a815f4f5,d52c4dbc,7faf4f0f,d76a35e6,c2570632,6602bfd7,aef3b51c,3a2ec9d9,9ad3594,b223afbf,4d292f0b,88ef9372,18dc2ce6,e53df212,cc548e01), -S(5ee148dc,f4fd3d7b,b43532a4,8c782365,f944910a,eb235d67,f36642a1,b15a4581,898252a4,64cccca8,bc958dc,363cbf6d,b044492,248c0a96,aeae3bc4,26c67c93), -S(a07ec6d0,9829e04e,135566b2,d0d677ee,7e6bd606,21474cef,3e9b512a,753174d2,eb8dda9c,f3b44412,ae50c684,18453765,42697a15,33c84e78,fd75a8c7,11201514), -S(9069843c,36cca54f,aa3f5ed0,3c1d803,abd12955,4a5f8729,ced1352f,ab628d44,7140b7f0,e955a45d,aa2ddb02,846bdfcf,85163b62,718c9a51,3380b3dc,4ead8950), -S(69a98f1e,2677c441,86720bd,3b1cb073,9f06a16c,e43f7e0f,680c14f8,6540c36b,d52b75b3,a3005ab5,69041e3a,398549df,8f432e5a,c0d7e268,463b9190,191767ae), -S(c9297581,bec70b7c,55abfe17,95337b68,b99fb132,1d203a2a,29b82462,15e29633,36c4eaa0,5564673e,8ca1f783,82070d49,b8151afc,ec6c982f,2950a371,605f14c0), -S(53d50d91,1977cf5a,da1fdde4,7d44f6df,98d66efb,c858b92a,c490ee97,77c593cf,84db77c8,96dd1607,2c45c058,cf5bb2f,6435bd45,60bdbcf9,b8df71bd,404848b6), -S(ee15471,8e67e1c4,89d62145,5291a5cb,158d8fa5,84f7a134,bfc00357,ff578ed5,d9d90c79,3aefe401,c7017ff6,56d02ead,12318503,37659baf,f573c9e1,e4c65f0), -S(19e16e0a,ae3a4e80,ba0f66a9,7d415f37,784270e4,69e16560,7fe3632a,4bd8f1e3,6aabbd97,55c15f11,5a2e8287,b6fe91cf,659371f2,de5c86c2,a8deb96d,27037e72), -S(e93d52c6,12c07b0f,4f2f93f1,4b37bc92,3c3d7171,fad16472,146fb195,fd92f33d,933450e4,30e9c8ce,5a5948e,63f6d0b,40fb2ccb,adf5376d,4c076a63,9490ffac), -S(bedc3252,ab1e4676,63def49a,781cd7d7,98d01f3f,7cc1228a,9e396d86,7e8af12c,445c8bfe,9eac928a,b2d1d143,adef019a,7c243159,23a7b190,c763cbd6,dd305271), -S(28fd28e8,723d5c98,d978ac74,b070402f,3fc2315a,76d6c2e9,cd996b97,bad6375c,3ef59add,897dd001,4ef7441d,a62a8ceb,2c62b7a6,f5674ee5,b916851e,efdbf0d7), -S(7e8fc198,22ce5d20,dc04a61a,d33e4d66,c17ef03b,7fd53acd,e9c3e01b,21f3f646,ee5db413,637b4c88,d8cf2e1f,5d1d3be7,1d924962,38bbc30e,1769343d,9590cb3b), -S(b891fd94,36a14ef2,43f7ce7c,91d30887,34d1aee,8ace1fe8,ab3b29e9,2aabcb5,8af06c1e,ebf9bdbb,e1ad2f06,fdee27a5,4dc1c0a3,b08b17df,8e6ef7c5,5937c215), -S(236a16f0,21e85cf2,d5d62763,ef051bb4,c532dd26,cfdcc64c,2429f15d,8082d6db,bd24dcf9,f41f4c07,4fe6b6ea,450e3b9a,fd9c711f,b83ad683,43e65b13,3e654f3e), -S(d15acc35,21f6c40f,e7272e60,ba7b41ad,36351083,37683d43,4f9c576e,604b255e,7669301a,144b952f,cffb2e90,8d1709b8,87cec28,e7766930,eea8e753,2afb792d), -S(3b2c4a9f,cbd14308,fd612624,e5236b7d,4c363e3c,ab30aafb,a1092169,5beb3b78,69218228,5d7ebcaa,43db5109,46b93c22,ffcb7781,9c0de27e,3254ee33,3f9ed9a3), -S(b9f6b09f,a02dde42,453dbe34,b2388f55,4d042646,993ac018,5e7a6a63,2374dadd,7ee30f24,51683425,b8597189,a053a181,400df517,5934d2e7,cd00b504,484d9b3e), -S(f65baeec,e811aea7,a83f78f4,8e6db3c2,76fe63d6,11b4477a,42df67b8,4995758f,372ef8b8,9c75c669,7bd45ac9,68680c8b,14e4e558,d38e453a,2bd0c176,f6218250), -S(1f9d4799,d02782b8,f35db2db,eddb1715,e75779f0,82fd59e4,766067b0,6072bda7,86680af8,c57394c3,d50f2d5f,aab5d475,dec645fe,c02279d7,9366c450,bd3806e1), -S(c753e7d6,3dd4a9d6,384148fe,ed1a5f7f,1234182c,918dea50,2b44733f,d3f0c813,d80602df,ea4d0507,3b311a9,74be42ae,8e832f13,25790319,cf1a66b7,ac04c2d8), -S(6e294116,8eb1bc8e,55a0f2c5,e26b8b81,d6ecd829,5bb092c5,d0384073,c294e8c8,870f2e47,e00b9980,696aeafc,49adac42,32e77a5a,f5945f2,2f148d61,a9d4dcae), -S(eb2c36bf,298f419f,45fbbc61,7ea5738c,872df682,f537f965,3a58cab6,e38d2570,4619e86,3f2b9923,9709557f,932768ca,284ccf53,bdb9ef10,582d11e5,3e1afc31), -S(6ec36131,e3a55bb6,7b95712a,45ca3c8d,fe85aeb8,2746457a,cded305b,e9ba4607,6160727,f7b6db03,ad31828d,4b04a023,b07f1b41,209f4689,f126048e,21e0d9c0), -S(6825bfa,13237b39,277af3e2,1814e510,8fc51e84,abdbea42,8675ff6a,35881541,9f03c24d,c3bd1c1b,c45098c6,8f2ae07d,ccf7239,61c6a2b1,a3466d7d,1afd035a), -S(c8757c03,ce5f4fd2,2fc61bb2,e8f699ae,a733d64d,145c6fc0,58a68368,801fadc1,6601f2a7,e08e1249,5509bf1f,cf149459,928e5976,d7469e0f,e2e625e1,d9c99b0d), -S(5c1204d6,f1ca66fe,91b4cc5c,f2895ee8,2edfa489,a5b97205,808d9912,1e24a6b3,876a2e11,d790214f,d52fb598,ea7113f9,9ec08052,ff09035b,4169316c,82ba7122), -S(e0c03a38,9c612205,6b9688a7,edcc3869,5cba30ba,9038545d,33ddcff1,5f9b697e,4c0ad413,7a6e9b87,8ca914d8,31aa0371,d1bf770f,b73f1cdd,3d4dbd9d,d8fb4b21), -S(79c75424,ba72a99a,22802f65,56110084,e8adec17,355b2e8c,d2e7f8d5,13170cce,129eb5da,2ff02b6e,1fa41283,39ef9fed,3f12c606,bd55ccba,5809375f,dce59f1a), -S(8d73db65,e37a52f4,fc2b038c,56d8e371,450b65a,58614369,e1dfba92,2dd451e8,84458df6,859fd26f,ac74fda6,e7105d27,25b64fce,c4d86e9e,1dff0284,1d051d15), -S(41320642,e7de949,fc8fd03e,1b22a2ee,421bca4c,ef0e3ea,40411de4,962daddc,134f4f62,58c35358,cd33ff69,69a6b044,b36faf4a,77fb64ce,63289922,cff7d38d), -S(ae1b7bdf,21f2fe17,8a510982,f1d69a28,2f565cd4,9f3e6eec,d9412995,7b1652fe,6f6e9f98,45ad4699,a84d91b,9fd41a78,30b13310,c7f7a71c,9cdc4796,e1b33aad), -S(1d31ff82,2fffbbc6,1c3007cc,dd133dcb,624d612e,5d74acb5,f8370a8c,dd332d24,9fc68745,ee1f3a80,82efddc4,a01b75e8,6ffa49ed,698ec087,a9373623,61ae9d35), -S(f075d743,465437b,ccb185e3,c5456d2b,5546009f,79b3c591,d68e7c30,e5ddda1b,8c864d4,af8e89ea,8a1c5806,2c97768b,3e5b4c18,5f38af10,dd5a3d78,9f6cf73), -S(f9b07e9,abefdd37,a567598d,a23dd08b,7716c0d1,94cb24dd,3c6d6218,1f5fd2ed,1ca40c2a,69b92115,68e093e5,14312598,92cac6f2,c4cdfe41,16f287c1,71b1ead0), -S(14695d33,c187b712,c5f86b69,c0816fc7,cfd31486,e4fc0cd,b7042e37,cacbf5dc,9cdd12b9,c39a3237,c980047,e239b1c3,2b6145ac,853d331c,6f635efc,5cabaa82), -S(989cab0d,803b6665,33b78fbe,377d8db4,e1477f7e,6d962a93,7822e811,cfddb013,12f6454b,e88fc235,cb5f2de1,92404327,8b03c574,47c14fec,94538b54,68014a92), -S(88d1da3,4b47fb67,cbdb5eda,a463da2f,372f9605,dc0f0754,4a746ecc,a8409f4d,c2f2ae0f,38594687,7b814e11,333065b9,932cf4e4,1a6ea643,e6496175,4d46aff6), -S(2c6d9e3d,67e3a096,687b6c5e,8607293b,883017c5,35ff1594,aa8317ef,5e2fb573,678732ce,d618d76e,4ef02ae2,49485852,349cafe2,c9a78360,8a3d2c43,ff6a5d1b), -S(e0115fd9,be5488a2,e8383774,bf52b761,d75291e0,ce3d3fcc,aa642c37,66531cf9,49d36cfb,80e6ae38,d21be55c,3e885db1,fb773a3d,5c6827e8,7dc95ebf,9ac4cb3c), -S(1e994028,eb203a9c,da816a14,b08a00e9,7ec4cfeb,e6fba4c4,37dd1e41,68ed7a34,d7f4af61,ad4768af,959313d1,b5565c70,3581c4f6,b04cc1e2,bf27f202,36a6c94), -S(da12d2f4,1d60af63,a209844,1e5deb8c,1af51989,7a6edeb6,b8033621,1ac738c4,65561894,467e391f,c7de310d,fafa2ca0,c2d475a9,ddc506aa,a292d809,3272e70b), -S(aa3b79b1,4c5c6e67,ebbb8f7c,d1dac8a6,da3df0f9,af7c548d,ea0dc6c4,70830532,27a74ddc,79f6cee9,3bdaca0b,833637df,bb426cb8,58ad93e7,4fc1e285,87857cb9), -S(a25e2e8,942e3353,4a36ecef,62c71508,6f1e959f,627287d,f0e7dc67,6457acf6,3383132d,2ab2de4f,890fe37c,74b3253c,fee9265b,e2ef62c5,a755af61,abe00463), -S(c8ffe7ba,62d8ece0,843bd801,6c8043db,2e71d0a4,f91f2eea,7503824,1a3e67eb,fb507024,6a0e3286,8f6f6e67,7161b822,ac9d1aa,267658af,895cb9ad,4d94586d), -S(3352b6ba,380ee90d,d846c6af,ede2a9d6,de4d082f,46bf3a18,dfab2943,409ffbf2,fd6036e5,d7b2ff57,376967a8,42bac428,203b2784,4196fec8,64d8ee42,b7248472), -S(2ac42896,c815a831,a7b2d28e,af6a8c3a,803977d2,661fa36a,11143a43,7d179d55,2cc1490d,70b9f5f5,96cc8294,41fb5c43,44566d5c,77c651a2,34ba058f,b4b05823), -S(ac5917d7,64a4dd2c,a5c1db3a,75cf56a3,4a695e8c,ddae8c0c,74594857,cd48986d,5958f85f,f6794368,294d173c,14937aa9,eea64dd6,80dbb96b,c3e7b855,a87c92df), -S(c79122be,5424c0ff,728368c3,a0ef6ecc,3026bcd4,12ab1ff1,e3443d7b,dc2b46e9,2abca3b4,be4d53f0,40fb7d0b,3b28f4f7,44e4a96f,1e1cdfd4,cdcc7276,30332dae), -S(b3015fcf,1577fc15,337847a7,2b6c9bda,a7d6649d,711a156a,499b5e67,4e6a8ce0,2e826388,be577c02,f2fc3f2b,ca4f1ecf,546b75be,3373134b,1e440319,b78fa759), -S(b857212,b941cdd8,6f80063,3167a5e5,7d6fa385,c7ed08fd,9773de0a,4a481af8,aeb5aff7,329b6227,f614b8ee,1e2784a,ec5432f8,86d29e35,916ca3f5,7b901ff), -S(18f3f92e,a869ba6,9f64ec10,6e42e4c6,438504bb,709734f5,eac1a97,a418c23e,a9d95cb6,dbc06ba9,cf35b953,b0426ca5,167766ff,a533d47,bf40e55c,9e5cca00), -S(b6cde393,b06eb82d,ac45aa40,b094dd08,1a7b4bdf,f4a6caa1,7a1a2d9b,de336e60,81816d39,5db23bf3,9335c483,a50ee3c3,710217f8,9365a04e,1fc1cd49,20fdb244), -S(42ed0806,c78c2d5c,851f134b,341fdb4c,949c74c9,7522e681,81423a0f,64a6f1e5,fac85e8a,7151a4e3,b7b24919,828153c,237bbfbb,4a49607,a70f595d,9535d66d), -S(bad68afb,e1931a,63231202,69b4fbd2,a5b84ba,a951fa56,4ca07bab,d3160199,1b19d063,7e89fe43,894a2c4b,e8203e1e,cda6ac9f,f7e6989a,b1581d81,8c1f7ff1), -S(74c6a877,29197f39,c253450d,ed7cc4b0,948f1c05,3c91d120,668f09ed,f56eda31,e3a383c9,b0bc99ac,1eaaf1e4,47d9a088,e772095b,8a30bd75,dbb70622,44f46d29), -S(ab75cd77,a5800af0,9a2b4ed2,fdcdb6a3,d6b32076,ef5d9211,8dcdb4d6,acc25547,dabcf737,6f03afe1,6d2e8dba,e7634bcc,1cf0302,7545c57b,dbdc97f1,6bb1491a), -S(1951f597,1bf190de,295cd417,1ed7fc0b,6938e031,8403dfff,10434dca,9fd7b7c2,321f12d6,b8790ad8,2a956947,ef0a615a,76b6b678,5c765d8d,e9f04cf3,9961604e), -S(3095615a,6dce993c,646b7e39,1fd86117,82ee418b,cad9c9e9,413db342,45c76edd,9745ff66,fad21c00,68699f49,158f578d,b1ec962e,d288e008,cc667a95,95513fa7), -S(9b2a6fa,60b7fa62,f0cb6c41,91f3b7b8,fc0d549b,98520472,86abe23,4cea3c1d,4763f538,6bcc3b22,4bd2299b,92a10572,7a761b3e,709ab6d9,dc875615,43baa2b7), -S(df52e023,92e2a319,cfea1f52,c58a1039,27c14e64,8eba846c,faac077d,13493c3a,eaf8a802,9f682f59,295d3d,d44c11ae,537442c0,ac61e6ad,1971e975,5f1856d5), -S(3cf08be3,65e6164,6dfe3e73,83ca54bc,ae2e1b36,522da9cc,accd5ea3,4de03f45,d2eaaa72,8b2cc3e3,75bb14a4,4f52aa90,40df35b6,282c0b0c,df8c3a7c,8e75b435), -S(e7d92472,23f321d2,9a327ad6,4d08549b,e38a216a,d9ee8e1f,7dda5956,c65eaef1,d0cd5049,fae4996e,362efe1,f6019de9,2b57c8a5,fdd17a3c,a9cda468,e6a5e5d4), -S(fe851c52,f05568b2,ecbe964,bd80be47,98414ab3,c20fa0a6,d0b114c3,8ff6afa0,3170ce7f,99584c1,82fa6cf7,47197fe5,7f7f252f,e21a38d4,cefa09e2,697427ef), -S(993a0c6b,10fa1b82,8a3e72d8,89244094,cc60ef72,7f9f4758,53f09161,fda8a1c2,51be5ca1,3539c2c2,7a1d395c,3d89567e,cb218a99,3432a424,96ea7e69,95a6fb51), -S(ec46aba7,a6af89c2,7689933,2910bdf8,87362c46,a2a3dd0b,e1e6419f,8b2a2036,cca7634d,1afdae1c,d764d553,80190aa,96a5f444,70db8f07,fe59d460,c2a04380), -S(ac7188a6,8ecba28d,59c786e7,e127335,c332697e,2980fe52,ef3dcd2b,f8227c6c,e7ced64c,99c08050,fbcec989,89f99a7f,faf89fcd,2651d291,66f40c6b,3fba82d), -S(27e6baf8,f83129e7,14858346,ea158821,c474fe2c,fec352fa,61f00808,e662502b,84fa023d,3d371686,db30f0fc,65491b6c,d7a5043,73a08a5f,8d63f94,73f2cbfe), -S(4deb11fc,8f4610b0,c9875767,704d48aa,d55c06f7,2712d577,22f48359,38acb0c9,1769af84,c88f65c5,70df086a,e07abe6,b1a5b2fe,95da770c,ca57e11,4c6dedd3), -S(e2c30e5f,a831d62f,ce366bdf,1415fed6,574f12eb,c4ad36b4,d558081,eab8ca7f,6b76b320,252e2b24,a49da21f,f51207f6,cf2621be,992fe9e3,758e2abd,adafa7e9), -S(293bfb9d,d46baba6,8cd67e75,35e944f5,79690edf,4d17bdcd,2295d044,be309644,8c3777df,a3f4188f,4643b137,4cbc8d53,6fae283f,540d18d,514c8162,4b7af701), -S(adb8b1ad,d80a6120,e90ec376,14f08f81,b668cbbf,db85bc8a,9fb76881,f3feb2bc,7525e4c4,56995383,c9d5b8cb,b920130f,b9225012,a441eb5e,f6ec960,2181b070), -S(a03cc251,b299ce99,ced67920,11eca35c,87ecccc2,80ca61f9,b35f4fe0,8828afc3,34e992f2,9a8b7e71,804c5bbf,680622d9,536c58d3,316138bc,77adaec1,1f0a28f9), -S(e370ad9a,8a78dd7a,e7631e25,bc5ddef7,b5ee9fb3,449cc56d,3c77b12d,2450c42e,ff2d4db8,24f0f626,4f8c61c5,a3ab3cd1,d731ac1b,36503024,61f7c333,d939715a), -S(e7825767,be268da0,958756c9,c10a7f5f,a8b90b0b,f9279530,d5d60cb9,3cf9a782,e8a54111,66446979,5ad4be94,31d267df,9e471de8,9c2f386b,ef52c14f,85193030), -S(67768f1b,a78c76df,4f0e0ea7,ce2faf8,4fce8e5d,d43707a1,586354bf,77c5d369,a33cf627,c206d44f,79e3a473,a07051bf,202dbafd,cb74735f,1af2c8f1,27e4eb4c), -S(3c2296d9,a780ada1,a795d3c0,6bb3cc74,b00a7232,5c244ae0,57cb18d,5e0b8aff,bcabc5c5,2e1260d9,b14f9ee9,70b098f2,edd5163a,65b204b,fecc6a00,cf6c7f62), -S(c3ef3a3c,da7d376,2b128546,c8402603,7aebc362,c2a4d869,f2583418,2d8c8109,207ec4c2,6673447b,8d899e7,62104c68,3d0dba18,ca98c373,432cda8a,a6ffd6a5), -S(1d97f529,2fd92440,7fecb4da,a0baefab,15670b03,fd635cc0,66c078ac,fc35b80b,4457ef24,3b6c9e3b,e99d7a01,9d95b706,fc2530a4,7a88d11d,ee4083c2,fa7a9e69), -S(22bd1fa,eb1d343f,cbd595ca,f80a9128,c7b6371f,e5ac920,a31bd2a5,990a0a38,e2157272,a9ec6919,6ef17add,1855bdd,31097aa7,4e332779,9dae90d9,75155910), -S(dd8b69cb,a32f727e,e5c7e09b,5c152bea,badfec40,8ff36c66,5a95f572,82dd7b88,f8024917,d1678ffe,52ba97e3,48e74c0f,2ccb06d6,8ac7914a,378b7e5,a86dc3de), -S(2b3da42f,b0ffbe4d,69143812,a221f92e,496d381e,a420efb7,944fc66b,ee5eccfb,9299b809,47c26fb9,b5a3f004,7041f494,ad665c1d,ff304479,9fe0dedb,4ebdadfc), -S(98d2a44b,fba2fcf4,5b33a605,513d4c0f,8c036bcb,555f9142,3133be23,7e616db,70f5bcb9,b499ea99,aae3b8f7,f33169c,5af06f3b,55dfb8a1,623d7a2c,d54b556b), -S(37c7450c,933b1e12,8d4572b8,deaac8e0,80bdb588,ab90ffeb,f0d6fc37,2feb2219,ad0cab20,39622393,5d8a8ee3,2198ae9e,950be80,12b5448a,bc030b42,71920b32), -S(d8a2d303,8a0b0bb8,c85b0a07,79a88840,166babff,ec651b00,15c37f89,f11067e5,18200caa,7e7a67cf,e5c720c0,ec1f8ae0,ac083011,9ecced1e,b78802ab,30198d13), -S(c27b256d,eca6b591,c1e0021c,3d1da818,8ed96783,11a90a0d,41396932,f9214a5f,d30baf5a,3c64f47,4ce7d705,fa836a89,9161e75b,a0cdfee9,5f03c559,78024cdd), -S(b00215c5,b93cc894,c508a613,20debae0,58a3e4e1,d826e3ee,cbd168e0,384f82aa,469355eb,844e6608,7a390fcd,f43372d5,37389f99,33d240f0,3dcb0b6f,3476f0b0), -S(da646c43,2f525192,efe9b58c,5e41d190,f5ae5e36,9d8353e0,21aa9ff4,15a663ad,742d960a,863eb936,50a84bcd,5d4a1d50,d1243ccc,77698fa7,9135a351,fd5e9864), -S(381abcea,fd9ecec2,897a543a,d712bc1e,39a76062,b2d34ba9,8c06e7ba,6694a9bd,813cfc4f,a40bc405,941ca90c,73648d66,790e7925,31a6e64e,d432287c,24fd7891), -S(130361a0,1be7546e,57ce8b7c,c97cd06f,db4d2498,635821e5,d05cb8b7,46e7ea7f,448b60cd,668facba,4d56471d,d492e529,b7e204fa,778ed89c,b9ed021b,bdadd193), -S(95df1d44,7739e3ac,7e958445,1b269507,8f32d917,b512e4e2,fdb143fc,465ed004,5807bb76,184742fa,1745feb6,b3705ae3,283066ff,fbd0457f,720d2a2a,4931e728), -S(d9b612a4,a3074698,e06b2c4b,bd27b668,8c71b874,6808d245,188eec80,73292c32,b7e771af,3ca2ef2b,e3d82568,203f0a6,3e8caa73,d6f2fc32,17ad4b53,bbf6bbf0), -S(c882600,f804cc50,6342436,10b79f56,7c9d9276,948413f8,889a6bb3,fc16cf79,835220ee,694bd660,ff321b3b,d931d082,f6efba84,dccbef51,37492ceb,3c03e11e), -S(8ae9f886,4415cfb5,cbb8b67f,8076df4a,19c0aecd,82a63f66,ee5d1a76,1ca3ee6b,4e24aebb,1b507a13,fb1f3f33,7059794b,e81c5f13,4825806a,e7da3723,8be7c7e2), -S(70558a7c,756dc54f,337a3159,aedddee5,fbe3ffcf,5ebe648c,9d6c4c42,e56de4b2,67959da7,f775ca30,c942b87e,a5c7e2aa,5ee64254,4b600134,493fe07a,47a3ea82), -S(ec4bbb6f,6d88f798,832c4b59,d6e1ab57,fe559818,a2ee858c,e4273770,81c46b46,55933669,59789697,ea826bde,7929720d,6887bff7,4e910b3b,44bf757,a2cad075), -S(e7f069e6,abcceb3c,30d28256,50e8a469,3ac693a8,6ba5b120,fc827400,9f737e9f,2a9dc479,b3a7627e,3ca49295,7598d942,34f4bbf0,304c34eb,cfbfb662,1fddac1f), -S(54b175ab,7c18c090,2f0f97cf,4444f362,3916122b,1767fcf9,ec576ca7,5a2617f7,b5cb03e2,9a829c80,81f16888,3adfe85e,917e6525,8cdd4f0,cd3fe571,7adc6436), -S(da20f8ff,2b64cee8,7572fea1,21f98044,57bafdfd,3b1ead53,6fef24dd,16e08c2c,6e1898d2,b7482032,6b299591,376525f1,700ddcb,8e2c8057,40ff9327,2cee5bdf), -S(55244d3f,e177f889,3fa2e982,6ae89927,1b0bb5e0,f3764941,95a9e90a,8d1367be,abf46ed0,93f617b4,85d7719d,b4878968,ade00c3b,7c8dbc70,c21561f4,90dd3b4a), -S(a2c59a7f,d001bd82,48813d66,2c6ccc24,ad815cca,89ef749f,891a219e,956e931e,fa61c08,4a0a648b,5307e771,28a58d14,4d1084b1,58f1f824,f3d96d,d091346d), -S(d94e65ad,9f2cf491,192e5d1b,ce9d42f3,14c0a724,5c3b351c,f2ba3a3f,e70aec21,3d503a0b,df638ea7,5ffb2886,b3a9d723,2c427fb,d4921c4b,b1eefb86,2eccab8), -S(eb24a84e,aad08175,13705448,36b99c05,adc0e7f6,ae871a70,b42d24e0,a6287c55,3c4e2230,208b5750,fdf24d95,83d94db0,58e65604,d555a0be,372a5f4,a39858de), -S(69ca3107,a95583e6,c6b76b73,56b6a65d,2c45f0a6,194b69f,ec56efbe,289f8141,594001e4,46916b8a,9f977542,281016a0,8c8290e9,92e5e87f,fc16d49b,ca9f7155), -S(f7b24587,a436adea,15f6cf87,bc065d18,dec084ff,6f6582f0,3782a977,515595b,30391228,a155358,4b1f8b74,da91239d,89a4fbbb,93635cec,bc2453b4,9f355331), -S(16bfd7d3,572a6fed,c10a6e8,f6ffe3e3,9090448f,71884026,f6a16688,5f0f0d92,17a933d5,f2b3ed3b,f09927da,25331207,31a30a81,93681cb7,3bc0b2a0,c0b7f436), -S(dec8fca7,95baf9e4,379aa5fb,777777bb,178e086,1a738053,17f8d676,5cbbe9cc,99f2da03,32b83f9b,b712732c,e9b7ca53,b7bf6086,46c7642,620fc738,6b74343a), -S(f6b5b4ea,ba3f1b89,d399f6c0,eac8abe1,88a9cb21,9a9d4d3,7b578447,62f3956a,6cda2c16,8211c18e,8722e689,70fb9a23,54d09606,8e104c7b,5a6f6812,fb854a25), -S(2f547664,916072d9,2754da2b,556fd3cb,d9b67045,4bece334,960875f7,df57559a,c3c27849,64cabd54,6487f05d,45544b4b,bea58b16,e2a2e3aa,2105cff3,c8d0a5e3), -S(b98cac11,e194e80,83d39bde,8b28103b,d09bcf5b,bb163b78,33e00be3,3f52779d,dde188de,3763488e,7ddf8bb0,12291cf,848fc21d,25ad040,6217a8ea,e1fbe6e7), -S(1fc36f4c,99b540d7,a74dd2b6,1fd71f1,b095343c,3d7856c6,6febff21,b5c61286,6d165f6e,ed6343f,36dc761e,63f6068a,1a583086,cb76ad6d,a6996fd,8fb303f7), -S(13cc7352,2006a383,356e7378,cbe74e7c,873e1a8,c96f437a,995f5549,616dfa5a,f73ab51b,639aeff5,ae8deaab,e5fe7dc9,fe8cc203,ec66f16d,dd789031,6da8f614), -S(a42b8522,d7b620c2,8011137a,76719fa1,3066761a,7a612946,60c9fb3d,e37696e2,e0163b30,5f5500e,74bb9e98,c7f8763d,4cad602d,d01ee3ef,404899e1,1df9111d), -S(ad1e64b2,63b364e0,477657c4,33601197,61b2efc3,87c5b2f2,71befc20,279ca300,52e1f8c2,80ce5c76,70533ea1,4a8d75b9,e4e0ad6,199cdf0c,c570daf6,469e0a17), -S(b25ac32c,4406382f,6c28a12,f4e1b491,d7cb9a6e,2f03cbbf,46c26d95,d70b6295,db173a50,1d02a785,ab98ab65,2e814ec0,fce3ae92,e3948610,3141a844,93113f11), -S(507ddbd6,2908f782,9bd54ac7,948cea3b,ca3f5551,d5fa0b8,736ff2d4,a38440fc,76e3189,b588462c,93de2716,b5d79d42,8339a81a,1bc2d8b,e512e33d,5de5ecf8), -S(c300e40b,425d9391,4e2a8624,830f119b,3adb2e8e,d90f4873,46dd02e5,1ffe7006,b588f4f9,e9a315b4,1bc6484c,3b0cd1a,de816262,80f14767,9a1c3b31,1e48df17), -S(19d029eb,114bd8ff,952307f5,1e04593d,a4936127,dfc72bd6,8767a462,36b31b6a,e56c64e2,b1f14ecd,1f7dc29,be51fdaf,d859d6cb,78c5dd7f,5fa0f221,bec715fe), -S(b972dd3b,e3531c85,f1d9580b,8ba77429,747ad431,4c5a7947,3c54d647,bb93ba63,b1076055,6464152f,c5477005,fd6b4ec0,e8a73dc6,63fd6622,ffd31170,5ca7af0c), -S(148c6a57,f606ff5,2489a1e7,df84b1bc,11ef7b68,9cdbf0f4,f583be09,db595b9c,308e0362,2a681b0b,308f11a0,71742e4,f501d089,9f190e9c,239689d,2de198d7), -S(f8eff5a8,48a0b184,768135b,8c159bdc,ba86397,c38a2255,dd6bc746,549521cd,9fc518c5,d2bc6749,8fbb9ac0,8c22a070,e948321e,3b11473f,b96a67e1,2d788e5b), -S(61cb5332,ebb1b0c6,badb58d9,c15b8b1b,8c5b0a95,601220a2,a2fdb007,325b4442,fa90f15b,e1636b62,72ae71b,5711b43b,53580f04,86b6472d,e14737b6,8267242f), -S(9ad91194,210d4acc,b4f2fa3,f69f9fe5,707975f9,99f3e40a,9b766e7a,ae570b9d,bd770b3a,e6f6ccac,9d0dd1b9,bb5c451e,c27a8d0,ce02b491,a6c40afa,86067ce6), -S(d6985c89,71c21dc4,723540e0,9901194a,a898c0aa,33c4bd7d,34d74164,cb46ee8a,3c62000c,c8969f08,2dee7159,df6ce660,89e13b1,9c71674d,fdecb469,5e4eed89), -S(398e5cc8,4a90fcbc,1af56815,d56619e3,74e30023,9f95ed2f,3b0c3d32,fd0657d1,f82f5fe9,99c25624,9ebae25b,71946c98,b16cf462,cdcade65,ad22c608,7776fd49), -S(d5b3aa26,c2400d25,7032782,b35cffcc,902fee32,a28fdda2,f36eb3c0,1b19ea86,3f3fcae0,a7f0956b,2ab41211,a8941be3,358b22d2,1eb18b0e,c0afbf38,95e8e17a), -S(6f6e1cb2,3e212a5c,91b91407,7c90d465,eeb3c46e,74addbc3,ed228a1d,8fa201f,c11432fb,60b782ac,9dce6e69,e8a544e4,c5676f36,7c959239,c4dbf548,610b0f74), -S(23eaf533,24bda09c,ccf5edb0,8d0b5904,6c42f17f,12f64c81,54b884d2,239239e3,87aa0fe9,c37c0150,95ba3f68,96ea597a,a38f5a68,d8fdd6e9,a9eb4aa0,b6dedc57), -S(639f2502,a5f0073f,95352a3b,63982bb7,f215e0b,c80d3f7b,fc37d1b6,2ea89e18,a93481e3,8d78e490,6fe37f44,a198b85f,c6246f0,50d17193,f01962c3,c9351b24), -S(1e78e21d,4f696d89,b0b43eb5,e5d8cb03,46c9d030,65a4ee15,5f81ac27,b8fff65c,3a8103ce,e0d7e645,69e22332,911728ce,20793c12,c7d45b0f,3d840641,11221f8b), -S(1ece1fda,85a726ba,49bc7ac9,23e1599b,b070e8ce,134858b8,cb4d714f,2b539ff0,dbbc6f14,fadb9d5c,559b3b2b,df070bba,11d8777c,b5526bc9,ac951dbc,9815863f), -S(e49e79ae,f17ff1ea,b81e3c47,97310952,6dac7ac4,ecba2a57,85696de8,279af373,92b0fb30,368189ef,dacf5e40,1ec4dbd0,a4ef28bf,512167bc,42f63cf8,a7f6ba73), -S(ce0bec53,1c1eaeeb,868bd283,9b37c225,fdc90d0b,d6d82e58,20516b7b,9c9b81fe,9ca80cac,80100d58,68fd1bb9,b174b0c9,54d17492,12ebd194,5bbd526f,6f842b97), -S(df282fc1,b4fba7e4,fd75af57,805d93ce,af88590,3b57cea8,38f5edcc,2e7efb52,27487ea3,77eebb18,699eff2e,66909c2d,9daf7f0e,32e13ac2,17df0d1f,b8701c33), -S(e82d0d6e,29b68dcf,aa8ebfb,4d8d5f70,2d6a91dc,b10c5c3b,c7363360,6c937510,ce1dd596,232791f3,7efdfb4c,7da518e4,c98e8f02,d36c7230,3cb3c52,69bdab85), -S(cbf085c,5316258d,6cd5e721,b613f97d,7e22cac6,2b832bd7,e2830f34,2f748f20,a5efaf98,97cfeebd,b07bc80e,417e73db,bde10972,57684543,151c1940,a92f7e68), -S(dfd983bf,84da8670,1a475a89,66569aa2,59c36fa7,9a5f5142,fa62cf34,105817ff,91973764,28e0cd11,11b8ad8a,5f41d6d0,3ac5b930,5701d1a8,d621da05,16e6083e), -S(e89e41cb,5dd179e2,ecb2a48c,af7f3dbb,d4d9fb3,78eb0822,6652dfff,593266b6,7dcbd3a0,765dfc52,8244c19a,df657719,6ed46b1b,2bf62042,949f0f57,df872d01), -S(20b45025,780c01e0,e8bc2899,7f59aac4,ff9434f6,bf4ac433,39096769,f3e360da,4bec5654,5409a944,c68f0942,a1fca7dc,aa89a2a0,4ca9d6b9,b325eb06,9f7bff95), -S(ec4820f2,955c17b6,81381e12,8acbe1e7,75669f02,8517dd41,f4723d3e,64d75bb2,41ed16b7,5dc65672,eef6166a,b86a419b,ceddf23d,d365e63b,578388ed,bc6bb8fa), -S(b15cf70d,523695d9,48dd1f7d,2f2a12cf,aef60bfc,93a79410,2678ce11,c4233424,63b11e19,1335490,8eeb94c,6bbf1875,f867cc17,a599e83c,2aaa4553,47d549fb), -S(d9e85a98,5cb2dc07,790b0db,1e5a43b2,a51b882e,846bcc2a,8c2930eb,efb79f6f,482abc51,54846788,1b8551f5,e0162ba8,3ca192de,1ca4ba97,19ffdb18,57583b57), -S(6d8dbc0,cf0b7081,c03e9bcf,16dc7445,3c9eec0f,d21f82c8,d05c70dc,bf61db91,ee91fa7e,4f5f59a7,5841d903,ac0a3f0b,68c837d3,aedeac7c,bb9576ef,a7f7ece6), -S(b12c9714,2b5a8ef1,cb2b0cca,9316dd0e,7969a2bb,f7fa34ab,4cd412f,dbc500b1,690c027d,e9327f7f,3f761509,c57a23b0,b2d7cbc9,e5392472,8611ba10,7e5a8e61), -S(970d6bb7,2dac2f5a,7588ac62,31a7425c,aa120592,80f4cc54,19b55126,ed4f36f4,3f541ae8,2186eabc,562d3e1f,7492a8bf,68e45210,9e5d9ed1,ab59aaff,9dcbc58d), -S(41605872,337e0cc5,f9322c5c,a4dc3e81,40b8bef3,b99c1285,e0b5c53a,d08d25bc,3a52bbfb,d18d532a,53187d3f,f9140aca,38058be8,ddcafdf3,83f4204,780fbb56), -S(4889a88b,7e9a5d65,bc564fa1,12a6318e,564c5e39,4be6c4ef,875e79e,f33358e,e0757939,a788755d,c54469d1,3e82d9e,a9502478,3dcc51bb,8856c5d8,629b1da3), -S(90ac2fb5,a463523f,ee81a501,510874eb,ff69456c,3670decc,2d14b3dd,a1bc284,b6f10a6a,c316af7c,dfbb3b7c,6aa30846,10b2f44a,1e415fce,d67245d9,72d2fc63), -S(9286dbdd,9477d600,ba2a941f,e467ee8d,9a7b114c,dc42e488,8648854e,febc5a1e,5ef9e3d0,ce7f522a,c5a1e46,5281bf98,a63623dc,f300be6b,d01df5ff,6661c68c), -S(6b774b76,50623f6d,cedf0498,683c05b9,1de486e0,5f9f64b4,dd13b0ab,eea0c53e,a3dbed6e,ebe68c9a,86468874,ef2ef5ff,3142266c,756b48a,3314698a,c4a20162), -S(e5335352,fca65cbb,8fa6e275,ce8a0432,d7ddbbf6,f8854e4a,371b07c,909c42b2,30fb3def,31c8bf51,8e2542a7,83736e7e,d87f1c97,70465120,47faf3b6,7764d77a), -S(f87c5b0d,a8edd93a,bb33e606,1fc34377,54a236f1,44bc0ba6,1cd26f91,86ac75da,92434741,af204fee,a03027ae,1ee5eb45,82769d1b,c264472c,dfdddcbc,50065424), -S(dd9d3fc2,96eda501,3886376c,88af214c,3a4dfc9f,eed0776b,287cd32a,2fddd2fd,32e630b,2da6114d,f09ff5d2,eec619e4,48f849df,399e5e4a,e802efc1,dcad04a6), -S(10108724,51bbc5d9,b045666f,fc45ccde,c29b3a10,60ba8d76,5fdd1f5c,1dda495e,c86404db,ff9aabf2,599f6c35,e6a8d7f1,2654844d,add8c787,86158faa,b10b5f85), -S(22f7f223,9c8fedfa,cdfe80aa,84477ca0,df289636,2f055eea,3c63bbe5,58443a98,661ed060,8413a4b8,775b9916,14d848d0,269dc75,4d2ff2f1,b4a18fa7,ef0e19f8), -S(9a1ef62a,7567f9d6,9d45edc9,3ecdb7a3,1ee6793d,a2d387a6,304e0185,3416ae70,81f8527b,4c9fafa1,b2fdd185,57998861,4f6ea270,463f8261,814d190c,80f93f4d), -S(b04946f8,8b0c5fc2,13d215aa,53e3d90,df45d13e,bf7b665c,d41ebd3,58cbe5f4,2e92bad0,9b485af3,904446fb,14fe3624,c447e72b,41519297,133933d0,b6191869), -S(aaf764cb,7db7d191,c2dd7061,c213b469,bc270677,7ae0ce31,b0a3f6,7ec26728,4c4f42e,5ffb9d8f,e0625906,b17b7857,8afbd773,834e40bf,c7195f08,19aca859), -S(a236de9c,e071504b,e8108d5d,f5cb7ffa,d4a333e5,1afb1579,2593706e,fa04efc7,773f065a,227634be,3ec7d3b3,4ba462e4,d50f79ee,19541896,948ad725,c26bdc88), -S(3794260f,302e614,aa700f32,e41a0ee,c772d549,58b11533,2b7de77,925d7cac,d1896d9,7b5e2ee6,9ab7e55d,83381ad9,bee1b87d,d3991f53,4bb67237,830e8926), -S(a2436b37,7fa45dec,eda48686,e0705068,ea607b24,58482794,aae3345f,353f6329,e1da48be,8cc2c88,5bae924f,df1a328c,37f96261,3470a841,7784c4f,b965e05d), -S(f9616f77,6a125158,7165411a,582ccc1,2317e260,89412bb7,5c2a63a2,dbea5658,39a790f8,111db9b7,f3b69bf9,9d0982c4,6d97a18b,c937e6f1,3db36ea6,9d7471d1), -S(4a720ef3,9c907f62,720ff0f4,c5d193df,c9bd3613,6f49f72a,69aaee15,b3b7fa42,6ed9eea,cb95af1a,5b91bbe,27ccfa4d,f352a227,67a250a3,179f94e4,bee433f7), -S(dea00421,c07efdd4,24749981,713c1c13,fb23f974,fdb37f45,35314d22,b75cf0b8,2e91b078,2b3dbf41,3de9f98e,e421ef30,bad6cb5a,b57e457b,272f3f46,7709aa32), -S(7e14f09f,f55a0b2a,88518714,68340514,903b2ebd,3525937e,2b0efc79,bb1d7b41,30fa7849,3660b715,514b7fb4,5aa50324,a7958bfe,4db78914,966340ea,c8ea96d9), -S(6536425,5ab57582,feeb109e,7a9657c4,dfd8fbf7,57be61c5,a769ae58,56ae990a,bee94b18,61d474d7,40674349,1b875022,8eedcac8,99835433,529a1621,bffeaab), -S(8448e3ba,f77574f9,2bb731a8,d0d4d3f3,21531c7d,189ba5dc,2edfd54,78ecb11f,425a1eb3,727a5bea,478b82f,d9fb7c9d,b933a7e,8283e897,d1d21ad,2281d39b), -S(d2ec1adc,1d30ab11,b1ba87ed,7765f848,5d097e83,3ffaa26,2eb5aed1,5778ec35,beda7397,61ff8a32,b0965b47,55c186a3,8d24e8cd,5dad81b5,4a106abb,335c3994), -S(3b205375,ae0ddf7,c2dbba5c,9e14b5fd,e8899448,4ea0d82e,a939e1d4,f1d8dfa,bdab6d0a,8d1db118,785bddd6,81c3a402,460137f,f4f1c26a,d940708f,969df70), -S(eef96785,6012f0e2,5934efe7,b9199255,869334c2,59a62384,f2cc4b4d,6f5865f2,1806efdb,ecd0588,17db47ea,10ed1866,6bf0e9c2,7a2bd661,91d92d1f,4ba0a9cb), -S(9271ab48,6a17d2d9,c91ef3f8,73c74d6b,754bdfa7,67172cac,53ea741c,e101abd3,4ba3ed7c,1ea7d0a5,5c4ad38e,cd032e5e,782b69d5,3ade655,a8d8354,422de96b), -S(9bbefe44,70872b67,3ce6afe2,43c32b8,e2409b69,b57f15b8,e1d2b4e,d0e760f6,a1c6f4b7,cab89ff,ea846bf0,20ebfccd,77e7ad4c,68a8095f,c9b56a5b,f57e4dbb), -S(cbdbadd8,5cb42d34,cf249e78,1929bc4a,90977ed3,e6c7fb4,5f0713b7,3e3ba051,1b2a60ba,9f4f727e,c057d149,2ac04e50,42fe053d,89649be9,4fcff26e,8d3ba7cb), -S(414eb1ca,a37e098c,6d4257b3,a9e22047,652e5c0,e4872547,7e97a2d6,b89151f5,27600f8a,b3b66f86,6e6a712,c8d2d557,736b9f2f,3b7be72d,2783a5af,35cdf7cb), -S(be0e548d,4302918,60ac6c47,4593a5f7,169b3eff,c9d18878,6eccd511,e1f195bb,fd26af99,8ab759b,c9a83d54,6296efe,cb0faa62,eec5a7d9,98a0d80,e36a494d), -S(ff38855c,7925713c,80c0600f,7cc3e60d,9aceb7d4,b1199d75,2a83a67b,6b1dec1b,e42b3d08,f12b19ae,600479ca,b593fcad,bf680fb3,da54a1ca,d072d1f4,46bb8989), -S(157631db,883dc9ee,b5b3782b,fba4e430,9426acbe,5ed06fd7,662f06c7,c776e829,cad1de8e,426da993,4a8e573a,5e041952,4b3a01a2,e29049cd,c9439de5,c5cbc4a6), -S(c758ec6f,4a7d15b,efa56470,1f8a2278,ed886788,1aa2a772,c20fbff,ed05885d,e3e80138,4758c6bc,60f10beb,7d75e7c5,d0a541af,38ddde3,b7c5f709,34fe0ddb), -S(e20d3b67,cfb8226b,7b22bdd0,87044f7b,5b29a277,bb5286f,80093eed,69277e67,ce6a8a7d,c1bd236f,961610f0,15a9cda1,9ab85200,abbc6d0b,9a041ee8,9d97c743), -S(b1d70b27,a855ceea,149c0508,2f88d465,6aac5541,aabe223e,4b13028f,10a2aff7,4df082c2,87170b69,88b05b37,1d4b5181,773741cc,70544f4d,7d3742cf,77884caf), -S(f30a09e5,9c163445,5f231a0f,52d9e6b7,8c336b07,5f1ee6a3,bdfd4cc,1bf213fc,acb8bd60,eb919332,a405023f,c799072a,a2838dbc,7ef8d042,7417d61e,41c6b00c), -S(8a615da3,f0f92f20,e8dd5ee6,23178403,ac0287a3,93173dea,1bba53cc,2cd268d8,bd7a5a1f,ac8d4157,6b51f9bf,ebd581b3,ebf470d0,43731e4a,4dd391f9,423d32d9), -S(14d45568,f9b4e6ff,f8062209,7dd34f36,17d3fce3,e5357ead,baeeb480,2a43e7f7,25e65c8d,50296272,718ea121,cd5a1365,d134a134,fca3a5f6,324d7cb3,85f9f163), -S(706f64f2,a7008aa5,d3eabb07,b4a3a3bb,f18eab6b,cf605117,c70cc0a6,280e2084,cce06389,bc03b45c,cb235c88,19639a27,5a78ca00,9e99978,236411bc,687c93c9), -S(db4f0639,fdf573be,8d7d4f84,4d8f781b,51731003,24343be2,6c8805ae,fed3b91,bd1564d8,8abe4aef,dfe581bb,3673f874,38248b1e,7b11e019,6e158bf0,5cfbebcd), -S(43e3c600,4f3cd3e2,aed372d5,60348976,f420d1de,95c70a4c,eadbfc9e,df393d32,bd09845c,429c91af,9e9b3441,321c68c1,888f8c31,15960131,85c90bd8,6b9b30bc), -S(13192002,45d0e72f,e9f289f2,d9be96ac,ac2f1adb,37716658,700aae4c,91267ef6,864b391a,aa20047f,38308f95,e42f4976,494e1a35,100affc7,2d435f85,f936a039), -S(752bff23,288a0554,7f048770,da6abe2,e70431c4,60a71765,40b1c124,89ae7383,aa2af83a,92ab2a29,1c5f89e6,61a18075,d6c3e8cb,ef6fc0ae,c283e77b,56fdcd5e), -S(af0f3d24,25247b8,cbe6e377,ed72afe4,420a886b,aa995671,d638884a,ac238fe2,b7fddd96,86bcbcca,f363b3ba,ad214771,edb9a392,1bbfa25,870dbf52,a42e9622), -S(6be310a6,9ad4a56a,cf79630f,e8767f0b,c986eeef,609eee6a,f1a34657,89c3b93c,2ac934b6,f549d51e,8bc3342c,9fece7c1,c79fc301,bf006cca,20e014f4,b1a9c768), -S(a53b9a96,e9d44aff,ff7f4393,ee691d30,ca4a115f,60267b16,ce11027a,73a7ef1d,d70e70af,5e8dc02f,b3ad170,734e8b13,8567dae0,d73f9754,d6070563,8abfe3f5), -S(e782675a,5a2dc77d,383e8d03,fb2b126e,5abcc07c,391e5597,d127e60d,bd33bb45,8342ae33,fac4979b,fd47d5,b9b40d85,db40f79d,42308ef2,4110b7e7,7dd842d6), -S(eed988ec,3da0c2da,b7235b89,53ce7bb9,7ad8c4b3,7ccafe78,adf5f2d0,911a11e4,b86c5a28,fcabb2fb,4f1c83a2,77174144,b0eb86c5,aec7c52d,59b624aa,38bfff3c), -S(86783a2,5ec820bc,44aa4aff,85212dc2,fb169f73,4b3f359e,844fcf55,abb2a991,6addad83,3d08b1f3,3640ccab,4a68f35e,6ab63752,9f562c11,3ec46833,66e8da1c), -S(3304c750,d62d2678,beeb4c3f,55414ab4,f9507039,55da35a0,193ce243,503b1400,7bca1f1d,87c963b,b2ca8a41,c675b87,205af0ac,ce3d458a,e6ab5f37,fd000694), -S(cd4e3851,b2ad955f,e42e24e7,c071215d,9c4cd24,d456bbb8,452aeef4,4312532d,850be683,bb89207d,62663852,e5b1a38d,d5ec8fcb,c11944a2,adaeec97,17db7bf3), -S(c32114d4,d0c47f05,c31f859a,d26895af,8d46fe98,7565b2cd,ca7363d6,c07cf256,80cd894f,7869eb3c,7df5c5cb,279648e2,adad337,d4f80f5f,501b872,c8b7e9cd), -S(ff6fc809,143454e7,bde3e327,bd7aaeb5,6e7c8c33,93137be5,e63b0ad1,87f3fccc,75aa0f16,ad2cebf3,b8c0be54,aa991dbd,83789abd,214e36e3,3b29f06c,226d0e9), -S(64f9456c,b7b73a61,d9e788d,c31369f7,32d0e34c,5b763e9f,bfaf83a1,4890a8e7,778c77f3,fa3b7edc,afb39532,607bacb9,ed2aedc3,7734b191,ffb5b8ef,867414d5), -S(d9e41a8f,2ffb8bbc,52d10aa1,82d9b0db,f04c0326,8f45d531,500d13c,e25f3d54,728316cb,f2927363,25bb3d18,15fd624b,53e6b442,693a29e0,8d2c98c2,ca524a3), -S(b5a615d5,1241e064,81421f21,45ec55ff,c953769e,74f5c96c,f760d085,2551644e,e2889361,fa674a81,92358a00,61e7b210,c51f88ef,a442b849,d049ce6e,6e9f26eb), -S(5a0c994d,18e62a9a,44358a14,791f4a22,457551ac,5b931fb2,1856928e,a00f15d4,5a706762,8f5ca41f,7df823e1,e27f26a3,de85ad2d,cc2598e5,d8238a0e,587176d), -S(51deb73,6840951a,a0e44ab2,da2a62af,15aacfe,c2740819,9c57959e,10a03fb5,4a0a72ae,f05886b0,6c03b91d,68af04c6,818d5ca3,4e278b6e,d830833d,c15745de), -S(5d967cac,ae97fb90,7f2b8da6,9768a0f,e8a56c52,e79ed9b6,ae4e9a0b,fd92e51e,d840c983,bae8897c,e443d9aa,874bfae1,7475d00,c0728dc7,5090400,47043ef9), -S(2e71c7b8,e187f250,bd500b91,1526f3c9,154457e4,35085672,8d2bc76c,c82b8714,53d13e6d,51840bd5,3e8ddad8,6e6479a8,7b756d57,bf3e9658,c0c0f434,5da398cd), -S(c45ddde5,3660689,113cab5d,f4e218ca,159273e4,db18fb12,d2d80397,1892e9b1,e3bfafe9,fce4db8b,a68a007d,f4c6174,6addc8ce,13b63537,472a2672,48f9203e), -S(4792e0f,2bb7cc27,c44df3d5,b3dfdab7,319ee762,812ff2c6,65da6ea1,2548110d,d3fada96,78c437d8,5d9d9577,3e40ce3a,7cdfa6d1,3e7f4db,17e6502b,b17a71ec), -S(ba662d39,c5c81e15,8ba7427e,8c0633fa,e8e9ef04,7fa408ab,3836a674,328d458f,48ee6efc,f0789fcc,901cd9cf,59fe6d0c,d3212180,20f90f22,682048ce,ca9f1138), -S(be51e863,6aa87c9f,d348a0ad,a7bec639,2ebf2ab3,d4cb68c,680ef1ee,6cf6e806,71ff99cc,7f6cafa5,90bb218a,cdd62880,b19ac007,8f171c81,876370ca,affaa70d), -S(75bac33,bd6578e7,c1afb10e,3521cd97,a51546e4,eed4ad4d,e70d5348,755003a0,5d700b34,fb93c9df,70f0961,bf5902dc,c51c6ed8,163e1fa2,6972e474,9b6da1db), -S(d7647193,14152aa2,98572779,1d1120f3,106a1397,3b964b93,8149694a,fc584bfd,6fa6bb33,a75c0111,cd6f1b89,177b419f,d361676a,93d0f7a4,61c6ce99,e667d6cf), -S(9ac1d334,59882a0e,bce90ae,1a404f61,35e9465f,5be0ebbc,61a479aa,f348800d,b7195d60,a7f4141d,145fd1e0,a5e58305,b1610ec3,4f97b09f,d8a8e57c,3041f05d), -S(bde59b,e8de3bb3,cdc7f5e4,1743a489,eeb99171,a89bcba3,5eae33f8,cfd94d2,208b222a,5831abb,e5f343c6,761343f3,211078d6,ffd59690,9fc976bd,86f6808c), -S(58f7e872,6a34f41f,3720b5df,38a3df88,58d2238d,e60a88da,d4198326,f5e37ea4,13f8cc5c,ea43a637,28c5cb5e,b4fc5381,d5618b4,477758c5,4dbce46d,ad7f433e), -S(fe6d09b1,93d1a7c6,c5d5f6f1,522b63c8,aa257503,9add5cb2,21d5950d,3c4bec93,eb383e15,24f52785,6d8535e3,c6f2f8bb,deb71907,b6151510,a4839b05,7e3e6dc5), -S(8cca7fbd,d0a041b3,e196b08,353c704d,96db3817,29d42f4,513ff5,467ddd0e,23a0dcb7,dd044a24,cd9202c0,4c32cdd1,fd25c979,b0a1aa62,67bc2321,ce7a5f1), -S(a63de000,cd76bc93,7515a124,a334719c,bbd4538e,9d04791b,2b0de33b,bedd2bad,4afe72a1,d26fbe8f,8f3951dc,1dbecff9,c8aaaa9c,bdfa03b8,a6c48cf5,764f65d), -S(5a42a678,c32a688f,e7cc9688,9f93078,8b5f0126,f1eeba7a,c585b1fd,9f97003c,4117bd18,e961dac2,d15be023,6e1254d7,eba89a0,b4ff95b8,82bffc4a,7a375f3e), -S(3c01ac6f,1ba11409,6817408c,5e6191c7,d401f258,f0345c8,6b0c83c6,ead7ce90,f39943df,6465cc6f,792a99c1,b2c97727,421fc8ef,11b2cb9a,cde28709,628efb9f), -S(ae63ac2d,78e0ef81,312fd73f,105d8ecd,8d5777d0,75d06600,da8f5b4e,3e20a8be,50ccbedd,e4d4241b,bd62c0ab,68b2322d,c0e55c28,c8f71ee0,40dbfe6a,d7e33d9f), -S(c793575f,b3ca9516,945bc82b,aec1114c,5d8f8e0d,7cecaac3,31e209f8,22d01044,b2d3a441,ab01f822,366728eb,dc843b7a,82c82175,fd4ff08d,700a2018,48766b1d), -S(e6438209,26baa22c,e33b1588,1b5c0192,b14e72bc,f162f04b,5e6d5941,8053e338,90989550,9fb4a05,741ac6fe,bd4b78d0,15710c50,6c1c3adc,955604a3,1907684d), -S(5d9b21c1,3331d32d,d7827982,6d41a5e6,8ae70be2,b9d5f346,a82b8ec9,aa559323,6e086fdf,95f4a998,66b3f471,f3c722c7,4da8c7c3,1fd65705,68cb434c,1427e5af), -S(81ab7527,8cd4e683,f127e7df,2153fd93,60bd2f07,32a506e8,55f60082,7fabec86,cff8b01d,24be6850,6e068910,55a5125a,ab7a554f,81e5e8c6,78348026,ee7248fd), -S(4684137b,1e19dc84,8a521ed9,e6aa7747,548535e6,6b9fc1b5,a533c580,e7546317,8c2f57ae,7f42873d,5e3ed228,a9276a9,cd684c42,c43113e5,b465cf7d,eef75911), -S(3844877b,e43eb3e,171f614d,7a56aea1,4615ce67,b09bc928,b6a16b48,3c15639c,a2e17211,48d95e9,6690d982,4a7bc84c,c3f0388f,e54e2546,9b58f624,c3761634), -S(d4246638,80a8efb2,99d3d73b,4efd73ed,5bf70111,2b5cde7,631067fe,2b9de212,b98986a0,229fe086,c91b2a3b,4373411f,baa31c98,7f475ffa,1c29ca,93d4b80b), -S(515b8ec9,650c5448,6eab830b,4ee0bd7a,4525c8eb,19520c3c,6e6a214e,a7861c47,a7b12837,51812bf5,c37bc48f,ce08de95,94e4d619,18726c31,57bd660d,80025185), -S(4e499a52,6352b7b0,3d78af31,5597155a,eb4697b8,14ff1d5,93b9b838,6efaaf8c,bd4f5e6b,dbe5a232,c42b0ea4,e55f507f,2ca33587,349b1f0e,56a25820,60ef57d9), -S(2c9a7cf1,553e2593,c455a8af,9b12a0c4,26d579ec,6a097483,a7274edc,98dddb99,99aab288,24298866,f0f42672,395d39e7,338aee86,35c4cef4,ba45f067,83c8c8ba), -S(7d5bdb5c,fdff2871,23a9b78f,3ce189d3,ac50fd6d,fc49bef5,953ad197,8d27b0fa,c76a17fa,97ffc25c,8549d7b8,f01842bf,34afe80a,27be4c4d,fdd68229,2dc83ea3), -S(fb222262,444d6db2,43abdef2,9e0ce41b,818a177,db630c50,9340eef6,24070256,8a42ddcd,a7405cce,9782e8a5,23ab108f,3e5be176,49910b24,c8084253,46b8596), -S(b3212a32,2e415360,62622dfe,43da56df,4beeaee6,b8b5e783,df514a7a,83eed60f,c9396626,6dcc8af7,56efe8ca,e86a7b28,4b2e847a,8e571911,cae76e05,58fe5417), -S(80c90758,1ead4640,94ac1b9,3250b9b4,caebcd74,582bbf20,16f013da,1f4f01cf,d42a5504,c5be0a40,e7bc4242,32a9d703,58370eb5,a54be08c,93f43a22,6e5e6ad5), -S(50d17433,50bcf037,a310a05c,59adbac5,e2fcda09,3aa6ed87,9340efc8,7ce0e228,9e733972,8e88d9cd,8a4e9e7,7dbd7b49,114d5a71,6d91088,df928d60,743bf2ac), -S(c8e7f596,3faec5a3,a32d1ee,65d1596c,a7edc87f,486a13d2,c7ca7b84,3b358cbd,37250705,1891b406,34a9752d,942e6ff5,67fff1e2,d67a88de,ce79ec56,97f5ec38), -S(91f28714,e47e051c,84bb29e2,db84472b,e3b78524,c998a071,731e4f41,9b94d2b6,8ea1eaef,984af3cd,21be9097,99f68033,7c6e3479,643e0c68,b00963bb,d0125f0d), -S(d50a1905,ac4d2195,5c2e6733,5d38a08b,26e29809,674e1b61,8004d18,f823f402,83cdc5b5,33145488,35884fbf,f14b8e5c,35c1ffe9,29fc5222,c7e2a868,d5906827), -S(c45086cb,387b9bc8,a1d7b71,ae74a87b,50ed90e3,a0027766,98f7ad4d,809666b9,1c0abe25,d46ab7cf,dc4a5ba5,e3fcaf27,822b5f0e,1bc08af4,452be7ba,d480e605), -S(b486a681,f9b26f12,c67ba147,7ceb43c0,90539587,72dd1dc,15cf1e74,9fe3856b,f4bd7623,fe97b6e2,6f49e292,899a7f4e,e7925cd5,3fe51cc4,33f77d1b,76291240), -S(c7563596,946f57ae,f91d12a2,4dbd2d0f,726422e2,ff6ea15c,f70c2e7,868e6f8e,566fef1a,aa3316fa,e935adc5,bf1e9682,e3d00e24,2bb57e1c,3009e6b0,df58449), -S(6d0b65ea,265366c1,7740e473,f823ad65,f38081f7,86156199,421a8b46,117b2733,4b724837,8748545,c6d0511,79d22b3c,61932bc3,563eadc9,a8edc5d8,1c170f5f), -S(87973dc9,379225c,50366d92,f0591837,71828fb1,d1d3a65a,20edb955,c2e48414,bb226cc0,67c7fc4d,99791a74,301167e9,62e92498,6ebb0fad,fcdde6ae,8c39223e), -S(72e7347,cf657935,be5939bb,648bf628,6a2e870b,cdae70ed,bd2c499a,be83191d,431e74e6,bccfbf3e,3fdab221,e2274a77,947d9cc3,5bc55c01,afa2d33e,8234cccd)}, -{S(bc4bb9a6,292aa09f,5c66dc9b,667c4642,6b08211f,a9a80f5e,f3f17b,21f275de,5d0e0492,39a862ec,b9649572,6f11bc09,cebd9f29,d9407ab3,1603054d,d9b76b07), -S(59fa87bc,4f47100f,f37135c4,1f5da6e6,28b76376,e0f365d0,eec857b,4b342b19,cbd82bed,1859e567,2e37e18,e977fdc3,6997482,a2db416c,686b3b64,a3c1d66c), -S(3af64d00,ddcaaef8,172aa0d8,adf5ebe7,fea87204,38125e07,eb74a5ef,91c17acd,4d695d52,ab785972,a425f6b8,f9f51e54,7067f9ab,b2af1085,bf22d1b6,7f51202), -S(31f9458f,d3544b7c,cf0a55c0,729ccb70,a57fc498,2078ba85,1fe4bb32,164e9259,31c6bca2,eb57ad06,e74da59,c824c720,17bbabe1,2e71a906,e6ac2e2c,36833b0c), -S(f2bcf05e,bd8ef03f,55d3d5ad,dba85359,3afb6b49,d72b2df5,c8107020,185d8173,a0c011a2,513c227d,22f045d,59d763cb,7c820ab6,e0b35144,66acbf77,8c188b22), -S(9373aead,2e733de2,cd4ddfd9,43675acb,40e2fdd,79c0bf12,45f8cf95,f2ece30b,8f171f4,5c1cf577,7416c873,a87af091,2a2eb20a,82f07c43,1e1f1b00,36c3276f), -S(5d2a3111,6cf78432,c8a3b0c4,a5021720,dbdc5e94,d842779f,6df51fed,5cc1e47,fa5381e6,ecacdb0c,6f326569,771b0f5d,d7e3c3ae,7c64cad5,ec03220a,33a24c91), -S(56549c28,f339c6d5,77efa8b7,3d795f64,580dafb1,f146268a,c7e751e2,fa3f041f,7aae31dc,2b875c94,6c2ce9aa,a6fe33b3,13c3795e,a188f343,89c34a48,bc3093a0), -S(ff4aa1c6,f5120040,5d488787,65f9931f,366fad1f,8a7d9ebc,abba9805,f6684aea,faa72c87,6956050f,663c172c,b3a0a3f,56e7e698,62723659,7a20c0ee,5bec6ccd), -S(65873e26,5ad6233b,41a6d42e,ebf1fcff,e8b1ed8d,97eb9131,1ede963,f8058c6b,80b955a5,d1648b0e,ef8d883c,24c2499a,f0f9350e,d003674a,fec69be3,d9f9d2f0), -S(b3a54b5d,3e19513e,b7be4c78,633a0e77,b4ec4015,d891bb6,35557fba,eee92f4d,1aabd4dd,3a995ac3,8c021f50,f2fcc578,5cdc724b,2b657f2f,9f82e777,fd449eb0), -S(30e69221,e75f5bcd,7b017467,d36abe41,d76b3589,1f82f38a,ff79be7e,fe8a7d44,95d5120b,807d3f47,76b7ef43,3ac7db28,e6b83c07,1e33573d,4a45eb8f,51296c88), -S(3a61f393,d842419f,f9d49dcb,e169bd36,2e28f92f,9d6c197,a441027d,9edc36eb,8cc6782f,898e586,1faa62ee,dc2ceee1,b21ae86,9e40e69e,20872b74,361f6f0f), -S(f46f5bea,e58e4a74,1838e312,57e3b579,5826ad3b,6c0576c1,f8b30874,c3a5779,91e35b62,55148a94,df34dcba,d2aa00f4,95e91eae,4a1c2d97,43a7fed2,d2713854), -S(6db13572,e3b35a2d,fdee5469,52d69463,19b5a95e,9e7ed8be,95cace14,471ee6eb,38c2be05,a1fb0fe1,e9dd09da,2684b4c5,de4e93bf,60fb3816,aa4261e,fdc9d79d), -S(af86cea1,e34c2d74,fef9d3a3,43d66574,2ca64259,f848885d,be0be05b,c8cfa432,8c8a2d2,da789ccd,b7f259c4,124ae844,36890818,5272c381,16bdb76d,f71af157), -S(89e5829b,41074025,cf6929d4,63dac04a,bd3139df,21b589d2,af8a0b7c,1c3c625,f762d80c,99197627,346af77e,f5295bdb,d86b5fa7,94975c6f,881386fc,e2609ddf), -S(2d589866,819b012c,ee8b7f5,63c20617,cf7d3f3d,ad56d4e1,c909c8b4,2071e6c8,cb7b8d2c,ff2bb979,1ff6f9d6,28d6a67a,80d1029e,d8d08573,f5e3b6f8,8dfffb67), -S(93ea11e0,e298b3ac,16ba686c,f5c1b089,55ed8d67,c318dcca,cb320d08,7f33740b,df9fbfeb,fb1547a3,92954300,98dc59b0,8af26c3c,ab7b42f8,5489af52,409a11d7), -S(febd58a2,529be1d3,8176be80,7daab920,32cf355,9ffd7d,154c9962,ea66567e,299967f5,5fbbd509,76271d5c,53975b3d,a4b43d1f,71f12ba,4a618a1b,5c11e484), -S(eb2e3d64,a5eecd,bc65bf45,405c8af1,bf4683bf,465b4a1,f8dc4627,b5b5c81,3c6d2f03,b30b2e49,4d056d55,3d2cd0bf,8c8f41ed,14b260e5,7bab5d0,c77dc06f), -S(9fefc3ea,d2ff9b51,57c669d0,bfea2c9c,7bac751f,9ac83c1a,143d05f,ba408216,10f0b7fb,b685e767,41fc9a7b,6c90191c,6b428e32,d9c3e611,c97aa120,8e361bba), -S(90b9eb4f,68cec46f,b7e426c8,94576858,a49ed785,a1b5be63,9bc68e5,33db8479,9aa3cfd,271602ac,5e9e84ab,343bef4c,9f8797eb,79d247f,7fde53be,11d32335), -S(2b80ca58,85919764,80e54e26,ba726c31,8b491c9e,56ac6d4a,f2163064,c69ce44a,50a00290,17815845,90773443,1c7c82dd,2e071d54,7d4b657b,f9edb939,24cb2a65), -S(df8e261a,55523b2c,933d0d15,c4bf5a0a,a8b2d01a,bfa7e064,d48aefd4,44485775,3d043bf8,7dea2305,274957c4,b8b5b37b,cd477b00,7d86f45d,b36fb42,c53c20a7), -S(7ac6a221,445bb8a7,ddbeee44,3aaa2de9,86ec1fcb,551caac3,84e2d37c,8aa05558,746446bc,64e61523,c52e5a56,b1315151,904a3d75,43191b9c,c32172e5,f08d22af), -S(5c0ace30,4217ff80,bc37f783,aca722c9,5027492c,3335ad3c,aae56270,c58509da,39685f11,9a646344,92a1157f,ca4548aa,ee37d52b,87d0148f,850976b8,4006dc6a), -S(6cd63750,f8318534,74da52b,11b8d66f,2a72c83,582b8c88,31d6be9b,ee5a826,57ca2d88,aa5f6970,54a6cd3c,a568f9a3,cd850d31,3510b1b2,adef4822,a943b3b), -S(9cabb7fa,7d9e6d89,42dad033,a22a1acc,1587e80c,fd7a2c78,fbc9bc11,c2cba6a0,f6bd65e4,1639bfe6,44f1101f,6acf65bc,ae5f56c9,f132b37f,8233f568,a23dd0e7), -S(233059ef,878839ef,60e1756f,771003e8,9af5569a,c5b0b849,fa84184,b9b9964a,654207a9,ff112902,9c9be9e6,d3d24bc8,a61a5c8d,4c25143b,5643e004,4fba7520), -S(7cc5b46c,9944e309,86e22624,99805a7,2b9ed814,954494cd,18c74882,aa3b8f39,c7ebd041,c5877c83,2cf05c42,6569ae0a,c1a37583,ceeeffb8,8cbc7090,ebbd71de), -S(9c55c21a,48c766a9,bc31a0b6,6e65a719,ec4d181,994cb533,3bebe7f,e017faec,4037846e,c6ca685,5764a8a8,230b07b,ccb9b145,b0d4a0bd,8b26020a,2d2c9da), -S(7926a60,bfdfc1c1,4d20082d,37b4a6d9,8e7651a1,4ed2a3ce,547a99cc,feffa208,da120ef3,d60469f5,dafe0776,8717dd2,5f95fc58,87594181,4b54604a,1aff86c), -S(c52dd3ed,e63fc9db,95a88ed3,e62064dd,f7f9112f,c30acc3d,3fc8438b,7d206c14,e65252d,2ecb95f8,a45059f4,68bfccfa,75b3b3ff,2ec9bbf0,46f51b0,416592cd), -S(831432ea,8e1ebdd9,3e254f18,15ad0c16,d637b04,85d43d4a,9eff1221,5835ec2e,af620dcb,328c94fc,b238fba9,3eb0d1eb,6f3f2838,9aedc2ac,26cb4f87,ea9cfb8a), -S(e5b822e9,72a7a2fb,723c135,d6d45602,deed7cff,61124fab,ef5a4fd1,68828773,117f1b94,6f715282,bd5bcef,fc2a340d,de226d52,cf3a9643,bc8c5119,542fc9a4), -S(59b98a72,bb15c51d,15f93497,bdea606f,2505b1fb,f37e42a5,73fefa84,b00deb6c,cb1feaf,bd5325eb,e604aaf0,480cabde,d6a5bfa0,bf9c4bed,674afb3d,65dcc5d4), -S(8847961d,6547b9d2,29f1faf2,ec0aec4b,8579c8c3,b1fe967d,eec280a2,ec45fd92,5280bf82,96b0251d,29ea6573,fccae24c,bdc4af9b,77043461,32103fc0,badcacf6), -S(bddf032b,d6c8709f,4b0f7b0a,cec96259,6db33d02,3d2270c,7824307a,b88bd4f8,b2fbfc91,c7944fac,dc69076d,90a1bc58,4d202119,574f0fe2,223f7821,c8100dd), -S(966bf84d,b5ed857d,cbe278d8,25167aa,eafcd957,597e8c08,241702aa,fe983af9,85e373bb,9788f0f4,2e4d6bf1,52136f90,b0fa7325,d2c791cc,4a7103f3,4ccc0b20), -S(7a16d469,e57ae4ca,46e198b0,4f970300,c2eed190,58d81028,ff2e1283,267099ca,4bfdcb6f,cb3b9c0d,782737fd,505c984,41c82029,db95b83b,c445b581,d1ff39fa), -S(818ebad5,7b04a0c6,f1235c71,634cf8d1,945a369a,8c707856,c58d2316,5bcd13cc,3cb6c26e,a053581e,821fcb36,174e91c5,bdd56144,7e3bce4b,c69f4f28,8968493d), -S(72059db7,2d838163,58b16402,653d875e,da620a67,5628a861,c6162f18,8a2bac61,232ebf0a,d0cb25c1,78626633,d4d61d47,d358bb35,b525e624,c2d6ba41,698f813f), -S(e407793a,b1246e86,aa9f782e,b1a0422c,28846f2e,49fcd886,4348c22e,411259c4,b339b1ab,dab01588,e8abaf1b,39a29055,66c14da3,1feafaaf,ccfb140d,1dc1efb3), -S(50dd489d,851e6b2d,af877b4d,70990326,dd9f9b0e,c22ca933,99dbdee8,ddb7b8f2,a9a28ecc,6d500065,4d3a3747,27be80fa,f41faa1d,6e51406d,13622655,e6cf5ac3), -S(5b592078,d50b3a6f,c94aa2cb,5b1e3a81,74a3d644,2fd12c2b,765678e8,7e00c8a2,8ebd56cd,313938a6,681a5ea4,61409f81,a4af4495,31266c3f,b915822e,845a8d7), -S(f90cbdc0,a228212a,32eee9e9,43e786ad,3a091308,81ad5f04,8a629a7,7035998b,6ae4854f,c789ec49,bbfc5d8e,14cc250a,1b862e51,cb343ccf,a0957b18,b9eb5545), -S(cea133d7,6121db90,c6281060,ead76d4,64b3825b,79363a04,ab0c0bd4,8abd9437,c66be897,96a25bf,867cfea4,f0803e1f,ec3c5a3e,178bbe6d,a972b2e2,e677dc41), -S(a09d9e59,5a4baf0f,b1f479d5,5d3cf051,7b34c007,b41d655f,efe61dc4,4111a4b5,2f21f502,f9752e2f,9848733e,afc40463,8e29d45c,1a294ce7,d09737d8,bc9bd1bf), -S(bebb4360,ec850828,b96a774d,2da91f0f,17c0a288,47796341,d617e1b9,b8728951,ea06e33,55603e97,91871935,f01cb416,bbcd226c,83cad5b7,fbd0eb39,48254a25), -S(d7cf537c,430cb0fd,434e555c,c1303b4,3fb60476,2b7f617f,4c2fdfeb,d5654461,f4ff7415,55841324,3b944ca9,adf91cdb,dbda99c8,90dab0be,8ae2a294,9e61c0ae), -S(1ea3f684,892f93c4,aa9372d,6ba193c4,8e6abb8,868bbd17,d91827b3,54424d5,dd549d14,a684f6fa,b1a401ba,47f42a89,14b0d012,80d24bed,743e3521,16ce17e2), -S(ac0890bf,ad8cab43,fa85b5ef,c10a5c7d,dbaa0237,daf20cc6,efc94c78,d95a86fa,a16a3028,69f2ae14,4566701c,f80add76,48d11ff2,1dd2596b,c30b074f,a5f3159d), -S(6d573525,43fbf521,d49d5b15,36f83a01,748d3470,57254639,4cec6785,860000a0,98b9f97a,9ae8bc6a,7ada1bd1,9a225ffc,8727ed3c,32b169cf,c381a60,3590acdf), -S(7be891a,771227eb,fd583033,e3801618,28cdd0f2,6e72cbd4,d9ffd169,92d7f1f1,be22c30c,3cade74,14bc3a7c,c3b4e5db,7ebb4ca8,b3ef67a0,b89fadf7,7b404fd8), -S(97f0013f,10a9ba96,58a1a5e,bf8f2d6e,4f2c56ff,9acc6221,177d2ce4,fea65efb,bb88987,7b7d1929,4dd4a011,7440707f,916e1b2c,fbf2b0a,5805c5b6,d8e65e3a), -S(77c3d2b0,b7ee36dc,69b75d91,11fdc25f,3996642d,a59b87b5,5f5840ab,cd5cb1b6,769c9cd3,7c4f4059,60129e1a,4bfeff8b,d86a41c8,eaa4e3d6,826a4cf2,5185c5ab), -S(a0a234a8,da6fc04b,2c77c7a7,a3b79f5d,7200df84,76d6737a,e879e4c3,a080fe5c,b9b8a2a3,59af78,9d5f0448,3f77e1a2,923a28f0,9f928067,4bdc1aac,8e8f0bcf), -S(1374c3e7,fbb1611c,8449d724,7ff49167,230b630e,a0c2c0ea,6d438426,9a91fad1,21d482a9,d29778f7,dbc31471,fa120bf5,abfae23b,185dde67,2198c725,47721db6), -S(f6c035f7,270679a5,4cac1f52,449f357b,cc36537e,669f056,3bbe022f,541e5d67,d470bd7d,9459165b,8bd093be,a3f64f8a,fab85bab,25f31046,c3db4167,5e8e7e77), -S(1baff567,622fda3f,7171e2f1,f66498e1,da1a2973,c5ad784a,6fa5af2f,23cfdf69,e1a87fb,1dcf917f,2dd6856a,48de7762,a05e0c12,89233db2,49637e69,15a5aa4a), -S(eabb2399,ebd468e3,84bd7c14,1329f972,96b86a47,53cdefdb,3b539449,d4e04d92,92d94943,ff0dd405,fbf02d21,875b7f13,25eda73,ad65d332,d005870f,951e3db8), -S(9121e2c2,13734da8,23ec445d,cecd6740,e1e5f513,7771ef9c,72589419,25f25ce2,8b1dafb,ebf4ee9a,3c39f51b,dcb560eb,f3e27409,589505d8,a9c18946,847ddd63), -S(51616592,730c7580,c2ba7dce,8f2d7aae,b71c1796,e35223c6,8a6762a8,c0566563,5af04478,c1509a8,905e271a,80c01376,bbcb5161,a78bcef0,1b5116b4,adcf68d8), -S(5489e35a,4800b74,e7d9d8b,99841485,2fd80e19,b290d7d6,22ab9f66,de8dcc11,3ec6df58,ab461f1,9a0879c,149d042e,8e7e5c2c,98dac706,19137120,74a05492), -S(bbd6f40,774d7bb8,e3fd18d2,b7f3c2b4,d1ad882d,73e101ee,3ac247f9,b8720005,17134bcd,6f74cb12,48b10902,b9eda37a,fcf8e5bd,50604a0c,65d08952,460c04ef), -S(1d99eca2,b542ff0f,470e7b46,ffa024d0,ebef5635,c0149593,b4b34f6a,d4531cdc,2e9cc03b,b2e5a461,a3122521,e09cc6c4,63d8e6d7,c4aaffa,c9d036c9,6b74d882), -S(32c2caef,93d345c0,9451725b,84b1260c,a9defe2e,228f985f,f33c3f33,70afa675,6875bdb6,3c8d28df,71317042,d2328d5c,24614210,4d134068,a943489d,e695920c), -S(25107b07,4ac55835,81afb4d2,dbf5e1b8,21c26b56,75efb3,33abaed8,56d0a5f2,626b9614,2d70c2a,5572ff7c,606abe47,cb90f850,2c13d478,3ca4e045,bcc7ba39), -S(d542e001,894cd3e3,97ae2519,f4b69c7,59308117,9ef63ff0,a9d586b,3fb324bc,bdd28dcd,94c208f8,bed304f3,adbffc7f,76cbc70d,333dece8,b2680b6e,19076fa5), -S(c1b950e2,e7cb74e2,a4274cbc,b67772ad,5c32ee22,b18c3d99,e4a92005,3edc000f,e8329595,39709b81,58f892b7,2ac9c0a4,e1e692e4,da526980,2b046759,58f0ffda), -S(8c6c041e,b8b3daca,fe89492e,91829869,2451bc8a,e4dac8ea,8cec1d49,c25778b7,6bb9de3a,55fefdbe,4376c9ec,dea4bc24,ade146b6,c454a441,8c47120f,f1f55d56), -S(4806db6f,bcf9004,e4cc63d5,555ea5a1,cb9107d8,e060e3d8,8fb79fe0,3acf1e46,c0f5f482,288b0036,ca485a74,a6bfc264,88441487,63804ece,e620e47a,16160e95), -S(4b3e050,26545104,176aabd4,40ef4ba6,451bbb0d,5420edb0,4063c22c,2e7d8928,42ebb34d,ec06c95e,11ed8e24,90369796,2d8634f2,2641925f,f765b06d,838b5cc2), -S(be7a60ae,bc21640b,2f027c33,f6ec9422,5e66c16f,1d946ea9,dd881101,5d80a21e,1dd12d43,2b2a2f60,9d434936,ebedc2f0,b9c20747,32275c94,fb7bb15b,bb323bff), -S(550813b9,3c3dc22e,4dd576e5,50042b51,34f1a905,2b28af39,cf87bb89,84cd8211,33cfcf61,91cc032c,dc284de3,7adf0de1,a83e39f5,27273eb7,f361235a,40d6da10), -S(33133c21,98343b11,424655b0,8ed83de4,ab36c87a,1c5316a0,686145f6,62be725,fbf5d264,30a71f5d,bbf33aa,be2ba027,b8abc0cd,37d0130f,a99a6698,75f011b8), -S(dc21892a,8b5e8ad2,2d4fca59,7941bd5a,5099f82f,e47ac4be,7e705a35,9a03eb9c,7d49d315,1d6b6e97,1f8712db,197b3c8f,aa8b79d0,5957379,6b895bbe,581242d1), -S(64e648c6,98b6ee15,c168e71e,dd031c66,27486a0d,8f858342,80d55924,66421465,7244a14,2e7fa0b9,a41195d9,d74655ed,4ac3f1aa,9f055c90,326bd32a,22669878), -S(153e77e6,b1704f24,5ad12253,7f11e9af,e22c2647,67293dbd,fa51e415,950f7b2d,7bcddddc,ba3b79d,7cb6254b,a4b4abf0,a44fdc4a,131eb185,c6a480a7,755cbe6d), -S(24ea7667,d2747412,2adc6c73,4a8babff,df7850c6,a7e60647,e4825f80,9f89147,385b29ce,bad1ef7f,c661e36d,97bb9eec,5d415c7f,613d82b,39f8b131,aca17278), -S(897d6779,70dfc489,800087ee,c67c957a,5299358e,14f63610,c991db4b,530c32cb,42905602,2ecd9bd5,9d8e3d49,9e037e07,4268033c,6ae4c9b8,ea579d96,daca5c6b), -S(beaa3e34,26dbb441,5ce9c604,7db0821f,79af4e5,faafdcd8,8c89f265,77462905,c0fa8760,f9964d11,d2152f01,3590180b,53a67a35,16cf7c3c,403361b8,aab86634), -S(d2c97e5f,85b4025,a66c29bd,23b5d30c,4c8f066e,f68ece5c,df907b2e,558bf547,1e320de1,3347ea0b,13ef7f68,cfc4bbc0,e10bf7af,c031f64e,9a9f2c43,181ddb61), -S(1ec48a1f,169baa2d,ef5bf8e4,e1ec8f51,d91c1667,6906c912,ce084f2a,9aba1d6,498a5d90,6ec47ca9,f6d7c5ee,bd25f83b,a14884b5,a4ad64ef,3fe9ebed,5ef0932c), -S(313ad91d,44f622f7,785b3ca5,6cf9e8dc,389d5aea,b696342f,ce58ecb1,d6e9b45,60f8ac86,3cc5eb77,c8f83c05,81aba889,d48f65ca,b9757076,7d9973de,f4a693df), -S(93f7f233,dee42606,41f8fb3d,d67e6e9b,cb2fdcb0,905e9b0f,92fb2094,701d6ef1,1cda7163,64ce202a,b53e3cfb,b4bbdbf4,1e124e57,85f91d5e,5a5f3205,a4e4ba13), -S(56694a44,a4455ef0,a429a5ef,d11b6440,bfa6e0c1,958b8f2,e3a8d00c,b1f5feed,ae0e21b6,669e1b86,e27df62b,7038de4,fbfd1b10,72da3ebc,82432787,ba5cbaa5), -S(7a6a7dba,80380635,d851f291,d7dbf6db,bce98978,805c738e,8c80c20e,c57e3a0d,673236f9,ea37dff7,c9eeaf34,b63ae652,1b38fc9a,94c111f2,b3e253b,34f05009), -S(d4e820b7,aedaf95b,de86a889,f0adebc6,279e0ce3,b0757972,d574f64a,3fa6a6bd,42762fa9,1b1cb9df,85c55acf,95a421a2,d4da6f01,69474abf,61209ca0,4f062939), -S(62f26014,d06ef2c6,ae6d459,6e45b2e0,d7d28f11,ec84fe61,8baba130,1d483950,d53fbb59,f239a52d,592b6f98,fbe311ee,4c9d4e20,b6d9a8ca,5698503b,eba1eeb1), -S(bc5ac17c,2a9e3731,7dc80bb8,7eccb0cb,ae804158,792b6926,60cf3f53,b2446eb0,e2a67966,a8de04a8,db78b4f1,e37c6885,b99b188e,1d4a1fa3,5e9084a3,96e5d8e1), -S(80743e30,983d175a,ce9ddb09,bb1adfc8,1b059b9d,73c51b42,d29a9f5d,673fa494,eff1e042,89a84d27,2d941b5d,5bbceaff,d3b7069d,9d704317,4b35e2cc,12dad80a), -S(faf014bc,c17df331,1902a50e,fb18469,9f0344ed,b6b057ce,5c922f22,97f5ae5,47301fe0,6fb57e8b,5fd121cc,be2da9fe,e8e918b0,7a9d9228,43e41de,77e2c1f9), -S(9e89950b,e18485a8,14eeccec,4bd484bf,e2c027e9,54cae11a,52bf2a82,43a6faf4,e81f0ee6,c85c5571,f5ae6a03,3ad4791c,68f9189,507e53ab,ee15e035,6372f6e1), -S(496b3eb,ac55b991,fea92454,e844e5a3,fe7595cf,b25fe7bb,c358f0ed,38e9cff4,d13d035d,ae0d457b,540c6b67,4db20893,f75ddf53,5c6c54ff,95e46c76,14a58153), -S(24ed90c2,3547169d,bc55f880,33204740,a2fd2119,63737fd1,debc0578,400c675c,f37940f5,e3e25da7,7ffa143a,865e46fe,a1dd1230,fb42a627,9e791ee7,38b739e5), -S(9cf8971d,43eb50d2,e522fedb,9281026,659612d,2fb2bea9,d7f6a65e,cb2c0703,b0b6a53,103cd33c,6e0c0bd4,5cab3923,29012395,f8e8951a,1fc4c9dd,95cbbdaa), -S(f6c823f2,ce2006a9,6cbf68a8,61f00eaf,4d8524ad,3467f8de,8dc64911,e89b1f7f,6eee9a22,59ad8c81,277d52b2,cb3b5e44,1259fc8c,52868b74,4946b0f5,b8d9abdd), -S(4bfe7,5bafa425,7f1fd25b,12b68afa,abff6771,89f05d07,85e06d82,b6906316,4ee94fd6,a5388fc0,1ab5da36,41b5c562,9f7c966f,64cc387a,9b3336f4,34323adf), -S(d15fa5cf,a481a1b7,8c746f3c,a19e0979,8b7e777c,4841d73b,ec4b63d8,b01c0019,c6fd422,76ae3e1d,b28ce840,29b8079d,7dba4c1d,acaf27d0,d2b29bbf,5ed59f6e), -S(bd17078c,75e7c325,80cf4a88,8d43c5ac,c323d8c8,4e9d5e29,c09c8c77,14ab7397,1094e3a1,21abba10,7da189d9,2f92c5c,f00b373c,89f346eb,351450e9,7377cd4), -S(1acbdb1b,79389dd3,5dfc607e,2aa8134c,fb04a655,c4848cb6,b5b73491,cac2cd87,8d2bcfc8,72da8a7d,1b89863c,ab7610f4,297dff9e,bf9e3f18,8a6bd6e,99421c97), -S(49e5b6f7,243f19b3,c36c5411,a6e34e2a,f61a99b2,38958b93,819ec7e4,6d647af6,9af4507d,850aab9c,9b1eb3be,90c15460,3756e29e,fcba23ce,313a4dd5,290f1385), -S(15bd9023,bad0eec9,fb19a720,e0a7be10,df78b3b0,716978f,5ee37052,b19d1f92,9cbac74e,7adf5e32,8959d826,41fdcaef,1d4eb24b,a5bd24ff,8d2625a,12d0ea80), -S(9d03f121,d28dc96f,ef6eb2a8,d3737033,e9f6703a,1683aeb8,c583b78c,7910eb6,46723472,ae342ff4,fb9fa789,8e063379,3b9b6781,4bdd8f43,840110c7,4e8e03d9), -S(8abe7e21,f025f340,6929eaf8,c818b016,f7423717,c893b6fb,cbea7ec9,7db98a5e,8bde4e6c,c37c681c,4f664731,719ef10e,e0e7f6c,5739cecd,32f6bf87,c1ac6144), -S(66135e6e,e913c965,ecd190c1,9d4bcc5b,e238225f,3755aee0,64852da8,96e848df,c2c5133c,9c033d30,2029ef21,1379858a,ec918357,421b7614,13a4deff,6f855ae6), -S(5dfa7af7,596b611f,24b57d98,59a5cfd9,41ffdfdd,1e80b0a9,994966a0,338d3b27,2780b496,8fa51ba6,b6256d78,aa25249a,982c091d,40cb9336,863ef2a8,9e4caddb), -S(a5a9782f,f7c90216,3a235a3d,9f548af4,a0ccf508,1aebf0c0,f9d4d772,ae3ceac5,144a9e55,f017dcdb,fd093573,c47b9954,20cd8a63,bd7cc456,f301cfa3,b7e7b8ab), -S(fcd5fd1c,44765529,413ef8b2,63d60414,c6b1da8e,3d2e8463,f0d6567c,f9029916,9877c363,d6180a8a,b005d5ee,77eeacdd,ffc237eb,a30da48d,ac582d0a,84e8cb31), -S(95be1f47,e0aea7c,4c0720e3,fd528ece,66627ba9,3f172875,76b1490d,7a8cc395,f68eaaf,9c4986f5,32adc845,31ba80c9,2c817962,1e042503,6e58bc46,f2d18720), -S(bca58c89,dd846a85,6698681d,450afd5e,621c9ecd,3e1cbdc,d8f85582,4a9cb047,8d0160da,d653a54f,323bd258,74360e4f,573d9a18,c3360121,e18f33dc,5be1191d), -S(1508b726,9d97108c,9c4a01c2,59fe7022,dfe63662,c6b695dc,6404a9cc,3a532a8b,e4f1b655,35250561,cf8b38eb,1b43bf23,430fd354,5045c434,dce7d3de,c22528a8), -S(b2b2dff3,fb9b7b21,411195f,c095f2e5,d69dd4de,249aebea,b266f6b0,c45d65e0,f81346f6,2377c415,a05c0a4e,b0b70a3e,95361575,9241cf7a,22918713,199a5cc3), -S(b087aca7,3b1daae8,b5655de2,6ec08874,14e3c2ad,fd3c84fc,4c6ad73,b735664d,402e931a,b04132c0,2efe8d75,6197ee92,90ec0b64,abb12862,728bf679,42244f36), -S(eec45124,dea794fa,c467c17d,5f843902,2f7befc1,f535897b,da946e66,bb22dbd7,18288f3c,6d89b340,d250bbb,afa10261,a30ab71,c47d8f36,a6a29312,e79945b5), -S(9e01ac6f,214ad3e2,252051e7,9802e09f,ff5a1f5b,16fc97a2,f82c5427,515a4fb8,c92a340,a9798e40,b8026d1a,826eb59,e6db59a3,efa12ad3,b891450b,c7ed015f), -S(97c0e53a,f2dcf282,66568795,2fc72a69,33e7161d,7a9312b1,261b0085,8bdd386e,5ca75fc6,b5aeef6d,7655fc27,1fe56c05,8d7a65c7,912a23a5,e4105941,2b20cd5), -S(79f1fdd9,179d870,45f8f8d3,c0f6e14b,2c932673,1cc2e79a,4fefb3f2,9966a21c,38eb64de,e16be6b9,57c5e78a,7a64a55c,90cf0ab3,a99c964f,b0dcbc5a,7f15e40f), -S(53559fe1,d3222709,8e26093a,61770eaf,9bfcb7e3,e5de16eb,df6e8934,a9522921,4278efb3,9cb23458,305c7ce5,bde295ad,856c901c,d4c7faa4,bffd6c9e,52bae725), -S(dc3c9dff,d1ff296b,17667fa,f58231bc,d2c26a9c,8f6485,514270d0,d5d00d37,701693a6,17f6ff10,afd51c26,e760e0d6,8fe749db,aa5b35cb,636643d0,b3755ea9), -S(3b1ee2f2,9ff89f3e,78295dd1,6128690c,557e188b,f76b86c2,2698e0f2,fca33213,69d4fd8,e1886d81,d22461ca,81c20e95,ee813d9b,6bc39af6,38ba71f4,72db25f), -S(8c9b2d19,a576801e,e03f6108,84d1106b,e13481ec,817d892d,4b233aec,3514d12,55e30950,d67bff85,a1fd0efb,210f0180,d349fdd3,20f3470c,3bae1c70,21550dfe), -S(fcd42391,288b05d8,8e23e673,7d612ce2,f45896dc,7953cfa5,fd32fac6,f8ccf8e5,83c5ecd,4148c600,d9416831,68ce71be,dc571321,6ce07f5b,779a1773,412a8e47), -S(92cf957d,a51ce801,64e6ceee,76defb26,f14d1922,9e9e1933,4f13849e,f7922f44,cf066667,272a2d54,acaf3fad,2b9515f5,c8c23828,18a91eb9,d6b03a61,475e2298), -S(646d5ab7,421ef1e1,1f86c4f1,6d308cf4,401ed527,c975643d,e0221f17,6c2441b5,3313b887,226eb9e0,2956f3c4,f764892a,3b99bf6b,8106575e,55c792cf,3645dea1), -S(3a99563d,d92cf9c7,85a0882b,9f51af44,76af2e4b,dd23495f,341a524b,d3643954,8bcc950f,1eabdb50,c1cf6e63,1b491672,9dbc1df7,44769283,e52a5179,303ccae5), -S(e8979b98,5a418b6,13d4d43d,d004de47,f6cb8e38,354fe810,7f47b741,c69a780f,c407e05,a72b449e,43bd8069,9f7b2559,ec26fafc,a016c735,a8fa5142,1beec4b1), -S(5c69255d,207f650c,59fdee77,7d59dcd9,dc75e3b0,8fd7fec3,d6f69929,9dffc8bf,a1ff812a,4690c166,48a7f3c8,cfbb688,fc5450b6,29f8f0d7,41e36883,ba570674), -S(48e3a29,a1be4db1,d1fe34ff,fa352356,a75d97d9,1dd73448,10f9d8ac,ded6ecb9,8bb6341d,d3431054,893dbf21,34e02153,2a1ec461,1f42ea41,d43859a1,4a6fb78d), -S(fc9d5478,5428ea33,8bea7507,488e5505,f82e680a,778fce8c,9f84aed7,ffb235a6,884e8b36,19ec9e19,9650973e,bb160df7,a116f429,aea7b742,b1837e,43dcc4cd), -S(5768babb,8f16cf85,98c268d6,9965f913,1ba2df86,8f96958e,5c926960,9f86810f,a320eb27,3667ef78,4e0a1e0f,a4d452c5,d9eaa349,b44d00da,6373a0b3,377da289), -S(499c15bc,5bea1040,5ef65654,fce454e5,4072450c,4ce5f279,62fc1f69,9bb103f7,3b539537,3e537faa,89adc347,74721df7,ae1554ab,ce2b7ced,38f67b41,9b157e3), -S(e90e567c,20c1b561,be3a3c9d,8a227233,73503e97,a1e88e,d6928465,77188951,26425fb8,49136a00,392a8b01,4248e2f3,10b0321e,d192e9b8,744e7873,5c393396), -S(5555e213,b06a7807,98ebf522,9142f5fd,4867d080,30ff2f63,8b637d74,3ad54e42,1b82a7bc,610284b7,758d1d75,982cb069,dbf77cea,c9deb76e,62eb5324,d726b42e), -S(9b1c140e,38b3899a,c77eeafc,1784805d,1efc1363,d25ed7fa,abf923dc,dc53d9b3,94bb9ad9,9b01e6ed,af7b4807,1ac2f67,ceff22ba,3ed4a26c,7b1b82dc,9c5fb8ea), -S(268533bd,33f9c398,5d8ba9f7,d6d111b5,9ea49cf0,8227894,cd236cb9,4c4d6e45,ad5ce6d4,3f70c08d,2b1aeec7,6e7d421d,41e61276,fd2c5a7f,4d263479,177067e8), -S(9bd29abf,3d69acb,1ca7f6ac,68e47d1b,61f8612b,30c36cf,4ed79939,583590de,530faf27,794dd14b,9fc084a,dd6b3cff,e0343608,501937b1,e7f7fffd,10942e2b), -S(eccd8863,8f3b2819,d828b9c1,2c0a76ee,663f6113,ae8294ab,e7ff5719,c8962cab,18da1af3,db016cb,45d7f9ce,dd4bc478,63aa8092,c674fca5,8f03f703,82ccc799), -S(8968de12,d40a30bb,99b10962,568b1f8c,c37bac76,7fbeac7c,21b80d58,bd64560d,268bf30,ef631569,800f6ee9,548cc7c4,15c1fd7f,b21413d6,3ed5abf4,936e5b36), -S(450789b4,297aebad,346af999,d4ea3e7a,c8867ae6,19a59c13,84b1ff3e,1fd092ef,402789ae,6ace54c0,54a26184,c651e8d3,814c6fec,fdb560a7,51943ca2,24bf25ca), -S(88b90c79,49a79d99,b05a2dd3,cac61e38,783dc306,fccacd97,892a75be,34e67403,3a565d5c,eecfa071,2c9355ea,67009764,7d0e52c2,d6a6a49e,3317014f,56554bb7), -S(e5a45f20,e3f5989a,a9b04119,6f7e1e8b,95f4b397,4e1c18d0,f19bc12b,ceb5464b,d09d73d7,e6dc8239,ef9758b,ae186e54,a5cb4d71,47f6dcdb,ec933237,3b677018), -S(51b99055,b4815a86,d0bcd8b6,8a7b47ce,7e9a93b2,3ec5f6a8,7c185c34,1647cd05,4fa125a1,35f26df4,ad7ffc70,29268830,9f8ad7e5,f3683eb9,b3dcddef,45fcda0d), -S(1dfb4a44,867afdba,892b9f71,1272402b,cd38318,f8f7aea,68c16eb3,2c07d565,4312ffbf,15775c04,e187cb98,166b5bb2,c42582d7,5b8938b5,83613d66,9622253f), -S(f271ed8f,c137af31,dad55775,e38358f6,608afdd5,4cb0d1b6,883ac66b,7b645fdd,1494c658,faf514ab,912887b5,c90e6bd2,a61e9d97,7e1ffe65,a49de27b,4e393bb3), -S(ac2f0db8,43cc7ee6,e268cf62,344fd232,2f0e40db,703a7d33,5437e7ea,de7cbef8,40ddcc5a,53d8a24b,8b5ee481,ef331bca,89e76293,7d1ba22,3471c562,ee7a2dc), -S(1801ee15,c8041c65,b9727159,8194a957,a404d5b2,318308cc,d737d858,4b2015f0,df400a6f,6a50057,1ebdb755,e686b759,d604d434,b9f198e2,21b2b514,30eca9c9), -S(8d304b28,32eabf93,82d71e3d,cbc38a98,437d6a,70c5b084,4486dde2,1104dc80,fffb5a64,3fa633f7,cf36e574,31acdb02,b98cb4b5,9a0076e0,8f5e5061,623b8157), -S(4e8645ef,99a816cd,74a0fc67,48cc116e,a61133ad,8f6bbe55,46ab9aba,adb148ff,594d010d,ff31677e,8c602038,5e071e58,5a72e97e,4d1c2d0,5564c102,56441c4b), -S(b8c26b70,b1367df7,7a14a385,aaec861e,e3cd3945,7282bb2e,935271a9,6c87d589,df51bc84,95a0c2e8,ef469219,f05f054a,5a5f85ec,a20f8acf,6c424ba3,9faff23f), -S(9934e27b,8be7c41,3f5e8ec,f2eba29f,26ed2ff4,fd588918,bda07bd1,5b87f4a1,4488848e,440c0a1c,5d11a3f2,784728d1,34b9a08c,6210494e,c1cf6a0f,71c334ee), -S(56692314,f6a9764,47a1a988,f0a2faf4,e04c61f2,b835f22a,25b57290,b1ee5d14,d8d72ecc,1afc548f,cb1f71e8,144f9f7e,463edd9,5422a607,7b9b307d,15326fff), -S(737a268,a2cd3d43,d6741235,69e2e118,7ae90fc8,669d27ee,504f9e85,5eda3c2f,e3d24166,a5ba6183,730c11bc,8b41845b,3efb7154,6eb1a06f,2e90dcc7,33f68b47), -S(90d40297,4ae9d5c8,f4c59207,e58797d2,8c007a6a,4f6aeae7,9e50bb4e,fc34fa7e,2cbdc969,4e7ee150,b51a7e1f,d81d01eb,71d48027,3f349a39,8773732,4b315cc4), -S(4639872,2ae68fdf,9a98eb24,6a70946f,c9bc927f,37a3db42,f0cda419,7dec8163,6dc0a8b1,81c16b97,da97fdea,ea20bd03,cfec3999,7e192b1b,3e0bfa39,a1727f55), -S(c48cb232,1c02051f,2f1e5aa5,c99f7d00,5bb8af4a,61691f1f,493d834c,549139bb,3eb61f34,a2009094,36aced01,4a11b75f,2d35d6f5,67e5fc5e,2fc7aab4,437a2c5e), -S(eaf967eb,d5f0932e,42a3222d,ac0d874e,af154f8b,47beee08,2ca7196e,efb429f5,870d0edc,43dd51aa,6f518b4,901049e7,865565d9,3e54e475,d587d94d,ce88d994), -S(291f8c36,ae17ff86,d05a5a81,31ae3079,27221af7,7b97d66c,812a954e,ad22d49d,3b515fa0,bfdb0fec,61f838f0,e78bd29c,360b9ef8,c6f599fc,e1c518b2,f343d8c2), -S(d6280bf9,4334749d,49b19e44,b811d99b,2a522e73,dc2afa03,c130a48c,f4ff39e1,5f282a7a,be629408,9672c7cb,c9e46e1,ed2dda5b,653cc490,93f4aecb,637a1024), -S(9f96aaf7,8b26bc25,e321837e,29f3cbed,ba6fe62a,3a66c59b,cb52ae9,daddf9a9,ebbd1df8,a818a28c,e1a61b6f,ed13f139,504d33d0,5e27b5a0,b67c15,b1333394), -S(bbd26954,fbec8b4b,d27f85e,44b1273f,37321a28,fa938eeb,f5e5f50e,fb0e8a40,56a517d4,c54368cc,b40d0653,7db7ec68,79d7d4ea,dcdabc1b,722e1a64,710e9b6e), -S(35597cce,40b326e0,d9044225,82726039,fef5131,9d267240,b2455142,7ff6d7d2,ab1508d2,278b3b0b,fec8bce,4dea9bd9,31859fb0,2f600cc4,b67bf9f7,4f2b20a0), -S(8849429d,39cdb22a,b6d22361,22a59786,2baac8d7,5f858ab0,33c5037b,81eaf963,ec203255,647d27f5,f134b011,cf390703,18006dba,f5ffa74e,593c2711,f765196e), -S(f7519d31,1493f836,ae7c6f8f,e8ee5f11,ea2ddec0,90eae6ad,84c6d0c0,3249130c,de7b22f5,ef095528,5a163142,255b168b,c004ea10,86269d7b,ebf032be,d9a6452c), -S(865cfb50,e57bdc46,166d2b8,17e9b4f9,73db89b5,2fe4ff14,1898bdc,fb4f3a25,36cbfe86,15368e24,b9673fb,f593bfe3,d1a0fe03,54f98c00,bf8e59cb,be930c5d), -S(cf3d6532,8bf2bfc0,8d36a93d,8aa8e8fe,317ed071,3aaec871,48bfb50d,ab1919ee,ad96a551,9cb8691a,e1d535f2,8af23967,704dc578,b7c38cf4,84ddbc90,2c1b26a9), -S(6ede5a39,7aeb2f30,d577c225,29ed1ecf,d28c2041,75e950e,12c98c1d,2ed1c48f,eb102976,b4237833,7761ab15,a8d0c228,a42ff5d3,a1279fab,736e24b4,47ae8e3c), -S(146a2544,cdf67ec3,3bd216b8,51d4127b,bd9dda77,4a78697b,e010e61a,7442a22c,f7cac2,376c246b,ad67a10,ee0fa811,10afccc6,d76a9295,f16d6034,1876814a), -S(bb14a6fd,2129d75f,5aeda8d4,d69cae8f,55b4950,7f709a96,af39bece,8e1449a4,feb4ad7c,1a3a224c,bf4bac58,617117de,811d250,8a948a19,a94b9cd5,8560eb09), -S(69975e93,a634cdfe,2ed014c,33c65a53,b17c6025,ae499a69,599b33ae,bbe52428,e16090c4,2cb1ccd4,7c7a9b91,4fa88027,bbf7155,374fb95a,ff0a06f6,4758e0c9), -S(e281888b,e9ec00f5,71e9d807,35c1c762,4bf8b739,c94f3178,868a7291,9d550848,2066254b,53733824,2a5b697d,a05fdaa,8e2d3b6a,840a7208,6854b55d,af88c3d7), -S(96531c48,abd9bca2,19fe05e,c1ff1ff9,90a526ff,5c7b5775,804c5db1,65b425e6,de07c8f5,32e0eb64,fa76442b,e4269e52,95212bbd,a9cbeff5,40b012df,f0b3ce09), -S(59d3a12c,3b2bf72f,c4ec6d8d,88594e97,89f30670,eae71e7d,2b98e9d7,3d5deb0e,fb338126,9a57fdb5,6cecf38c,ee63631,f520fee,6c3b334a,a47afb7f,7f5150af), -S(1267bcee,c8f3f086,8187271b,3a283241,935f1822,ae5e8e8f,5a4ba753,89869795,5249aa32,41fdc011,606724fb,6085491a,d974d355,9d27f8a5,2e80c376,92b22736), -S(446310fe,7a9d1f2f,632cc948,c86ca652,7358b910,e9532e2,9f394ed0,12c45ec4,f7ff61dd,f72dfb99,bf309210,286005d7,8328137b,6394354e,dd9cdcbb,cff06cf5), -S(7edfb2fd,a3c15d42,b29440dc,b7c7e74,c9530a79,6290cc12,86ecfe49,96583244,c7dc5dcc,6fc1ac75,5eea622f,69799c77,eb5c3883,a628f14,c61f9cf9,2db4e2bf), -S(e34f4c12,896a8400,a79db9e7,a5b0f67,99fde06,5e381181,f79bbb9e,b81d5e8d,e3dd7871,3cc68c48,9a877b32,9e32869a,ca89a69b,2ba6e83c,78af9c60,79f87f7d), -S(f49e78fb,caa129ba,ad6fa192,a26ffb62,d6825cb5,f933c2a1,c8a2c872,c5ff35e9,4e1c9c4,c176653e,6b87bf9b,39c5606d,ace09e3,c3c268c1,a51e52c,c4ebae1e), -S(71d7f117,738286d5,71ce0b08,aaa1b448,fd4a9d22,2e6d4ee1,b8c0d0ea,9275656a,751401a4,2fd576ea,6bbe6e0e,e076ec36,b9db65de,a747b31d,e1a66a02,324e5b30), -S(29f56789,8efe1baf,bbbd435c,7abb043a,284d16a0,598a5a6a,49d5875d,7577dd82,c3a6e7f1,80afe6e7,b761bde1,7893aa7d,2dd34702,6558c1e7,9d4d80fe,108ea6a5), -S(435afc66,f252c63a,fbc56f9c,342aae25,bbddbfa4,9b94a8e3,3d2a68c3,6730e730,d8cbf58e,e7cdff53,e4d52865,c76b9331,7553814e,f9f8c4c4,9c93e49c,7bb98dba), -S(c326c1d1,b2d1ef3e,e4e9367a,48970337,f711bd23,3c619e18,2bc47227,2e53d813,559b707c,4a73a245,c6d57194,9ceee5dc,b5d53645,d576d6d8,309e92d2,4bc959d1), -S(83486a4f,75664f,58db5cec,96af658e,6f669946,5c5b9e71,2e66ce5f,627d6a9f,eb7258a9,30b5e703,39681d8c,452e518d,aabbbe83,1312a65,af2723ab,ab61e04c), -S(85b419ec,e16f8d3f,ef24f1dd,6f8ca2f0,ea7ce0b4,bdd6da80,20eb0f83,7c799bb,37f888ac,3474341b,30a32573,2ee9db8c,4cd9a9cf,64350f64,8845c63e,fffe6343), -S(d6b6f0b9,cfbd4126,2f6506c0,89c1132f,7da49d8e,f9afcff9,ea97a224,35a85015,c5b7229f,dfc148bc,140ab9d4,4895c5b6,db02ae00,62585521,70aed317,c0e39fc6), -S(40f7b48d,1070340d,2382ba1b,794e4069,ac9aeba0,fefa8823,aa9902f6,4386c221,985b387,a3720bcb,a99ee10b,28ad253a,9202eb0b,3167d462,b664d67,f294509d), -S(ad6a6bd0,99789a6,2b3602b2,f75af03c,33379054,cefe6397,a135cf78,a0e13a99,249eaf4f,321d9011,39ce28b,4f09ee1e,4fadc6e6,763cd737,96777f30,aede6256), -S(2e15ccdf,25e72fd3,3007b705,9703b13,5f8a94be,cdc35523,3b349a64,60331e8f,e3ed23bf,5f320a48,e1dcfb9e,38fd2bc4,fbbd5e2a,e16072a9,9f704ae5,2d4c73b3), -S(aa9a2531,8d4796c5,8443eb4d,559dd43c,29efa4f3,c994eef,a1791027,784d4fd0,a32f3a7f,cf3b4494,a4970b8b,d20f4c6e,d82833ab,eadca5b9,4ddbb5a6,e27bb427), -S(f16c0ce8,cc87f208,5f98919a,cb4dff65,b68f88da,6db10674,c4cba867,bb410345,12dd4b03,86509e2d,a79f3895,d1c3cd7c,f5735529,b049204,9b7434fa,64fd382b), -S(f27ae46f,14efa234,e034fe01,f4ed5cf9,251c99a0,fddc9e5b,13ec770,4cbb6bba,4abb2ba9,5877455,ae76d4d2,56216ca1,78b1c12f,3fa9c10e,5df21225,4071c557), -S(a966ac61,ef7d10c1,47ed0ce2,cc383cce,8d83a66b,bd18aed,8261e38e,67983e7b,5d2db9c0,ba8bf67a,d385146e,8ac20c72,9fdbcb0,581cd956,a95ab89e,a927bd2a), -S(ced076ef,4951ee63,ac196d1a,65cab7c5,5654d12e,ae16f4f5,4c2637f5,6b1cbeb8,2b763b9b,bd99ee6b,5b6c934a,ccebdd0b,952cda5,ed266d5a,986be5d4,397d9f7b), -S(9afeb8f7,f445a1ef,c7951fd4,62a0a3d2,500f3527,1f482e01,edc9815c,2deac969,93354851,99ea1fe3,f74a6991,6fa53f47,2d1918d3,c4d0d526,34909810,25830723), -S(61c405c6,93115b8e,325be640,8e30cadd,9e42dd98,8522871d,1612a44b,95c41d92,efd7f73a,f38e21c6,8fa28d86,b3a9b241,27fb686a,75c53c1e,3b693191,d972fcdf), -S(42829070,a896e684,88890114,2763cfe,3376ef87,17aabae2,43981213,9be22ded,d15986a4,412faf10,ccfc34ed,162f21a9,54cc5af4,91ff671,c4634947,9e539da0), -S(d9945ab,e280b7b1,4bf7e65d,ef4cd279,57798612,50a1bb5e,28ba8bec,2b66917e,52902f2b,af8976d2,c77a2026,a8fddd2c,8f2b948c,5086870a,168a1ea5,cf43d134), -S(bd3fb006,3748f21b,cda6236d,a13e129c,905da160,2d8c2867,f39166b9,56a37a12,47654773,9e7ad500,cd0f0853,f17bdecd,ff4eb6a0,1af3822a,1201ed09,a4e52ce1), -S(831294aa,a3fc6d7,e0179ae1,753fb809,1fafa015,9c94c40,a41f4ddc,aa6937c,27509e96,b66459f6,2698d055,7c38634a,543f1eac,ca68f3bd,4d64d3c7,5e5b7e07), -S(c74d8a85,c5d11787,31b8d227,b74cc264,b2ffeee7,ca997e49,d1b0349e,2fc121e,5e5fcdfd,cedc03b8,4555a2de,118e494d,2038a2a1,27913850,e816f707,fb9688aa), -S(1cb36b06,a6aaa255,8126fc5d,b69f172,be012a58,de7d8688,5ac5286c,33e7a20f,a84f5fb3,67c6726a,e8b60e7d,d4302e7,dcd63930,2eb425d1,b89ac986,ee0e6d57), -S(5d69d200,ccad332d,faacf513,433bac35,d78ec863,2928331f,eaab7dda,69a5ce14,4370dcdd,77fc209a,8d558c09,cd6040dd,74ff975,b2b94436,bd2ce044,214926d0), -S(585b2e1c,b53d61de,89fe127e,d20f23ee,26dfc569,67659aa,22a35928,af247514,fa29933a,8ecbd8ef,8a7e94a9,ea267f31,a2deb759,b25c1762,1753bda4,d489c1bf), -S(a222828e,1568c08,3ea870,50f9cc86,17daade7,cc60a72d,a8762f3b,40a107e2,ec282fa1,7a70e5d6,529e5d44,15dbb61e,8e4a553a,11d39f4d,e3183126,73161aa9), -S(b879ab5c,38135c35,a57ebd6f,1ec01a9b,58758942,7cf9dccb,3b6ca8f4,dacf14be,18d8831e,b11a8461,9deae96b,60c656d9,f4ed65d1,71a0f22e,27d6931f,7f34a310), -S(39168674,a5cd3c38,ec3a8293,78a2d108,d44f4fb4,8ed3b09,d491c127,c8f74a0a,e65c3f7,8bd0bea0,e96e728f,d30c8d27,10ff67d0,23dd218e,813b768,b4094faa), -S(1a4db770,85065a91,61573aa4,b96aedc0,5d81647c,fba56946,a5e2ea1,77e7bdfa,78b0b79d,111c0203,ffe518fe,f08d517,78f1a564,d21e2e31,cab63d69,1e0b1290), -S(90b6412a,2626e9ff,1dce75df,c56744d6,f471fa29,d676c0d0,cc8bf515,47b9f0aa,4a7236f5,81fa2637,ae532b97,c89fd6aa,fd2db809,6b8d2b1b,cf6c9ea2,4b3713e2), -S(a25e3d8a,119b1f0,6474144e,81677ba1,811dbfaf,195d460c,1624dee5,39f29dea,cb0591a3,816a7a98,5875ed34,5ecec9c0,cdf02537,db28464c,88022850,2478d032), -S(5dadb41c,b58297b3,e84d87b,275198e8,76c48bb8,aee3041,ed14f7a1,394bfdff,8db26ad5,ae662e79,23ba04a5,87e7b2e8,f64a52be,8a76d4e9,5193e94c,9a80f4cf), -S(29fb35a9,f0e0b7a,d19d8af6,c4dcb5f0,19ac7cbe,b7bfb535,d23de4ea,33df5d00,41ba5e42,64f63b20,eb37839e,44deaae1,47bb9a22,1ef94ab7,737efc3d,ad61693c), -S(7270c153,a2fcacf1,18644892,7795fae1,7fdd4fa0,3e9ac70a,4fd38cc5,c5e3ea33,f6c35e5c,cf398440,a96d4c8a,f981fa04,567851eb,75431a14,83e026,ff6649a1), -S(70efa7f0,33743eb,4f25db9,c43463f9,77a2cba1,ab8e08f8,59fa7780,cf7129e1,f906a344,8cca0734,ed895706,7374c12e,14e6b573,ea4c90a8,b7376eb4,20adf7be), -S(7ccc2d79,f905ef7e,83b888ac,ef445b4f,a7320fa3,79562154,d0482d62,cefffe38,b7453f38,9861e0b3,7596d5ac,e41dce1,bf45374e,845542bf,cfec71ea,76bd4cad), -S(f171415b,58f085bc,cecaa5e9,b9afa67a,a05d9577,a28ac4d8,496fcd12,9b50d0e4,95257e0f,18ed2c0b,aa1202a0,e8f62779,a7add6b4,d601deb3,4944e59e,2e638d56), -S(39baf2a4,d41f3930,33330786,9f181ce9,e15e895f,2f209948,999ba05a,350a08ae,5f4a9728,b84a666c,6a6e8318,9f1e6f91,7c97a419,1d44c8e5,6fd6c358,445be74a), -S(b146000f,16103232,297377b6,f31fc96f,afd90cf7,27f0b056,55e41f27,1830c607,92adbf3,b453cd13,1e8cefd9,1884b3c,b7da48fb,24195581,fe59d23e,9725e0b1), -S(d6127f7e,e94765aa,aa2c463a,dcd518c7,e60ad583,6bd485f4,574e9e09,57ba6556,31d3eea2,a91bdff1,6a420533,2e768ac,2531f0f2,c9d94656,26472c65,4d665745), -S(cd28080,e877f416,d6302aed,aee760fe,a2b0f90b,23549aff,87ef8af4,3841a67,f67c8c08,3d69b201,6f9261f4,81e0bd84,568137a3,777fcf45,e4a4c90d,8338aa19), -S(78d35f78,96872666,aa5f339c,b6c68680,ae42cb38,c75bc287,8e9dedd9,3b0ad38e,7544e0e1,4fa07cb3,9144fb53,7ca57508,58d1380f,cd1909b0,56b722ee,fd55217b), -S(aebbd769,392bf374,2e771e65,761cb834,d8a09f94,400a947d,c6fcf062,3e0fdd6d,15bb21b,35f0abca,5f7755e,79cd222,e58cf089,af78cd0e,8e4a6df4,4576f6d1), -S(cc7bd0af,bd44445e,64a77303,5b66a1ab,e990bc1a,475c0454,2c2e23d5,913c6878,b0bc23aa,53ccb546,51972c58,ceaf865e,1a892ba2,bb7bf626,15793163,14663e29), -S(94b69939,f6ab4f6d,6b5a18e2,4e929afa,c83c0c98,cccfe6d,5b0c1487,c5915805,cf58329b,c8ef2ee3,52ee357d,6ed05bbe,ece97acb,7936bffa,428a6913,1e3e678e), -S(4596a3e,b0156e46,c56b2492,6bf8c419,42588055,96d160c2,fea2cd15,1aa84b61,39740352,fe7ee595,2e114853,d0334099,5e9a97e,f3fb66b4,fc6b1e02,632a39f1), -S(b577c857,297428bd,c331a8e4,e46afc59,f7b2ec2,be244cc9,f52a6d4d,b41025a9,529091ed,1e5525f6,e7746c36,575041ca,89ca74f2,7a7f1378,2a36a8dd,5526abb1), -S(623cf92f,7d87dc8f,74661d3e,411aac0c,a6c9191a,1da93b06,4f756cb0,3b7a80d,6909b404,ccd9e564,b27f82e5,ab6348dc,de6cbabb,c40d964d,daeceeb4,d48d3acc), -S(e9aee76c,9559fc77,5f473da9,faf84e81,3f1d643d,693cac55,3b96e27,1197401a,3893a6a1,10d34bb5,bf007cf,c116b17e,287d3ef5,2451a3a4,e8b251a7,90c5c2b5), -S(2581ff3b,48d9f30a,e533c291,be7078c0,41d75248,fbe46a8,c984e6cc,3880dcb,1e15247e,b97fb35,14da7f82,895fdf41,f84dfcd,9501cec3,c12b1524,be8cd289), -S(72162987,71924cf2,83db564f,c75aa820,4c9d0d9b,6acda46d,7e328c61,a3147823,88da7231,356038fd,c4af67b,3a852a38,e6e12c30,87388b21,c6f357b5,37d25dfa), -S(3a25426a,b615a75e,f8a6d5c5,a5e632a2,6e8e79f4,59eb209,ad7594f1,1669cead,d5316c8a,6f24a055,1d8eb237,91b9aafb,7a00e304,35101080,a543c519,3331063), -S(ab26ff41,8cf02d7,57a0f582,1155f54b,2b5f796,b201ff90,cd78d9fa,76b45ee2,6dc0d3be,9c7e0cf6,60e5441a,7b6fb9dc,fb24211f,cd727441,dcf86644,8e83ebef), -S(9ac8ea3e,fa78c588,69cafe04,23fa3ad3,176b9234,5a3c4cf,8f2bd449,2fa38ded,4d8b4740,b0aa16,ef6a54c1,3591b0dd,58e4faf4,a28aa4c4,b1c730e3,ad66836e), -S(4c1c869d,464634bd,d849b99,a04632af,b8213762,c58d8ae0,858af29f,4a26c0fa,8c557687,bf3dc006,a90f0c3f,6ea33067,ffc34b38,9a75a2ac,3ea843ab,d7af17f2), -S(f73695bc,c6dd5e56,8185b3b8,a99182a9,f04957fd,33cb7013,d887a55f,32eb746,f615ef29,72d2cd2,c4adb932,a201567c,5672d44e,529a1248,3bcf05fe,d6b86fa8), -S(41e8d3da,705535ab,b53ff304,3490e669,4c1f754e,713afbed,34b59a59,c18d3f9b,6dd0728,21533413,b6011200,e4320941,1df89a1f,efdb4c21,8453606c,957cebe6), -S(623f4475,c0691617,1c7cfd60,2684fb11,24f934bf,524559f7,142404ce,d353e0d1,8c94a4b3,bb7de410,fe2e3d1a,c41f2bf3,c01866a1,5e354fea,596bbd4e,e90f08d6), -S(961dcf95,64da916c,9a6ed43a,a8028f8a,8c65a1fd,d561cbf2,a0d80bdf,ef10566f,4d3a2dda,d5d81a8f,9e7940cc,957a4646,c3b7a734,457ed088,998b0c10,1987f16a), -S(5273adab,8a2411b3,6e2566f0,a148d688,4003748c,c3bb79f,6bf48340,75f6ea62,780cb632,30acbef8,bca93510,74a28fb5,51573656,1802992b,52f64319,393cf529), -S(170c2667,d45ccc19,7ac05e5c,2df7a0e3,37ca47e0,68f360bc,ee9c2134,81a0a8e3,6e82b129,6d24dcab,c529e4af,538154ee,319b40df,1cf31f7e,23fee9fb,4bd3a8dc), -S(7a240b1d,5df36af9,b4d1b988,c428d12a,e64cebdf,280da6e8,dfe0d7c0,117f8e2a,d5a877a9,dc46a181,6939b345,6015c592,58591cfc,63ea46a4,d228ba1e,465ae6b4), -S(6a6564a9,abb91408,c90a508b,252b68ea,7b11cb38,aeeb6bac,4eeee422,6058ff9c,2f4c5766,e3dca65b,f991b74e,bb0c64b0,2bd2668a,62e4b97d,8f3b35e1,c3ce614e), -S(87aee56e,bee43b0e,d0fbe101,93218ccc,9d4f8d9f,c51a8780,e0955316,b97c71e5,b2979915,9110931f,d2d9f95e,d6d5217d,6d957a,c2bc6f3b,c23a4555,e19a76ab), -S(193d15e,6ca2fb6d,6ec3b10,945f1174,8476fb29,327e941,ad1f8ccd,d7d41931,fb7cd3c9,2cd51aab,2b78b0a3,b9e5f78e,5846bdd6,822e1525,10d08357,3bbf1ba4), -S(352834b4,5bff7ebf,b0a20cbe,13d51e8a,b4854209,a8c918e7,67f6986,b4c1f0cb,e2676927,9e22fddd,dccf5a71,c4b33ca1,f8e5cf24,43388704,721f3c3c,8669c8c3), -S(843ffda4,5e72ac0d,b27a17e6,65fcb27c,34d325d1,325612ba,6163d5a3,9b16e8ef,e39834d8,c2ebddb4,791a5ba9,a525e210,acef4fe5,9184e737,851785ae,9b228d55), -S(b34d4e5b,5f86717d,2c77708c,a14f42d,4ab21bfb,de36ff49,eca9ffb8,b92192cc,6e782729,bb40e31f,3a0ec687,7a6bd690,6282c723,5691fb73,6baa16bf,ccb70670), -S(98b7f92c,4d4c22c9,2783b2ef,a38b71ba,477f79e7,85d4fb11,acfb2880,709b7172,e30e234e,af0847a6,ee61a5f5,3f0f413b,d68b115,d8a726c0,61032d6,70aadf1f), -S(4e7e4cc7,a37110,6aa13c5a,e47e6962,eb774d7b,5b25d31a,7e6ac83f,ec89402d,b14d199e,9dbf18cc,e03f5cb8,e3e0b555,a6a7cde1,2fc6ba42,52956c43,27f874f7), -S(4db22218,59bcf734,f25d2a16,3af8f5a2,58422913,34bd5e2e,4a322589,d0096a61,b99740ed,41165371,e1ddfe62,4e6f3a02,47ed46cf,4c589067,d12c3a38,b75701e), -S(f1fa9b2a,6983e6d1,b36e4172,20b9fbb3,6ba4383d,cabb2da,845a63ca,8fde624a,539ecb7,cfeaec83,22861a97,4738844,53795076,1657378c,8950a660,251c50e9), -S(eec0d4a1,f551ae4e,f54ba956,e84de711,1fdb93e6,3c7b64e0,bfd4ba42,ff91fa6f,d16347ed,3ea3e986,a1067fc0,a1e443fc,c80c6277,f1018148,744f5faf,65391c35), -S(74be2d2,526daaa3,3ab34527,f26e6979,4d9dc930,7044da0c,babaffa3,be2eb41d,aec5d61e,477d998e,d18ade2a,1eeb48bf,82b34408,e6823fc8,f7b57561,f0c56ea8), -S(6d248800,29578c3,141a243c,324a7e36,c694ff50,1adc4280,31ee3d1e,ca32aad5,58acf9ed,b1b5ddcb,72da7a52,6cf089d6,839b42b7,4fecdfa,b7e6996c,d80c3e96), -S(7525d819,d1dba5b1,1a36a2b5,62a6e65c,3d2d1128,8f1945c6,7daa7149,5894c52f,458998fa,b2444201,b8a57992,50b76be2,f79599b5,fc87f83f,d47eede5,feb5351)}, -{S(c8e595d2,666f4913,1f375b67,81b9113a,d0760e5,9477ca17,8863828b,307488f0,a82cf2a9,d823af13,5c23a04b,bc12dd81,2c352a48,27e19030,8e089d9d,9c316596), -S(54970cd6,a06f81d,3566c34a,ed5eb8bd,aa49c821,41b6518d,88efb994,a67d65a2,cba9701c,b3f620b2,b4756bbe,1d7b39c2,2226b871,19e7525f,ef9f11b5,c2ba0f36), -S(f9b9b054,543a96c4,25baea4b,5b1d7b60,81596be7,7a06f02f,bcc4926e,82d2cc91,1ed468ba,7a674ff7,4e872773,85dd5fb7,fc1f1603,a5a8f249,c808aa14,775d54e1), -S(5d3a25b4,dfe080a8,a13823aa,77847487,2e6ef73b,5fb862c8,5439fe36,cc93bd64,5f49d6f5,507baeb,5e0498cf,83f218d5,743b4d93,82cf0770,a734d6a8,af76c5d1), -S(1c8ed0c3,6b0ce521,89f5ad75,8189df2b,77646a19,8fc3b7a8,9e48f978,5f903409,126ac278,e1194e47,39a5c44a,8b62640f,bec259f2,28f479c0,aa4e5abf,861501d8), -S(c8665b4b,43e23686,e27d34c6,d6739250,4af34435,287e78e3,f9e054f2,33f22168,34161d68,636cc48c,56d9618e,1c92e9e5,83c5fa4,f87c1f8e,126b1ac5,ab79fa7), -S(e7675296,10359a1f,29d2ed5f,4ee7cbbb,a4e9b5a4,5ed6cce,10d36059,6ac24773,25662f83,ea425398,328d3874,a63438ec,3995da3b,a5a731c0,45b8d269,f07a0b0d), -S(875c0b21,43d3a01,b6310ea4,7726f174,e8b9ecb3,34b65ea0,59f877b5,e7455d8c,8712b814,a3ebe72e,df1e3899,bbd34bd8,6d021e7b,a2e9763c,ff526e35,4a4286ea), -S(d4ef4e,78f2d6e9,b0e717f8,21c1a56,3902fe88,c47f208e,facb68ab,5c176f05,2fcbca4e,8338fa10,22b432da,7b40070,90473863,14e28e04,268ade75,57a2d554), -S(31513428,e66de83b,a631a2d8,44e054dd,8ecec644,134c57d2,eae9f6c8,e5bfedf1,316bafd7,aa48ab94,ae682ec2,ee1bc88,f04f2c50,c975b441,f28143b5,5d4bc909), -S(33260c29,cce9b856,dc9a50e6,d41746e5,e73fdded,1fd25d3d,c3659fd6,c2e72575,665cfbbc,9af473b,b647970e,dddc260e,d53af968,79c0cad6,e12bcd3c,392a646f), -S(b49a875c,d46f3ed2,34c3b611,88046b4c,aeffcb5c,1c7b959f,60613357,b6fcc13c,76006cfb,21f12143,6684ecfe,1524011a,a08ddfd4,c26a96b2,f56da73f,ef05fd37), -S(bf528e3e,7a8c7c91,9bc3e4fc,f0cdeb0c,7f8b58d4,4afa7663,e2fd2233,751e615a,c7e0587,674f3012,f05b7d26,f067b45a,8efcff89,bc2f341f,c0f2a829,b2d50b99), -S(b358b816,5db58b6f,64118a5a,53b0f2e3,c319fc59,e4a57657,1fa54214,108d66cf,27cdd287,96758b2f,bff761a4,9daaf43c,8864d04c,dd6bb8d3,669f393a,b74ed23d), -S(c8214724,1e0b2fdc,f054d7b7,75452bb0,98481f33,ef81f4d6,19fc8bad,715cbb76,25808ef,36f52935,700fc3c2,8f02a6a3,37b06ba3,75864817,806e35b7,26a3e9b2), -S(88c95ba8,4f5fea33,e8d848c4,24d4be91,9bcf15dc,988fb9f9,b14648d8,3bda4294,339240d6,a490aa81,e6cd03c8,af69fc90,fb43de16,e456e1e4,40334e8f,216ba662), -S(1222eb56,b6341323,87f28674,2b495da2,ad989e9a,f5dec72f,21022834,190b6a5b,30e95537,c9516bcb,8ba67b77,983f4eba,3a706386,af400253,2f54b15f,9894f072), -S(5adf18d8,e472cda5,d379e5a1,4f66cee5,da7ac014,84b685ac,9234965a,27a0cd69,b36994e8,d17c5c0b,1219db4c,1fbf5746,434c094d,e53e63ff,3d9b4cd7,ba429d1a), -S(bf3bc2,56f019e5,8c0861cc,91a5dfda,bee7f384,70e5462c,5605973a,519c682c,38356061,b7015d4b,e7f43f21,d3b76e9b,bce0c749,c7e0d96,e6bab6b5,8dfbd650), -S(10aa56bd,a7ddf207,c898b73a,22f1e8e1,18fc453b,e1539267,be025cfd,c8194571,be79e52f,59320f5a,65626557,e6218a7d,a4cdde5e,ab00b23,9b411bfd,377767df), -S(2b2c0c46,900e65c,caa1339f,34d1449d,91f937e2,2524df3e,95d9a370,d940f31a,615780b6,6839ae65,87a0bd3e,45d38f8f,d4413e3b,ca1afe68,944e7e77,917d0182), -S(a5f75480,d53b0649,dd72d8eb,a9275117,b84fc3be,288fa3d5,e274a287,27c2e669,a766ce73,12b8df27,aa950f7b,29c767e,fcea1614,de5a6b42,3a57becd,c496d6c1), -S(d886590a,d11c94e1,9aab94bf,9422377b,528c1302,20c86f14,f13ef07c,34a61d2d,2978b774,2968150c,9dd0739f,7b9c4f0f,a5214f02,f828debd,6826d5f9,62cbd01e), -S(63bf32ff,4dda2eee,8aaddd62,8cd75f44,7535c843,19441e07,801f7339,89ce1ad8,6544e852,8ed612f3,d4df9037,4fd22756,3a5d7edf,df910d68,fb4571b0,679f1238), -S(2e42372d,88db8b8a,631c083,ef77015d,c98b13a0,597c6efd,141bac97,ee8dfce1,6454e588,664fe42c,1e9b6646,e82889b7,4497d435,e46c2a77,fb05fd10,c28986f1), -S(4d3b7d17,a4a7d26f,7e79fdb7,477a8f42,e208014d,3f61445b,6c921a3,d5808110,9408735f,f9c384f0,46ff6b78,5ee8914b,a8da4502,6299e09f,9361fae0,25e8a19), -S(c0c2f170,44e952db,3b5e3125,e75c4be0,4b91081f,1858dd2c,ca1d11e3,bfeb42e3,712c1211,f321e4ee,5b014757,87a7c784,fa00d429,fbf1ffa9,a3884a10,ab633dd9), -S(832a63c5,105ae2af,8ae9a062,9f41bc12,d6d9a16,ad764346,fbf45561,fc721e3a,8eb47da6,f5ec89e9,483abe86,d9419561,26d78380,a6818efd,1d6fbd90,9088db06), -S(56db6941,c03ee58d,c4dca632,db498e62,1872a29a,41c42082,79ec7454,bfdaf0ed,c29ca102,5ea7525,68564f1e,d15153ec,aaee2ec,da3ace93,e580c8a4,93e9e4b2), -S(3b46ccef,dc3a713,10e4c8c9,215b3afb,65c354dc,c37700f2,61635e20,209cd7cb,6fd7675f,b779a43a,ec66d9d,66f47d3a,d41c3e69,9db107a,ece85e75,16d924e), -S(ca4d848e,15b27c5b,926cb160,d79ddd80,c618e30,1d0fc2e7,3fcb56af,5ec7ab10,604ec,e307566e,ebaa545a,9a080f51,e2a0b5ba,4a09c8cf,393bc4f8,6f483d27), -S(53f8eb4f,c8858582,e5990bd8,ebb19e30,fd6dc262,ba6102cb,3b71b6c9,e47c764c,30c7dc5d,4fae504b,56a103d,b9318647,c5582e09,e0868bfd,ebf2d7de,e5f6fbdc), -S(4754af73,cf1cbd8d,c231adb2,3cbb589a,705bb81e,b8ad0ab2,3a61ce0f,db6df49c,6784ed08,73ed3a36,14c7b35c,916905d3,dee4ccc3,ab82ed94,1dd4da1c,1d211af6), -S(3c593952,1d1b1fd6,976eec8f,9498235f,4ed5594f,73f0cf2a,14b8a78f,196888b2,4636c4d4,aa2e1f,c78eba99,2dc89151,3c4e380b,24aa1701,8e99785c,2088dd73), -S(a7b104b9,7c1c0fb3,1d30a49f,b2377ebf,df7020c2,d77b0b8e,b47428ea,c60ddaf6,9d7f63be,bdf87d97,d18cdeac,4f97e900,f5579bb6,6b5da626,154b3950,df14261f), -S(234cc1eb,2097b150,a72f1e7e,4c405679,69cba876,f22a9828,4e639e92,2598fc2,677e291,8042accb,e4639988,d49c85e0,3cafe4ee,601eff33,398f02da,9bffce39), -S(b7d66767,4d02da2e,3c1692d5,1dd8d383,b8456c81,c7cad8c8,b2d55204,79c10ca8,da5b5c03,1e4139f5,24920932,74b15eb3,bbd2e5f4,95ce94cb,cc4184f7,f2344d40), -S(c32a186a,6fc91998,8df6cfb7,d2a39e03,9a60f1dd,7852da99,9af32688,200f2a6e,cd027a9,a1c5d0c7,6381638b,21f5bf33,71514b49,9733cd10,fc36e3c3,3e16d262), -S(7d824a92,83976eab,a0f7aaec,4619d13d,abf75df,7062ed63,ab09ad73,7f805f7c,81745e89,a8b8c725,32c81120,c527e5bd,772adbc8,e93c4d03,856596e9,942865e7), -S(ef890d13,a3567150,2f8aec43,59e2e293,8ac0511b,13f99ba3,c1b30a0d,393e0e65,d24a9d5,bab93079,5aafb32a,fb5dd8f5,9589b27c,76a3a5f2,728b5f33,3aaf2e6f), -S(49e7a49f,df1d0355,5a83db30,1ce7de93,84d50894,36e4881,33b31031,4b8ed333,86f8051b,5ddcfd72,3c9b4961,80b5f534,48f9f20a,6560698f,43b5f59d,2205d5a5), -S(87a54ecf,9d6adc7,148da85b,3aacb374,d65eaf67,a978fb07,bbc920c9,f68de37d,7500154a,11651fb7,16bd4b1d,7d74df87,d948ad8a,441cb9b,74523eba,b06a33b0), -S(1c75fbec,2bb178f6,58f8bb0d,58c59d28,37c5bd11,e7c9766b,fc8c71c9,5bcb4fd8,ff17df79,c948583d,ae95c4c0,2be215ca,94189a75,18860da3,55a29332,39c3be51), -S(8b50c207,f02e2d39,dd556a0c,54deb2a3,3a96e8d7,8a1a4d5c,9970986b,46caac7b,9e634e62,448e57d8,8013de8e,6c1dd7fc,39aed80f,5e118cb8,2a659f6c,694874b3), -S(7b4d6114,72e2c781,4cf7a7e1,b2e0587f,f7c758d2,96bde162,7071d9a5,e9ccf458,54092c01,2da6117d,bf24543b,c8143b8f,bb90cfb5,106b3a78,18e9ab6,adb8ee2a), -S(50d14331,162d65b0,6ec4883d,936438c,5cdcc98c,3265b6aa,3e9c898a,3157eddd,2494eb8b,894cde06,5238cfeb,8841d428,e6fc09ea,14f31250,e921f7aa,c5235e7b), -S(c5638477,15e5e0cd,7412657d,63d27e6d,c8126eb0,b353acb,4146e93,d5485293,4567dd06,d6c8ad85,35415a06,eaf9c387,d15ad758,27de781e,f0b2ddd9,fb0af414), -S(cdf1a81d,b618837e,77c4c319,a78ff7c5,8ac2693f,f3ad9d76,f5fe4639,8523d152,3d29f818,1ad01726,f5a57299,e9f8d632,ea50a6f8,f7bfd917,c60cea89,2e026e9), -S(26163253,c6617468,f1b78426,b153aa75,fb2081ae,91f0291d,91785fa2,8eca2271,fe9ec597,5be387cc,600be7ce,28ff3092,fb0cc11e,d235ebb3,bca21d5a,6761f2d2), -S(ffbae863,2dbe89bb,13a44bd4,85685746,160e9cf1,5e02c547,a73b192d,3458b265,c267055f,ade9c7ea,c0ff5356,b3f1062,c764c5f8,b182207f,eec0e345,cab843f0), -S(86e20f88,bd61ef73,2133367e,45235980,b2cf0cb,9801d795,5a3a8faa,53eb6b31,7d7fc09d,a9051669,1772b443,b7204199,51587976,3110865e,96f1e9d8,676ef639), -S(7be39fab,669be73,cea39240,a16922ce,5f1c3bd4,f4036d17,97599c8f,d52bcc73,da152535,716ce5d8,3b223f72,1ead270c,d2f78d83,f1f6b8e,61c6371a,62794829), -S(5dd3e3db,62673c67,112f2457,dc42e903,3b5ea586,676d0411,2c913a03,559c9570,b31c875e,977f1205,3ebccaa7,57e69cb4,d3632130,999b5a5,ef73c4b0,5950cfe4), -S(54692082,90733c07,3032ee6c,208658bd,a87d359a,bf145837,20bdc18e,9c3abf42,a3c73d09,5209d326,8a51d21b,37058b54,93636657,c699b58f,bd209210,f936f72d), -S(d170eb9e,bd80c03,282137c3,a1a36112,e2d965be,a530f5df,fdb34634,32f0e983,82bebf36,6b21bb96,ea0a162b,1a91557,5679c33f,ceb4bce6,2698822,2db01840), -S(2ce91172,e6c42333,67487389,f31600ff,f6f0e5b1,3f7dfef4,5c3119ce,5b5d87ce,3c95d405,30b49147,5cf2e0b,e5e2b0f7,ec84551d,931d09e6,76a1e552,c221199f), -S(b133731d,95483e43,cc4f56e5,127279a8,a0d32cf,26e33971,bcdccf69,e3b04f52,bb69ce36,c7bb5973,794fa89a,d4bdfd69,8bd26211,caca7866,b12b5ffa,fe4c27a1), -S(c9e45724,8dbba2c2,7c9cd09d,de0bc5e4,2bdfe86,2f3a2e1e,12c9126,6861d76a,f36e6024,f5f7c255,e684d368,ed336ee0,668e6bf5,dadd8fb4,6c58b03b,a1417014), -S(99b6d58a,d4524f00,fb7d3c0d,4a521143,fb45283e,2a8f5ba0,e85f1833,5c979828,2acebe0c,9de8dbf3,14b3140a,fcf81a74,b1db3e46,bddd4aed,9014848b,c1598140), -S(2940748f,7feb4edf,c05a0af2,4ada767b,aaac74a5,b1f7d83f,c5590780,640f6d2e,d30e19a7,bb721cf7,f2f47351,a8754476,f97d96dd,39cd6a91,4a97dcea,597e2258), -S(7b53ce3f,456591f4,534d9476,66e01d38,bdb80580,6555d569,72404e0f,5963b5bc,c03dc414,99b7f26c,cd7cab45,c9cce637,30f9b615,19fe4d3a,e9410474,b2f62209), -S(f1e0953f,18f81648,1bc8a21d,34ddb5ae,1fe02974,1dba2322,c5ebf200,31eab9c0,93e9a091,9c6bc9a3,e4a161f8,3f94d274,b1ef4ac6,edb975bf,b62cf92b,97f1baa6), -S(6037926d,772b3333,eb75a6a3,381b3784,ede8cbaa,a4c1aac8,fe09ea20,ff3c6520,45feda12,a4bd9518,96e83b91,bbdd05c3,dee627c8,39c8fbcf,e27a050c,9b082ad6), -S(7f845fa7,49ae8a9f,cb394dba,27e7d86b,e16eb956,b08dadf,a55afca8,5a1c6850,210c0682,9d62dbd3,d1917505,4b428305,78444ed4,ec3ff807,f6593ec2,f39dc1b2), -S(d3780383,8c1390ff,c1b679be,8192b8d8,4369eaa9,5eaacb2d,df7b0d83,4fae6ab,e9d5436e,79c4622f,1ef6a773,af736727,d93f5f09,3d0abd64,acc6f37c,4b7b3975), -S(58fe6127,196f0b87,8acac65c,c0a73b52,7c979d75,ac15ddf9,7858bc4,e4f40400,340365ce,74466016,4887527d,7da89ddd,69ea1bb7,93f886f3,654dbd7d,6b9ea145), -S(798de133,1d82f361,6fe2c597,ce8ef82,9e1419fb,1615b76b,e4e44929,518aeb8a,f8eb34ed,b9275578,74d5abac,2568b1c1,9a751cf7,f2812b64,9b75da50,e0c3d269), -S(ed7c18bf,c58b3202,c97a31e7,4e82aa88,c9d554e0,18afb73e,2b8324fb,bacff740,7337a0d3,f8f42f32,ed0ecb1f,44907dc5,756a877d,d8507b94,442fc5cd,41d5432), -S(41633de2,56410771,aa494b3a,3390898d,e78aeb06,3e8a061e,18c3a2dd,d9a23f5a,ead81878,b28062b3,e421c0e6,c1202092,121fff76,80dbc99e,7af681fe,c700ff15), -S(17392b06,3fcf041b,2cd4672c,780edff2,9e1e17f1,356285b8,e80ba54d,4ca6a67b,af99f6ac,2f9e9178,2af6b677,7163a0e4,b59c4d90,63f8c2c3,9167743d,38231860), -S(c4229eac,5a8333fe,75e90571,5ec787b1,7ac350f3,3ba996d7,8f1c106e,d5f0dc3,9186b6dc,6cc14aee,8833d89b,501e4fd6,ec8158e7,2f96530,4a3a6577,8cef072), -S(a985efae,9458f1f1,8ea8ffa5,84d7dc63,25cf125f,a210886a,e1b1dd23,84c2e786,1ba41023,1036e351,7bf58cab,5870f244,315c79f1,edce488d,35907eb,a5b5e3c0), -S(b5fa6b30,6ba70431,ca33cd5f,82cb1f50,3df04589,c3c66b60,dabe0fe6,e09356a6,c1ff1440,3a4ee6af,940e1af8,f9c2596a,ebcf3691,8f9a77b9,730bf075,42c9fef7), -S(c3ce2028,9e90190c,5ace17b6,7a9a23c3,19161a36,9f33cb91,5cc57416,292d0a8,ebd0b498,59711041,3560bd36,1dffc830,8906263b,a0102ac0,2d871e34,856aa371), -S(ee376a1a,fed708c7,de2bcc3e,54a01427,5e75d8b,a6d8b417,75005eb6,8b29d94c,9c3833b3,1d73f289,cd3064f5,7a1ecdba,48194e3c,66d82f2e,e3086749,62b8aa52), -S(aa25c37,a2e2be4a,7c0c9e4c,e08e20b9,88de0af,880c1a6a,e3117910,9e5b187e,f469297f,1e3010cf,67310d9d,719f7a59,258d2184,1804cf55,66615800,3691a7a6), -S(10ad3adb,7a865784,c2e044ad,19a21199,77cdcf69,3d2d3292,26ac352f,c75d11a9,1e6858b6,1deff39a,1f69708f,56017ee8,a332ab60,a48e2783,e2dbe50,a176f355), -S(5aac0d0b,a2a5c410,39541de6,c53ae936,6fa07ca8,373831a7,fbd87a38,784af72c,4d82d068,9a91355f,6c51df81,78964947,95614a2f,5b5a4d07,20f32e1e,7be78ec2), -S(490efeaf,914e09d7,6bcf2c9e,15553327,d971c363,50fd4134,b9dac978,4a6bea86,bcd02373,44959244,9eec797e,6f50a9a0,5153b3d0,436d5d0,361e7c6e,cf8400df), -S(9c653d81,7a6f45b3,d7e001d1,140fab91,1ee8fa84,1c361ec6,2a62c0d,1f617a19,ccac651a,db81a595,ca2eaa78,f6ddec8,c18fa0e1,7ea19db8,ee4a431b,87ea83db), -S(6e2f2c34,ac914200,759acbba,28e9a2d5,718a682,61d6afff,46171c95,1010c79a,70d43c78,d52dd510,ca0660a5,40ccb0c7,75c446c8,cc5544f6,32da3c20,8fa84e80), -S(b5b1797,730398e5,c056f91c,3c63d762,cbcbf871,9a032ec4,e53a49da,6ac4c7e,db4299a,1e5d8330,abc09c26,191c592f,556236f4,677afacb,b9c08b1f,2e0c6dfe), -S(93beaed5,d689a857,a5c95522,3520b40d,a9616adc,a58e684b,6c47b343,cef0e604,7e04853e,283c490d,a9751ca2,35a3dd37,11597e26,6391bcac,443023dc,e7b58199), -S(d67e7b92,d30dcc65,ab6dcb6,da8daa6f,42aaa41e,980793a6,2cae02ca,14386b45,6903a40d,ada98666,40583bb6,7baf9b3b,4320b11b,ed904987,f11f6ef9,e985763e), -S(31d4214c,d168bba0,cde7dcd7,54415c1e,1313c411,ed3076a1,17e29a84,184ede0d,bc2ec4,65cd6863,5389a499,970ae4d2,953d1b8a,df8a6190,8af2d7bc,48c4254d), -S(4c03265e,9d1b0818,a0249b0f,acaec62d,13525fe3,3a963dfc,7cacf779,a94e42d2,4fc53174,762449a3,a54546ef,1a1a6012,4fd935f7,13fea628,1eb231ba,27efd9c5), -S(9eb8fc83,a180b5d1,d720fd4e,6c873866,1221f706,961b3087,80b226f,7f3bc065,aabb671,9a5ecb53,9266139c,642a24d9,892d3367,146d5718,bf6e2efc,d7db3dcb), -S(7cbaf999,bf2d62dd,cd5d521b,cac74f1f,4e0dbc64,ce42554a,fa140e01,c1ef4a17,a812aaae,59aa8835,7095750d,b0efce6c,411c7d8d,32077185,22470643,9e8b4094), -S(a1cf427d,9a247655,f017e35b,4f5dc500,f91d2936,b54bb1b5,cd928f5a,add7d9d5,92e76ff3,8fc6dd90,67a38f3,c974770e,ff7fb86b,b9c4cf19,724decf7,682ebe14), -S(ea47daa1,d527592d,a1b67019,acf67b5,3729c0e0,44ad194f,4a884df5,b64d1e88,8a8e6e8c,70c33c68,d249c670,3133a665,359af2f6,1b339a26,6c64c227,4091a909), -S(d2bbc061,a7dcee9f,a9d0d95c,5de7c07e,6db3ff3e,1a051042,532c0ce6,be80730,b00cc82e,6a643f46,2a605720,c862164,da039008,34f30f57,77d15564,4a85ba4a), -S(467b855a,410a691e,e4b0a463,4252d6b5,c5c6f075,acd2d942,141c2db1,fd6daeda,6fd32e37,9ff7ac09,7b9e987c,6fe6dcf4,628756a2,48dfc343,9f127a64,50ce339), -S(841cf771,c0ffcc5c,4a5d30ed,2ff39fb3,c7e3d76f,b9ade58b,2c9c3f91,30589bf7,f4bff35d,98ff8629,a9b48cc2,fad49d8a,88ae7957,33e573a,82649d75,cbbc4c32), -S(5d9f954c,d2972a26,7110d9f7,dbd34b85,ad9ad480,769b7d17,bed01d45,d523c583,ce860464,688413e6,ba64468f,6fde939b,1f9e3d95,b7955a50,6e92e235,c1f85b87), -S(1dcfbd70,cac8cb18,31531b3c,256ae415,eb846804,663fa826,7b1edf87,11d076eb,9579cfae,31cb98cb,62e54b86,cf90abeb,4b537093,898b732,98263988,b870288d), -S(6fb4b3f,2ee3128f,14d810ea,a989d5b3,5feccc55,8d44e3c1,694e5dbe,14d98cd3,f67c8f00,9205f82f,cd2d801c,6a19e35a,61ba0cba,fbbd15f5,c7259a23,14505719), -S(e17d12cf,d261f5ea,db611d02,8f3720f,e4d00e61,5383389f,48c59c0,791263a7,b8bbf87f,4aeda898,1c3c2ad1,f474a7fb,69f45180,57a8011d,7456b688,3839bf4f), -S(3fd5048a,4e2ab188,6f0b1cb8,cdd59182,3e94d853,b9640a33,cb3f5718,ac30f3eb,14d769af,5dfb719e,b4a154a1,f93e10b5,c1d23993,36e1597,2fbe4c76,9c088441), -S(36941001,5302571e,d7c4cb7c,3d479f55,e89193f7,5b52bc7d,d65ca207,41d14b2a,c747a1d8,af196bed,df1c5321,d58a0a19,171ebf1b,1a855b9a,3f90f16e,c333393f), -S(42b5541d,e161fd92,f2b92c12,826fda42,49f05c1d,2f79d951,1ee4fae5,3269e1f9,d6cf742f,11daf585,bc7b4be1,784d55de,2ba3b918,4df6d81f,723eb593,2862dc5e), -S(dcfe0685,c9452c9a,be819a8a,574bc35,760263a5,edc0e018,4093cf0c,b4406acc,fb84c487,873ee72b,49dd61e7,46a8cc1b,8485c4e8,fb5f9725,a17d98d6,62aa9d58), -S(cc5e07b4,c76bd9cf,c9b040bc,c3d0805e,487eafb4,430f2265,adabe2e,7bcd5874,6668bcb2,7a297c14,d4a046aa,59028e39,be049894,764193b7,9dc1658b,bbdc3d25), -S(74cef0b6,e59cdf5d,47244fed,491b6c0e,76d9b185,1a3f084f,9f783a67,d5f4c70b,3560eae,9a4c4b65,3831bd98,d97c5213,25b07f32,d40b215f,a93f2332,b6a8209a), -S(dd1b1359,4ee43b44,1f54a620,6e6295c9,80bc664e,3b5c19f4,273e878d,3340b605,4db95cc0,f8e2020b,c0f0eba9,d21cf630,e6c5ff77,dff8bb2a,8b496dd4,22cf6a0b), -S(f42815b4,76b4407,9ec05cfe,aba6f179,b72dea78,767fedda,3464e9c3,53b3ccb0,89004efd,2cb91fab,7c8908fd,b454672,4ad8d851,55473b21,e8e3d984,6d913098), -S(f20d41d8,c096d2eb,d480f9da,5df1bff9,570dd299,16f87ca2,19ed3fd2,d6c072e7,3eab3c48,be7e6d6c,bd1eed0b,33c54d49,72d96f86,67bd857a,8fb3190f,92b22a9d), -S(d84b9d43,20d76cb6,13df70b3,d0dbe935,852fd9b2,86978807,b6288a3d,27828a28,73c0bf55,de9ae18c,a56b98ae,3bc86a48,15d1265f,62d5856,f0f2b182,b4596941), -S(ba0ed2aa,3944454c,7581223f,d1dd113,9d340ee1,11d08d7,98f278ea,7160ca10,766d5ec,49b48092,c007fa69,a06b22ff,e02cbc30,6cbc75ca,1a5f0058,73c44299), -S(b5393ee3,7a8170c5,bbbf70,fec33e90,71e52f4c,47e21d79,e9f7413,d68050c,7eb93838,f871d769,733ff7e7,d21e3848,8632b7e1,6483202d,50a2fab7,1fd7180c), -S(820d66e8,41b5de10,e28c147,d43a0116,6cbe764d,c8ea6a42,e7743732,45b84190,cf3a65e8,80727c33,3e693586,78033805,6482b2e,53889a0,bbf834eb,c94ebbf3), -S(247cc086,26f54562,8d48634d,4bf7348d,cf60e598,5570527c,c20ce901,ef4172b5,acc2fc2a,9c939cec,a51312c,d56734f2,87d906fc,c4d42f17,82606c37,b0584dfc), -S(81c41e2e,752e0d9d,c66cc618,5aafe042,8733913f,5b597ad5,66706d72,da80dd05,8ed860ff,846ddc23,e466619e,480d944b,f171707e,721110bd,119a128c,e8a623ef), -S(24a22359,7bca9222,dc0c82f4,b7ed4ced,f5f41ddf,73e5c8a5,88bee89b,3b21fecd,7555cd9c,da2e75c6,d8c5fea1,50e3feea,b3ea1573,d7c163f5,e43b3d2f,31b0f5e6), -S(db074838,ae29a327,b85361fc,c9ad2bba,38917d58,c17ec58,9c22d6a2,f9839185,a1f7280e,35bc6b7a,b05c1704,abb46a90,43b3f7d5,30434450,f94ea1ff,f787412f), -S(6adb02c8,fe669d1a,8c7fc3e0,60eee0f0,73409111,c6013619,770d0ccb,bd8b950f,3fc12c9e,b1d19234,737a4e64,9aa06032,35d4538a,ecc6cb9f,dd1f7777,46edaf5f), -S(e06dd5c2,1d109fb6,3e5429ce,11fd5a40,5118a84f,863095c7,dbfc2374,6ce1429c,961b9d5b,c5b82b23,c8e69b15,15e28700,13094f48,c8ef49d9,37e1b440,c306eec0), -S(1b599e47,ef4e5369,bba2a71a,98cb03b3,f5d9d30a,a5e309d0,cf7e2d19,27f95c18,5a40c3b0,b949efeb,ebbd0ee7,1a81c9f3,d6fc20f6,c9effd98,f0492ef,82710072), -S(92da076a,ca5c2267,67abef5c,d06a830a,a6cd1d3a,2224a845,184b2e7a,275eebd0,db28e087,d7e29f20,d78dfa27,bccb47dc,f2a3a9ee,db0db1f2,63dad719,4ce9e997), -S(afb97660,7b94dc70,a87a2be6,53ac2f3c,9a2a474d,ef065f77,b06fd417,44b13992,68d14dd8,e3caf1c7,e39ad23c,f8e83577,d047530f,2c7d5b35,c509a3e0,51eb52ae), -S(bf4f278b,e99d1297,742600d5,d7ce7791,970de902,aad9920f,a8083a3a,a50229c,b4ed5f80,f3995be4,22fa8237,d77b1424,1fa974b1,9b725016,c20e555e,f0ea2bed), -S(c059a980,f1a7c648,95a1acd0,f9d2cd8,9dc02acf,c372740b,86fd64f7,426ff54f,dbc12822,e8155685,170456c8,4d548f39,afba1676,15655d7c,7b8c31ca,499902b8), -S(2f4d9b08,282d9adc,2d80bc6e,b4c1e2e0,553971e1,f42fb8ee,be615d47,61c023a8,fdb056fe,3604068e,2f5e5223,d3076d67,41e939fa,f2e7d0b1,76d3ec89,868cbc06), -S(a7425d49,934b13ec,85aa5c30,d628b94,f0054374,19c5a0c5,6e126a7b,261c005f,f475be59,d5dd5a7a,42d15531,df24fbd0,12d84fd8,e89ca95b,23bdd70f,10b0326e), -S(dd3d3a96,cd232751,5820439d,6455bb3a,d749947c,884a2e90,5791253b,aad726bb,9afe6071,4de46f80,d22b7ac9,a555a7f0,6e830819,437e9f98,b944d8c1,d4722027), -S(7c427ec,eed88d6,a48f7204,e43ce8b7,a4c5b6fb,ffca57b9,bd128903,c3c7fc46,495bdff1,9b1711e,918448e9,a46416de,e2d51771,43007e1d,c1a64b4b,8d1a815e), -S(bf610437,6539cc63,4a1f3e2c,4fc3f762,69752d64,2756bbfe,83bdc404,f7be496d,5bea9e3a,33d7318e,9c03baf5,3e5a0232,440ae61f,25407ab4,23514eda,1a69513a), -S(f2dad2fd,178ac78a,168981db,14c4fb0a,f7e69dbb,453f0d53,456470f0,a22cc730,e571813b,2a091f17,23c21818,789e78a0,e23e74bc,b4d037ed,f8f49fef,9623f42f), -S(51243664,8693af91,8c79fa28,d7c12b37,db24f719,bc0dd0e0,28c6c1ea,19aa42e3,fa116d7d,7ebcbfdb,8ce76cbb,e6203cea,25b65559,becd1ca4,65f7dee2,6e49746d), -S(75f316f0,c9706cda,9cbf6c8f,31266c75,5183ee71,a098359a,ef06fc3d,ad645fb8,518d90ea,af8ffe9c,44cc122d,7659d292,8a979e6f,de2654e2,e3554b71,b9e7b820), -S(565d92c9,93f08563,f65eb65e,6ae4edaf,ee409d1,e00a4e74,5d439d84,a431a5bf,b8cc1eb0,1a532023,ea17bb56,f9345420,a40b0a7a,d247ac43,4ac9347a,51bd0f31), -S(64b17b4d,a0341dac,bbda0a6a,e386e2a,64d0e517,2a4b904c,b26e45c4,497554e5,4028951b,3f17ae55,d114d6f5,ae793460,91d8d00c,c1b2aca4,f0d5b51c,3f8a7492), -S(70ba7f8e,65669610,5496614,c6c1ddef,b8c23f0c,847d8be8,37b4699d,511e3ce1,cfb1028a,2ddb2865,633f358b,e6439ba9,9fa8b1bb,eed6d988,e8652661,9bfcf28c), -S(84c79c6b,23bffd84,4cdc85f7,3180f451,3e6cc4fe,adb7056f,7de267a4,75605d68,beb80b8c,3b2ddf4c,2269431b,bde9aeb3,55e97faa,385c8776,4bd15fd8,344e8ac0), -S(c6f4eb7,106cfe74,82cdfeeb,af421137,f8665713,10616b0,b2b5ce07,8f5ff9bf,72ccb3ee,52b77765,e931298c,204e7b07,57c3845d,5abe7ebe,37db5aa0,203fc81a), -S(c58b8483,6b41a2c6,f56abcb,61cb493c,a314063d,9091ce1d,9b13cdb3,fad79f90,a1e846d6,5fce2f4f,37e210f8,cd7591d3,fe1f6c93,7fa4ac4,ec295078,7cfe84d6), -S(96e430c8,2a74ed53,7f5a181e,20faea66,ee77588d,66eeaaf7,50dd5b7b,e42ad21b,5aa2ee54,96d711c6,e8b95609,ab383b4e,993f928e,d76843d4,52a5a1fb,3e137368), -S(53868e1f,bd086477,60aae23a,3f2763f9,cf6eed71,19ce1c17,b226b48,fa85b8cb,b94b6a7d,4c86d90d,98c8d359,45949b0e,9c958ea7,651c901,90e5988d,e142493e), -S(d6bbe341,8a6bce46,2f091e5b,161dfb15,8c454eda,add230bb,254a5989,df9ef899,f1690322,6db63393,c01fb1ba,3bd83bcd,dc95741e,8ffad9e,56efdb08,837340ac), -S(a496bcf,4317fb5,c87a41f2,58e716b,98f5305c,fc957c83,c2c40397,49de94d5,2479a3ed,e3fc60f5,ea880b29,353663ba,6d9da119,52468686,bbc2d0f4,fd8dbe21), -S(5bfbaf07,3c1cb96c,45bd1191,bacd3bab,8c33ef0e,e9708164,98240b52,3f943be5,96009bac,6fee957b,2e26f717,ddf40b4a,69cdbd5a,946e70f8,b70587c3,b7fded2e), -S(955fa716,f7f0eca8,325ead5d,dac3fed,bc477c22,3c0fd563,2e37ca69,ec79f61a,418c98ff,23d7de2b,2460806a,75fc0328,5ffe9660,b7447a36,c088883d,623476ad), -S(99d3b933,e7d8c8,e1480e6b,756732a6,445036e,9b964a32,53f3cc09,f3d9211,97e70dfb,faae8f58,5a7b5da6,b0c775f4,9c095d13,5526b521,d57c29b9,b2892dae), -S(a01775d0,5b9d2fb1,277f4c3b,6edc8f7,c342c3ca,e9244fee,57cc2d9d,d5b096de,376293db,5c929468,236828a6,1e291811,316ca7fd,90efda51,2bd750f8,62ebabd8), -S(697cb417,bea89412,91ec8ed6,f62f1914,96a22208,905dec11,463014bc,2e9a04eb,d5049ba,aa04b285,f3085c24,e54ca476,cb266f3e,15699d12,fd250e39,ec4285c9), -S(b23ad54b,f9504c8a,c0bec876,71d2d41d,ee04bbcd,c5ba224f,85e3d4b6,84d8889a,8f0b0da9,db0467aa,5b21addc,d3951b72,8d23099c,47bf7767,24e1eb23,ab32e7fc), -S(c8af03ff,197dd38,cdc294d0,28c0c418,2d517dd7,54669894,812d870e,65160c40,d4537dc1,e594be6e,cf2e3ab8,6f42cc3f,a70015a9,ed8e2850,4fb6f9bc,676be0cf), -S(7ea5647a,f0f8da46,6e6b0615,28d0f472,79ae2a2f,5eaf0dc0,64ccf902,e060cf1a,bc5a47f0,d95e37c2,ad9c5fc8,48eed4f3,c62c974c,9b96b250,ec076851,12a88ed3), -S(78cb2c40,71bc6abb,cbafee4e,cd413181,cb1b5483,ea1db7e0,f902f31b,346f7ac3,86f334e5,5560d9bc,60d8463b,269c2626,45eb9964,970dea35,eacd9236,3a36d198), -S(f968919a,7d90997d,5863c9e4,e214cb37,51dfa039,75d876b2,3f1376b4,ab79cdd7,ae3950e,56e4c856,ee56e236,bd581033,6991f8a0,e9212c8d,9e9079f3,9edc2038), -S(d7c2fe4,6d1ec3b2,3dcf9992,357bffd2,aea9bfea,da187cdd,6bbaeb2,51ebf663,ec953c2c,5fb70a14,b21791a5,979a182e,c3facd73,a59d0f50,c3231485,f376039c), -S(63aa7712,4dfa263b,fc8c7b,85dda505,14d694b4,5ac9f06e,1482105d,ac04af87,d368c24c,18de3ed8,43f521d9,3633e9c1,53627e54,bdc10eef,15491802,41dbd9e5), -S(47fff446,884d94f7,a1b2253d,2f2cb718,70a6a42e,36f63feb,65fd7e98,213117d4,ac52a32f,55dfecd6,68b61733,3fb4b7c6,fbefece2,d2cd43f5,667bc42a,f17d02ef), -S(b3d96bde,5770d471,1a91b0df,17c785c,ff7f51cf,c4d46c27,7dffe07e,6c5d1173,78e408bf,6d204097,40a1145,becb61a9,c78120c9,957c6457,12254e2e,f5a1d77e), -S(f17f1d4d,7df494d4,70321d27,420deb68,22be3877,78df53b2,37876928,d6b2168a,4398f0ef,7cbf1188,dbced020,7b2aadce,440b1df1,7db6870a,a05c6d56,4038306d), -S(10833a6,6f75d109,e5251b43,f05d9069,2bc216a7,bb06032f,c2d142f3,cb1eb1fd,f77ce6f4,73e861ef,23f67a77,a5052dc3,4b617279,1e69a688,308439e8,7d91bfb4), -S(301bd783,a82ad1d0,daea7641,6575db5a,1763481b,3c2f94a4,788f7a54,6f9af647,66ee6029,13b6bf11,e8e19392,633fb8b9,e2a3dc51,bd891ad7,3fb80d31,854333be), -S(98fb5877,816a2c9d,df0192e7,beef06ba,c19b3760,b82d8e08,1f6b2431,dcc20d6f,de59596b,914b994d,83a68c1f,eacbfb8a,17b9c54,9561fd48,4f7f2f80,bcbc24cc), -S(5247f727,1de92a64,dd35147c,879ad2bf,4cdce035,2c077e0a,19164052,e19e2d68,75cae57d,3e54bac5,dd41655c,f62f6ec6,7e84255c,bc0bd176,aa505569,675ad042), -S(51d7bfa1,5829219f,6af5d2a7,1ff220e7,9de62e7c,a3909d4a,37c918e0,6b60504d,9d1a5e54,77025129,1d42c64f,14d27eb2,cadc09c7,bf3899b1,b85119b2,a5326f4b), -S(533fa077,4c05ba3f,b32ac60d,13fcc4b2,a20ccf97,bacf2abb,d2d9b6c7,54678437,a41595f7,3d604126,7b82b50c,22d39ca7,7454bde8,97dff46f,3c57f7d8,ec73e818), -S(a549dd6f,2c8f422b,dbe464c,48f61d13,b3537a7a,2fc5a8c0,91d7d33d,221ff3c5,ad126f86,b69a56d1,2ae18f0f,253a1989,ce80a74f,114e3813,2199d1ac,be03efa), -S(7b9161bd,b4d5e56a,c9df5417,fd84aa54,798b9328,46218731,ea289cb2,76a612c3,72e268d1,53fc13cd,743debad,16c98af3,4756244a,65b7f7b,33794aa3,1aaf497c), -S(21557200,4f644ced,9c2aebb1,43beca5e,d54bf17,d2cb1ea6,492f19a9,25a5be52,19dff558,9c87a8bc,d02af10c,4b32aa25,c80b2542,62ecc0cf,bf4439c5,c2184cc5), -S(93d2caf3,c1a0a83e,ecd9adb9,abefd119,1000e482,2670e678,8859fffa,a2784cd6,f443827d,c5437809,e5cd0eff,b48d7b7f,ed4b3ad1,a724cb7e,35aea03e,655895a9), -S(388a2c3,f621470d,eab3d1d8,765d6af5,629b1cd9,10ad662c,43abab6a,9cee5283,653f3611,7e335b31,48df68b5,a8cf6fbe,134cdf35,f659f14b,9036b933,654df3e8), -S(9d9c6f6d,7032898b,77dc7738,426723ec,dad11684,bde6e061,63ed6802,69aebec0,f20282b4,96183c42,8275eaf5,95834713,338112dd,9f2b0924,8445d56c,15a31276), -S(6e1d3bf3,98cfb2f9,67464d53,755f56d3,bd4de638,4425975,d96df00b,b500e825,6f8afe06,eaa52db7,291b41c5,959aecab,e7111b74,fb260d40,68f2a8d3,895012be), -S(dad8454c,5c6fc1e6,35c4ded8,1f2e3870,a5f24fea,be8b6d7b,a2adef19,32bbfb53,7c6aa3e7,615cb467,42b42973,64222157,de26f811,b4046d4e,591f9824,4fddec5e), -S(5ade9345,11ffa26b,a147ee6,fab27693,9828a8ee,7cbf5e3e,e9052b,a01e0893,ed84e129,7d98895c,b7ceed84,52db80ca,3f44d127,d484364b,652b96bd,82f8ae16), -S(d6e9e33,6a39b415,e5909463,9d621291,9c81a084,dace8a97,a0372042,14cbe366,4f274e3a,1ed0ecee,c7d1d4bb,28712e03,7632b43,e1f8b75,a9100b4a,f74e90e9), -S(a913a4b0,a990ae15,60caa68f,e45bf7b1,af500129,a7bc652c,b47e80d3,34bfedfd,1bea9464,6a332e2b,8d94dc5a,32ce31e3,1aef6c83,ea7a261,99da6cf5,7892f63c), -S(7380fa59,b95fbfe1,8e1c3809,36d10b23,27fcf8f9,21aed806,1c602498,c2c6ca5f,fa24454d,bc8cb2b8,9462febc,2e74fd72,8d300617,a601ff12,a599d2ad,bac2fb7f), -S(9614b47,50073368,4d26bd95,5b9f4df3,8dc11bfe,4ac65d17,6149e1f0,89f3a69f,12a2b07a,49812efe,1d3559f1,e282f268,813e5572,8c959a9a,129ba886,9f06a66b), -S(5f2956dc,436e7a52,176d2709,362e511c,cbda57db,ca347ec,63b63147,33f14d5a,f7b399d7,7b3e1d75,b5578e3f,f324ae9a,76c243f0,8dec8cb4,9bf7a78c,120ede0e), -S(22d7dae2,38885aaa,fd51858,f4bc1042,5d57599,2fcb4eea,eaf6c222,c0ae9e7c,6f3e789c,24247afa,9ae0adf,18bdc160,b1d6d956,7ee8fefb,e9db9ae,f0734909), -S(9e5660c9,a5f53e77,59586df,b2b56dcb,8f1af69a,aabcd59a,73573711,3fbd4dd,2868aeb0,5efe76a6,8037ca6f,d97c2769,edafed65,3f38555e,15ff41f7,fd1fb8c1), -S(7abf134a,123ee2a5,eb4bc1fe,6d06f5ad,655991c3,dfa91ebf,ae46ba80,899adf3d,c96dd41a,238cde21,3f628bba,a2488458,c0e35896,f32cf7a0,45b252ff,ab696522), -S(95da0b80,e45e13cf,f5f4f4a7,5265a310,8424fa09,f07f2c07,efb7a018,b5edc82f,ab645319,b3645cee,d1e4823f,838435e2,79f4f41a,af258432,b210a73e,569bb4e6), -S(8a095bad,b000f2e3,26b0c8a6,f1363fb3,4e2f59cd,978d736d,d05614ce,dc849fc4,4e367851,5c42cfe4,6bd3b6b1,6a09bd66,59626f10,a0087591,6b7d178f,14eae676), -S(de5f5b91,eb34ad1a,9d3c60ed,29c683b2,59f4c7ad,819bdaa5,f751c1b4,7ba28567,cb9d478c,58a02246,44f59a4a,cf2fe992,15f541f5,febe0ebe,439a1b8f,baeaba58), -S(94acffd1,b87c644d,b359cc14,c1d996eb,a1d7e773,d902dd5f,7086502,bef6180c,8e58ff91,ae72b071,abb09a19,4afadb4,b3a54c3f,91857b3b,bad991bf,a605cd78), -S(fb75db19,87635a41,e325f08e,3203e0bd,e7ecf969,e46244a3,5d63dc5b,a64a3336,14d19c5c,220b044a,72b58666,9c74ee94,2df157ae,67524f01,9707806e,1bf73c59), -S(9808674,a196cb3,eb0b2558,2a9bac0c,659741ee,ce6b1c49,678e318b,f6456081,f5532b86,3408f545,aa218a22,405b0839,9e59fdcb,e2c54230,9955aade,3660aebe), -S(f2b603e,d1d8506c,b1280f50,f3487f1e,71d797f0,f8c8a1b0,fd153683,18d843ca,1d6f91df,d7bbe002,ec34bd9e,9b843620,ff43a756,88dc1398,e23b73a4,9d3e53ea), -S(b9327718,4586a524,389f7e49,adac31f7,45ae323c,d3ccb1d6,a2abc65e,863e684f,b28c0f77,b47bdf1f,390eb8db,b94c606a,84084e09,1202dd3d,654abc10,3589b6a0), -S(c16eaf54,572c1a6e,142b6617,b38992a7,9cbbb577,348b8768,56ccf471,e21b7b63,bb9e7a6d,6d8ed16d,4f8f5009,76edb112,4d5c7ede,cb2b8abb,73de287b,5099035c), -S(97c03ecc,6a87d198,13d68f64,a3cd91bc,ddf45350,383b90be,c5565c48,531999e9,f5cf3c4d,71be1dcd,60b39aef,f1cb8ffa,62d3e07f,33d4ea1e,adaa0569,3c239ce8), -S(6a224e6a,85d31717,10013b13,14ed6c31,adfd153,df8bb9c6,47428e85,12c1786c,690a057e,ef9e425b,651f55ca,8c72169c,bf337e7f,cb779ce7,81e1ca9,5feac5a), -S(1e89ac78,be4513d9,38e58385,7256eead,54afceda,32edfe63,c70b0f75,83eb9ce6,bbc32d24,d58f47ff,2686d804,4e62e575,a1f1e805,75587b90,1a362461,93f9aea8), -S(40df4fcb,8648bed0,44050957,8ce57046,bb8daebe,5a7ee63a,e69decdf,a5de87b2,154c0c93,8f5dbeb1,80939a49,aa15239,e3308e56,ae8ac16,3be19bd9,33fd07f7), -S(a03f1ac5,a3738a09,d4888626,72f00159,59c280fb,274e9974,7447dd30,260bbf8c,9d28b67c,3455e338,1d1f84c8,d60e4fed,c39b5d05,8d17829f,ccba683d,cd65f093), -S(c7d9dc5,d2712b0f,3da6b4bf,1b6d74ba,de6f9586,a794a1e8,4918ddc,d115d1b0,b1727ad7,6666c0ea,5abfd80a,6aff8e66,b8b63c27,6a8ff457,573d8336,fe65dc0e), -S(3c1f81b0,2e8794ae,135db6d8,ea6e1cf2,adcfd535,634ddfa3,773555a0,e0efd26a,e21915fb,abd19ab1,a4cf84a2,a5275a50,24d0fb7d,c841fa43,284be38b,788d9390), -S(69503972,3c4d14a8,1cefd3c9,ad7c4a1b,d5b01ec8,530ade4f,fa7aca65,28ca332e,20bee7c6,5d499abd,f9c9fa2a,585e3f73,cc52141,f4276cfa,aa856c84,6114c1a4), -S(da655560,50683d9,5f81b2c6,e504128d,5f58fa43,4cfdee92,c0324b84,77c3ed70,297e7d88,2009d30f,bf0b5aac,1c7572c0,78192a1c,475fad61,64b25ea7,871017ba), -S(f1ec70eb,ce501e37,f79406ca,f120046e,6b064b80,b8db9d22,d41f9b8,a229cee6,8688ba6a,ff61aa53,4dd93b02,e3eed5f9,f1622d2e,6fd3a3fb,594b9bc8,5beb55bb), -S(fd0c93c5,c2334d97,1e1eafa5,6b62d377,d1104ae9,1c10e707,a404674b,796c51cf,e2529070,a0ac26ae,bfa954ad,801d0e2b,cecd4102,77a7cedf,5a707dbf,6c8ef5f1), -S(514a3ce4,b9f518c0,ebf15b1d,56687638,7eab4df0,85f93f0c,53831536,ee75c78f,8b998180,c9e78405,cf9cbf2f,7495455,6d5dd04b,bafb010b,db7a4cb3,6bd6cd30), -S(6d0e5be5,f5bcf0d2,37726045,727ce85f,336bc6c5,743c0254,9dfed03f,234fe265,df071d23,bf3e151,5995d25a,f7c8cb48,d81ec018,af8513a8,e842e3d1,484f99f2), -S(d37f48de,9143228e,d5d02ba7,f5d97b07,922e75b8,54eeb91e,86643a6f,cfd8416,f7d6e782,af5c8c0d,f9d2c80a,e582b88f,bf9b0824,6e749d0c,9ac72afe,847842c0), -S(d44815f7,46405f75,f03f4749,b5696cb7,54fe1633,7c721602,cfecd1ad,fdbaa875,a6b75d70,4d5c965b,43284bc4,d4db5d1c,980d4bba,e8f8157d,c1cc322d,44fce058), -S(6ee0ca27,441c80d,83b710d7,a6e4f5d1,a497287,a16e3f67,7ad24df4,4db8a287,60d12357,350a737b,74f857e2,ad3865c3,5dd54e00,e70d1aea,cd77c12,fedd02ba), -S(86edff95,6ae4aec4,7a8b4927,4170faab,dc19828,c14f3de2,84362bf4,5bf49d6d,c9f571d8,1fd0b910,7043a52f,79fde3fe,339b17f,ac0e6461,8c601c17,375955b9), -S(c8ea3038,f056e115,aede11d4,ce113663,da276b83,12510e72,1cd8600c,a4a573ba,a662f00d,952d21ae,e26f97b1,6b32dfa,c0b58c06,6cffcd79,3755cb3a,85fbf3e), -S(541b43c0,16ce2179,9c7db4f0,e06b6c7b,bf006f1e,2adedc1,e8f4e8e3,1572b199,27742f79,a0986843,1560799,c11e0f43,be6e8631,7abf4d25,36e09e25,38b90ade), -S(1630dee,a2d1311a,a7c0cfaa,2693595d,48c274bd,d24cbc7e,4c15e458,f7547d40,f1a92fde,a7d828e7,bf7b1c8f,512a21b9,7227eef2,daae040,f8cdfab1,a728f20b), -S(126f6117,456d919c,49325ee4,1cb1ace2,fdd5bde,31208bfb,58b5fc1,62ec799,4c23a017,73d47eaa,579e5cb5,14bb8584,7955f03d,d097d527,ff366b81,1e6abc81), -S(b6210ef7,1bd1957e,51805a9e,70c6663c,6d8aa371,e1012a46,8261653d,a3470c98,c491d5,e98bff1c,7ce97493,612dd726,bdf69d7c,a4524721,79ec57f0,fd123b87), -S(34291314,3842cc68,b0184bb7,13f7c6ae,aba928d1,5df911c3,3bddc99f,ec8a5786,4b63c3c0,ab6efb2e,bc343cdd,dd43d553,582a53a9,3c3663bd,138eb1ef,d2a245cf), -S(5aa2e234,938e26fc,12589307,afe2d797,bad41d73,3eb6dc66,da9a56cf,d4b6c4d4,db91df9f,1856f8a7,83696842,1887235,5111b973,10fb5975,154cdfb4,2f2f2e64), -S(8c50cd04,5904ac5,d9c6d555,e7bf188d,d2318edf,cd90ab90,722d8552,edbebb92,f60add37,b3578fe,f798d8a3,99834ef9,16e9ca8e,2ca8b9e0,1537e7dc,533154e6), -S(591e3233,9e5ad324,be635ef3,50884aa0,bf3efa8f,7ee012d7,8476ca35,ef586ee6,6e219d2,ff115d36,b3688e09,b4788bd,19b5e471,6f09eb41,cb598ad1,b60c069b), -S(7d4464b7,587b74e8,82c85444,4d7637b7,9b6c586e,b4a032a2,6e07b60c,470d82f8,3f1f3d44,6ada0a0c,4e082bf2,c31ac7a9,d2deee7c,4d9492ac,81d47a3,db7794f5), -S(92e55e29,e333f65d,1fe8845d,42d585cb,55db9cf3,223dc567,29906df5,bdc93387,5ff7c2aa,25b670bf,5ab2b57f,831c3e6d,b9801ba2,10aa76a1,2eaa45e8,29a64454), -S(a0fbf93c,c47198c,9492defe,fedb5ff9,dcf178ef,70a0f416,5128d18e,49083c28,dac0dc87,4bf9f134,fcae7932,46a6306b,5c876455,fb493b04,9a74f94c,82cf0a56), -S(5484f0ed,aabe9633,f0384de8,5f86e77d,8153acba,b8922863,6fabe9de,3dd12fef,180e070e,a3712386,cc4ca4de,f54c0399,fbb017cd,3ac0704e,52d60f50,8c0f2c2e), -S(f2452493,34b7983f,afe9d99c,55023ae8,c8591405,4cfc930b,3c76bda5,6c106445,6e800534,948b6349,f85c5164,ef5bd33f,f8d209eb,fc25944c,110f04bf,fa47c604), -S(d15f5c6e,20f96f4e,d1aaa912,b47198a4,fdcb1101,c258cdd3,52cf0246,2679f845,7751370,ef04b59b,bd74d4e6,286d690e,9158f004,826b2dd9,37070544,b06df5e0), -S(75ba968,f35dbf2a,bd92c08a,24930949,7a50bf27,efc51572,232e152a,a5988818,64be1522,78e3c24a,890c584e,8f2561c7,62985b74,e803d124,11910af2,487f9491), -S(c7742126,88b392df,ccb6721a,dee4f49e,ab1fa24d,84695994,f7d0a7a3,3cd52f21,e603fb71,9464ca60,a8ff9047,6093b2ff,e9091815,58ab8d7e,aaa7bf14,396610c6), -S(d15a536f,661f00d6,ce0892c5,6f7ec1ad,614becd5,9b5d3019,a24923ad,7bc828cc,b2d1c3d5,a9a84da5,cdd277b0,512835f,48b546cc,3fd36b16,f83b8cab,caad96ea), -S(64a9f14e,bbb02687,cf9ceed5,636cc349,a8e55cca,4913a221,641a0916,6afcb872,76b2ccb8,2dcb7837,97d31ddd,bbf9abfb,5173b495,6a6abd10,f9a583fb,981bafe1), -S(9eb0c54a,9490fc39,75170e03,1d3be45d,1eb54587,41db3f40,19e83ac6,be7915e9,fd570313,71616577,36c736c3,b282b0c3,f1f9146f,1aa9f,8fa1b34b,f10e87b), -S(141e12c,501af124,a22cf65d,b3996c76,44bfccdc,2920342a,4f3becfe,d279005b,1b6e9acc,c61ad52f,d8f00405,f2191432,b379492d,838865cc,58eb4bd2,c1f1735b), -S(63f9a52e,aebc297b,5665752,9cd93a78,a0ff93e1,f94629c4,bb9b19ec,68ee1895,8e403a45,497dd525,b2924861,978da88f,4823236b,338ace3e,76330b21,a9ad14c4), -S(af31b58c,47a9c9e7,3bbb583b,2178deb5,bd430031,9ddec2fa,5e66eee1,f0ed8b1e,d1fbdf75,8ac15977,cb8c9e1d,7863c465,cc4dd8e3,e299f116,74b0035d,291e1472), -S(985570e3,85b4ce30,847c2a7a,cf5a3c80,ddacb47d,dc1ce66a,d001cd13,36293ff3,5b13a12,75c5b519,10398a58,f42158c6,1c064600,809d7a8d,b31e14c0,84578854), -S(37ac2f59,ef79be35,41e46114,c4f9ad15,e6c8122,db85b62,59604adc,c8cd303b,434d325d,e4ba5b11,7b876da7,8c387d13,3d0fba87,d784cfc2,1ef689e0,4c1d52da), -S(2b002a0c,280419dd,7911a522,28ea70a9,7ec2f9b6,db5316b6,7581a6b9,7354ba70,dade84b,34a23024,785c211b,73b006d,7ad1e3f9,e344c783,89d83eca,332e4734), -S(65c4d14d,f9a0853b,61429a40,50d2aa66,19f63bc7,12517118,784c0100,9d7ee08d,4cc1bc89,aac9c9b,931e9546,cac82cd9,6051b17c,991cbafa,efd52f44,e514241d), -S(df27b45e,7a49695c,8c38d85e,5eb7e9d2,8cbffd71,8520f681,1144087e,8a372c32,cd3d4c1,5ab586fa,ba4af68d,9bf04e13,31f7e5a3,95d14c67,e4ce598a,4077fc6), -S(268c1fc,eeb3d3dc,55daac92,23b9f511,418917b0,3d8a8210,8096ac34,35a820d4,d623750,3c42a02c,5a386e1a,f39694e9,844272b1,766ee986,6d4b67f1,81086fd1), -S(cbf09fd,f85c8ff9,3b1e800d,8e5901c,35728aaf,3d2824a2,bd09e1ae,c76fe1ba,3876982e,cacf4bc0,aa53fc48,6a98cc01,8ad33f67,e4ab0abf,dc8677cb,e9619556), -S(4126180c,88d7066c,8f7877c6,5e41b4e,c15f94da,e68d57ea,a2131b1b,6b9bd2bc,1bfa8de1,71947fed,a0c8ce3a,2cec0e5e,e307f7e1,dd3b7ca7,4f0e0682,c1c3d087), -S(bea8d718,159940f,dbcbe23a,5911dda3,c75b7931,cede87a1,5cb39de3,3f35c022,e723c23e,6bce4f27,fbc219d5,7d7ea196,e3ce1273,58e7eace,9d6b686f,efc35509), -S(2275f050,a18ed0b7,af54c69a,aabdc987,9eb9dd35,7211a964,23ad6e86,48624e3a,3c025a31,1a0ad11d,c9d930d0,7bd101fa,189415f7,c705abeb,bc585948,14f4d88a), -S(1925ef48,16c17466,f7e16c4a,7c6352cd,a12a2a15,9880a482,a06f8911,21b32fe5,30f83429,fb20aa48,ca4470bd,f90f9d6f,1660e583,5868e67,94ec16ff,e06fb81e), -S(18720528,a0612661,3ea23c29,356c4a2e,db74229a,79f008a3,1d6e1357,f873cbe2,ec54426d,a41525fd,d74e018d,dca72be9,e7a28000,2abe1a12,4a73ed4,21893106), -S(b8a6972f,c526acb3,4136cbb2,4850ad15,cd70a4d0,ed66a9c,8605b257,885c9d8f,e043953a,698e3225,a35271ad,2a173fdd,a1d37ef8,98c630,d02b80a0,cd729fd), -S(3839720f,b5c7c3d6,3a0ccf99,c0f951ee,b257d818,b3ef1e52,b530aa23,8ab06887,9d58a455,9e5268e,48292e9c,c6d78275,c733c2b5,b31326bc,4a0546d9,7d950529), -S(c204f868,e6632183,88024c76,4ef92286,68ba2867,bd301c88,1bf8e7b3,e6677e0a,490e59a9,4dd95482,8b386c0e,d6778f93,5a692d4c,74f6ed47,61aeb26c,4b1eb048), -S(dab95115,4aa1451e,95cc374d,6a6d6801,9778f54,9672c4ac,f9d16b39,ac2464ef,e32e5c8d,453be5b0,8c5ca506,b7875565,7f269a75,daa83a4e,f11e1266,f442d85), -S(ff283b71,7118eaba,52225bc0,ec0328c9,72e5c13,3ffab3b,801dded4,cae7e596,36d8b7e3,4dd684d7,e9b0bdf0,3d60304d,7d990a85,a955cf3,db681d03,b0af5d43), -S(30eb08e9,6f4de692,d2eddb8e,aac47b48,1f3406e2,235560e5,b23d0b9,f2ec4597,cf05cf0,26ed3094,37aed28c,2dbb6f9e,94f83333,15f00832,1286dead,1c931be4), -S(9a51edbb,e9146fca,d3c9580e,9ee34252,6b2d59b,c0531051,76bf3ec0,b86dae9a,94d549c6,2cc12e09,63c844cc,5dce24db,834fdc93,4c8b06e9,afc10f34,f08705c8), -S(ac1836ac,2f0d0158,650238f0,7b2ed1b,111bc56b,b176558f,7e018111,ee520c09,562e108a,a842608d,7c86eeca,f6f2ebd4,ad4d14cd,48c3d068,eb658c28,ee1aca36), -S(5c33360a,1bc8e85c,b0f78d66,8f6ba33e,4537e0f9,88525a1c,b186fdf,7ec65596,8f86a399,ba2038a,9faa311c,f2646ad,66de6c86,c3280d93,71d1bdd7,d9df698b), -S(40798759,c22a7b60,464fecd7,d506bec3,3614c895,c6d60d14,d1ef646b,38559793,506dcebb,aaa057a,433b0eb8,96d35070,a871e11d,216d6a42,19689167,b8588b9e), -S(36466772,ddf9865a,c6940a62,abbbeb24,3092f44c,58e3c052,9cc0d3ac,738d99cf,60ad37de,b41ee4dd,8cfc755d,e309157e,608b0a5b,ef385836,8c7c7dd1,cbed7075), -S(e6169ba7,ccc02fd,cfe63742,910a5e9d,3a3e1661,d8da60d8,32b86e9d,487108de,f29ff08b,afa4568a,4ba97709,477b086f,31685c1b,a6de5c1d,eba8269b,32c2cf41), -S(3bd8fc06,2fe50198,b77aeb1d,d42b9536,7fc172a4,f2528ffd,597799a6,4c0661b,c73a3d92,bf87cceb,f0020063,115aaaed,ecf414eb,f03179c1,86ef37bf,b452795a), -S(aac77264,829bfc44,6c2427ee,8b732a82,3480f11c,32cfce72,35b0b5b4,6749260f,c788928d,b75ea7ba,e216d8ae,91559d05,8597b9e6,3bc2fa6d,276c29f,50bcbe7a), -S(1dc5e0f4,ed05486,c883b07e,e78f1b96,49858bcb,6dd396fd,17a19dc9,a788a1c,ee4fc404,d662abb8,bf7122b6,c3a226fa,ef491513,49231623,a9d1a796,cc6233ff), -S(82a1f055,d885501f,114fc40b,123fbfd9,f45499fc,fb8720a3,c730fe75,ef1a8601,39fdb201,d30ae709,486fbc27,1603bb93,826ca4c1,395bd9a,112ea4e6,476ec20), -S(f8721b28,ea842788,863a1ff0,339ee75,7c508ec9,49e4f4f2,71d2a460,f0c14ed7,761ba386,5850303c,4449a3a3,44ebc7ec,bbf365a9,4688f254,558289fa,5b0715c), -S(9a8d123c,71377193,79d44740,af95d63f,ee954c28,55eb7aff,56707a1b,f0ac683c,3479784a,e683a3dc,c1238f37,5b6ef82a,487f6e5f,df487ba0,10477e45,49652d9b)}, -{S(49e7429b,e0d97bf9,3f17e9a8,53fedb6a,a9bc6edd,8e85f44b,9d2f1469,b2d3b178,ff9e5dfc,2746679e,9826039d,578bac31,c08fbaac,a075214c,73c50f,74568fff), -S(e872efd9,8147527d,7cf1ee62,e4980ce8,f1a7f561,a34ab662,1d503a7a,e98c6433,c8c62103,fe01e381,2553e68,5e7d221a,974cd4e9,f3247078,de37f5b0,1b9ccde6), -S(617f6235,8bb46c55,7608c7e9,ee198fcc,77b61c64,5e953cb7,419375ce,1e06fb58,fcd7edad,db70f22c,364cca9,9a792f53,c71474a8,707e2cbd,551d2626,6b373158), -S(86810c6f,f27fc69c,31d69ee8,4b616345,fc1526d7,9dde9dd3,5e1fe6af,d8fa0f55,718e736f,6c57643c,a8c0aeb8,b8bc6466,108e0149,db197a44,14f067a6,10ca5f84), -S(89aa4974,44ded8e2,4553001f,4a6247e8,bade925c,a35fda1f,38a86f84,b5b6c581,dba8df4b,9c9f02fe,e5a996fd,f77c870d,4e447410,de27d7fd,942e554d,fb1edecb), -S(9d89ff53,d85f9e10,6c78c86e,b114c12f,6852a457,d91aa28a,75f2afbb,e9191fde,7b1b4d70,5beb53a6,84a6f596,e6b22751,28b49be5,2ad37ca5,bed6a952,68880ce6), -S(b21de2d5,767f595e,5b873e39,9c02beda,571cf7ea,48236aba,fdd69729,14e4eb86,1cafd24b,2414958,9812ceb5,1d02d5a7,14f35c04,8a333f21,922e6baf,52942c7f), -S(d64c65fb,627b3d76,135ca1c3,ac8794e7,a62609b4,a71609ad,73972df6,4f75ca5a,6301fdba,278e846d,246e4a54,10108682,7e815fad,d30a58a1,3247779e,a397bbdf), -S(85248d03,5f4598a8,618eed84,92ef45ce,29ce24f7,4476cb9f,95168197,6fdf83fc,ddde2121,e31b1986,6ccf28cb,b1f01925,7ba53c8e,88eb3f3b,a8faef83,274de6f), -S(2ccb22df,abaaa33b,6da3d166,b2f85408,231edf40,fc9f7f89,24256378,7f10984f,35fd70be,fe7d802f,c65e02de,e5aa7ac3,67ca0b20,a5e3404d,a5e59eec,8c9cef5a), -S(3f5c061,fdd98ecf,ac9fdae0,3b527223,319a871c,c385a134,d1b7e35c,9bf5d42c,a1ddd10d,1789d24b,9fb96387,8789a472,96c757ca,99233b97,899bcfe8,e7760cca), -S(2e1525d,f6ae8b7a,84932980,1d4fa138,5fc07382,1a197e00,f9a8c235,68a75647,af7a996d,71ece94d,4384bcd8,60e947a1,cde4ac6f,408c31f8,cd67f0f4,a0807f6b), -S(247becc0,556b2585,9e426838,bd34dc9c,e194ac7f,b4ace971,9ae317a6,d87f5316,bc63b0b2,8051432b,4a6917b1,7afd8b46,d8fe2599,99c8f254,1e5ec22f,cadc8c9e), -S(3b39557b,8f9bdf90,76acd422,c46d1681,f7b3d29a,40108214,2035e3a2,8c204aa7,773f2a70,7e6288a7,9c3efb89,19eb100a,772fa946,c59f0bf8,6796b76c,1d7194c6), -S(d1bb4751,49254987,5e4bba5e,a0d2cfeb,703e149c,5ef6ef14,3f4df5d8,93199e7b,75d04702,60bbb309,73bcda42,808c4cf8,1f33dd89,e5412e7a,bbc6e722,7f0e4acb), -S(2324c1d6,96933334,b3023542,c506687d,8e7b6854,cf0b1ca4,902c8874,39a3a4ab,269c5c10,3731f1c2,419a5b53,566cfee5,a878c33b,c2aec368,b1b60a3c,bfce7776), -S(5896a34b,37869f15,7d19b9e0,cfc927b,7fe0ff91,a173f480,b371d18a,1d72c0ca,ea9331b9,b281b800,38edea52,1ff8a3e7,ab0b7e2,e431e9e,51cff269,cdab8c52), -S(2553f696,b32af6e2,1cc2089a,63439911,4d7b9d96,a883651a,c66f1d8d,1b74dccc,44c3915a,6212f827,3f02a0c2,b2de1e74,295b31ec,d2457da8,faddf543,c9244ffc), -S(131b4dac,25fea2f,715da576,3c175d97,657bfd68,21224136,5da967e9,c91b8ccf,30b40489,73a61cc1,91ec22fe,3429589f,13aad7cb,cbd533b7,2e692f75,f728b668), -S(59d0164f,e8150846,874f1658,3af49019,e300a2c,4807d18a,389f9b12,60585910,eb91680,a580a52,510ae709,1702abd5,6264181e,477c99de,6cfac0e,5533ea88), -S(691e86be,3a30e851,4286fa5,517d1fbf,c9a969ae,d7837e4d,78f6ca3c,e088f2f6,b8108fd7,e5bdaa7b,9d34f1ec,b5251705,76ef53bc,243b864,d20261a2,b9a6ff5f), -S(c68d096c,23f562a2,2ce91404,6b82a43b,22b1e7b2,63e58107,96128ab,a680ca71,c5eae54f,b59583be,509466d8,95ad482e,ef73b8da,808be571,d79402aa,26723774), -S(eeaacf5b,e4ec2817,1acdec98,7b5cb678,91666932,42b4c546,8debe163,430c20da,13e8c773,d867856b,af5b27bb,ad7adf86,a3e4826e,12fb2b9d,504e63c2,2b2460c8), -S(5e3d98ad,35e8c90f,131ea3af,2c99c45e,7ebe6eca,38d02120,c0876a8a,b4b8dbe8,a019fd63,9bb8f5dc,b4776131,398be36c,b3419a3b,27596462,1ecaad5,8a3ccac7), -S(1a43b7db,a042bd97,ea23ebfc,1384587f,4f66587b,1fb0f3d7,c32af9db,449ded4a,89667998,5946f126,34f00e5b,b7f0402d,ccbc8ced,a8389e83,872ad821,3bdc2f32), -S(2222292a,ed3f69bf,1ed2cd12,3272a7b2,b57b2b29,c9f756f6,9fdcabf1,1b67dd57,6f6671e7,d22b9cd5,d70a6490,46101054,f48a39a4,797964d,c4c2df99,a982b3a7), -S(5d5bc560,8ce7cb81,ed23304e,fce25034,8dfd497f,80dd3d9e,193641ef,9358a16a,b63c4202,be581677,ec334ddf,5855e39f,9f8f9544,f9f1171a,7823f0ce,61e2051c), -S(1a669fa7,2d96cf78,886bd7d1,36e7dfb9,8311b4f6,9067f47d,12830ecb,612ab969,e45ba9ee,f80c5a3b,179726e3,4b770860,552b0a6d,6ce02e70,529bb5d8,b2eafd9e), -S(acf341a7,add1eb1f,b5dffb5f,cafad928,b40ff6a1,fc0bdc67,9380690a,7daaafa6,69a7231e,ad015747,60b6fb6c,4a7eee54,ba348bb0,1d201d86,614b9397,89c00cdf), -S(f4238dfd,447cb48b,fb9f6678,11168126,446caf0f,3345ed,a31ba759,3115318e,5cfb371f,296c3a50,6d8569f3,60902baa,35e710d3,619c14f2,3564f6bf,99bf7149), -S(cc328f03,fc2b3590,3b8cdd05,514dc673,1446fd17,3349f0d7,a7a99da3,d2271847,883c8b2a,dca40796,68b0e472,c37ac41a,c91dc5b3,1aa84cd7,7f319828,3b72e2b1), -S(8e9bba4e,5fc87283,fb3a1b71,3b493127,e0c3e5e9,e3f2da4c,51ea3d98,5f3bd579,325df34f,dd64edd4,880a8ca4,5bde671b,af67a76e,f1a5a27b,abfb42e,c2b7d29a), -S(790ccd03,fad172c5,10af246a,a6e4a87c,56db01a4,55b4bf11,8670e5f6,54b0f816,de872f4,63083283,536d6943,ce8c67b6,6476cd8b,ce802fa5,e0817c5f,7ab684ff), -S(feca35f3,f030cc1,e0cf0a86,3a11d035,95b2ccf,7569dede,1393cdaa,a972d1dc,3fa066d0,565406d4,52aefc9d,ed45133b,48933d79,e0a25533,e9a24d98,f608818e), -S(c6b38388,cb66141d,777b3d50,c5224c63,94e587b7,9b62fee1,6fa12c9f,d7771d66,3b9647e9,2ab35770,e0116e36,27a31526,ae48a595,5d46b7e9,b27e5747,c066fd80), -S(db412fb6,3f925c6b,62ed566a,de8b4768,f3c0be38,dcd165eb,eac7a081,fdcc43d7,fc305dce,74f64672,2eb963b,792f312,4b5da5c0,ec8c47fc,254648e9,e562d2c9), -S(777f3e29,83e8511d,90ec346b,1cf6ecef,4539889a,c124da88,337dfc6e,222eb810,e0abd8b1,fb97b582,27beb723,3308a89a,9dd5cfa7,303d06e9,2c2fd427,ecf3741a), -S(a8391b7a,3c3e788e,724e373d,821074ea,b1768e16,f3cf7b63,80a0f9b1,7a1b8fde,f9feb354,ca45cf5,fa10eeea,1b4f4936,2e4ab403,622cb470,26f529c4,69f61d59), -S(1b86c4d4,40532e3,968ddcd6,2012e455,34ba0045,82409c74,add1797a,fca29640,2217842d,fcf1d171,b18a57c7,1ed6d329,4491a422,45e93958,570fbf81,9e6bcb41), -S(65e2a22b,779056bb,6f7ee1cc,efd63066,e5cb594,a9496d6a,772c4e18,f2cc7d48,8adb10e4,e984b024,b420ae65,d2dbc7db,2c12b4b5,65b7b81a,434d16cf,52926238), -S(c5090c8e,ee079598,57b8bd0c,fae29cdc,e00fef57,49204908,cee6a5ab,1d4fd970,fd7d0324,fe41fd86,3b103e61,a391ee36,167af582,e07c2cd4,649d31b,86e6c976), -S(be9e98cc,c6a230a,3e63ae7b,f619d6e6,b27253a3,5f26648c,8c3f68b4,e193b24c,d32895af,d8886f1b,9aabedc6,9a79fb9d,ca71471a,97728ca,1a55e701,e7d5bcd9), -S(2ff0dd75,8de2de40,1ba00665,c251f6f9,e342265c,4a400684,ceef256e,7d6305a0,adb558ad,61769a42,3dfb2d3c,c44da3d0,15a2aba9,ebb4e29e,70fa7ae,6307f4d8), -S(5dd98c43,caea001f,75846c88,1a39fc77,cdae9882,62cac6db,f6160aba,f00c8d51,2cd50bad,48c1a136,9a37762f,e56fec65,8a8a3e36,90813d50,6dd94fb7,de90858b), -S(18280710,c4d14765,b473cbf1,567dbee7,d53a127e,2aee22d3,198dc5de,43c3745f,1c8e417d,83b0540f,fe800ec7,1937f855,a1066dd8,4f7f6a06,9722ef2,e2ab4bbc), -S(7f3fc319,62da2c5f,9e90a8f,308f69b8,d17497ef,7216a5c7,228ce9a4,1b35bbae,ff754dc7,ca0d3148,96b18f27,c516fbb9,d4d21cf8,48a61f0e,4bf3cd60,f3b1e7d), -S(96809ebf,3d08f713,87271a1,762c9d9c,17355ce1,be770361,e69506ff,f9bcc41d,412737a9,3b3d1835,cb487c78,909ccc46,624f8335,46eb168e,bd8c4408,44bdb4ab), -S(9308499,72dcf389,d1200b32,6a60b0be,72609de2,2a66989d,17c97f3c,e61f2769,fd307c40,3c29d78,14f7627,b7575ae6,40bb77f4,89272d91,4111e1a,2c81abc1), -S(a66a4d1d,1e2bf54d,b359db03,a339c40,4e0cf102,88dfa02c,da95c158,74057754,16d1cf4e,79d00675,cf6dea6,7d8b6c2e,baf59eac,cba2bfb8,e30ac368,ef875d5c), -S(4571f513,f3b73e0f,a7ca0801,30d6fc0d,ae8fe66a,3caee9ca,807177e4,40256f28,8849186b,79fa99cf,49674ed9,9010bcda,7e2458bd,bf259bf0,30a3b655,61b88842), -S(28609798,fa0a5b48,f19bc873,aa62da70,85c8b9c,271b348f,ada1ac16,a0013bcf,9716c9a,493d484d,f6c588c1,aca279be,327e59f5,92a04f5a,840bb7aa,34b407d9), -S(77b7e18,e37c4a78,721b28f5,1e6cab87,9c4149d2,92fe9675,fcc22df4,8dfd6465,179a09b5,2733b042,f702d649,4b2742a7,ef82d050,efe0992,4584d6e5,328b14cd), -S(3c25bbdd,cfa0ab2c,cce10476,79adcd9d,bb63595e,8a7bb841,cea608b6,82c71f5c,7a01946c,b0e650e4,53dce44b,eba509cb,fdafb57e,f130e4d3,facf9ebd,6d7886e), -S(c22b973b,99f9b4bc,90fc9e0d,b2d73c7a,7f1051a8,d19c474a,3bf9aa43,3b0fe52f,e0253dde,dea6cd0,1507b251,176562cb,7f73c22b,b7d10015,61fbd723,4d5eac80), -S(18c7f4a8,3f7dec0a,76dae14,3a49ecc2,4d5fd4e6,5880ac51,627c86aa,60a8ce71,978901f2,3d35e23c,36dd34d9,cae08290,641163a2,c55c3028,11fc4120,4a35653d), -S(61147763,8a8c8924,2fc31730,2e0b1475,514025f8,dff26b1a,eb4b7f28,51cfa5c,23152003,f2d12370,84ba60fc,bd653aba,37c6b20c,18c85c62,b6ee196e,2c684d5), -S(1f025444,17e67747,ab9f81b8,7a960663,ef3effb0,259d1795,f25c0a4,96847292,8d7ed884,5cd4cb73,27d31f87,ed6f881,a0de6f51,768a5ddc,b404139e,d064fb4a), -S(90493828,a1633ce5,8f962a78,2256d6e2,949f39da,9a865dca,d84b3e46,408d7b3,4c6bd158,92330e5d,1d97cf27,fc8e8fdd,99f39bbd,7ede306b,336530fb,2d46e51), -S(ce69b160,287b6724,8a11db83,418a302a,daab31a3,9c45b5a4,a02643fa,21918461,617286d3,c223891d,c86a2bc9,5727aee7,3016650d,cacd6692,c4e24a7,69b86701), -S(f20ad3bb,1b962fac,3d9b2c08,df726791,706b3006,60f894ae,379a6c02,77e3e8c5,fc83a778,44e35741,81dbaf95,de91240e,879ccd42,5c28a389,a01943d6,a954a5fe), -S(fb535599,ca57b6b3,94205071,f1c07afb,ace578b2,5d571bc3,1f669a8c,2345d7fd,b25fea48,f9f36d15,feb50f75,2bfa03a7,bfbbbd7a,8de04ba9,eb58d6f9,e4a77c1a), -S(c3793655,c789792d,e43a07f9,61d774d0,34253bdb,31c3428a,8e941731,6cfe5565,748af2bc,9459b7a9,cefee955,81d3716f,2c08d5ef,f988ef1e,85a14290,3fdd72dc), -S(34304c83,9c33334d,216d1b4c,4808d14a,f5952d45,9b8cc1dd,5e64c6d3,30807110,82a01c14,95639827,8c9a0189,5b0d1e62,572b1ce3,565ea53e,9afa8d27,36b17c75), -S(8100ba8d,43d8cf1a,53f973fc,544804c4,4c2e96b5,9a877496,7a7c4f57,862a0fd7,675c2c52,5de39794,2c42babe,8a3b8e65,1c1aba24,f2da644e,a359a0a0,892e983f), -S(b3f979e4,487081d1,44161dbe,37ef2da4,de16b9d2,aee1ca13,9f018e36,d4ee64c9,bcdfdbb3,e6cec91f,3dd41871,9fae4213,be273923,a8daf8bf,919c0145,11a93969), -S(df0ddb93,e54b94e9,cc7460ee,f14f3512,86bc8f0d,7b928a6,294f8ba4,2577910c,b640541e,b5958814,e348d634,faf04a02,3a38235b,2250eefe,3145bb40,64abecb6), -S(54a2cfcc,eefbd58d,3924f305,2bfdcce7,508e7d82,e82cf354,9a4f0141,52cb717b,17d80293,d00c0d82,47013168,24e6138d,1cc77672,7a05ddcb,909642b4,afb88578), -S(fd384aff,fa1398bc,1881dfa0,d8b72dfc,3f6a4429,52d301d1,53d8bf3,705b828b,78dcfb76,f958da03,dfd7f6be,21f36e7c,59c7effd,c4e9a305,b934e9da,2b30f684), -S(bc7325b3,181554db,1e19f120,b6bfbe0c,8e4c003a,461ac2b0,83269e23,12d3395c,c101647c,9e2ccdc7,7ad89913,699b3b42,5850e30d,e52995ba,7985f73b,db6700eb), -S(e9ed80e3,9ed744b2,1a9aaaca,1ef4959f,64ab312c,d7cce151,cc6e383e,dad0185,ab101dc0,af3ef33f,9f0d6bd7,4ab4e938,25e999e3,4730a9ea,4ee67b2f,4f0cc790), -S(8f63fb71,67716f8a,749439f8,25f2ef87,3c4e3d09,6bbe06ae,2aa8bee3,faad24ce,76d6652e,b0845f33,42b48ac0,8b2d70a3,9c601e79,fad31dd5,6701d729,1331a5ae), -S(8ed0dda7,5d3a1e9c,8a497ccc,aa3579fd,ca5f8628,239a01ab,30abebad,fc6b3476,6f4a70a4,54d8c0f1,4bad62b5,b9aca8ab,846c4bea,565870cd,28f2437f,907269c2), -S(7c2d0104,3735fa17,5deac20a,5997c20f,748baa84,75f7492e,d4889de1,f6666f2,236d1659,54504475,7677240,efee6bbc,559b64b5,96358ea7,5dd1598,f3e7fa6d), -S(d37272e9,a4bc1bac,edfb2131,2f66fa5e,dafc83fc,39ce55b5,66d7b395,9aa937da,111fb684,50913dee,2c6a1a0a,7d7092ae,8db98713,90a87a41,4ea52793,839d7492), -S(db8375b3,c8c574ca,a8d66487,13467abd,793f75ab,47daf5d8,67f9018f,901684f7,7b23db42,56ae1546,31e11cb1,37c091d2,3ea5ead4,32f2038b,27e46571,75526e3c), -S(d077223f,149956aa,1dfea1f,35f1b237,f59809a,8bb0e78a,f9bd9520,34867886,71fce205,bd0b6728,766da89b,55168777,b2dbd672,ed8b391e,97e74d25,2ad028a4), -S(1deed30f,7b7c1a02,eba5d86e,eb1e055,9c776d85,e264e842,8489264e,4f68c907,a2050287,d41e8218,9044b3b1,bd1e4c6c,3baabd0d,370d6f2a,d39676a3,ef4c672a), -S(ab0be6cf,57a6da4b,f6ba7963,aeabd62,d2aebba9,acbfffd7,a18e2579,c137752f,7d6c1113,7535c914,dc58a5bf,a53a82ee,8493ac83,cb1839fb,badc6fd0,4575b70d), -S(3c72f165,69ef77ef,a32347fd,d14e7ee4,82206c3,1fd9bb9f,367fb84b,9abb5d06,3f45f3b5,d08ab10e,1785f62b,20f2efcf,2a6b104b,cea583de,89c791c8,e2f732cd), -S(b0697da5,6030bd3a,ec311758,fbc0f56d,90544123,261eb75c,644b37c3,2f888601,50652a49,a3b7a325,67211693,197f136b,f38102a6,954dc6e3,c8325303,2378d6be), -S(906ec5ce,4273798a,9350a79e,8d64970b,3209033f,9f7c56bc,75e2b3b6,6003d338,a9a0a4cd,7c512984,ee4d1da0,13476077,80c664c9,8e0a416d,856dc7de,5923c702), -S(64b6c18b,d207619b,35f76f3c,f36b14,7f3dd79f,c0147536,25d7566a,c0350a7f,4226dcfe,f3af6ef3,40b883c,7d4bd1cc,f9ead936,d1d42a1f,59e9754c,23ce3b92), -S(b1d0d916,e6908910,1e5262e9,9ab94a46,e0a1db5,45b9c572,3dd79212,4afb34fe,be9d6c09,3c1adafb,5e8cfc25,5328a31,aa7daf65,74afd3c3,f5256ae5,33f67570), -S(55fa9d6a,d8005a2c,8889df76,6b3bacc4,dee487ca,e65a036a,9b1839b8,2a0c3c3,cfb17a06,2a9edcc7,88f5ddd8,a0f12211,c21877d,80c9f30d,cde71a8,af3c10c1), -S(c231d95b,6144337e,b25cb40c,65d6601,cb4426d4,b6d7c6f9,9bfaad11,611a1854,b0b1b6e2,4bc88bb7,a277a3f3,bfa74b9,9b1eb5fa,a16f4a7,e40f9ae7,629ebb65), -S(b6053327,960dbcdf,f13842eb,c50cf09b,d60cb656,3e1553a1,7f7985ef,7486afd5,7f195737,9ed11b9d,7ea08068,c6dbf3b4,36eac86d,2efb81b2,99f89854,65766266), -S(8ea8e96f,619bac9,c6805dd6,e8115858,50b80cf,1cd7fb59,e9090316,c9190de3,92a305a6,8a1300fb,64eff4c9,fa781270,2a85a71e,bbbc7910,a90eeb87,8b50036c), -S(cd8fe341,ce670725,22bb9043,f3e31f31,3bab3052,d1316da9,7e96bebe,710bdd8f,3a3e6072,295bebd1,7da2462c,8ad8cb3a,2c170c35,9d2b96ed,d805f0c7,fcbb4ae4), -S(3fae13ae,cc9b0b32,37d94c65,f769c57a,6265f37c,7057295c,dfbf9086,b27cb599,5baae4b3,eea7ac21,4372748f,d8b6b9f6,24755dcd,b92cb3aa,63a5ba6,16b88a97), -S(7b9399a9,49077156,b32b9cbb,7bfd9416,c6468838,c87971a0,d9e221ca,c8e4cb25,504b1b97,c7f32154,f2e5664b,8c180f96,a51783e,c041fd2d,1e8fe493,26ccadbd), -S(8ab4d5e7,e112d259,30e2b4e,7ff4cf77,b2957e10,fa9fae5e,a2f80940,8200e511,6d0328a8,69bb9ac0,71b6a4d2,939fd4ad,34066606,1c3ffeba,1500f831,8aceda6d), -S(87acd768,24a369d1,210fc798,69368ad7,fb01dafd,f5ead811,f5d03169,ba270d4d,8b9b706f,15ebb721,9654eb04,f846d1f4,49a6979d,53dd03a8,214fc285,c86baaff), -S(f8179003,b5a2ba0c,ae5e7c33,90f99da8,a1ee813c,c5ca0d10,c8b849c1,42ed6ca8,20710e6c,7ff5e563,36855a43,a372fd00,e7bc7f97,d7d0ecd0,f7a63641,a96b2c8d), -S(2a2b3fe7,d2c78d9c,3d62a9b9,202ea02d,e422f14,23e300fc,70cd66e5,ddf9e69e,ed122cc4,96eb517b,fcc5b393,8fc97001,194c3c92,f612d062,95ac6f5a,7d69ca3e), -S(aa80d414,e1f91e31,73483761,a8c34490,202ef4af,4b39e6c8,8726fc29,d6f99a39,7632d7d1,e312af35,7ad03c90,a5ef9476,cdd8541a,ec03a0a1,b02d8ef2,fa380245), -S(2e6f7aa9,193b67e8,c00703bf,d7ddea0c,199c857d,90d03571,2b41ab0,6b074d98,ee2dd743,952c47ea,e03653a9,22bc1965,6783beb1,76afef17,36bbe2b4,3af27827), -S(d3ec2365,4346428f,d38153d5,eb6f82b3,409baee4,4bdc1c6c,27b198d9,b9403d23,da15f943,6b0ec0cd,c4769650,8da28a12,32409c80,4484b395,40ca3beb,437104ea), -S(54500eb9,33d4fbc8,d8f96e3e,dbc93e47,a91b799b,510fe73,61a507f,95973a65,277be627,356c7342,56b97d1a,87f733e2,10531732,6eff535f,6ffecf48,ce635e9b), -S(b3543a2f,b3898a9f,64eb2863,7bb3a33a,82631cd8,d1e41b22,7ffb268a,d6710bb9,383187d1,bf8afbb5,dba13d77,25327d40,5c363bf3,f8e4a13c,1e259b16,c7dd8e3e), -S(7614313a,176d1ddc,c28147e8,39d54d78,5a3f42e0,5d7d436a,3be2c1f6,b7ff3606,d540b46c,d87f555d,fa8dc374,8f1c997b,5d4c1c52,1675bb7c,4e3a2d15,8c1e70e5), -S(de1c503,447eae30,e3fb1ea,bcfd108a,cbfab506,d52bc997,b1c124f5,b610af17,3b7d0b8d,e4e1de4d,c17c00e,ac0727bf,f41b0730,2080ea3c,9c18bf85,9608423a), -S(47f2fee0,8bffc7fe,5e7fb417,70ea71c6,9a30308b,cea4ebc,6b2861bb,8aa94a41,31659afe,6a09292,da939f3a,fc89e4fb,3fd2f288,7b6efd49,ef1df90c,a48d6e3a), -S(824c2c6a,f7b9f3ff,a1dcb278,ae2bb3d4,d7112ae1,cb66d524,85c49cce,35382572,dd548e84,3ac82ee5,9004320a,db9f728b,dfa0bfa8,5544e55a,fe8518f4,a9350006), -S(af4482f1,1157be70,14eb09fc,80bc1857,43ee62bd,376f7df9,f7507df2,34f6881,ed2202dc,182c188,3dd864ee,77b51deb,f8d048d5,79993a77,3fec978b,c880fe6a), -S(386c5a63,2e56795,54c53c2f,824bdd3a,c8c22364,612efef5,13942da3,cb8cfef5,dfbc9df9,f1666b9c,54f02eef,d482e71e,c33aff7,3d8c1025,7ab17b19,57489127), -S(5cacf202,1b442903,333796b7,d9d1a8c0,a8a26b00,2ab5cb3a,b6c7a5cb,87ea778e,e522602e,41b4b90a,cd6c121,4959990a,d77f3f9b,87862949,2c4119b8,54e31cae), -S(3a783ed,2357399e,8cd3c67a,a2e1f321,9900f6af,368080a6,7f18f6fb,c5442e65,d23403f1,474ec6ac,5071d084,2a05a58f,826e4418,c19451b2,b60ba182,777290c2), -S(fb6d745f,a0bbb00e,f92026a9,f216d470,9090649d,5e761f37,6e4dd81e,51c84954,39cb6685,c0001c34,1d1d5523,55bfbf94,5a97446c,593e0518,baf039c2,368be918), -S(12d8154c,ed08bba9,d6be85ad,42305603,74c82c2d,bc06d80a,2199d3ca,e113eb96,90cb6ad,3b62fcdf,d0d2f3ee,9e89f7d8,cc314d6a,bb22025a,876f4001,21a3b4a5), -S(313583fd,66ee564,f546350f,22ab1324,fbba2319,ef69cc81,6c4e9e0,26b3367,dcda990f,b4f2de57,72d6fa51,36da8215,f66d189e,dc91a46d,d50ee2c2,3398d21b), -S(d27b50d5,30a6a777,3e81ea25,77682a21,a6055afc,4bf05d1e,f0c1e5ed,a432b6da,f2a125b1,abfbd478,74b1b1f9,5d03ac5f,24610d34,d8b2ca9b,90b30c63,33dc9214), -S(d78933bb,d228b9ba,9332a511,a6d4741e,a42ca4fb,2b79b6e7,1d4f34ed,66a57e5a,61520901,c37fe630,35a0a80f,86e63939,133ec632,41f3daed,e30af5ac,2f470778), -S(a737c959,b9f386eb,e227f5aa,6cd83868,7a911290,e8ecb6e8,d24a3f18,a1171965,6648f272,322bc673,f8d4b877,aedf25b7,dbd2bcf6,bcbf3fac,ebdcf2c9,a531b149), -S(9c2033cb,d00de2ca,f6a6280a,fbb615ca,f0513816,aa12d994,e0ec0c01,37b5025f,1efcb986,dd4d223a,1fc4a7be,58bc6f3a,76b02646,c23a0c7,7f174a06,c75928d7), -S(75b51376,1d2555ab,87027458,d6302f77,26434e84,ff7bb7f2,43b5a6a,7afde413,de0d1bfe,37af2be3,302fa887,ea87a678,264534e9,c065df8,b1f3e326,a47fcf4a), -S(79fc6858,8d117c83,8a8b8134,c8071d33,2245e6b3,6107e1d6,503c3436,cb00dc8d,78d45ba9,69490bc8,7ff05b6f,2e6f8be2,8700216b,db76b74f,dbf4577b,f6169914), -S(de006398,1d8914c5,8702699e,40486195,a6647110,2b6576b0,6879b41a,207b6bee,22ac0aef,4a565e1,f159f6cd,5e04c68a,22e80d1f,f946aea4,f5127fd5,8707dc78), -S(db714e6b,52d32de8,43cd649c,a39307e6,540c048b,e0542b19,cefad32c,a9b435ef,d1ea87b3,ab9acebf,3573625d,b2f58a73,fb3864ac,369ca451,49a42262,b1915101), -S(25fa0fb5,af46c0bc,75b4fe67,fdd53d51,2303219b,38448403,186c23d9,7f7b6242,45985834,a9766f8d,9ea9dc82,3e6d55c0,75393446,f38e3e39,9b2b7b9,d6b34f6f), -S(acaac641,852406f7,69e19429,b1820703,fcedb664,407a5cce,8d96c779,c1e51edc,1bcbb918,88be19aa,4f02c320,4f18effa,cfc9c376,ac3dde0f,a529123,7f715cb4), -S(3674eede,62af1a60,77df180e,260a2d02,db43b440,b1e7ac3c,4ff368d9,8c3d8ed2,d0a393d4,7f953a8,fad2e045,91c62914,14b7ef2,694cebee,6a1c84c1,b8e19888), -S(f630a661,e54045aa,54a86a9,386e0466,a7428967,43d483ee,72a87d5e,34b255d,4ae7305a,be851491,83b7dd6b,f9faa5a3,8c2812dc,96475a3,87906759,85feefa2), -S(6b191486,9e262afc,51a94712,72b4765,78337a00,3556aa96,52acb8dd,36f1b3d0,853d994f,f728cf33,85990b39,d8736d28,faa0e8b8,c8b7c5f1,693363fb,6c842ebd), -S(c9fdccb5,be931d35,5e3e4baa,816d6cfa,7af441f,2d6b653f,d0fc90bd,c7afc681,d2d0190e,c3360886,b2b3d3b0,d8e05211,84c8fa05,b912a105,374325d3,75548908), -S(5e16743,c976a908,fdf3bd1d,46735de9,f3446673,4af3bd3e,fc6382f0,d834b500,3a8b87d8,28d99eeb,351186aa,23b76376,682ab598,165d7f4a,1c40d8ec,62840a3c), -S(67858166,15c4c7d2,f1f2da88,1aec2147,d51ae770,ff2c7afe,e007e4ce,a4faf4b7,74404a26,5f0d41e4,6e1f3bdd,929f26c1,f80b229a,18d0d3d1,68e936ac,e3447266), -S(add083aa,fb71a217,6ef2b08e,8bd713da,27c5cef8,958f47e6,f90dfb6d,1c1bf122,b835f39f,27e27cf,28f45ceb,7c26cd60,691a89f8,650dff32,44374957,c412accc), -S(5b0c33c3,b669dafd,74c876f1,72357a12,8117c8b6,59dae930,fe2310f4,f96a5d2b,6aa36784,3a973f6b,6a03faa4,b1226950,f348b6fe,e19f1c48,f4dbcb6c,3a141618), -S(5ad43f2,62f9125b,55a419bf,e6ff2a04,4b09460f,fe6f1a26,d8ab6127,33d50301,701ee81,dfea7250,fab2f190,63df6120,ce47500c,debf7371,49772e84,cc53d54a), -S(8b78adfa,af8d7d08,d1c24e36,1623da1c,659dcf91,dc51922,2e689267,7277c05d,3a0cfce1,3c25700a,9b255606,f8123a00,ffbdc3f6,8eb3fa88,cfd3b478,e4ed0fc2), -S(679bd899,2dff3884,dc680a96,134290e9,3c66029b,922706e,54f3827a,383a9e17,2a70a1b1,948a3c01,f5b9e98d,54069cf9,b5a7dfe0,d7ce12cb,731b1fa,83a8d54a), -S(6b82fe,fee6d419,b66b29e1,88954e32,6c426a92,bb539779,1bf562f2,e06fa73f,918f66f0,10980d3e,b3d62bca,d37074aa,766bd449,cb07ac04,5ec1aa25,36b258bc), -S(a2174424,8125296,680f8187,493e18cf,41501fea,2d4de1c8,25b048c1,5ef63cde,2cc8623a,42f2c485,7832e98f,a0830c33,7b873166,7ec7d7d1,f560a0d,f2f35b36), -S(e5c0134b,90cf3791,28515ea7,4a1a8be1,1f35c98a,74322879,e6144f0c,7c74ca2d,2e6b7b85,ce459368,cb2e0cb3,a3291d2d,8f1fc947,2df3111,87ee6832,3477d908), -S(d44c099f,3388ffa5,6dbd0761,814cc46e,c0f0950a,869a4fcb,af3c0022,f3bf3618,a93be4ea,b5e7b6e1,b3085f3,85e348c6,aaefff99,2c6385d3,c6b941a5,306f3940), -S(85c3c19a,33794fae,f400eaba,ddb4f122,64888604,ad1096e3,8864a304,e2c07ec2,9100190,4f8c0961,50d300e7,897caf49,c3869abd,ca59c78b,504a78b,cc313d46), -S(8398d41a,77875b8d,ed646346,c5d24772,d1b13891,98c1a196,c6247c87,c7d7b8b7,4fdba1b5,9a2455e7,5fd6a3ef,83def66e,74361e5a,7a4e5143,7e4b198f,329db7aa), -S(eaa31564,d148b856,be888987,4f4b7442,38fb849d,988bfcc2,acee61a6,adedb93b,408065a,a219f9ff,395bf932,9b172642,181495f8,43900489,9423ebad,3dfd0382), -S(d2c6b904,a0ab1acc,a12e5e1,3e794364,cc7d3c25,b53b7bde,812fe296,6fb23626,85a2ee1,df9d42cc,f44e327d,62369563,74fe8e73,c32ba9bd,153d833d,6af8cff7), -S(f00854d7,742141b8,34d0c2fc,76b73993,a9f92f1f,256b1865,e9863989,cc5bab82,3346d28,63813a88,f874c5af,eabb768f,a5621abf,c57a9002,965a597e,1f7632bd), -S(207635fc,7364852d,15a13254,9f21196,262a1535,bf6782dc,3ff2dab3,e429f9b6,ffbab84f,ec05fc12,63c6083c,7192f825,987b6f4f,a1a9ec5b,e01e1374,652700c4), -S(3cb8abfd,a8a5556,15252acb,c538f91,a8dd2523,a3ef5805,23367641,904b0fd3,9715d371,20f86a86,b98980bf,4c9fbed0,cfdc2e8c,fa86d60e,9d35222d,dbbee8e8), -S(8dccc315,1f8cba9e,384cd23c,c941a3ba,5a11be94,3af2000b,18127932,9f276291,6de7b0a9,49487cb8,6adad7e9,bfb0df97,30f460e8,ad19dccb,7b7e9a79,57fc48b4), -S(4f0780b5,137b113b,b843e566,9bf5dc39,cfe82b2,d6f61d4a,76555b56,9c93cb6,14de9aa8,8e7d9cd7,61f7d08f,41c4c92,f57f6a7,266e878c,cf407bea,11b9719f), -S(d2005b24,71e3e622,1ca597ff,9b0a59b,7eeb558f,5103a39f,630f7a45,85500810,1bf3440a,477786ec,27dad5b4,5d219403,9cefd000,802d0419,df34eb32,cdda121d), -S(4b4d17f5,c1f6b85b,60a1e1e1,a9d1ebbc,dcdeb1a6,3d076dff,541950bc,23c347d1,f8ffeeec,e591cb04,21f97aa4,f016b59d,610fda19,34470b9c,67248011,8f07332c), -S(a4d4b2c,5cc168b0,a24f2b25,4710ebf0,d5f70a4d,569a966a,cb8e1f5,2c2b7beb,f2307744,f8634646,19723122,71c7275e,2a2ffa6a,3a227294,122c8786,b6941609), -S(2fd89831,52c10fd,faaab8e5,dfdcd737,b13a394f,4c924adb,b8aee90f,2bf5d1a1,89f91750,69d4f115,d3e3cb99,4f1c298b,9de9f312,74d18976,65238a84,dd5f92b1), -S(2b66ac34,a669780c,d779423c,17e7a26f,f19cef5c,49919fc3,76255ddb,62c5e2ca,13b2ef7e,c4fb5fc,93fa016f,381dea3b,cbaa9c90,193b3c96,c1a3d86f,e2bef8c9), -S(1a1dbca8,b710565b,152f3886,e4793f37,36095569,2e782f1d,3ea662bf,87305c27,5af8c42f,99d74980,baae2dac,a58c2d05,718a0abc,ce40ab54,565e7452,69d7f0dd), -S(5c85b30c,d201e36b,c6c9d70e,da01a999,3a4f24c8,ea0e03f8,226eae2c,877538df,15ed51d7,85ebe78a,bd000285,b64685e7,98bfa397,40ae17b7,f1ddba98,a90ed521), -S(dc5a2996,fcbf99df,257b14f0,658725ec,184f3411,9271fe9b,9da19708,6aa487de,45ca8e07,e82cd9de,8dbbe106,1ade8c62,846cdbcf,85ed5b13,e51d1680,4b1e3a0), -S(ebcb525c,747d5ed8,d877f3e0,a632fd7b,88f7f894,84e16ddf,6cd8ef6b,f5925dcb,64a4b31f,50fb389f,cc92640d,c7aabfa4,189e46dd,15e7308c,8d7c551f,789aa33d), -S(a63c01fd,826ef945,43243395,2344af73,9bc5ea53,3b5e2e6c,2fe64b76,58f89238,867fcca3,7e861b09,4ef2f151,75ac0101,36cead9f,67b00d09,a50a94ad,453a1d69), -S(fbf5906e,e1e05f1b,850cfa93,34b3b230,391fcf13,94791696,fc63d6b0,71c29c58,61290a35,410dbe52,f64b4b4f,a5dba1a3,23c98bdd,f6dd7957,383bf40e,ece088ac), -S(b9d3198d,ed13334e,1d43b7a,e909713d,af368d88,a62db5b4,1552ad31,7325e249,4ce0e6b,72358d03,4375c5d4,633ee51c,ff9e453a,4ad7e88,9dde7d51,83adfee1), -S(b928d409,365d80a8,e7b3e61b,1cc2976d,c1db6158,a31be035,d1e9a8a8,66e976fc,ba4ef615,81b4f698,f653dddf,5956fd95,f6a55cc2,618c0d39,c3c789f4,61be8e7c), -S(1b4fcf81,5be7ac87,60582a9b,39b62317,4c72e043,48dc6f17,caa6fb5c,9dd46d1e,c845031a,df207d9e,3e006d11,880f5c82,50d225ca,8dd4d3c7,ed0ab170,5bea9b4e), -S(7f33cba5,c5391f36,b5d1f186,50220df5,cb79ee4e,cd1ef5b8,2b2d8280,394b7d68,91025af3,68487978,1d88dd42,f4746c5f,7cda4733,141c003f,ee4fb1fd,8523141b), -S(986de6,fbcab206,264c34ad,c38a397a,384bc794,b03e57c4,e3f0d253,fc94c3a0,b148492,16a7623d,d23d76f3,9cd22603,a88f81f0,a2351dbe,b825d1c1,6d46ad81), -S(f9d3cb99,a0ace3dd,65eb373d,24b3c05e,eb995a5b,65891ef1,3dcac23c,4784f224,3f94c6cc,95fd7fe,63c97138,90c031dc,c9361fc0,6ec5caf8,2e392c1d,b6fa6058), -S(44b5b53c,9da33493,bf040994,d195f45d,c9be8284,4d12315,4b782a98,b45383fd,7dc44fd,ff6acc88,9536ff19,4d28d892,d1e1fe0d,5d59860e,b58e6283,88a0fe8), -S(90db2c94,39ec0476,576de7fc,e6efd4d9,4cdc5052,56cf030d,ccba218a,3b3037fc,3f243dd4,4b9e8733,1548c213,9728de99,b520d31c,876dcc8d,ddb218e0,835e7f8a), -S(2369f76c,240f538e,ea7fe150,3c753bd,b41f031,5f703d3f,236745b7,ffa1f7ce,df31a9d0,dbda6762,ba904f41,3f46ce84,419a6734,56c6013b,939050b6,5d4bd15d), -S(67ded26c,dd7da1e6,d8373706,7adffda3,3d9fea3,8a7bfb87,5ba7d6f5,96ba65e5,73c5c136,d53162fe,35e5a3de,4190a79e,cc181f23,b5367ba,7d237903,890f540c), -S(3bebf79c,fa918ec9,2fda707f,800af057,13fe0ec3,efc1edbf,b9fd5917,1bee00e9,39783b0,bcae56a0,33e73001,e1fb24c8,c708c74a,fcb42664,53962973,d361f8b), -S(31cf34dd,edfeb1d9,674a2de5,11d7177f,e054181,34da2b0e,dd955c52,67eb605,659dd41,89c1c195,6dd21c44,bb37c910,df2ee864,aa5a2a61,a08a9349,34ccf9b0), -S(86439b3c,3d830a79,1f5cdde0,35821955,2eb0772,f5323278,b8baea2d,5afdec0e,8e5b5552,e244a208,6d5fc389,4965e367,77395e4c,d88b0c6c,ed513dbb,58836e0d), -S(a7041438,d237f957,cd3423d4,70bf34fc,152d1823,c389e5d1,d700a5b6,34101b4,aef966f8,c9acd2f1,625bfd1a,712d135d,c8e0f270,3fde3ee0,3c6d274b,101c26c9), -S(8c29a32b,b154eebb,a17eea82,9605b681,4f728f1e,7be0053f,139f6599,d2a6b023,a9813842,6c2ad3fc,e157de97,69caf8cb,f2db0618,b5f307c,200414c8,2fb4608c), -S(ede37b46,82448954,d786bbb4,874a61d8,dfd38de4,a7968876,c0585cfd,95ee04ce,3b9bb92f,a8e8b6ed,b30cd1cc,5225a80a,53fe738c,cbf6c2fb,4afdd6ac,7a10cf53), -S(e5cb4478,e91d2fd6,26950da6,53445dcb,5d591ea7,5915e637,3d82f963,f3ea6a2e,dda0bf97,cba5a77a,3051a09c,7d29f91a,3b8b1b3,c1649ef5,23c692ba,18cc8906), -S(e85f3a7e,cfbefff0,f3ad866b,3838208b,81d8c4e1,dd2fc809,8149f56d,e4c90aec,732a7905,ff3ffe33,d05738b6,1e6c0f57,4c1eccf8,e883a75c,76e50079,b00a9799), -S(79029c02,c2b0322f,2bf76cac,4b5f8356,4ea652c9,3ffeac8f,7f7882b,e772cb80,3e630bc3,cbf85752,f90b6312,4b9bebfa,612337d5,efc8a0a3,157dc666,27020f62), -S(9b827836,a74cdfe2,3dd8adba,542e13a5,c8e413a,cbe32695,b77fb140,8ce640b3,66e4c425,7d99f9cf,d9d6a18c,fd40e7c3,9fd37363,b0228206,f3ecb699,d6b2f2be), -S(bba7b2b7,facbfe34,b945ac0b,9d609b0f,3f0adbc3,eecf16ca,ac54484,dd564c6a,3619817a,1304fe3c,48272292,5d911d7c,ca33980a,33ddf647,19eb63e4,b7a1e6ce), -S(579c9681,cc98eda3,684b5d4,7f1ee3c4,5f8e7ace,c620509b,56f9e116,4bc905a8,48bc6bf5,90bc2d33,937df32e,a082102a,2f19a6cf,6ebf0985,6acc53cd,b2933d37), -S(23b30759,4b171e8f,ff9de455,f5eea514,e4c49e82,6ce3bbf7,6d3e750d,94c4fb8a,df57c655,45cac843,6db4dfba,abfac03e,a0489ead,6fe4dcbd,d12c2d2,21d8df8b), -S(8b4de9d4,f5c53178,aef16a7d,73429825,9e87e3e2,7a803197,98793d23,4c4c29da,a66d90c4,9d441721,3a399ac8,2c84baf2,67569201,3782a5ff,b2cf55a5,7deba029), -S(396fe929,2dbf359,ad3dfdb9,58e7337b,fe8791c4,d2ab6dbc,35d8c436,c30eea03,69fbad37,4fa06b57,9f67d8fb,48a6f09,99b77ba8,5fa7b6eb,96ce1028,44fc5371), -S(56acaed9,34f376d2,d036b7b4,7749829b,f7d32a78,bc6b419a,c25b33f6,808d94de,aae2c24d,8569060a,4398c5a5,a6173cd0,dcfa15e4,49642720,32785ff9,f0a7c164), -S(18ccd734,cfdeac35,1dbc13d7,2cd095a0,49a7c6c,e3fd781c,ed552e71,5ce14b0c,79cbb2d0,82272c7b,9af52227,4354c2fd,80a4c2df,5b434bc8,4c1e99c,f45a1e61), -S(73f91ae9,f75ee99a,227785e6,7ee3e1f0,384fc259,6a95d8e3,2436ffed,17f81c6d,f410e115,f57f618f,225caab8,388c97c6,46a37aeb,f184bf2e,408bae0d,ab2d475f), -S(f0216cb6,e9868a3a,cc859cd2,fee969f,b35fccdb,1754ea51,52995dc2,1d9b318a,e3a9a102,719d8398,610498ef,b5dcbb0,27fb3509,af587b9c,2ab5b5f6,35e2ef1d), -S(8c92a0ec,935d03d7,5395de25,3c2c9e15,7026a8d0,ae59a2b1,16d175d7,f70a8b46,8a9b5351,f7a8a20a,e159fa6f,afd58419,bd0e9dc0,def54f15,aa12abfa,65eb73c5), -S(be3bdb59,6c9ec252,5d7c23bc,788ea0d2,7f4c51b0,69182cfe,c095a13a,20b650ed,932c016a,7f006ec8,b73a6d7c,1ad1f2b,ce72706e,bd7e8713,e8a8d093,3586c9bc), -S(24fe525b,362650cd,ed8dee61,7ab4fa69,b06ecac3,fbe31947,4dbd982c,52ad2260,d9c484a8,e7aa329d,136dcd4b,612e0768,3796dfc2,a544a237,73548b9,be96d555), -S(f3a2b68a,8d16b9b1,20067bc0,6ee2f0eb,bab70ac,d6abe6b5,b12ce933,edfb2ff,a3abec92,539974c2,c2217584,2b9ec9a,3bfd4b3a,21c64a6e,ac3f608f,6bfb45aa), -S(fc9a67fe,9cb9622e,a9f20b68,3b19f623,5e12ed25,4a1371b8,196e0629,e43eaaa2,8e3329ac,2191732a,45afe600,43c6c5fb,ce9283fe,695d4f3c,9035ea60,2ceab399), -S(c539c35c,9bf0bd06,af690154,88e4eebd,bb766ef4,737c176b,3bd412d0,f933554,caeddecf,f0fd023a,dfc17791,95f18c1e,bea4bc70,b98eb85,405d5739,d5871906), -S(15871ace,89c88dc9,1d1bf56a,eb4fba,8f0fdb6f,df107705,65ef33d6,345c8ce4,70577775,4dcb9ec3,4765ad82,2070a26c,53c5fc5b,d3a6d8c5,1fe9eb83,635bb9fc), -S(1087625f,6eeca00a,fb9f7bf5,f4b94515,2316693a,ec8fff6f,57217e6,38804398,24b6cd00,e9ad027b,386afca3,44bf48a4,ad587342,2d3d24a0,5eb17150,bdc1a929), -S(98d7bcbe,6aaf808e,3909c417,66e54495,236e1724,6372f821,ea07fd82,686c0d07,b911aaec,47b9e901,4c990d08,e094d124,d8fcff77,f594244c,899a736b,e0661d89), -S(865989f9,35c9b044,7ed36d43,90ee5bb8,6403ef0e,67c3fb9c,eca1f2a2,f7e170c0,533cc475,ed1df473,30a032f,1db8ea42,d6b0fcff,f53007fb,cd41cda5,cf06cc1e), -S(b67f49bd,f912c892,9b26c35f,bfe2535c,830e8e4d,6c62930a,aa8527c6,1ef9cf14,151ef7a9,c08909a7,5daa0d85,e593c7a9,501e492,dbc41800,bf03fcf3,5c12c427), -S(b1ed1735,9a5f07a2,568d9740,3bb402ed,b313bbec,7d037bb0,cbaa2ed3,eacbd50c,5635c19c,1932696d,577a7bbd,411cff9,81bb057e,10436fc,91000bed,b638afa1), -S(6d268375,ec82b57e,7f8499fc,bda8f952,ff6cb4ee,a0f7785b,a8ff6610,84963c71,6b019ac4,d809bf4,1ebd90f5,4d8de537,6171702d,da3e4e21,b2301014,87379b95), -S(8a17346a,c18e4d6e,677db3fe,5df942cc,ddc66882,e39002dc,5815ea02,1ca5c332,c457ecbb,add867b8,70b28f7e,b27bd804,812c362d,1e94d89d,741abe02,59990928), -S(4dbaef58,9616daa4,4a8f892a,e48ac0e5,135b7385,25178135,a233af40,fbe506,90df93c3,9badbe3b,6eb28cd0,8120df1a,442429ca,d8d80108,af4bbf19,2d37b9cb), -S(cb18b241,a5d1bd30,361bf7c2,beb4a14d,3909be2d,dc7c62,d44e35c2,298b5a96,3c0a09a5,d96cd4b2,a1d15a13,341d455f,c04e3008,87c4ea96,d8f71c7f,ed84cacd), -S(cc463ae6,a1114d8c,107f543a,ef50bb07,cfcb222a,de5920ca,58ccaa19,750eb90d,31b54fa1,d115415a,b7931343,a8143a7c,cf2877d3,3d3d1f44,464163b5,c61c77c5), -S(8a0c1391,777b772a,c90d4d50,6f0a398a,45b2fc65,331a67c9,dc39aecd,835bcee5,b8d2bc1b,21248b66,2acd6e9e,1ae802f5,34558837,7da057f7,ad732684,79e4720e), -S(6fc3ccb3,acdff113,69caa83f,e304303,4a9dd77d,fcfa6c25,876cd2cf,75a5d7fc,5d0d64fd,d8f23aa3,5a7b9601,fa6d6deb,bdba27c7,2f227cd6,c4d3889e,49b15379), -S(3b10fd6a,125c3a47,2315bdc5,9686cd80,5b221012,65726bb0,64c974e,e74b778f,20bf9e4,521abdaa,347fb4a,a98a70f,303842d8,4f3e04c6,92d798ee,be97313f), -S(cd78581,a4707b5b,710bb827,b3d9c1d1,ee4a595d,29f90d50,607e3970,620ef0c2,26f5320f,2b512c50,e773a94f,3efba18a,cf343c5d,553f9ffe,67b39cbb,7f0b8831), -S(9bfce83d,b9e2cc9,969d17aa,eba0e037,22cfdaa2,a4175180,ed8d8ce3,7a7deb5d,2d2cbbf3,fc83d702,2d39191f,42eb42a8,555c3884,21add05a,18bb4376,4652477), -S(124e59c,53bf8d0b,a4189a1c,5de61726,3f6739dd,323ba104,892b505e,d8248d31,92d050a6,3e83521c,4b08061d,aa635990,46d52c4e,67c014c,5e33d7d,a6e01942), -S(20948e19,7a26173a,44011c9e,41676cd,661acb99,45a9e4ca,c0dd42c4,6fea02e1,8138a593,be21c5c2,472a37f0,5f2e9151,31bf249e,c6128dff,d218307e,4b661d48), -S(50726fe5,fad5628b,441bbed8,5347af3e,506cc7d3,43d7f0cb,213d63a,aa54365c,47b065b3,280c1f8f,585e05c,dc9f8b28,73f79479,b95a1bd4,c0a80469,eba92c48), -S(fad9bfdf,550fc926,da189531,91111112,a4120e56,db459577,aeea7e13,c2073f2e,a87e89e3,8d49513b,23aec5cc,a251098e,c6216ae8,96257461,2a7b4e08,470d680c), -S(66fe56d1,7395a7b3,b016c8b0,e5cdafef,d9e652cb,526374e,1f7000ea,b956f33c,ccabda97,a6b6b288,54efefa1,ff17f621,88b7cbc7,c3d363b3,25c31235,ecd26292), -S(8273997,5b5cbb89,e4246a1d,6428bdfd,14cf068a,6394a31c,a5cad01e,de3f6da,54d7090a,afe68aee,95a2f829,9d324bcd,9a1c4e16,17370b1f,5b940cbe,845a5013), -S(dc038ef1,5db1cab5,25660c8c,11afd35f,9423d230,2bf5b002,5df30400,a84907b9,cff2179a,904e5f81,e996700d,e64a548f,6ebd7b06,bc12a6cd,2ed74af8,9cabad6e), -S(fd501f6d,fa76dfc5,8da70f14,32eb1053,a5f82fc2,70ed661b,fea83798,acf02483,c04b3038,c2f4916b,178cd919,e953853,77d7555a,a7e3695b,1cc8fe89,d5d001b5), -S(c33af33b,fd47af39,ff687775,aa5e6ead,430821bb,695ba499,e4433a2a,d6190ed4,18555539,664c445b,6d317892,1af772d,7ae10c15,62d1ddde,91f47b5e,a1d4898b), -S(3e1835b6,34c53347,5fd5b032,334dc281,97068930,fb7bdedb,f8988b64,acddd3dd,2fcb5d65,940e235b,f8e1de7b,6aedd7d0,d2061181,dfbcd049,85df1505,a8c61db2), -S(c3b0ff1c,6a0ea466,357ebb78,f9ad0335,2b964b19,8e30e1c7,5b37bfc9,87e0061c,3ddd3d1e,7d97ee9e,748637ea,d8ec4987,d06b1f11,cf9ee9bf,12e85965,8574a95c), -S(1b690634,fa027e38,cabd8f87,3733476e,4f8e4bb0,543c5f6b,88575103,b51f29b9,3fede999,23be0482,caeb15c6,c7f2a00b,92b92a97,e66f2db,2c5d76d9,aa58210c), -S(4f661a50,fed5fbb4,ef8a1888,f1fbd3a8,b35b38fa,91d8601,80a3a70f,17f4fa8e,80e5e5c,7d41736d,29f94284,ddf06611,2cbbd024,60723497,9540c1aa,26232e59), -S(4a251861,333df3be,7b5852a0,f8eed900,dc58d2a7,3cb6d2d7,d45ac506,55126096,7b0734e,be6edf25,b9b4845d,8a93b0be,4f9958e1,2be61a3d,1513dd71,1004361c), -S(ff1c9a62,10360484,6bf46453,246be39d,7f595da8,dc17c86f,8c441b28,64b99d6a,7f01a489,404fa78c,aca02b7,f12a654,5692c8f4,fb787e4c,6e18a9e5,8e1be696), -S(4df0bff,651a53e9,30f631a0,3b6c170,ecce67a3,f92ed930,79e92099,46994deb,c79c834,33a1e795,f4334535,67e122de,bc81c4d,ab48a11e,a64af4de,4c6ebcd4), -S(2dfcd43c,a0000881,15845e7c,966004ea,bd4c909d,fb725642,18bf28d2,d66610b0,6ea9912b,e3232c75,c25b8272,820db699,bad9c292,8d2fa03b,c37dadb5,75a78b1e), -S(2cc759bf,7caff909,4abb456f,f8cb214d,f9353f97,e4f802f0,879b7ded,69eab4db,76ef9968,553c505e,697e5981,1f85a6bb,4d41418c,4b3b5dda,a024d69e,3a2a66e5), -S(a72077e5,8d73d653,66cd0f70,fe79c8ed,e9ef34a1,3e03fa67,70ae3f99,3210403b,8638634,217b7929,f8bcdfe6,4a64c053,5cd1640b,cadd7a2c,e6c5b880,90de01a8), -S(9c598d95,41c3ef74,73c94eab,20021f56,11ce40a2,34936d66,3130f788,14136c47,49702707,51df2f9b,d41b1ccb,1ca90f65,1ee65f69,75262725,b6962c56,dcdf2c4d), -S(5704f6d6,463ed861,cb25dde,343beb26,6557e3d0,7ef35c9e,cc435efd,f880622b,6d605d31,402c9bd0,9360f2d1,1a4f7a36,ddb8ee7d,543932c3,d546162c,cb0e4660), -S(d47b07dd,58962226,fdd1ec80,4a484496,ae3dba3e,41e18f9b,8e48ff60,4b00d727,26e1094b,c62614ba,1aa4df72,f3486975,6b8eafc7,b04a3770,22865b3c,a52028c1), -S(3971f023,44b7b268,754180f4,fa30d0ed,6596d59c,eb806e0f,9186c9b5,54e62b09,1895d58a,c951971,39d03562,6676fdf,cc53dfc0,317d976e,b0afb990,cc1b91f), -S(4b2be90c,e3e3a804,c469fd40,57bcfff6,6e9a220e,713455f2,ce4ee3d3,3cfa73c0,c0e2b79a,cf348a04,6f301f71,bba98de3,b9d1d8d7,ee16937d,e11e49e3,67c3cfd2), -S(2138e37a,29bbb1ba,2f051d4c,984d36a0,7531aeef,63fea098,417db4bc,241a180f,2e243bd0,69c0f7e7,f7319bfd,bbac12de,e03cf686,c97eefa6,dd58f17,c747bab2), -S(bf7bdaf,15838ccb,21a9ac7,3fd8d2c6,2013a163,85b583c,4c458db7,f8ba787a,8481d283,c1c4bac9,87ddd181,b12a2e79,a60e51a,2323c981,efc7cf51,a1768168), -S(e000b589,51237195,b81ea4ec,a4cdcb3f,b509eb80,4322ac0b,69feda94,e78fdb1a,cb527a4a,39a9c03,3dc01d1,d4221deb,b89b1126,8594dc82,fa5faf80,e538783b), -S(dbb2947c,2602e2ad,19ae7079,b6b9fbdc,59bac7dd,1e865f8f,3c802ec9,ed951414,9f646e9a,9f069a54,c1f3e88d,e8fef48d,9c6860a1,afec56be,46ac8943,d83e3cbf), -S(40bab32e,d118cc1a,bda71e7c,828d1ca7,aac8087,b720766c,409f4d78,e711dda9,ea7cd00e,c553e8c,56c9f992,b16a9830,a4ac30e5,cdae357b,148bb413,9e2b1d3e), -S(b2860f17,55e3341,eb6bbf11,a043b6bc,bf70472f,26b2d276,e9c30516,9c478b9a,bf7cc672,94909583,ac6147f6,2c9a3a64,8249513a,9f5c42eb,d0701bba,24b9b1d3), -S(d6e4a042,7f254b5,f2449539,9d6c0ed3,a741022f,f7fcf819,8a7ac04a,3e0183d6,ab1127d5,17900200,4cce6a56,7dc4b9a9,c88518c6,a8e03d4e,daabad76,f86c7be0), -S(57c70171,aaae00e5,e98dee16,e0d74df,82b05fda,8a01db96,67ce4d8c,ddfa9aa9,f4306dc3,1b82356d,8875244d,a713b6da,9fcc95cd,6c861ac1,1df62e6f,c6469e32), -S(e95ec894,230825f3,83442633,8cfef200,69ecfeb1,41c4bfc6,d0d6f2dd,216f36ad,e1f9012d,ec6f62bf,a1b5df85,c4ce2572,bd5ffb4,b8bd28d8,bf982833,e2d50eb3), -S(99d32dde,ddeec538,c8189f02,40bb4d44,cfbee72f,b3d42f9d,319dd7b6,97481451,75d2e691,ca7706e2,9d8c3686,d3fb1ca1,5a505a11,7662a2ed,347fc0a1,8531ab77), -S(be2418b9,b2c44233,b4d97d43,87085579,9219604b,f1a689fa,54523d2a,85677b93,69046a2b,8c329e27,cbbf7b9,d31f2009,9f5aa01,fd0b3905,988f2299,1d73fe99), -S(a88ef29a,67ddd120,c5d43d52,9d270c64,16750835,84a5dcc7,2f05be84,7c3b9b3e,902b663,4466410e,fd0d2251,ae10edfe,72a85d32,6d6a638c,122d7160,49c6881b), -S(95ea7c70,c4d0afc7,b31826e,c6dda0e1,491181ae,8970cf24,b99a8f41,bd428b3e,6bbd0bdf,d884903c,63a2a1c,df73f6e0,6ed335ae,53c64cc5,fc775666,6d8a15ad), -S(3341585e,671b8891,2d0b2944,334649af,a0bdebce,cd445e40,6e416ffe,f2cdc88f,bb17510c,f427e741,5b36269f,c702fbc7,42e36c20,95b69fce,bd31b7ba,fec345d4), -S(34e362c3,7c2c7b59,c972eb54,ab315cd3,da472933,34a305c7,d35c754c,3a440045,5e5d2940,3119cbd0,685f1cb0,b1e446a8,ba9ad625,8234ea7c,8652f971,c53d1b44), -S(f8c6c1c6,16b8bb82,c8d77244,86e10cfa,105e9a01,675da3c9,8e3936ee,ee01cc69,dbbe7cff,73929f21,4bf4fbd8,aba3f18e,461c4855,a204a7f6,319ffcf4,2437fbc5), -S(f4f98cf5,2be30eae,fd2ab1a6,dbfdba9f,8676cc6c,8b32a6c8,a53b10ef,dddc3051,77fed97,782ade72,bd5e41e8,c4b376f6,fde76267,b0a0cc45,a56e3f0f,ce6b2f03), -S(8b642ee4,8487a3fd,2d983039,48cd523,6456f3c5,f9d8f4e6,4f0af631,96b47d8d,22ecdb21,2e8ac0db,bf74c4b3,685339d7,e417686e,1c5337e4,872db54e,aed524c4), -S(5f6923ee,efc718e3,25d22dc,445e04ad,dc460268,58349b42,528c0078,f2a725fb,4ead0dc7,e697cc39,35d46533,73a21016,1a00ed11,273c3ba6,9c5f45a1,a4f38198), -S(1da37bdc,abdce508,9dc3aa72,2c93fb5f,64dcaec7,759064f7,82926829,b91ee1fd,1ecbb28e,f4f4b980,d92db2d3,c78919c9,e762dd5a,ae449d58,7105d84e,41f686dd), -S(ff3be7a2,cb1cf4e9,7b276ef0,235a7eec,addee879,78147bea,120e8ae1,bf888cfe,10a7bae3,da012eea,89b0cea,8deb02ba,1515ec2b,e0b83d05,a4fc152a,8b6e8371), -S(1658579f,72067096,947817e8,e9c22574,8495eb1b,75bb3729,88d45b93,d90531fc,d4538ab,19420b47,3ee869c1,cd1fecbe,f1a8ce73,871a7195,2319bad6,2ae450c), -S(96edfb55,bdc70246,21e1b92c,d2e85b07,b0ba9244,adcb5dae,f82f7afa,a97956c2,3666a36,1c8d1b06,e053ba0c,4a76dc88,2e3fe10c,e741defd,48ebee6d,4877cbbb), -S(4b4d282e,853b581e,55ec4271,e78c2cb9,ebf1cab1,8c15bdc2,2cdb05f1,7f8e44ad,2be45bac,a3257d2d,ab1a5e66,216f421a,2339eea6,89123e15,2bf7b010,e349ee2c), -S(fa12b099,eef9acd5,4c1c6224,117bfb60,12d5a208,553ca232,e030056d,1a141e17,40ed149e,d62259f5,fc98142b,9753503,ab7e9736,5238d4ea,c80b6859,52bba875), -S(c6243386,53084c9d,7bbf3b74,39f0b21a,ad2e5233,17259d9d,af2de00,1d4605ad,3b5376e7,1f08cd2d,3d319056,94608618,960e73fc,d27625a4,92613667,caacf3a)}, -{S(9a1db7bf,53241ed1,df8d3ea0,f70c0b26,76b43ebc,bcb4622a,9704b0a,3067400a,e3638ad2,95740505,455b2e1e,d495c57a,54ed8e8f,c647a6b9,c69b7dd0,715cef52), -S(90bfdcaa,eda30aca,f86d6eab,82407089,3746efbd,62f4a400,86e0589a,f3ea5cc3,9400154,63e05bef,5a4e2c2b,8681a1aa,95042864,447c7bcc,5ba2576a,eae911b7), -S(4666582a,2265fc0,643b1f3e,d003ab1a,d4567a1c,239e82d7,15a8f6c8,23616100,d7efadc1,2e71ed16,cebcd191,f34a70cf,eee6a7b0,dfa87724,dea4e464,ce50c9bc), -S(a5338432,7502bcf1,4bb11dc0,33e544bb,7aec0e46,f40145c4,db65cc46,203d969e,b228140a,7f3fcf9d,fe400a28,90200ef2,6e5f3c78,989406cc,b9fd31e2,e9d54049), -S(d6da1a9c,c1d81eb,9dc9a048,9acb4b74,d119dd52,684f12d4,3fa6a74b,7130c43,6ca8ebef,39c08b97,761cdb6,dafd2143,55715bfe,e8ab8e12,e51bf1ed,6eeed696), -S(27249c84,e21154bd,90034fe0,c5c5c510,c6b90e32,1ba4aa98,ca34be19,c918fb5,60327ac,f3fd64d1,ab14fab6,afe20b42,cd493af7,1d3fd0a8,ec2d064a,ecefed86), -S(cf6fe5b8,cc605dce,97c1b586,e3eb5945,38c02888,43bbeada,65a6b2c1,c2d66d66,21f3d35d,69afd6fb,704d1f0e,1cc2f720,2852892b,afd431f5,8fe3c1,3df78c1f), -S(cb10e984,f228da46,2063ce84,3503b423,20898a8b,98795846,8438d88d,4f0344eb,5bcab6c0,5de27bec,714ec992,dcb2875,d53f3f6d,a5ad247c,c81e8093,504504e2), -S(58c2a274,ce1e7d49,5a1d7fb9,7ff21f88,9e6e5230,5453eade,4ffad95,36037bb9,82e4a06c,5f7a5dbc,5e30b43,dac01491,addaa6e5,8b1a33b2,c082b4b8,fb50072), -S(d59e4e8,47e98edb,a494a195,25d1ffa8,63b2c22d,2476b2d1,2d704c0a,b30a56a2,bc2296d9,53902891,4278647,fc755979,c8d5cb3,502ffedc,8f412cef,51245085), -S(bd7feae1,1c4f02e4,9b1b3697,9370f319,88227ebd,9f4a6711,62e70744,6e452cb1,84cb5bd,1ad0381a,c9eaca88,b50e27da,efffe65b,f16f6bde,50bdbfee,69d22e72), -S(4757cc99,f4010ebd,d2e8c24b,ce7e86ba,febc4175,3f1f3ea9,f7afe8b1,3b0e7070,4b5cb36,55e3f5b6,bce14af,62ca1ad4,97480431,3deca874,dd2f8580,730ab36d), -S(e673b505,1e2f3e1a,f28284e9,b32d0c9d,16e7918a,1b8a13b1,602444b8,875d3d4b,f17f068,d02dc75f,dea5ebff,549a2f86,f9598c93,4db7050,915dc965,830bcc1c), -S(63d23920,6855af5c,c8c7f9d5,4986513b,455ca801,e172937e,a93a98df,78f36679,f95c588a,ba4d4bfd,fdac3c8d,f8a7d14d,7800212b,504e3deb,9220bacd,69e12f2e), -S(e74fb7b5,202d5a24,37a982f3,5018450d,ffe2e238,cd4fe3c0,60ce38d,18fa18b6,4715c0a9,f58d9421,6c3535fe,d6140395,e302e18e,2df0a870,52cd05ac,db917ae2), -S(1929be94,197feeb5,ac631038,f07c7db8,ff2226d6,c1763d47,a45c9e5e,7719c60f,c7816c80,8fe129ef,9a5bb8c6,674495f9,3f1e711,133e3cb6,19dacef3,815826e1), -S(76a43955,8d625d34,8c5cb3a6,e2274b60,8c93f08,6a0a7aea,be1858e8,7c1c359c,9752d697,a67a1743,9b5c4359,76658df4,be1452ee,1d4e0645,597f59a1,c60b3618), -S(4a3c36c,6418b8ac,920004a,4f47bfa1,1807619b,9fa39030,95f1b0a5,d91f46c1,95668552,e63f7fea,cd2b09d4,9c49e2a3,2f2fb824,11c5b819,c0efd09b,d64f6b8d), -S(9c5a32f0,d1a0f2db,253d47d5,e7c44967,26bcc7d3,b61e3731,3bbe5fad,ccbf4625,232fee50,bfd72474,af4bb5f6,afff7eb7,17efef90,7579d0b7,38542e56,67e05de8), -S(672eadd1,652ec6b6,a0c37e3e,7c8f0d5,a51d6f40,fe7bb66d,b4fed735,2e066063,ee5ba376,b53e9238,efb76b38,2424c8ce,d3b0f91c,99da4a5,7c98b7eb,48e5b891), -S(f78a9f6b,77af560d,c42d7061,831270df,21a73ecd,a7bc19e5,bff6649c,414b45ca,9f9897db,a7ef70cb,f4ceb71c,2572c3c2,b89c9c0f,a18ebdad,fc413d34,5289776), -S(2fdc690b,b0fa8c76,416b7ab0,ed6fd336,af4eb887,f13d5b1c,f7aab941,a7f63690,ab602a5b,f8ae3e5d,9aeaade1,1d126154,2f38a881,d577daa8,fe89bb22,6352c6a9), -S(3e6d45fc,5d8a498,b31d95ea,acb33144,ebb45ddf,ca3fd8f8,b5b22f4c,9d57cb6,f7e817dc,b718028f,3b18691d,8b9a25e2,884954df,59141cc7,ed939e0b,94cdb2d3), -S(6bfab01c,caec1bc7,1c38fa8c,b62ae3fe,9a24ee90,f6af6206,3b12d9dd,e83db7f4,5fa5e4e4,9d5f9641,559636fc,35b60199,68097451,10bfda67,a27de3c4,6792eddd), -S(d0e37c85,88d9a4f6,f135156a,25a15af7,2835de73,53f7b4af,336df017,d69a7fc4,8b9d798d,3cb04f70,41ac72f1,38462cbd,533324e0,871230ed,c3a06ef0,f524e20), -S(3f2a406d,eef9506c,2432dbe4,cb2d0a6c,a794356b,7953abb0,1ea486a4,e5db86da,ba0e92ef,aa00c78e,6f854963,7d8cdb5c,30869636,2cd71113,a3cea5d,9b492210), -S(d8b41f1c,2d2eef01,2b994dc7,21ca505e,818ac75f,4a396750,3fa3fdb0,2cf56fce,293fa011,7d231d10,30daa322,94d74507,3f9cb4bd,297a2f81,c812735e,33dc13eb), -S(64a07ffa,80f69a36,19f29cda,d1dc1b41,d7d58d6a,83470353,1f8aeb3b,eae51d91,b9b83f0f,43349999,d8efd66b,695bffbb,f67d3817,808149da,23978cb9,b43ef652), -S(348c104a,9bede4ae,3fff9b86,15eaafe,440a1cc2,1ff484bd,b442ad84,86dca015,41820b57,f62d6668,ce7fb53,2f3d3a94,4ac47c22,ec302d69,f98f355d,ad9e79af), -S(29fa80b3,e0a7a062,678c4612,41fefd8e,95f8e02,14795ae0,2afe449,1cf58041,6e3ae72e,ed0db6ed,1398068e,79cbed22,791076f7,515d5383,8581957,a73761d1), -S(6ecd85c0,afd6c385,15d8ca8c,30d618f1,8963b70b,fe73531a,11444a85,35c4ef29,c3e0cf48,4522b927,c1615ac7,9943e94e,aacd0849,12cd7221,308aa14d,95f05021), -S(7602cb28,f9703b3d,e0bbdf84,5e4f9326,712582b5,1a0cd719,a6674343,af2d089f,5b026bc3,bae6db2a,86f6f970,1682d8f9,82363e02,4bb703a3,945d7e19,d0b9efd), -S(a59436c1,389b4c00,5e4534a0,c7ce00b0,56f72ddb,a2b920e8,896d3bdd,74b29723,36c401e5,df5f695b,959c0474,28c9366a,774f744c,a60dba69,4fa55d25,2a5afd9c), -S(55377738,4bd49ab8,21e96778,17e0e95e,b6b08aa2,92a5ed47,9eeeb607,a0f4e176,61257b61,744f2c95,2d80a9df,29e47bb9,ad933877,eea75922,a31acb83,ce7c478e), -S(ac7ac723,2ac8d976,8e34fe45,18f5fcb5,518ea1f3,37d5bd53,5d5df329,d20a5f4e,e2317908,50bc5a02,f14ffc6d,c3785319,c30e93a3,29304698,a136d6ab,957ed52f), -S(9e49dd3d,aa78f89,af09eb7a,a87cb01e,6b55245f,dbe5b5d8,4c43db0e,1b5d26a8,e0ea375c,dc5eab64,54d16b5c,ec1435d2,14b54dc0,51806c9b,e232c64b,9843812f), -S(3537f749,4c903cc5,f5842fdd,c28aa98b,973dcbf3,20e2da65,127e4b22,4c747f59,f9cfbc26,5666e24e,1a9996fc,389ee639,ca350fa1,7a2191bb,13a2de15,63ff24a4), -S(d7ff3397,7aae895c,48e262c,1c93a0fd,2ea94961,bf19f720,77978415,e0f8591,2d3f2397,1cffe0f1,74a3ab24,614f54bf,85f4c513,21cba826,de24b150,cf77abb8), -S(76336d96,8a54c4f0,365712d5,a34c60dd,ed6de6a9,f4883994,f4ce2331,126078ec,ce745d4,62ebd771,359309e4,ee03b19f,83db6e4d,5ce7fee4,f5e3033c,9bae1c7), -S(63b503a1,615b32ee,520657d5,d2354c66,6b7ba964,a5efad65,d5957c99,65bb6991,af4ed8fb,bbe3a6ff,ee38c670,688351e1,d4a4a45c,7d5b9d5a,ebbce84,9a4ee02e), -S(a562ffee,3f8e26b7,1b3bee24,2fe06199,a198f76b,8b98a8d1,d67e176,1dc070c0,ffbc04e2,c268c14a,1a0fef4,bfa32008,f38a21f,891df618,72fedd7b,5f2cc270), -S(5be4337,20a7b123,1a171a80,fb72b580,a7045724,20d10b9c,786cb0e6,2882044b,c592daff,38d12615,b6af0225,7f39cc28,1447e965,9daaf5d6,c45bd486,f140efa6), -S(86f7afa1,e672e5e0,f33b0346,fa6e3b0b,1087f85,1526271,2ec07e9,82b80843,e7425903,c36d44df,fcbd0d4c,1a272123,18463d3b,12aaf1d4,9174c4e,3777d32c), -S(74751604,d00ecf1c,a56ca92e,9ef64457,fc2f6abf,d067cc8e,b761e120,c0019c53,94fc0537,6f69a1be,f8cfe400,31078265,39d625d6,8ca5df8e,2829469e,d3729995), -S(8b6a6378,49ca68f9,27f0b6c1,e934892d,f100384c,5d902c12,feb4956b,44016e72,862e9458,3835340a,f7c4cb5f,9ce0c566,c1a42452,c4420be3,2ed88324,3f6d7cf6), -S(9812ea51,ff0268b2,f94063d6,ec285595,ee8351d6,b95bb35a,d6577ff4,79d9d18d,c4ab286b,2e9d9545,d1ea9b8d,6ca577f0,ec7479ae,97ffbfb3,27bd9084,8f3ebe9b), -S(4bc3c5b6,3e1a82bf,3ce44d48,25c82c65,8d5d69a8,a1e5b4a9,358ed443,f89cc7eb,4eb838e1,2eed6fb2,81d9de11,cfb5dad0,b08ae9be,f7c82d80,5f3c7a19,3d46b1b6), -S(e269b40d,e9dd3fa1,b5edbad5,83a90477,2421326d,61611b51,bfca9231,4afb2c3e,76633ec,7793b5e3,7b1c3bd7,981496a0,1b9cae51,2ce5d589,2b69c1f,a437931a), -S(7abe755d,9bdc8c37,e99d6917,e5d0dfb7,7e90102d,7c278af,e10c6f6d,74880322,fad617e,3612687e,d31b7597,2bc98e83,c7af5e9d,f4a6e12b,ca812f70,1c5a7a97), -S(8eb690bf,8c75a72f,e635bc55,ad05856c,9083a672,3577d776,2743b1d4,df0d88c2,7737abfa,76ea68e3,1482d3d6,95f1a7a8,ae4249ae,37c68c95,ae605814,6a288958), -S(d0413b90,c3426609,6ea9401c,8e41f0d8,37847c1a,47a47b3b,fd6ffe82,58d3b38d,38c1b369,1865a029,af58a847,4278fd49,9ea44686,7a8b4ef8,63b6dc96,c66e1a38), -S(1bf1b231,9468cab3,2011fffc,96f296bb,8bb64c69,47b590dd,d9d8edc8,ded3668d,1a87ff27,bbf79298,807dee37,bd488762,3a9b5c7f,c5d61e4f,d4de16c3,e7988c1e), -S(bfbadb48,ae5a2997,c368e44b,beffea6,b1682b01,f492c9c2,6bca3fcf,1a0e01f6,7fe11de5,4037bcf4,3418d062,d0bf0bd8,a7399f29,e65f5ecd,9f9e2693,dca6acbe), -S(c2d48434,f2fa7dff,d206ec93,5def03b6,ef2401df,c8c3a126,10f77d49,c14f239d,68e9c025,7483ec64,fe6ec6fe,1159d5c6,400c9d0a,397f0e08,9e92430b,51883316), -S(4af55e6e,f210442b,95a50aeb,51e87ee1,b2546337,664d3a33,9c12a655,2e3ac08e,4f81a92d,fc5c3e62,da712c72,cbccee05,da2e4cd5,6f901bed,a96f9b5c,5c5f9d48), -S(d89bf279,472e7b5e,6f41f460,3d348143,d15b1dd4,7bcef4c9,1274f9fe,9f868ced,cdd02079,9e9d91c3,8fef3631,12a3edc0,962bc718,b7f467b6,45f743e7,db1d66ea), -S(c7cd49a7,27c9e003,dea93f26,fb888cb3,770f5637,58d4f40d,ccb4e0df,d2d1ba1,85bc461b,7e583884,2d4e643d,91ad3179,30d9949b,b29fd94e,4090e6b3,3cf2772a), -S(e1cf9c4f,e0b525a1,290d8ec5,1a3cfb9f,6a78d2c,e817ec9a,a39a538,4f9619af,b6aa8225,d0ebf9c3,4aa0392,a81df722,c8d29cc1,f03abff2,cb7392ba,ac78f5bf), -S(4f628bae,d84bbf1d,fd568c23,10aa10e3,a098131d,65484a80,653b4eb4,ae59b970,e86292bd,cab0f1a,63ada7af,e350fee4,2dcbc618,6838123b,186974b4,16ff2a5a), -S(90b17b58,9674a91d,7c2c9443,61cf8adf,b47e733a,bc775b57,4838fd2,d40eeaad,72c69fe2,ba39f165,5ca31f41,7ccd004c,1eca2392,2973e47e,ffb423c3,5c9f54c), -S(1e13fed8,6aed242d,c543d2b6,9d3ffa88,c87731fc,c4f6ea48,fbdccace,b60ab263,9c1a66d4,47de8c53,2f740f38,af9a52c8,160890d9,5b573c09,9981297f,df8995b4), -S(fe036a4f,713794cf,c0cd3b66,b1a124d4,c6a5374f,810d11c1,30c16fe9,1d8e81aa,f7ff5760,544b9e87,489e3c76,addbca52,308b9155,a7848716,1dd8c1d3,f3c81816), -S(2f9a25b7,73b6cb87,56d1f4ed,691a4fb3,be7ea324,bede8c0a,b9446103,dbb96323,df92e84c,7b76c4b1,f55e77ec,d541ce34,963e9f5a,f4d68fcd,1685d060,c99dda22), -S(ff65bc77,a459bd32,21742391,6e2f9438,b6a38b71,c8c06d24,84cbcdac,ac0522d8,efbb8c9b,8ac9200d,71d4a944,4dc9050c,4661ff4e,fb0c953a,c1c1dcc6,2e44071a), -S(d0e325cf,775d47a0,532b46f8,4ec41698,82aba5fe,83c572a1,1bb18b9c,84edac13,2ceef205,c424441a,fee6879a,a577e1ea,423514ff,d95bc282,6e27b5dc,72f6ddc6), -S(27700ed2,bcdf8ba3,f5ee842,945d9473,9ead9ca3,7741f31,1fad3503,e052b8ba,69c780cb,d6f2c1f2,5104dc40,cdf07ec4,ee76478e,98732995,ca85b5d8,f070c8df), -S(205bfccd,37349c79,5077f5b1,16e63990,8703cb74,f2835302,44bbdcfc,fac24a98,edf25093,8cd87a81,b6f3da85,9129b399,a1971850,86bd63a9,1c370165,a22642a5), -S(a5f79343,8b402d23,6e9bc997,cd08557c,7f83a343,32528a19,c506e5ea,8045bded,9679de58,13c2c74,cd82315b,23b6819f,4981c6ef,f1a2ee00,af5efa4f,807f2b3b), -S(aa7da8ed,a97ac1e4,d2b2abe4,c8f727a2,5643c5ba,414ecf72,70a7bd65,612b1a53,83736a4,de5bae56,8d55de7d,6e2d4d6,eb5d9965,f08e08d6,dd6419e2,dc8d4057), -S(ee53a4e,1eefa289,af562927,9d58f02d,529663d0,8a290297,d7ea92c3,64f5d41c,aa0fbd01,727c227e,662fa63d,3d6a834,476e00e5,a96cdc97,d78c21f0,f3b2a83d), -S(8fc52dea,bd8b3e4c,fc6a2490,176b74f3,cfc55118,2d5134f7,1364a8c7,b083fdc4,1a8b2a23,d9119901,7e1de607,6ace873f,32bbb342,e93a9f82,ab1c3a29,18d603f5), -S(e0f5e5ca,6395d3d2,390eca9b,4bf50320,4c1062c6,82214c36,b1b0587c,cc0912c3,4eb1d022,b4971d9b,74244e8a,5565e021,b933b2f7,e8ea60d,fc259511,a7ee436f), -S(fd31a893,17476bc5,e278bac3,99eaaf6,1716586a,38410172,48170f7e,4d7821fe,190815b5,a2affc9b,1cb91237,783959ac,2058e75f,16cc2e7c,a825ab2f,8af9ba01), -S(1533bab4,eace4f70,74067a55,593498e5,59fa78ba,b74131bb,a2a97412,4e855be7,a04ff3b9,c6209ba3,69b19863,5cf8b4da,9b6a5a04,f90e29ec,9061a32d,f3ce6361), -S(8d549288,93390895,f1310e4d,a8b8ffd0,d9f8226a,b414180b,bb280370,93aa90df,fdafa930,f892b478,c7e6cbae,3f943615,ff08c2e5,64ff61c8,dcf19ddd,5c458081), -S(1b17a4c1,736fc761,f3091367,9ff22ae6,2ce76a6d,716e9b1b,c6cf28c7,cca59a03,9435ebc9,edb1a948,bc3493e3,e7434b81,cb671439,365843d8,819b4eb,786a191f), -S(3500c8cb,e37f659e,48e3b619,7007f250,9d964708,14c06977,a9861a89,eec11b52,8d5de084,b45912af,3ab8a8b1,47304a2c,45b839a6,41713563,f11dae45,2e5ed94e), -S(42def4ea,50df55dc,cdba6c04,ac2855d0,d706ef40,6ad56ded,50d49aac,3b41c049,9e354094,29b46cec,329d906c,9f9ae965,ac3adfac,251370f5,60b91550,4a7e114c), -S(b83c1c07,2087e92,11fc3302,fafb5be7,8fd4853f,9f8aecb9,5af83278,d488600,e51c2222,910c6d19,3baa56a3,63e330c6,390dcee2,c33ad00d,771fde6d,3bcdf973), -S(beb27e28,c59f5b87,d19b0274,51a51e58,f0d10402,e7343efc,d302437f,f9ea2004,ac188f43,c0d6b91,4525f6b3,5897d7e1,7a0543c2,3ccd8001,509f50d8,a95768de), -S(9408e5fc,877c5635,5a3339bd,3b9f7a8e,22a361b9,ee5e2f1a,a2b47eb4,cd665328,c51663b2,f9ad7dd9,6b120c25,2eb8493d,d68be9f4,ed4b688c,f5d2bde3,618658a2), -S(a4d0c5e2,9cf83c46,5a567288,e6c0573d,c7766450,d88ced27,cb036db,47ecc96f,ad00c513,63a3d265,1318ed9e,352be903,30febde9,7827d8ff,1b5b5bd3,281c0c38), -S(d38d0ec0,4d3819c9,665b42f6,24089402,e923a8f5,6e7567aa,bc12e5fe,c248722f,17e171c,5c6bbc7d,dd7caddb,652dfee8,720c319f,dad6b117,56596bd8,b554397a), -S(4fa66f5a,7c294bc2,a0fb7951,7e6310f3,217c2cc9,c712f6ad,c5042610,c29b7a26,8b79a582,b3d9acb5,5653642e,8b8c6f18,f17e0541,179c4d62,8a2976aa,3c760d1), -S(ec9def33,2bcc66f0,db0e6b3f,684fddc3,ff1a7ace,80c2adc8,82e4e5df,5ce77861,9ae3da13,563aface,d4988a5a,5b3a95b0,4b72be95,dd8ec898,f46fcb29,f43cae94), -S(90422949,23fc0bb2,3263ca1d,768919a9,846e8eed,4b595e56,2d5103b9,5a479795,7d8a7b46,e557e1c2,c621d49f,b8f382c3,1feccfbf,5cb8c755,1f02309e,bc5881d4), -S(9c926be9,68275386,95549bf,2cae2278,56410e3d,1e481cad,995c687b,e44bd1b1,56208afb,875c94cc,bcbb068f,f8ef6fe6,9615f1db,21c2b43b,59c8e80f,db5670e9), -S(8d7f3cd7,2a6912ed,f0fe9343,211cb3d4,20229f19,3e956ed6,9c4a45bf,c7cb84a7,a45a7fb5,d4e9c531,4defec11,ce95e054,1ef0575f,b6b7f299,72bbb008,c9c3c3c0), -S(a95eb316,bc91485d,9a220af0,a201378a,d0319bb3,473a0db6,e919b3b8,ff181952,41664555,3aea43ef,d7819025,acad34ec,6692f9b8,bf6a86a9,7de32f18,46de13cc), -S(8ffa8414,1e806ac3,df613a68,a8395111,93569368,6e2b11ef,a1d53493,34e8da55,5dc00c59,12cedd0d,4457e779,e82ba2ee,669f7fa5,75c42e1b,abc1aa7c,7cb1bb1d), -S(2f1645b9,7b58e33e,3dbaca4e,b4ee6fde,2245c,2c9bf124,46e262b3,434641fa,d3d0a603,6ded3010,319324f,34ae1e58,a6ac0b6b,9ea15b7c,3052b574,f0b2823d), -S(95232f86,d2d1482f,a6656256,3751c2a5,16e1a8a1,66988471,f6e0aa69,f1ecea2f,7f54837c,4633f938,c0ff4fba,e59b6e4d,1a7b336,83a1ec1e,fe1ece3b,a131662e), -S(676d2a29,50e66454,97e678da,68a5bb2b,126a8eeb,874fa8aa,ee3738a,cb7b3cc9,23fb14fb,674ca1bd,8ccb8248,48334f6d,4ba47d56,c7969cf1,fa3ab1d,78a22a2f), -S(91df7ef4,3ba5bf7a,11d8418,e553c5b6,d2031b89,c644d08d,88f1cec5,9d4007e8,e7b19092,f45b6d,7742d4e9,37d80d32,63ba2945,1fee1259,a13b5b1e,42072f7b), -S(1b64a5c3,e14d8fed,ac3c5eba,e6848e10,6c9db663,b18d48f2,b948be47,e8dc3b4f,55caac6b,18f294a5,f3dc9f44,ebb276f2,fbbb506c,1a28b0de,a55ad2d3,ac5eb8c7), -S(122f6415,3a73b8c1,f1c935a8,e99590ed,16ed9660,66816cb3,57049803,c7d7420b,f5bbe828,9693d573,7016fd9e,59cabef7,5eb7fae6,ec9614c5,3c47736a,f3276855), -S(745ed438,63d669e4,397bf391,14af880,f87334cd,62897aea,634b5c7e,cc6a074a,c5cb92e5,61812f7b,65930310,88b45373,b864b51c,18326532,b2eca5ac,8608f155), -S(4724facb,e60d62dc,da536967,a4650a19,1e582045,ea209834,f1989d0c,db8baad5,ad70a8b,ec1372b7,5e3aba6f,8c031d5b,ba540395,b610fbbd,7d5b6ad7,4e32a3b7), -S(a31bdf87,40d7a1c4,88f23ae5,9b54c976,56887201,6c307531,51ed5062,dd7613a8,e77b2633,af3e9b42,a2a05b45,a0f5c9ec,28f72387,2cb5bacb,ee5a8360,2aa282a5), -S(990e8453,81efaed1,8c3fda39,7d4ba832,d509851b,8503891c,c0ea0ae3,4f5f1f7a,339aef51,e4d4ff8e,49955166,4408c312,b943df2f,fa62becf,51cac7b7,eda7d8a4), -S(bfcc3e62,cfc9808f,bdceaa55,f75331b6,c9b1528d,455c33fc,9690d84a,d89f68f1,7b07149b,cf648a16,b3be662a,d203837d,fe5a2357,1154e65a,78841ae7,a906a7c1), -S(284b543b,5ad3aa4e,5a4ab274,9acf59d0,4045bbdc,1ad204af,3a7e841b,330c7ac8,43d50b60,d23281ff,1ce15241,80c05e53,e5fb5bc4,a4e0ead9,19a2add5,f55b10d2), -S(e4c147cf,beae087f,5c9aa83b,31514ffc,5734feba,cc743203,7a7a9931,4101bc7c,72ba3a91,3a2fa186,484bf856,ea93a725,5f6e3b1f,d5bb86e2,58e45e43,52073787), -S(54cbe831,a201fa88,a3e7ca1,aa409449,509269a9,1b229892,9e9f9dba,a7e8a8c7,60705c7d,ff74d8eb,1f85b9d1,d9efcc58,fe463e04,b19f56dc,a724dfbb,630661c8), -S(c8dc9e83,d4e4f250,5e8c16f0,a5e8de3d,1ea3711b,8a927a63,baa9bb33,6ff302c0,62211dac,15b97856,2dd71543,b63edca2,4868ef5c,6bc7e547,9fe81da2,261f6150), -S(4bdbd22d,5cb98e31,ddcd1e76,fb69ae02,1915be35,5fa326e8,506c38d7,3c93dd8b,9401c173,3bdd7728,fae5ddce,d708119f,b0cfdd41,2b3fe599,e75b5a8b,b84fbc55), -S(ce988332,84a3fbb4,31b716cb,3b6530ba,bb41785b,c7f0564a,8691289d,9d35e689,2d6d9b1a,7711c5a3,2ded418f,9b52c134,e822589a,789c2b33,648324be,508f4f14), -S(2815b2a6,ab505e2d,ad759c85,6aebc3e6,133826c6,d3939a6e,8795308,5adb6bcf,2e6764f1,f90c7ce,a03c5d8,a1465d26,fb2cd430,edf9f4ec,13ea71e0,51558b7d), -S(65380aca,14b90a7f,e6c6452c,c3d811ee,88128fcf,fa009d7c,1afb3195,8c3bd1cc,a73d691b,cde27cfb,dfe4180,e6a8d2d8,62615b1d,59ad3487,dc914045,39549ee6), -S(7bf3a1ed,4e7e876a,1404493b,7ba01911,b5707f09,f18694f0,fdc35e9c,27f1b89f,b6dfdc2e,e827967d,1d1218d8,975cea61,9a740521,a0e0b702,7df1ffff,dfe45572), -S(5f635ad5,952b3f2b,e341479d,239f4ed8,8c33ed63,87f62c4,40a02665,4e469aa1,a49b5262,32361560,c2105db9,3b500fa5,bfe3ef99,7efb826d,90781ad0,143fc0c1), -S(4a212245,8bc099fa,7792d0bc,a3d1d163,58fc391a,82dc7f47,2a457268,1be9ff8b,fbeb9575,6649a3af,923b28d6,788c8662,9b488166,23349b93,755d04ff,bdbccd97), -S(1b56d138,e71aa703,e2566a6a,6f0a29fc,e7a7b999,2c454248,5ab29c6c,eafc86d8,db7b41e9,217fd201,4f4e6ad7,818dfcce,31823069,d1e87ab,85bb5ccc,c870d476), -S(cf9dee0,3d9c1724,24ebc37a,1da32a19,bec78003,29def8e1,b7c44b5b,59e880b,20ce898c,1b9dbef4,f47c5b6f,be39a8cb,91bd244,b0df0bcf,94c01616,24ae24c3), -S(89458ec9,1bcac5d6,ba51b7dd,d32119c,eee5f535,5e368e22,3a35b9ed,b8bce2fc,33ebef56,190a0820,9e508e1f,6dd57a37,141cc7b7,ae8a3583,41da1ae7,24b40f0e), -S(bc1637f8,39b45eb7,66e7ede4,af989ce2,20ec795e,d8454ead,6053a392,18c6cf13,e64e7128,240d9c9b,4018c56a,bd71e9ef,30d7cd1,8a036ff6,13e4dc52,13e88b71), -S(212c6c8c,3e2d406d,4fab7bf1,4f7dee3b,a7820821,ecee711c,f63fa0cd,49341157,2c2caa21,7ae6176f,242ac6a,c951b628,5daa7dc8,ef35e996,12b7df6a,b7966006), -S(8ec5f69a,a77e4faa,a70d129b,685f996e,36d4591a,9f03a047,d853f81c,483a371a,69eb18df,9bc54f0,804f937e,4c88eeb3,a1e089fc,6fde0ddf,e37e2de7,892b8b1c), -S(d77dfe3e,6370e677,bc0442c4,4d71e7fb,fcf1b7a0,5a39831f,6c02daea,70eef37c,e5582098,dcc957cb,6308e51a,817c2764,1c34a3ae,4a1e931c,9e741c29,241df4a3), -S(95a98fb8,178ab7b0,45931f72,f9d3411c,3d6c9bfc,47b9db77,11dba796,6600d1f4,789034c9,fa371e65,e47e936d,d5be1c62,d660c12f,d7a0164d,1507b4b1,4d5a5d58), -S(dfb9170,5c2eda68,ebfe7b2a,f2c76eb0,c65fe431,d3a893d2,b202b004,bf532063,2842d35d,73985521,4dbf015a,a64fc5d4,5c763a0c,81be6302,ab16eb45,64e1c020), -S(ae011375,773a319c,12a49e8a,24f4a84a,70817591,d739c604,e76314ee,2466136a,fba7f0ee,758357ed,f296ec2b,b4d0f9e,6c38e29e,95daa163,f75c82ac,48988ba1), -S(e906d6fc,6930a06d,846d4804,f2affda5,955c0718,e920aa47,724a4903,d644d4d,abcddd9,fa93df1a,6c4aff95,a7ff30e0,8768bc94,5baff83f,1278dcc6,fb797ac), -S(39d6a839,e4ec9f30,7a4b150c,9c20f918,5626c93a,1a077cf1,b4259d9b,cac3eb5,2b0173df,699d9213,989b16bf,a17b0996,18eac71,b6f21611,e20cad8c,f9609c2a), -S(11541976,d8c7da9d,b9864344,a2a3ecea,499f538b,224e74c1,546dbb82,a343c308,692038e0,d63da9a8,c4c7b9b1,fc3384d7,d03e2dd9,156f90d7,68d31f64,eb46231b), -S(b8edf6b7,8b0ec547,9ee981dd,e7d8052f,7d613d32,a9677bf4,623c6695,515af54e,4e391006,443f4578,7951cf57,d47100de,7982d0df,cedf7c3,36193ed7,a7f986b), -S(dd4f1c04,c7f106f6,2d8f49b3,f96b919e,774cec1d,e470e670,1f72bbd3,2236d3f0,bb46966b,fa105ade,17aba7ee,a2c11e02,ace8524,1e3da1c2,4d30ad99,dc695175), -S(794d4cc7,aee8f9da,ac4ddc7a,bb4278ea,d8de11cc,c4dad583,45c3edb5,b9c7b2b4,d0024919,35a5f7ac,6ec9a6f6,85aa16e7,61329642,c002bb59,a9a9e135,63ef3688), -S(90dec6c9,97e0906a,fe63cf90,2b6a5a6b,ead0653a,6c9a8337,154eca0a,7e1fda8,3511f4a,49540228,3956e249,e9caa7c6,222c79cf,d91fcad5,c35b3737,931308bf), -S(dbe539ca,27d132f2,e602df51,6582c3a,9bda3a82,ce3b52d6,10f4bc45,17b52119,9f52a5dc,417ffa9d,2ccdf666,63ff60,8412460b,15adde93,a11ceb9d,4f859f37), -S(a3fb9a06,7f8a9364,87bd6b2f,eea9e072,6902c046,5bd3a9fb,5afb9cf2,8af34028,b3de3a34,76028531,192d614f,c720e0ee,e7765fa0,14dfe4a0,ce0ffb9,b32f123b), -S(47c00044,c66a8c7f,f6242613,17cc9950,438544f7,31398212,bfdbbfae,d2e34ed4,215f4709,e2bfec21,6990ddd4,d37a0c46,b2cb44f9,26d3523c,ea0a8b2d,7f949015), -S(b59b3f1c,cbb0cbdc,4e430788,f934f090,aa0e1047,24d8d1e8,b7329e4e,c1d6092a,f96cdb74,a7ece8e3,a9f631cf,7a740a2e,fc9c9020,8ee0a91f,42168990,d9a3cee0), -S(c4efffa5,92a27b03,a05686e5,8ce4cbe,d4768e15,64d30450,655b6d0f,5dc5911f,7f095e1a,9108c3fa,a1b1043a,ce870f98,264916b6,f8643370,4d36da78,deb9d826), -S(df9f6d4f,e169d748,5c09f5ad,a2eb46b,be5bb378,919291d9,e3f60ac3,2644b6cc,7566af91,e7c37fdd,72b68418,e6ed1929,c17517bb,bc8666f0,d5e28eff,4d50ba54), -S(bf3d3814,11130a19,23ae0b6d,f333c61,8ea598b4,1277a568,85582688,6bf8deb9,861edd8d,276fe3c4,cb7496d2,9d313697,77df75a,d8c40a85,19ea1415,9ebf533d), -S(8b822d8f,640dbd04,d2a35aad,e4309992,3133fb0,c97073d3,b23f767d,f3468247,71db728e,40b1eb39,7cb69211,1ad24e63,79727a77,bb028db0,51ef9b67,f31d036f), -S(4a0e24e8,6d588f32,7d41addd,c4659b36,d6406a28,91ace143,d24d98cc,cfea28b6,3c79f61e,71c3c9db,11c97734,da9d9d29,7b141060,589c029f,6eb888cf,7cb6f04), -S(3df98e9e,c1bfd244,86c6e95d,8ab19c93,c89751d7,d408ae98,44c90c2f,8bee9685,fb6bd949,afc7c8d0,a16e2c45,4869cc4e,899e6b6d,701eee28,7434439,fc61074e), -S(1196aba0,2bed29e5,2ab28d7b,74301095,ca68fd6b,1e2d0893,1e3145fd,3dd1047b,d8dfd4a4,781ef486,8513bfae,d0b0ce98,5d80f6a4,556da69c,aea24c1c,7e85b27f), -S(5746e37f,709a62f,af3a720f,2c7d5ca6,5ec8a3fd,3e223b67,b839dea,60cc1505,eec14b2e,76e888a7,538f0fe1,32268576,4f91d70a,19d9e885,168af68d,5b9678b2), -S(3c807748,606480e0,9266fd22,69b9c7aa,9a2f87e9,58d3264e,77cf2140,e0f2dcef,48b70aa7,6f86e7a5,c02c1997,fa029d78,94398324,82d3396d,2283dac7,dbe23c00), -S(52885fb1,f40dad6b,7c0f7f0e,3e9e230f,b45688f1,a9f3adbe,710bbff6,d56885b0,372ba4ff,192bc456,56240432,db828847,98cc846,e810c99a,8e33476e,1a674663), -S(60fe0096,4fb56044,c506b551,3504a800,7c2534ff,52f53f54,31a479fb,166616da,75ae6371,b05b93a2,499563d9,887f69ee,f9532a1c,6695e6de,966f0b73,90100ee8), -S(55439653,f8f659fa,9f2ad854,2b1beee6,6cdf34e,d3e464e8,45ca34ac,70d88434,c7883ce8,984db19f,a1866e82,f7cb0623,e6de0446,a8ad5fa5,3dcc775e,d2a9f871), -S(18ea4c5d,24fd7a5e,9463b109,20760dc7,fb4ae56f,db00f0d1,805a9e19,c02f8687,3e19b983,93a440ee,99fb1a25,d7283f10,cdcf3b7b,8b063ee,5eb05c56,2edc9251), -S(8bfd7102,9c7a5747,8eaaa0de,1417ebcd,16731b31,935b7190,d536089d,56dece82,b8fdf97b,1a4d9d35,f32504a7,2a03be23,e71fa005,48cbe33b,8a85060a,21daaf5f), -S(e4fcbc12,22987f5a,f97c0ae9,be88dcf0,23ee2366,4a2f3b98,d19f3687,b82d89a0,7539ffb,33cfabf8,582ec993,8c034688,f8aea8c,7fb6f73,ae09ce9a,e63b9da6), -S(bb20ed68,c9a83a86,99a42cf3,9a51af62,534da50,36bd8cf2,5ef7f7ff,1f08ef85,48d64269,af2c39dd,d6c2d703,fd7832d7,c409d76f,8a8ac99b,d977e7ba,760e7428), -S(2d852cde,fe404dd0,835c781a,11a23db,bce9b015,637c4a82,e0ae009b,aa2ee8a4,d69c9056,66184051,f433e99,ce03c3fb,97107229,d509cb69,59675300,8951f4f5), -S(37f5037,beda50f6,c485b78c,ae4843d2,cbbc50bd,c3588c34,54a09dd4,4b5504d2,d2ec7671,9eb38781,d2954fab,34f475c2,2c297238,70bf7ae1,1124231,2315d8d8), -S(7a5fc0f1,5747caef,61882134,40cafb3e,e8cd6c25,9cdefac3,60c4a9d3,6c96397f,bdba60e9,bb96fbfc,e1fdc22f,d4282913,7c717a1d,f907d441,94fbe55c,bdcc7d73), -S(d50843a7,4602c5ee,298e9ea1,6ecc75de,c0bc2b0d,150546e1,4605ef8e,c0d33eb6,f95baa7,aca33535,b559aad8,ebb18df4,eec43134,6ccbdc72,a3551b53,9797b570), -S(e5141e1b,a2a9e653,5baa4cc3,71f143e4,c4e3be94,4b81ad88,4a1cbd15,1052ae67,afd5328a,75f3361d,ce8b7e84,1e091835,2ef1f4b1,986dcafd,40ac6aa1,12a65838), -S(892a2bfa,f1869c35,34b50649,f4e3bca4,2fb6845b,f831471b,4b6c80c4,650ab82c,ef6c3f52,6deeba94,563afd1,5b9246c9,b397ac2d,1ac38a79,c7f24dc,1706a402), -S(7a8b233b,94e81662,1ff28218,c60e56b8,15e7f48,9bf401c0,182f05cd,57e1aca1,de6fd62d,713590b,f0e81723,a25540ee,3a98b68,68d4bfa3,d0b64b60,1bd02202), -S(66c7766,ec95259b,ca729173,a721d3c5,a1fef897,6ea25f9e,4c5ef3bf,93a659f1,23d66628,1cdd28e1,18cea2bd,bb8bd13e,af6fe7eb,d282e5b6,858656b2,31a8463f), -S(14c8b905,9c41ba45,7c8ef52,c78bbc43,6a9dbe69,4e8ca807,1b538e0c,eff68d64,e4c77c72,5c9c5cb8,2cb26618,7fd77fcc,cff42520,5428c0b,b7a5145c,fef3ea12), -S(ef36e454,185b6147,9e0c57e5,92ac7b06,d59a4d21,6d0f4794,15fa728a,181e4024,a2b298d0,abdf1d93,7e6a15c9,4a77a72d,4cbab1b7,5b27ff46,c217d1de,b47bb006), -S(6848b754,920b0919,b96c7c54,5329951,ac7f71,7cdfcd13,9923d4e9,d4fc3ab9,a9e4722a,59c84597,a6f9eb15,50230182,af76f6e,eb8f9b80,c4b14d7,2f07623), -S(a8f4f96f,c417bf04,15116fc3,d223494e,4988e32,855e7cb3,c52f3c77,382227ef,3f5ce509,f0aa36ea,c23603e9,b08e08db,4a9df67a,bd1735ea,1f3cad02,8f63bb8b), -S(372bce7,9b26b7d6,6026375a,1d8f7858,4770d17f,e23a53f4,3d84b577,4e1d540f,ea6ea296,59226bfe,cca23e38,f341dab4,a3750d10,c9e9d662,bdf90b95,c68ff345), -S(ede230c,fa48b0b8,affa246c,af849946,3c89b87b,148259a6,bb319895,c5d1decb,76eee3c6,85fbb3c0,ed86e7ec,9bea6189,56ae98e4,d1c7a17,e9f7d796,eb8b1540), -S(1fe48c38,964fbf0,438f3b,95d15871,d8037e8,a80bcef8,9cf19a54,370457cb,33c60da0,ffed0f,392758f3,76720d71,42a66034,ecfb83ce,ecb05bc3,44fa9fcf), -S(3ef6a0ce,d6b74a75,7da5e17e,cc0b215d,9cacd353,44c90c07,cb7b86e5,2066d500,a361d55e,82a75506,ddea417e,5f3ac744,9642305b,92a9bd18,b8fd2fc9,b3e0bf77), -S(165c9a99,4f26f8ac,528caadf,57d77d82,b74d3f79,1d2f18a4,e5947aba,7e25ff56,3016f139,a0e0c5f5,abdc57c0,86489330,f3b83dea,46396fb9,d1052753,785da130), -S(e07ff9ac,650d90bf,745bb6e0,13ae6587,e96feb6c,e1c003b,c0c44a6,6ec415e0,8bccd0e8,77dec06,e4aee5d1,76313cfe,de90e6a2,8e98e618,70e31b8d,8da3540b), -S(d1133e3,62cb9ea8,4d4da51e,763d1b23,ee018984,cbb2302f,c5789278,e60cd0fb,b66e8a8c,3f41461b,8d1358c2,5761456c,b5c086eb,b67a0ba2,b02166ac,9b0b2d65), -S(fe40c8f0,41c5f50f,789b4c2,275892a4,547da456,ed1a7558,8529ecee,6810fba6,a27031bd,d4290077,ad0e50c7,787a222c,3c89b27b,13159117,eea61c29,f126831d), -S(83b7184c,2b76a015,b80c1269,a78272d4,374a00d,340500ea,ea5df081,18ab986b,41ca7c04,774653c3,87782499,ae88e219,a16e53f8,1a87b1f8,768933ca,8315df89), -S(7c230724,b72fe375,bac73f94,5df4e542,c6789c1d,ebaec636,730f07a3,6c3a0648,a173576e,8c3f56ba,543fdbbd,c650d004,3fcda4b4,4684a6cf,666b7423,9cee0152), -S(652207a8,aeb1c301,932db5d3,854efde6,da5c9912,ca6833a9,79499ba,8549dc7d,14ff67f7,d0d82988,b0b947a9,b8ff8914,8bd0727b,f72e9ba6,18028c42,792aa3c9), -S(13422e69,12a1b8d6,db99e17b,7606f3e3,b6d5cd11,5f47d50d,587e131d,477f983a,f72d5395,a5b1badd,88074638,a079797c,134d7415,a7d4be7f,23b12b43,f1f2b1b2), -S(3605aa35,29438d1,90c78de1,7223c468,ef36b28f,bf7fa6a9,d809b113,7e251481,9de174d6,43288a16,3dbaa04d,f4cd8214,f3e68c8b,13b71ff3,215447f5,2522b8ed), -S(fabe9cb9,d1e80ace,f13e49c0,d9cf2e95,12091e07,a9b0ee68,144d92aa,8a3f5f7b,7c05d1d2,7144b868,33c1dddc,8374d4e4,16df20d9,e7111415,8203ffe3,8f662823), -S(df84793b,e4c7a574,9c5cdb3,10ed4e96,c05298e3,d7c7187d,93018dce,ac6d75e2,62d04b5c,1cb578c3,8784db96,8fb8786d,59c92183,c226df41,d164fffa,c076fe2d), -S(90585ca3,730b76,78a731ad,ac186574,911212ab,58d826d9,95499433,5cffbdac,85bcac15,d41303c7,bb2b2f87,eb3d5101,eb35818,815711f4,fe72d243,50f5f6e6), -S(89e17bb8,56178598,74821db2,28956cd3,8e8cc6ef,568ff68,5d5c2e22,5cadd959,e759f802,faf4feb7,4ddc888f,38b8faa,2661c56a,367da1c0,781ceeb1,7b30e37e), -S(1d43bd3,df9f1f25,c061538b,6d4fa0f,dc6b3be1,c7443616,51420d09,7aa81e9,ddc8f865,d85daeee,6faedd8c,172568fd,d290dc12,fd41925f,868fa03,ae8176c1), -S(6899bf86,10d6f8f4,f2b50e47,1eb5bf9,77924580,3b3a8636,b161879d,35061e5,c4c472ec,37bf52b0,3de23bcf,188dafa1,5aec0c9b,4f023e9,b54a8d9b,2940a66f), -S(b42ff8f6,6ea45365,485cf5af,ad243cf2,f6d63e0e,d4a0386e,475dfc99,70b9ab65,46d2ea18,495a980e,db65262f,efec578c,ed829315,15ac74bc,83d8d385,d739b2ae), -S(cc1d2622,9e9cacc7,f84bb974,e06e9dd6,62fa261a,a90e271c,332c289,1511dbd9,206e7e03,b8c33605,ed870f52,2e31aeb8,1b9f8a70,86732a49,6761f00a,bf0396b8), -S(21f031ea,16cd5c2,3c5a809,3a93656e,950feed9,64c8e2,debc0a98,64c3b30a,2d038c76,f07d43e7,f70d289a,32115679,232bb02d,7f237f20,82f085a4,2031f61d), -S(8bd83272,4e955741,3a6f5fe2,b5d0cd06,ca80a3f6,eb8f6449,516274f8,f98c689,71559502,b2442397,62319105,3b440a7f,fcff2a76,bb4e9552,37dacf33,b26d19e), -S(74c61963,edd7e01a,5ecbc8a9,76a1f24a,fad2b1db,1e632edd,6ebbe3c5,49d2af07,9247fefa,fd6ae328,f3cb918f,3b6ec823,4c0320c,5a317a54,19fa17d1,bcaf9f99), -S(1d7e54a8,597a36fa,4a32a46f,b40fbafa,dfa50c42,c4dc2228,b30c53a4,17b38f24,cce12594,2f1fea05,1cee6589,c26ef75d,f88d7242,bf3460cb,7bac2566,498e8ce5), -S(c788085a,893e3e58,bdad60f5,a177601d,5af89805,47bb9e1,2bdd2294,a850bdc4,44292afc,2ffbfcb0,5ac838b1,224bfa98,fa09f219,b81611d2,d83c9239,4165b415), -S(d87e2357,7984ef30,a3243b79,f0a53f84,93b38e4d,6b182c47,d1e6f48e,3d38db8b,b42950a9,16c616aa,1fbecbdb,70868cf,28106872,33b3b549,388c2255,a157a50f), -S(5d3ead44,592168fe,d898a5e0,bc7c0aa,ef926d4c,6f06698a,e5274aa9,90307ef0,ccc1e0ba,51eded41,714e8039,4a626a20,1ad5b751,5e6d8ad6,25895be5,8289f1f9), -S(ac063972,75d60207,fdb67802,5d86424d,d47b7fb4,8d20402f,bc683c2,b7e9e63a,b02c5027,e2488ee2,4c53365c,d9101fb9,5bcd0c45,85e25738,36156286,fcff1c89), -S(815a5ad4,fd1e59c0,56bfeeeb,b50e5728,18a6412a,2eef8d42,7e27c871,e41fcca5,4f358e87,5c7b6e0f,ffaa3026,205c07b,4a438394,276ae929,e24ff4f0,307e956f), -S(10902a4c,a24b6807,ba67d735,3fc9582b,ebfbe13f,fadf8146,e40016b1,40956db0,bbfdd872,793fa436,5263d277,f2ae1512,b5f349c7,270561b5,4c151824,6b430743), -S(858aa1f0,dbae0cde,a7640775,44f99261,af16469c,602f31da,3345671b,93758d48,ff63509d,d56ff954,3cb112d,941fe16b,b5fef4bf,96b8923a,c0e3d3ce,6f0e4cad), -S(1be90c71,7032671e,3cffce34,1a6c507,e5564576,ebdfae2f,bb28a20d,ccbbd6de,69edc8d2,20bec442,2cc47888,22eea780,3d4a01d6,1f8da9cd,4f8533f4,146c16cd), -S(6149cd0c,162f1ae9,163751a6,e967422b,8a80816d,deaab38,e73237c0,cca923f0,9dce938f,fd20eaf,b518752a,9cafb862,8416e3e3,8ba723fa,12442844,1bc7a477), -S(20696c11,f43db49b,d891505d,cffd36a8,a0fd20ff,1c56896c,51591ff1,421680bd,397ba456,6566244b,a186055,bbbabac1,620d1b9f,9d2d06c4,44069ba2,22041d79), -S(caefe4b7,91049900,5f6247dc,f1e49aed,22493a96,933ec702,c93f83b3,455fd6c8,6191fd17,4ff0887e,886086f8,c8f9cf8,5d3d3e03,30f436c5,50ca153f,cc1af003), -S(849d894b,2720850b,bcc0bd08,678205e7,1ce2b041,40fd138f,e16709dd,f3c9981e,8909d10f,494af391,a3ae9000,7af2a292,8f066ff3,22199e64,e3416799,a25c43f3), -S(d27b2fb6,e38544f9,eff19084,cc901d70,3356937e,292c1989,856bdce1,f6a22364,8c296bb4,a89bf08e,2ecd87b5,b49db335,b6e2faf1,b1b57146,3264993,77e56175), -S(37e04b68,f476235a,728bbc12,e3572929,97243538,e37bc2a6,bdf6b7,e8ab4d63,ce346516,383c0573,9de7a2cd,c4b0c0ec,9c3f7bd5,c3e8c27,271cb9e6,7ebdba4d), -S(b3c6c10c,5eefc0c8,832d9c99,183417fa,9351868e,42952b96,2d623305,9a1a3eea,d7ad6ba,968091d,fa8c68fc,49aff425,44f35d39,a75824dd,a79c5b1b,602ed3ca), -S(5bf180e6,763045ba,1453a353,49711a67,9175a21f,f2b7b381,8c8e5d8d,4927f107,72ed6000,6cbe16df,48d037cf,237cdbb7,93705ff7,2bf38c73,e6a87f1c,46ed40e9), -S(82e13ea2,3cbf23,ed3e2f47,922b08f5,9be10fe1,48de26e1,168b0784,45705ec4,288ae681,decf904c,d490b6a4,d5a3e5a,75bee593,ddfcce76,693ca57b,f39c1805), -S(4ac56d72,b9a5587b,dbea0ca2,674d343b,15adada6,f30d7a3b,fa481f7f,69af9467,5db2d7a3,3d42f04f,c75ee27d,7a7fe9d6,3eadc5fc,ce770e3,78d09ff2,eb62d78e), -S(bcddc00a,4fc9976b,6795da19,44f181cf,6bbfc775,cf4c0212,eb419580,82eb0e4c,30eed6ad,bbd149b7,49053931,65941084,470f0338,396a6c57,9fda211d,358a48b2), -S(9331e909,bf2663b3,8ef46e21,2293e63e,c7c1559b,853c3095,cd749971,79f116db,8ccef168,4504893d,30418aa,343b3f9,3fb0db2d,895359ef,f1b78d6c,1f074fe4), -S(12df2aa,c307209a,23b543e0,7e220557,3bbd8cb9,e341fdd4,6326ecae,916c329c,48d2da1b,dc2a251f,a861339c,7b92bea5,cfaaf0b2,3f4bf625,7493df8b,228fc8c4), -S(987e316f,f09ad376,eddad996,98228fab,90573f6d,60f13772,e55429bc,e77a91c2,82484e05,45aa13ae,23007c0b,7d6e0d0a,7b8ee542,bc50ed28,55ffc819,aac4cccf), -S(7be67dd0,e377aaa8,f13899d9,3ee2e9f1,623d5efa,ece91690,82c9dde9,ac7905a3,ba82932,93f21a43,23ff368a,86c8acb9,63328f81,5f003f5b,604082b2,4d4dc3e9), -S(133110e3,5e53940e,928883e5,fe5150ab,303af955,7450d37f,20dff5db,c8e2030b,54ea08ae,730c8117,ff1abf61,e89fa960,2e434dc6,c43c6a35,3a45d535,69f7bf96), -S(a000b820,53c27e06,3b6ac0d6,2cc0bf94,449ac467,800ebf8d,5e6bfe91,bab6cb36,af600aea,4261cc05,48e7e30d,f9ba50e3,e4ca8708,aa276bf2,ea7e384c,f3e3880c), -S(df50b710,59dd653a,f1f2b8d8,f39e12fa,134f1020,4e794ba7,9a734a39,eceb2217,17b8416c,51c8d01e,7739645f,eb5344c6,2c5b05b8,d27aa83b,d02def84,c128c04d), -S(b3b6ea83,cc9ee99,d7518cf7,94fcf12e,5f2d9845,b165330a,1e55c4a9,4a601b45,7e9aaee5,3dba428c,b042c0b8,87701d57,bec9635b,f54bfb64,13742d7f,3a7576fe), -S(7c81a6e7,36ff8ba1,82e516eb,b47be4fc,98e926f,bde294de,e371f068,687953c0,9d8d9b8f,a5b608eb,46bb5fa9,e162ff4f,47e2a8f1,86f41847,1c2433b2,462aec03), -S(e370435a,c9b0d2f,175786d8,6e2bfef4,ef7bdbab,3048fdc6,abab0fa6,ceee0cfa,586bc07b,a05088bc,ceafe00a,dcceb00a,4c1a3704,2f43f011,218ea8ca,7df4f04c), -S(999bc950,1d0b31e8,5175b27,17055c41,e5711b91,fad9af7f,82018e4a,a8f092d5,592cb475,2cd85ed,23d10139,55118027,7f6b5065,9b374ec5,55cf8f08,bed57ccd), -S(2241da6d,60fa77b2,f844f4e0,6972c230,1305d1d5,5d1a1453,16436693,232a622d,1b3ca0b0,8ddfe046,b916c1c3,7e7a29ad,9d235e6f,4f9aa72a,9676d62,e3770035), -S(d4e6cce1,884a77e2,dcfb08ff,6e4717ff,ec85343b,fa2b3415,1e290c2b,e9560171,3064c1dc,9eb6fbff,baac5bcb,ba14ed43,523db1ef,8fbbeb38,3e57dc9d,945e539d), -S(d2baeaff,eb5a040b,a7627374,ebf692ee,65316c6f,b30c03a7,7a6c7882,f98d0ef2,7f5b6e13,d91cd74e,6841c97e,32ad8e4a,3d8c572,1a206b30,e89c6f19,43313f2d), -S(150db822,7f60d338,73602400,27e859b8,7e4cc5b7,749d8d16,6ec3ac03,cba95331,12938598,70c09913,a855559b,2544d3b3,3de7a12e,da4aeedb,72b44568,7f6ab9e9), -S(bd607750,1e8d489c,aa24a424,8baa60,e0a86ef8,f9f6ed17,4537d826,c3e90fbe,9617baa4,c6ee1d2a,6231b3aa,5d145b30,6e0052ea,d1a0cbf5,1f74ce5d,7461b54), -S(ba04c85e,7755ff09,97b5c7a6,552e79e7,455b85ce,3498236b,6452958a,d01e04b8,e82629e6,1513be7,719c2e52,ddb4e8e4,3530240f,d4e3f199,b1738596,9498321c), -S(be1c6207,4ee93f45,6dd94b72,afdd295b,f751df9d,a77ebbe4,8e5de0a6,a6f9ba8a,3a1fdd34,72474e68,83130c08,b1e99e51,5c3ad11b,7c321b52,fce159a7,127599d9), -S(21c4ee54,bf48268c,44996b18,aa38a92c,7553eac1,2f4bff57,e89fd389,c9ebb1d4,7a0cf9a6,c45cd57,d0a1aee,3010ed52,220194cb,ea43715e,a4252272,71064b6b), -S(2ff1ff0a,14c965f4,9ee43f0d,64ecb94a,344d36d3,d90616d3,2b208024,4729d291,47d74f0e,8c9c7dd7,580ae2eb,3bf07a4f,320c80a1,13a5eb73,cfaaf7ca,e38e9803), -S(6d5ba86e,be2f0de2,eee9d917,aa69bf71,9ee9e93c,1ce7cf74,a993435e,480b5b39,9c19c406,1d3fb92a,4dc26c8c,26bbbab8,5b4e9acd,950a7ec6,824aa915,c1f9cd66), -S(49316bcf,122ac309,2ece7f07,c1449a7e,db2bab4c,29c7243c,41dff1d0,feea6aae,3fe2db4c,26ebc1df,66a03c16,deeb4f5b,4a3a32fb,2c2db184,7dd93738,a43e68b5), -S(329b8fda,fed0ee52,b86a0963,54c2141f,c22734d9,fa8e25c1,4376d539,72f123f6,35365b1b,8ca97c37,1f3c0d34,599d114f,ee3b67c0,fa4973ca,b0aee621,5f07de1a), -S(c74140b4,8c998c17,e7895174,b461c733,e687f71a,861d5687,9535f11e,31ecf62a,4a648bd1,5ce47fd7,b9a8382,7842281f,59a6e0ac,6dd049d5,c05748cb,ec607556), -S(92f5177e,cddc78ba,37a947bf,c72d4bb4,531ea7fb,1e7c103,d312fc2f,a8e4cbc3,2d348b69,cdf37794,383739d,3af49d0f,7fd9b0b8,1b5b918,9d3cb49c,ecd25d0), -S(31ca4598,daec4eef,975b3a18,b14420fa,48634ed9,ceb31b64,faea0fb5,32673490,574e1a82,b029e852,6e12a242,a21179e3,d7835a62,384da226,c7b9c879,43ef506b), -S(f7a66fa1,103f1fde,1392d998,fd5d8c2d,9d4804c2,999df8a0,c3d6780,ea915b36,94b115b6,897e00bb,166d01e6,e0b0e3dd,7399e7a1,98985a00,f06312bf,e31ce81d), -S(39cbdcb5,8ea994fe,f678e688,c01fc74,a643b907,b7d00c59,98d609c2,898274d2,5c256316,3717961f,3dcf176,73183034,9d881d7f,11544246,1a42a9b2,8b524e8f), -S(56fe8710,6d493892,4750fedf,8cfd9597,766699b3,ef9efaf1,26fb0441,d01becff,6b16649,80e3bec2,9ec107a3,f02a0831,5ff24460,b0b0e29f,208610c4,a3ba722), -S(e9ed0bf2,81770721,b3132049,e48ec3c8,9b33e62d,6eb3f1cc,b50ce7c1,6cce6741,ed06f8a7,d93913d0,fbdbd2f3,ff5448c8,f004f690,340b84bf,ded66508,19c356ea), -S(a3e250a,e5f568f1,fdb0d60a,8856aabc,a3d35a9c,4f23c07f,587646cb,41b9d29,3d2c6652,31f48e61,a6c4b571,6ba8a07e,5c8374d9,2d0ca6f4,970aef59,3f2a78f6), -S(bc08e135,216208eb,8bed1164,3deefd2b,a89959e1,20d3aefb,4f02976c,ebea4fd1,bd59151a,ecf185d,a0da79e3,817c9b67,605b46e6,41b733eb,a70180e0,47bbc4ae), -S(1008a624,ad6badc,60b3457e,702ab324,6ccd3f90,aa64d741,69539116,64ce56f1,de2d4c03,69f0faa3,5e039afc,1a650137,cb299fdf,8840bdc5,219bc9f7,b94c7219), -S(a298705b,a7c0a8a4,7b68b674,c63d9d7a,fac19b56,eba7f866,59cace5d,fdbb4b05,7b20b074,33988789,da3b41d9,5a9f0c71,f2965ff0,16714652,926f9e32,287f703e), -S(325e58ea,980fea75,a79f4254,60afb0cb,8f68bed0,71857e89,e4e7a88e,34b5cfcd,7034e0d4,ca1844fc,47d4c813,736bcfbd,7cf0c693,cbdc1ba7,b0d29019,44212c16), -S(22d51a7e,22bc439f,9179932a,254bcdb8,eb5bd7b1,515645e0,2340cb6e,8b94cffe,1da471e6,1c8ef75b,10525d6,132a14af,9096a429,e277022a,d667e204,91a786ff), -S(490cd510,a010e368,b3e4f0e4,266bd0c9,c04e3434,6d039f0,764f5108,aa31d6f2,2ee7815f,9ec437f9,3dc69f84,b0c91231,326c0159,4cc492f0,1f9b8d88,7fc022bf), -S(f8896cfb,f2d14e5d,ab1f3c2c,1e669cae,433a8a9e,42c7e68b,206a0d88,b4aee3ec,a84aa805,677a7c6,12e7930f,b91293ec,afee667d,2b033019,ffae8d8c,bb7281da), -S(9be847b8,3ff9d27,e74db522,cbad0ceb,3feffe52,1dd8e7f,999e515e,253ab848,c2646e15,b0865eab,c459a0c0,233bb52b,e202b681,c060f06b,ebb3a39b,69cc19bf), -S(1c6e7cc3,f35b404d,61d0454f,1a9b5c58,40b96207,95b613f0,a896d781,9e29271f,352cb00b,5d556077,c9fc75eb,aa1c28db,dad01cdf,dd5e75fe,ddd43ffa,8042385c), -S(56c10f,e369938f,13863e7b,5135ffc2,6da9eebc,5cfd6eb0,7f7d1f67,fa94132,8bdc142a,f7ae1906,c63e3de9,5bbb63cd,650ed4ac,b9a2c321,e525b512,397c5e99), -S(70897a5c,2d8d2e10,d24a0c43,a689c11b,be2b9f2d,2934ae6f,b3dd130,34046227,3f9d0207,3e083e16,f64ac869,5c1616e9,8f87e8b2,c9c95ed3,3bbd85b2,dfbee7c3), -S(e2fcd5fa,5c6af2d5,1297f97c,d2f0918d,320c785c,ba3802c4,48fab36,2147f39e,5308f1c9,b9a24e1b,855b038a,41004b2d,492fe91d,8ecb076e,9aea21ce,ecaf59fe), -S(463d53de,9f07ac1c,6eb5f7ef,2bc70046,261d6a64,6fa516c8,f7677ec9,b2153acc,ca198775,f0f19d71,48c138a8,4f5472f2,f8e5cecd,e2b7df53,61261cce,f322b762), -S(663438d1,82758d86,f292f12e,cd173445,2b554cac,1561f0c5,8f5fae70,9b165c21,23eb676,75e8f8c3,e78fa6c9,99d6e185,e0f789fc,80576620,5c50518,39e15515), -S(9a8317b0,65ed508e,4c9239b7,af39f42a,1d43bd98,8fc101c1,d45987cb,ca58f7a6,ce0db1d5,4df13594,57d9df20,6a487348,97102335,dd24b2b3,6e10bac,4d9b5808), -S(da6f2ca8,915e313b,8c4b221e,b81aadd1,e7468004,8030b8f1,48d1b733,caa33be0,bb59cc06,d267cb7d,c954338,9010d49d,466e4c3c,91335f62,1c4fe7de,d17cabbb), -S(7a18820c,1774251f,c299eca7,871bb526,b01081b6,c5321056,872da42b,9198954d,3d216aa6,1702fee0,9cd2a72f,e53d6092,2b07b51f,506f7a44,ae490af8,c9da7598), -S(1240d207,3d234306,70d9f2d0,17bf81dd,728e728e,5098238d,b0d79397,2628f5ad,612c97d,13c5a948,88ea389f,e809b656,77fccfff,d5db913b,771647a6,680fc074), -S(3862d4e5,c973e75d,ac6e6ad3,1e3e24c6,e9b8f5e8,6641b20d,f0bdb04b,ca98ecbb,524c8d0c,7f485be2,decedee,8320ec4c,79b1c25b,414e129a,2f848de6,ce3997b3), -S(afe8a621,bbdb4908,5726bbdd,b0d31469,33c75a94,bde06805,179729bb,1518467d,19b94d68,8a7346b2,e80ccec5,a393b7cf,afc4954e,5793cbfa,e02d7f70,7610fc85)}, -{S(50cd2e16,997d7d45,98bb2d9b,61aceaff,5ad5f38c,8286a0e1,d08055ad,726c7800,dd19c3b,c08b8d97,88f9de1,5941f5fa,6402bbbb,5fdc708b,cfc08844,eb23733b), -S(428114c3,8fc9e242,451a001e,34df1509,1f5c14a7,870f110a,fbcb0895,4c4b2496,4c41e9fa,ef00faed,fd12d4b4,9f5322a1,47ac4a7b,f8c7fc84,3a6250fc,efefb84a), -S(c0b87aac,8a4ee530,8476632d,ca83b163,3616bda9,5609ce58,8c09a48d,f544051e,a054562d,4bbfcd57,dc7ecaba,f110a6c5,e75e2d15,226bfb27,b8f88172,2a2bcdad), -S(e7abdaf2,2ddccdcb,736bf2e6,fdd79362,b02453b6,5619ada8,c018fc62,9fe2a74d,8e8362ef,abe83261,ab1843bd,2a477a6f,4a6a4aed,462e266e,e76f5913,1277c153), -S(ab7c1829,d773868,7faf5581,150db894,4d0a4815,c31e768f,ad3b313b,b159f72c,c687f86e,7e7bf0fe,a625143c,d6d7d130,13986eb1,5b2184a1,9f42a799,fb6eb703), -S(5f041f43,9394e0e9,23c951e,1fbfb8c3,8e1e3ab,58640799,b4ecf906,a6b2f4a,9f30e2ea,d04ebee1,f5e93cbd,2ed2682c,f2c22a0f,623f981d,f59d414,8c4d2d68), -S(b1347d84,86341ce4,84433a1,d00e9dca,63b94338,3818ccf6,59b80582,a027d202,2d30882c,d961fdfd,bb6c38a5,a11b6e89,25cc7e03,fe48abf3,3bbd86a1,6a65887f), -S(6e862ad8,859cd489,16a865db,cda120c9,2a5d8862,460a823e,9c47aad3,88a1c580,8854b584,e25c1b29,1c17fa6,bafcd67b,11c9ffa6,480679c6,8e253175,3faa4ad6), -S(a1b78338,c54bec48,aedcd65f,c60b25f5,eda31e34,d6badb32,75c128b,e3b8e752,86f46d95,157e23f5,6ab1f851,93e623e7,f693d74b,a08b47e,f776eeb3,cfe2ceab), -S(5fecd94d,128ae25b,b29daffe,c0d0131c,74df3dc8,9c4d573,e59bf41b,3f83a628,4f2ee3b2,3e5a008a,4c26b525,a5dfcd69,93215d8a,8547f13c,1c871f1e,fb082c94), -S(bca9377f,c179a785,f7b470da,51bec3cc,d6306938,f21cd224,7bc69651,bec76b36,cd1b6406,a55dceb2,c34e5c70,ee7fed4a,9ea3b1c9,92425ea6,72aeaf04,e5a464f9), -S(95d910c1,684c2963,6f90ac23,32461ef8,6d87ce1c,7dbe889f,405abb1f,cd0f57e4,1f095ce2,45a207a6,3c8b0602,4b4f25f,30e541d3,c325ff2d,c2c6a9a0,2db14235), -S(77cb5deb,ce99ddaf,4aa546db,274be540,a29b5664,5fdf411b,879e726e,61bebebd,df4b42c,63787720,42a10781,fafa09d8,e0329d72,1bc2189d,5dc0b56e,4700910c), -S(152ef349,2f9a22c1,87b70012,5b08a6da,68b50df9,1e671571,5ae11edf,6a35a3e8,d22a3f0c,654d88a2,bccfa6c8,704b99d6,7f5cf72d,ec1213b,f2c682a5,1bb91c81), -S(aa9492f9,6a2f4ad9,6f9d3b57,312edb60,1ab404e2,52ebbd4e,f86d5378,aa7282a8,bad928db,b54e8af4,2931d08,612ee412,c504c28c,31274bc9,d63366c1,c7f072e7), -S(a89ab05,ccb1edbf,1d95f7e5,5b2c1aea,e1c45b03,e352b2b5,b0e6a731,898a3453,72b9172d,548e4899,d24d5feb,87df8432,e1a6dc84,8dd28233,58a48c59,578cccb3), -S(e96d95b5,93801cdc,1b2b21f8,81f4154b,3967e7f2,84fc5a25,99c4fe5c,cf0ce66e,1a43ceb6,afcb7bc1,f285aaa,57dbb2d3,10d09cc0,1942aa72,daaf550,4c3c6bfc), -S(21de9188,2c8ca8a3,847b65dd,c667c64c,8378a756,cda3b9c1,bd6e438b,8b619cfc,d1d64895,a03b455c,1f52a019,6fa3191f,7dc57f9f,419d159a,d0faa03e,ea1f09e2), -S(9df78d29,3fd3a96c,f3d73bf6,7cec9246,edc8f68e,7b10e7bc,8a14e8c1,980eeb4b,d14369c7,993e8ccd,b89ed1ec,18a3fb7d,2659f70e,384a9f3a,55761eab,5925bcb6), -S(81a04986,e34ce13c,b01e334f,78bf2a3e,941e3e4d,243418d4,46fc0cd7,86f5dfff,3b6093dc,864ad994,f1c3b88e,81a46f1f,a916b51c,2d45eb06,46793fc2,e070abc6), -S(2f725b7b,8ba1d7c9,1c7b2d0b,65fd4328,f468b516,5cca7699,3430669c,d5643b95,dfc13e39,8ee1099e,4ecbd8ec,8847caed,e9872ab6,c9b0533d,b6191ed9,fa9b0e0f), -S(794a6094,8ad0dea0,907a4010,222754ef,c6e67a7b,d6c5957c,5eb004a9,a5518693,59897754,d7799fda,fbb2cb22,57687440,4c4c1318,b73745e2,e37b7f9a,51eee929), -S(7110e58a,64e526f9,a9caf9f1,e0ded62e,53450a64,3a6cd150,76983083,1d113dee,4629d7b5,e44421d4,4631658f,23ea59ab,1f15f446,790a600,483c1539,9c597aca), -S(1d550551,fc307b9c,b16f034,b79e7937,79127f55,8258461b,a786726b,d4c4aa65,51c47d4d,70f9090a,a7f8a183,75f74d4f,ac9c98ad,5c3bb916,bd87a9,aebc3de1), -S(4973c3e,97daec54,e5b9e9a3,6343e7d8,9c57380f,803f597a,25a386a,a652da69,cf403eca,b165571f,6b509b04,284c6e36,2f082b5d,5e7bc302,3ec0e55a,e73bc4f0), -S(61f7b3ec,444021b,ee3fd421,18e7b7d,fd795b36,d0145b08,ae09e1f,c0e3b07e,7df1f20c,79e3a7db,72cc08fb,98fed87c,ea923a91,815a187c,55e4430e,cea5e963), -S(42426dcd,302f698d,9376959e,50e6f471,5b1e2371,fdb03861,6ace0e2d,e27fa90,4c054664,1c4a0ea7,8280c526,70455e3f,51bee24f,acdd46d2,e9f82afa,db42d1fd), -S(80939488,3eaccc24,b1639e9e,656e7b76,2a310c4a,778b390f,d7a708d7,69c63fc8,b83fb593,a2e198f2,5fcc7add,310c8285,c19d314c,7614371f,9db28e28,8c2d47b1), -S(3f52b480,40e1ba54,67cd752e,a0265f50,c3bd1964,8f54dc8c,8dfaaf16,d9b3cdff,207a0014,1ee322cf,24d81b6d,2a7ccd87,be4d0b94,a7df9234,c0093bca,3a36d60), -S(c09cf34,bf1b1f94,15b63dc9,8baf66f7,68b073c,6b88fe53,7a9c047c,30703ec,757fd4b7,4f0fda31,99928ba8,39999cee,f2adbef1,8cf2aee3,4ce3708e,2897f95b), -S(8c1d9d66,b10dcb56,1fc72060,db7780eb,187b38ef,b18d6222,64188a60,da748871,b413ca7b,61ffe6c,16d493d1,1f955cd6,c7d7bb53,1ec4191d,85cf2f74,4506d8e8), -S(e31c4039,f33a6a5d,8682c906,612aa37a,3f522069,3948bfa0,dab4ccda,4f08900e,17d345b3,e92d1174,73330b73,cea9b1f5,f1d95ddf,40bd027a,b9b9a0d8,f84d5e26), -S(c4d82663,9c182e6a,b12ca500,3d5eca75,ee2944de,b9222c4b,6f73c58d,62d24bf1,cf4a0f43,e81dc58,c975d59d,73811d14,b01587c3,1ace50c0,b0b41f26,1f010e8c), -S(7c2514e2,fb6bb04e,829d82a8,ed9160ef,c9db98a,f898644f,bf2d01bc,97192be0,72114f16,4ec6ba1f,c41d6b0d,6746da06,4b46a506,171707ed,36cc6051,85f57ca6), -S(fd74379a,f6a18e2a,cd330fc2,49e346b6,89f7a73a,5f4d8862,4997a3f5,826a244e,dfe69f23,b9b2e402,f612abbb,4a4fb044,6a040706,19d6596d,b9953e6d,7179a9de), -S(a1c639bc,b913e3db,5702956e,9806430c,6572e908,a129bbb7,7c8ba5c5,50edb48c,7db1fa15,4c5841fa,c2127793,e9bef5c0,f749c99,66ff8d92,5a8ffb54,e701579b), -S(922dddff,7449c027,daa267b6,83112b45,a864a11a,1bd1cb61,ca76fe3a,77a6dd09,2beb84bf,87b85974,316789f5,148e4f18,386e20f7,41ec5066,2066c454,44c840dd), -S(ea7714b1,fcdceb95,407433c3,4c43a50c,767b3db7,fc7f6e6,81e79f46,44f044c7,6936f1f3,585c04ac,a1a2a562,424e084f,44e0b404,f97f1db1,37b3f00,b02ee04e), -S(cb4c8e7a,f5aca51d,448f3463,9c631821,9dcf6377,9383ba05,5e44966f,47fd36ca,8b0ff5bd,e8285a2a,1f4a223d,f6d496c5,15825ba6,d835370d,b2313418,b947b4b2), -S(921d8dd7,ba630901,3f365eec,ba09d017,2d579b8c,9550f6f6,a6d098c0,bbd08b3a,dad72fa4,9b0f415e,d9f96bc4,78a93e71,98d9456b,6ae10f3f,a1c744c6,e494e5fb), -S(7c9467d2,2cf5a364,191bf731,1ada75a4,3d081226,ff2e359a,47868572,3af15f29,50b15ecd,73341559,32ce1c54,e9a25b96,15dda8a0,6f4bc132,cafceb57,2fb48581), -S(48d10472,c10f4c90,713f899d,65f6edd0,af1724ae,117174f,55d4667a,b440e13f,baedab21,45103f2,aa668f05,2413b8d5,61ce5957,bebcbd8b,c49fb824,1af21303), -S(880d76e4,b95a3a8d,7ab6f9d6,f2069668,80069c0c,c447dcb8,f6063d9,271b570d,150d6984,2f638d03,881480f1,bd2a1958,9728ad72,f97d909b,17f79cdf,78416360), -S(286eebb7,f9215e09,969d8300,72b15a32,fc7733a0,455d2db7,71e527ba,e81caca,8584803f,db64bd55,317dcb87,a8c316c2,f48b3417,d0087527,338635c1,f78decf9), -S(b3e39ada,c92e1922,de3922c8,2c7e19d7,b5d10f4d,5e2cd771,492ba2db,444ede5c,bf9c1afa,d2cec5c0,66cc9e9d,61cce716,f58164db,e31f389c,2b596c38,e4c0ec9), -S(749ba52b,b88bc33b,b31f7aa0,fb95a62,932e447a,9a7a2926,56d16676,d66435f9,7075f278,6b7df61b,70065a46,7591fbde,ec40001f,242775a8,67fabdc7,45221691), -S(5ddb1306,a33c61c3,f0386141,7fd924ba,3118fa2a,53943221,b24cb748,841e4aa9,9602608f,4fd2f4a,511d012,320d05ed,bf1b5ba7,4da5f6aa,2dccbf0,83a18551), -S(6ec58a5c,d0ade361,93c644cb,e96e64e1,f2b519d3,80f7162a,b962337e,5b5c8918,85bc58f4,49b7fc44,1e95721c,b9fd8cd,63e8a250,83d9ffc7,fbfff18e,a2ef7453), -S(9b2f11b2,f66f7b29,e8421aa3,549c7565,87cdb7af,24354a3d,5e397515,f53f8700,3faff052,d2557793,b14a0574,942fb52f,1a53f6ba,e7f4c6c0,a2491194,2d9ca567), -S(d260f1e7,57c31844,9e12f1c3,15d28bf9,fce06b1,f7ce5db6,3210ab74,fa45cde3,54952184,1936423f,2314754a,5b419041,7510f396,90996d90,47ff1225,46672ce4), -S(c6b77e18,b935c842,52aba9bc,2a5f9a6b,86b207ef,5487e89a,7c754a7a,bd03b3df,1ae09c2f,61732aa2,9267ba72,8e22241d,efd6762,16b3173e,239cea45,60ad3978), -S(ea2c66da,fe996ba0,ecde644c,28fef595,490710fb,1052b81,57b63260,e53e5a83,ee91b4e3,cb71b268,dbc394db,7744ef3b,ed0362af,592bf252,71b8ff62,b821b8bd), -S(d6f6061c,904d3a40,75b2c0db,7620a6a3,9a7c21aa,9ea5ed11,c661132a,8cda9031,48fd7dd2,50bf50ca,91d362d0,f646dd6b,7e0f240,4ffc2973,4f131e9c,dfaca469), -S(30538847,93e3b958,a808eeed,546484d1,10cbb833,29a2b2f7,6f61bef3,b47eb9c3,ba914a53,87705dcf,349f5257,6bce5ff,d711fff,6fc8f6d4,3fd61b1e,2b47a577), -S(38558d28,18358d69,ac6b59fd,22660f25,58d6a000,35469f41,6f0970ed,1eeb8a59,8922887b,e256a2c3,3a3ea6,e745222c,9f07e9b3,f94ab1fa,2926e04a,ccd0c609), -S(fbc47f3f,534e67ca,d6f6de48,b88a0846,ceda2d84,afbb601,db71a61a,fd2e11b9,dfbfb0a0,652fdf29,5709b06f,2e61a703,d287b2f8,cee4ca,6a9f2627,2c30fd9b), -S(614d35c7,23a14b11,f3ea097b,6aedcf2e,536e077f,85cab312,74b7c9ff,a6b3112f,5b91b524,5a85c3a9,1194e8bf,be940984,c5866702,b51417ce,7a436642,d87edadd), -S(8304c266,a9876255,70768130,ad244f73,668a6bf7,ac611ff4,e782a6b3,761e5284,e47adf0f,66d4cad7,5834e7b4,f1a26b82,d5f9285e,a567fbfc,5f7fffdc,3df10311), -S(b1d777bb,76529faf,3ee711d8,58ba2509,c378c99,4dbf27bb,deac9d98,cd0202f,11f7598a,55c079f6,7bd036e4,e3a3bffe,159477ae,45c33ac8,8321fafe,3141bdcb), -S(7b91aed5,408649e5,41ea21b8,326f9549,6228e3ac,4e460b34,d77a526a,7972e4f7,12dff7db,c620f9fc,4ba287bd,2744e1b,4294e723,cf475d58,22f718e,c2dc326a), -S(56e7d74c,a4e530aa,7ae803e8,734280de,d87092d8,78ce187f,4a13ee50,c3d58f0a,d69161fa,901bc6ea,fbe62498,4ecc70f0,24755a0c,100ace31,7e677911,5a4c038e), -S(c83cdd85,43dcd105,efe4312c,f8f5e73e,1849364,668f0e50,dc40b13c,1c44fda,bad22032,de13c4d7,f2a61ec,947f266d,812e8b3e,d7fed352,93d161a5,844c96a4), -S(fe6f32d2,68be724d,28d1344d,8406c60a,70a2a009,db4c8e42,f434534c,4df9c3f,339bc5c6,2692a66b,853a323f,d09526f,3b336c73,bb4cc097,7b78fd67,96506d6b), -S(c3f6f279,fc937a66,a494b2d5,3bc6c2ef,13088c8f,842e1d61,3c5a35b9,ef2fcb5b,41cde800,63e8bbea,b2246885,59817f05,417d5311,e9fc8b7f,6c247488,10b30d64), -S(3dc7d5c8,abb4be85,9f6ba28,67dad2a4,7ba7970b,ffd77ca8,54107333,dcea1dd5,851d695d,54d5d7d0,b7aeac6b,97a27a9f,2100fcc6,facdf142,c82cdf9f,79c5cf7e), -S(2e28aa72,54ca6c6e,5891ccdb,1a1d2a85,53008b29,77a04ea4,d5deb497,bbcb95d7,361191d5,945c523,8908e0d2,6c08ba77,aa7db32a,5f19e348,a0037255,4105f55e), -S(84796cd9,233a7af4,7518bf99,778abd4f,a0238434,b5239f49,fba6b27,90f67bae,deb650d6,be46f3df,cd80fcef,20317c93,618156bf,343e9b2f,bb158871,5ce40c2f), -S(dbbbbe08,e4c768c0,531a3158,9b8abc28,f747bf69,228d16d0,8b0091bc,b292531a,576081af,a5aef1be,9916bc4a,2abe3970,12e371b,4c05e5c6,c97879ae,9e73c8a2), -S(25f6b015,45a8e870,592d532b,de9e2e8c,feece584,1667235d,a1bac7c9,58350591,5faff24f,2fc43cca,285366d2,578814c0,879cabbe,cde4b557,e7dc6fe7,43462ba3), -S(1cdd628a,a5ae5c80,85e83c74,986dda47,1d12fd07,158b20d0,d2d58599,f4648fe3,57ed9696,31e1134a,dad47894,f40c3e56,852d1ae8,5fba733b,d46951ef,7b33e5fa), -S(255c35a5,ce78bb41,ce85bef1,9804a70e,86aee3a4,24dcffcb,47180671,475080de,783f23,71984093,7db83676,7c3e20b8,f216bb68,bfa8b90b,7d9d95f1,1bf2db1a), -S(517283fc,d1cf1144,4f7375cb,77af87b2,3a11ce7,a954feba,378fc420,a05a8c9d,612cae52,640568af,607af275,4f6060a7,40b89f00,5dc02274,f2c6b8cf,e81c2e15), -S(39ff6f76,c8e4b6d8,4e742b0a,67725f83,51b782b6,638a032c,f9690635,fed32d55,c3d54b29,bc4ab777,c027f5a7,3ee75b4,a82dfb8d,5a5aa403,9f0a8787,dc054b58), -S(bf620a81,d6ad1d03,a66ca76f,c3b20e84,2fc75ea7,ca7e1f64,9818b27c,902e1ca4,4894f0fe,c2aef2fe,67c8aeae,5a9f0424,1ef68975,955eeb0f,66f63753,5d559351), -S(4c34e4e9,7584b95c,9bc6608f,7dba493c,97022eb6,14efc494,fb721fc8,3388a06f,b94f610d,b8bc4bfa,cffbd677,264ec28c,be18cdc8,db64154d,b62c4316,e9bb59e0), -S(76bbfe7,d39d6e03,9be09174,52fb322a,dd3ea192,6b546918,41b97913,acf75247,7bed078,7752a432,f0275ba2,a97749f8,754dee1,a5cadab9,5482d27,3c99b1b1), -S(deef7e31,9decf761,18e42c7f,27f427e3,4cae0d54,d7a045f2,dbe68349,c5b011dd,d3e73e4e,8f89b39c,83c7855f,8b5e352c,64f7b8d9,7a00c5a2,4b1b7997,c1db907f), -S(23f66927,d6a94731,2b43d845,fd0ee2f5,8cc329df,8ec37f11,75392bcd,c8d48857,747d60ce,bdc9858f,cfb28fec,5841d362,5750dd35,d08d0f27,4f173fa3,2fa0c4c7), -S(e885b643,c668ee81,4b94240a,4a68126c,625eaf2e,6f9dea6b,230a0bed,dfe06d9b,b575dd15,7436244d,191e3b13,d1bc8682,76940436,16b52aeb,7c731b5f,120d4bd8), -S(4ae81c35,d39ea1cb,7e5787a9,6a7738ad,89a0aeff,c556ba4a,d4dd1c5e,bf5a4044,76a3e3f3,96b88cce,2c978354,16cb13c0,f74bf815,ea9c9397,86da049,64f06d61), -S(490cc37b,6efe437d,35043f53,682dcc1,2b2a4704,c8102413,62fe38da,44717b5f,fb5c012,b205a188,6f1d639f,228f6388,2c598299,d2d6ee45,be44d994,bb6b6328), -S(c408d649,f8524311,14582433,d4abe603,5e66413,e65dddf5,f2ce6854,95be8d4b,bc9a1d0e,18504133,4e4b43a1,9d34b07a,1b3f7cc7,290328a0,71437e12,ed80126e), -S(af445e25,7fcd5ac8,54992782,30280aa3,354d296,6d494f6b,90c883a4,829ee71e,f839efee,87643874,2440e65b,870b0e37,3fdbca41,e57f3765,2cf479c5,cb7f6882), -S(f2c1adea,d2f8e95f,ad6a475b,199cc75d,a8471b82,1da81d5f,6d8b2baf,a1ea01bc,8e3543b5,36247e35,c2117eab,9d3e6783,f48bc2b8,b20993fc,1a0ff28d,1aad1666), -S(17b3dfcc,fdd57cdc,8a617eb1,5ec80659,fc695bcc,afd3a787,fd91d8d5,69abb5b3,75f1aea4,70f52f18,d2eefeec,7fff7f48,6718f784,a47cb32f,4f2c8574,591c122c), -S(f4d6bacd,1c8ac10e,7e97a6da,8a7d1af9,1c96a67f,fe76982f,a0ac95a5,f9f5a9e1,ea6179a8,1ccba22f,4dd93b19,5e151d38,cbede6c8,70a4a383,edc7898d,1f8f19be), -S(8011232d,32d4bdef,1fb56ae7,3e231a01,b877be6,72567310,2c30478f,50652092,49b91451,23311b4e,6c038801,f84561b2,8db03ccf,3df20b68,b35714e9,56b4f67f), -S(e23dd461,b79f6b64,5da455ca,90711ab4,cc117d66,ea8c9835,67f70207,ac5e1f31,8e84c4d1,ea634402,375c4d4d,6e8c8427,fa2479fb,3461bb5e,5fbf1f06,d34c866), -S(a2f6486a,97afc8d5,8367a949,278dca64,ed265743,16827b7e,7f3710da,9d7dfbc9,a723d6fe,419317d,623f8e24,75b365d8,cee8cb15,d1c8df2e,218f1b42,a72e7170), -S(f789b715,a7d5ba20,c1f8cb05,86cfe13c,59d27b83,ad1ffca7,75b2cb7d,9af88999,149bda63,63072ad5,279885b2,be81923f,ac9c4d07,2ee57602,5d99e727,150a26eb), -S(24078518,7abb2bbc,721e59e7,923f9832,77b13422,912c983e,d8670e96,c698c1e0,7e2f792,7976ba59,20748e26,ce48b29f,6ca37a67,6c8b4094,e661d5a9,be39588f), -S(8703f78b,17ff31d6,89833226,8fa9db6c,759e6066,ef8cf8cb,719f49a0,d7af6264,3b9c4023,d92827a6,53a7798b,fb21fe94,cfeb592d,a55e21a6,8c6615ec,2bda7ada), -S(52f6da10,3d75bdfa,4e0e7637,229f0c31,a6f5aaa3,2504daff,e1ef639e,2daa16e9,5d71c088,e8480d6c,e51062f0,241d0b15,9bd143ea,451193da,e13466c2,bcbdd037), -S(c68fa920,9f3a997b,2cc91748,3570ce74,1a0dcd63,1d7b483a,6f73a3cf,17b53eba,1f26839b,86154284,28858ba3,a3084947,883053d6,3bf039ca,89753199,21e505ef), -S(ed2deef0,9f558dad,84202b6a,e2456f38,39755fe5,6afb5aa1,147adbb3,915023ec,40be5a33,a71290af,e5080e32,dd9fa12,4273f550,9e78cda2,395235fe,c78e3274), -S(3538ad8a,98625432,2e7a9655,4e12d822,812b87fd,778e4482,b255b6f5,5c301442,5a6960b5,d21b0a7d,4afd9c62,7caec1ea,e8fa82be,e2ef80f6,50c56101,ba3a76f7), -S(a9580d1a,2b6544ad,65e45228,8e0dbdae,ec6de5e2,e9efc056,ff048883,b9f435d0,1a70df90,3d932f52,a9b3123a,1384cd6a,cb5b811f,bb267179,e1e4407d,9269af21), -S(efcdd63b,3c964ee4,f04a6618,ae526958,db1ac41f,bc53978,84529401,c0c53a26,913bc698,4d51d792,919b389a,dbb2acb7,7b3df92f,138355c8,7cb3caef,8cc50c7a), -S(c518437f,7344d6e5,8cb5ae74,acefba6c,a2ad92f,57f407e7,29f39221,885a8e17,efab7c2,145a8abe,50b46c51,9a679ec0,1fa017df,7c82d27f,cd2f93fa,affb5ac0), -S(a25e878b,9cf81fca,dc06a526,a9162260,d42273c0,49e7038d,ba66a450,25fc75c6,b08a8220,ff708833,56702dd2,b4971eee,956b2711,2767448c,7f2e553b,965f7bb2), -S(ce0ed297,f5961a82,327a1d8b,2c20f8c1,b996815f,c951f8d3,3bd0c16a,3ec45c3b,c4d21e67,8456fc84,955240e6,984b0a0c,8a10eeee,f40c6a4b,76aab8d9,5e887e7f), -S(b33ac12,369bf1d6,22c2c557,7fda98e8,f6bb4389,fad53459,e824bfd,e4409229,52925428,66a98f73,aaadfca6,940490c4,91e4ca9a,da343f8c,76b7f6cf,588802d4), -S(958d34e3,58ba9546,ab139250,d47f6bba,59f13203,e07432b4,f37da854,696e134b,e0c35ab7,45e91cb1,53ee07b4,f04f1258,9eeecb89,c30d10f5,d0322a72,7285ef19), -S(cc633cb8,b2465aba,a9a4428a,5a36c8b7,cb2fca1c,9702aef,8d54d249,338dac27,b6933908,62597527,8299b8e1,5fce0cb2,1ed84a9d,2533250b,6e417d2,fc19b06b), -S(61b81bf1,3ae0ba48,eb630593,512be80d,c4960d2a,9f0a6589,65ae04d7,36b4836b,43589e39,7f4d8df6,562fd8b6,8d4ee7ba,9faf441e,b1b09b8e,22f81925,9f0a9269), -S(2ce3ee71,b411ca31,74f0c249,7feb6bc,331a492b,85480be,32193c25,6321f853,32669ee6,8062bf36,b8c8853a,eacf0826,dabc81a0,48ef504e,e2ddf10c,8d6cb4c9), -S(6ecfd338,ab60c9a2,a50cfd16,498dcb45,8e6ac09,d5517fbe,f95f54f8,1b5a7551,b73277ba,4b7486a2,594f6571,a86251cf,54a1a5b0,9aa3017a,b4c0212f,cc94ae22), -S(a4cde541,dd4897a7,95f90ed8,75907a6b,8406a888,dc807d5c,6317c7ea,7f226d0b,5cd7591e,a305d546,14ff4233,600c813b,414fad07,8c1016ea,b021cd69,1d25d879), -S(4961a20d,ae4956c6,dfd04d1a,a261bce1,ff27a2ab,e0c3cfa5,6cfe51e,24c20fe8,9bf8d311,61ebbf5f,94c71ff0,7a9a04b1,92bc6cd3,e50baefa,71de2af4,f38a8660), -S(4b099713,d4622a37,d013359f,67983269,3274d1ed,4345cdb9,96ef3550,a57064a8,dfdb479,e07a1fb,ae741a92,2a468c61,7ee4cd46,25b1041d,f554e0cf,7fc5a776), -S(b5ae6420,8130d080,6c568d95,8222a1e2,3e649a67,8af5f0f5,89acdf17,8f79e9e8,2d883796,a8f45bb9,7d30e88b,99f6b01,dd46d91e,60d20d1c,430c36b1,b8b8ca45), -S(f7f1820,23de8475,7591f366,116bd60,5312706c,2d380d7b,16f50bea,71abbb64,5e3844ae,1db871e0,c12a7205,baf101e3,77af946e,aaea64f,c9aaf9da,e1ebbc12), -S(6d2620eb,ee6ec651,792adf63,9afb0fce,ee933e69,337ab7cf,2ec85ff,917ef538,e159145f,6aeff15,2e0403eb,f3082906,f98313f0,77028f74,bbe562b8,f335b6e6), -S(a98cec29,2cad6781,d4339548,10609d7e,77f7489c,2253c04,3ec1eb03,a69eda44,c5eb7257,c5b965ec,1ee643fc,7f48ca4a,b612f616,6a3ecd7,4c8da3c5,3c4efcfd), -S(6a88d0c4,4055a898,28a7003a,1fdd9941,4c1adb0e,90ed8d9,acecadaf,6a73920e,6fe7abcf,25385db8,be815eeb,14302bb0,5a630f92,2aae66cc,b0d42ac4,92224c97), -S(8a101a08,52559761,e2c6522a,6bf8909c,2547ef9b,550ee027,45e23592,89c34afd,64248f75,469015df,d9045beb,2de9573,c1f2e2c0,9f7a4cb5,cc85511a,f7182fac), -S(ea84bd08,37bb25e8,27ca0241,2cb8bd7d,ae47661b,f2460598,7ac20c80,753249da,15be2ad9,d4a8d7b1,964db56e,8415c890,93214016,e694f258,96574d48,45c8a1dc), -S(be2f219d,60dbe256,57bd9b46,18f62e2d,7501e302,885731c5,34b1187d,2c750f31,f521ca05,48ffffa3,dd70e0bc,79602b6b,617b9ead,b64e7af7,3d9ebcc8,bbd220df), -S(418d2b33,ce151147,83a75265,a876a709,ce7f452b,de9933cf,6e7ab1e7,7412437b,52693c44,5e1ff5a1,89b856d3,9d413514,aee35974,fc4678d8,86d5f998,a18047c6), -S(3e4685e9,3c65f31d,c58656e9,a8913d19,469f5e,2d49322e,6a99af10,c1142f16,1ed3edbb,6186e995,8241f3b6,ff7659b1,bbb007f7,f9b5f91e,92d5a8b2,c780d914), -S(35e15d66,d952ab13,de14a71e,20b1ed8e,f4b3f183,db75c62f,9af7ab3f,945b2d29,813f47b2,3fe523ec,12557edb,9e1b465,4582de57,5ca3752f,2e60be32,eb4333c6), -S(f025b371,b5c98b91,6157e1b1,53aac27e,ed42d435,53ca159b,48940bdf,b0f8d262,70fd31b7,a5470435,7936f98c,cb4c27eb,115be6ea,b4de7a88,1151e5a0,4364f12b), -S(31b36d5,b52ea8cd,c0298c03,8fa4f99b,19b3ae06,65d667d3,639ea3e5,c73875c4,924ccbf2,d1890df4,783760c,e6e2f50a,8dd8838a,bc87ac29,bbf89eb7,f0b46eb2), -S(1d57ff02,22db5c5c,f6f1558b,f71f0498,b706c7a1,84dc463b,77b4e21b,9d5c1699,b6238d2e,1bf715fd,d5cc0843,dad6fdc9,e1e6d485,c3584dda,3d06a1a0,414a3b31), -S(b5b7da02,4a6626dd,f67917e0,63a3a64c,f389e8e2,a631853a,c8e5f45a,4395cf24,151c4b35,22b4f1ee,2105b3e1,4ea193b2,ba6bf1d0,feb4511a,d72444b2,66fa7f0a), -S(2a58e24d,7f43233a,55a399d3,7cc0fd91,9b451985,13bd725,e24edc1,75ff6163,4f451eb2,c7374944,7296e447,406d5025,b5da17ab,8567cf01,ccab260b,da6834f4), -S(d8e2416,99d7e8ff,15853778,bb52a218,a2ed0c45,c7ebbdc4,a7357acf,86e7cd52,e849021b,83d33fc6,826c0a35,3f4188d4,37273a7a,7adeafed,6514bba1,a4fcbca4), -S(27f9e422,dd1b9a6f,64092125,71543d87,7d8ed097,52b2e6a0,cecd81e4,659e1f41,27563650,6d56cc26,cd289851,2274314c,bef8da2f,a4b1ba19,740d8ab5,4d4c3e60), -S(2071b53,72a746ec,a0795422,ea0dc0e1,b105e1aa,fe2fdd64,b08ff2c,47f4067c,1c95ae4f,986047f3,d969e8af,99775aaf,59a94c56,a47691db,fa0175ff,17641b0c), -S(b8decd7e,15355cfb,dcdb3ab8,48b2d717,3d61113f,58d21580,9292d4ba,379a839e,2ce7737f,7dd82aa7,76560921,21cf93a,a5e3c6d9,952c3adb,b6fb1f04,4274ad71), -S(23c7a3a2,70f20e77,d62f3d77,a67535ab,5554c821,71c77bee,1b05d2e,5ea67557,b8657a68,e2ded30f,19365bcf,916037e4,a1d87db4,632c90cd,ca782e40,b27bfda4), -S(b9af932d,753ba63,f7ecf070,d20d4355,42de9c72,a93f44e5,7b978e5b,7428432f,c2b21fb9,64593524,104c980b,a53de2c1,6e7408b7,33e2ffaf,17ed540a,6253847e), -S(e461cc8f,ad51c58c,fea92090,c2d3dc1c,41971918,687368c8,4c84a04d,d094704b,c1b114e,2cccc522,6fa3f753,5b6f356d,fddcad24,86197d90,4ab00cd2,f3d0103), -S(817e0633,4b8e706b,b7282b40,a4e243c1,87b24bba,6bfb69b0,d5a366da,c383e3a1,77593627,482c198a,f29a892d,5fb50a43,d10b4fec,5937d696,ee8fc6a2,20deabd4), -S(30bc10bb,d203182a,f7dbcf39,f0ee3013,7f26980e,e5f934d4,f151f080,b1341e5a,40fb3e2c,45dd0832,cb50d0f,4f45025e,3285bb6e,adefa1fe,4192e4b2,8a77197c), -S(143f113,8c45ea5e,a6bd339b,8d1aa91a,9db0dfba,90600868,309c0b5c,1a97648,e45fd7b6,8d025855,1c35285a,87fd77c5,1403c836,e0697b9d,4dcca76a,1422a6c2), -S(f3d30c38,4926b19f,5bafd37f,ea9b7c93,d4776564,5b8b4a89,199ed005,883e8c69,2f6179e,26dcba73,81ec7e57,1eb427f3,455808c2,21926af9,79efdcf,c7ff364f), -S(54fbfba7,13facf23,1013a1b6,ed7514a,4fe11323,3c363ca5,118a7d9f,63b4c116,dbfbec7d,152e7c9,2bb98067,37e926ba,66ed85fc,2339ad8d,410ed762,4407061b), -S(81d00298,aec59abd,c3ed4b5e,11d4589c,9c7a7ad6,54add200,ea6ab124,3b0c484b,226d41fb,a46202b7,ecf1ef9c,11acb33a,cdc15547,7bbab0c,1f56f385,6401984a), -S(2c088e50,50061a7a,47d84141,a858df75,f51c5c17,717b35f1,cce982e1,209712a7,44700a1e,99cd0f9e,8d05c8a6,18a75edb,d9d7f67e,45f5f40e,4c00eda8,290212e3), -S(2c903ebd,68f2053e,7a769b86,bb017939,556b532e,1b84cd7a,2397b1f7,f108a145,2915c5b3,f16b1eb4,8ed436d7,4a79c50,72a2eb02,b989da66,b164d475,941a8b14), -S(ffac0b8c,76c6b7d9,24ed25e,3f43ffa0,b261141e,715c07c6,c327a719,6b11fd43,9c25ada3,fe7d1661,1ba95eb2,231f00ef,cd250e16,68dd85d3,96025f65,4fe7da52), -S(d81236c3,7d7dda31,849e20b3,c7aebb2,b782a1e6,17b9d6f4,f56da4bc,d860c573,ac6628ac,98c0896e,ff1802ce,a43ae085,66e902aa,abd2cefe,b910465a,9f0fcf30), -S(19d94647,ccf05308,32903c94,7f149f0a,f1f7503f,92300232,a6f33e15,7874e321,3402ad42,87ad0814,4addcf3,2f7c60a6,6f65255d,ab4bbe,b10826f0,f5a07f39), -S(2248a7b4,37bb8bf5,df85b382,224a3d68,45965330,24f8c872,f81e2c33,610ac810,c3942980,b054122c,e806a67e,7f004b18,5288ff5f,d7e17ebb,97e68e64,1c416bd1), -S(d8a71ff4,a9de84f4,f28e78e9,4815ba2f,dfe48256,7128d149,e44d5419,da84531b,d3258392,34c87aed,8534e6f8,f03802b2,e76a5f20,552873c3,991c8d31,346f67d1), -S(322a4b9c,32ffd7e0,2548cbe5,9f50c2b2,e2a8c70c,dec7e39d,61505a2d,4d780ea8,809f262f,d258b1e5,b140822b,caf74d15,9fb764d8,53b653f9,7358adc,5891b0c0), -S(4b7a2f4c,e7cdc092,9bdf7d1b,bc91a60a,2e16bd9c,ad9f1cce,38ed644c,3a790fd4,5adcd298,78333b26,20d43235,8178c2b6,a4e697bb,81c3abd1,b850a334,933573e8), -S(2d7d8029,8da39ad7,ae7ee3a8,583768ff,fee73a78,728ffdda,b3921988,2ba3d8b,6f9e5aee,bd08f707,a49f120f,26869ec1,cfe9d9f2,a6e0f0ce,b6ce545d,43951358), -S(256b5db3,24dccb17,3b525434,ca36d6fe,37d469b0,4484dec1,cd44d392,b0f7aecc,c35db3a4,61f0f477,1a5d0131,12be5a90,64bcd516,2566a373,daa82b09,415c84e8), -S(9b641c2b,b2e3ee32,cf592c06,532dcd71,af0a1196,3a82c3a7,c0e809d5,8cc9b65e,e5925900,9d981017,bc12b524,b00ba98d,393be520,651a7b0,ea8f9ca9,75142814), -S(69700df9,b800a1a0,afa144c6,3a637027,ae53a786,e9938345,e147509e,ab6d44b7,227f91a5,b0492dfd,1e9b5d,bcd02bfd,4678bf86,8e69b7ea,e97e8b17,1aa1babc), -S(5ab9358b,a7008f2e,75392981,d93d062b,849cf9f2,216c48d7,4887d50a,3d8ae5d9,7b8e1ab1,9c6e9f7b,89a524f9,e39d5a40,90179745,1ed87e58,23f23625,115043b1), -S(46fa087,213b7db1,32997f64,cf9adee0,149adaae,e4d7c9af,61aa3193,606f12e9,2c428c7e,1c80e6e8,92f89777,d8afcb8b,8c0dbf3d,f8958f83,6ff1504c,e0517443), -S(c08b8c75,cede8e1d,c3ec26f6,ba7ae08,ec22f798,aa89e258,a0291e30,ee0c06cc,8454d21,18f72ff1,17866e63,5f65c349,2baea002,97b16e47,ef8876f,d8b7f5b), -S(f50450ff,aa054493,b0660d35,521d1ce0,156443b6,f5327e68,31385219,8e39ece9,aff228cc,970fca4d,9b583c23,b8e6eda4,feb549a8,2d767b4c,e535f6ac,d68d8287), -S(e80034ad,d9f421dd,de74ef1d,7a7e6e4b,fbe2dc0e,5f50b05,f7e8560,3c52ff0f,ef285764,dc9bb2fb,e6751352,a1926075,331c4abf,51e36cb4,36c9ee36,fea34e10), -S(cdbd6ea4,b3580bd7,29032b34,7e18c839,4832d8ee,11fd7a4f,c9c63986,54790037,80f51eb3,63d9f7a1,1e4508d0,643dcaa,7fd1570a,8d3e5f71,8371e118,d29f340b), -S(7eba7974,42a779a2,5d3ece2,a022719a,94a14eb8,e6f821b2,136c0d1f,f5637f70,5cd4f314,75808559,77def43a,9c974f4d,ed3772dc,b9091e7b,28745827,477a8611), -S(b44980a8,5e5fc57d,83d9791f,54418ad,5337eb5a,61746d6,71fb200,b5971f82,ff6cc373,5122c494,fed9063b,c8ad9e04,9842c639,db750623,997570e8,76324da3), -S(71057596,36c41dfa,b4bcd0e2,5c5d1d47,e60b283c,4a9762ec,10b15464,4cb07802,3a06998d,23644db2,b9cd18ac,1a077549,57e1cb99,d75ab6dc,c81db6e8,dcd947b6), -S(c134fd2f,c63a27a8,17e8f797,a120ed41,707067,c09931de,73e71fc1,84b1015c,5cd78606,9cc187f4,a3d2acc5,7b41d22d,cff9aa26,235ec094,c892a111,8488fa75), -S(8942fdcf,4cb81983,5e03559b,c81f4da4,bdba287f,b84c0ff1,2b023658,e389e146,e50d5d33,b47da2df,3130c838,5667c158,f5034d02,bbdf0be0,5760863d,a6cf2120), -S(3aed32a6,5d3188f2,ade2e91b,552d4c56,5d75c72d,dd51efa7,ff2e2e4d,49d71c0a,9f980569,e231ae71,3f524c7b,a616c342,340a1cc7,2a0a78fa,461c732d,8b3571d0), -S(5b824633,8060ac28,f228eee5,405b10b2,8b33ddb9,9d09aab5,c8f32ca4,b3aa59e0,ee4e5740,206040cd,91c46d93,24a94b6b,6439e517,cbbd0619,80b5e4ad,91938e4c), -S(4eac5700,26a7997d,b5864e0d,1e7fff74,61cccb83,aab89c90,bed839e1,a6392220,9506b28d,aacec4f1,9843944c,690adbc1,ca8cb6c4,305510f1,31521569,fbe3281e), -S(c205259a,feb286d9,bae84b81,debad402,c60a59e5,68a0f4d0,204e909a,41119044,16dad4ed,eb541c30,38af010,5ed75ebb,e281de77,c3e61e70,344ad85e,2ca34662), -S(dd215ac7,a8023c12,a7752db5,89b72cdf,90333791,996f7f01,67162221,db0b131f,8436a84c,4d7af578,2c377394,26012793,b99f5c4b,f6c37a4d,a2ff2847,c4222a6a), -S(2d71215,5647ace7,88354c3,522da12f,fc44920a,9fe67b1f,e05f9eaf,19997db7,23cb203c,4c904541,2e942d3,da6cbf37,3f40a1f9,b6d896ab,b797955f,3666b0b1), -S(59643435,43bd6f7b,658055b,2f9e5966,303c276b,b79438bc,10014301,7b6b04ec,6bf6b2cd,7c88a172,25a68dad,e029bb0b,26137995,cbcd9d5d,8f93c6e8,fadb52d9), -S(1fc70dfa,bfb7cf69,21f682ae,ebdc182f,f0ba39ee,8c28b779,325f9e7c,152a00cc,f79507e5,51c7b44c,c9525d97,5110a19c,3d51593c,4aab618e,641d6de9,466d8df8), -S(d1dbe6bc,1821a383,d10318ca,c23cd56d,17106937,42609427,edebb18d,9ff8592a,b45168f0,d49ba0f2,6a8729e4,c860ff1d,e1dcfb0b,7c1ff20,48b2cd15,be043205), -S(4d15bd89,53a4b5cd,5d11a16f,728397a,744db565,cf744494,b67b1b4a,ff07f375,9cfbab6b,e9cdb650,fe7ef824,c3118722,e68fc601,1b8e84e3,e7028e69,d3235565), -S(dec346f8,34a5575c,d58f3bc,86ca0d8c,9ef3f556,5b091917,c80f467e,fad12a98,20741ea4,793def6c,3b46e8d5,baaa6e4a,1f529cb2,880b4142,ef0a3ed5,6d445efe), -S(ccc91a35,3532454d,9fb0d811,941eeafb,890dc07d,ab4c117c,f9547c7c,6b45645d,9e25533f,2f6bd1cc,2fd8624b,a64d42db,fd8ac325,37f09c7f,1d74fe46,40aaad82), -S(feb81407,df6f1137,e257c20c,f58a77b5,83ec8f2a,b5acd9e7,12ebe6c1,2aef1d60,b7279d4d,470318b7,86ea0630,3e78981b,ea2aba8,162adfdb,5a8949b6,1c1e3e73), -S(ffe40f24,eef97a34,e57728e7,7c445209,29058d51,1bbe823f,b354f853,63009c7a,c71020d3,2946f80c,700ca0e6,a6dd43cd,a9461db8,a25b67fa,92008da7,a96e680e), -S(a36b2254,2f8d9055,41369ca7,793eb500,2f6d8a69,410086d1,ded6bdca,692d1b6c,b9b73b65,e69950ad,f25787d3,897738b7,5306afa6,8156419,892799cb,20a9556a), -S(92a24def,2b893f11,b0056962,b41273f7,76fa4a0b,4d525f3a,14236756,3d5b240a,9e9ad443,5fda1d46,a77ab3fe,62971060,8105f5b,a6d9fa83,47508d6d,7bd8d288), -S(8fd20215,ba152223,ecc28d20,749ccbdb,9d536b64,77474808,9d2cbac3,e0a11f77,434b10d3,33418084,ad2c42a,651b52c7,bff040b9,333fae3b,26935997,7f6be47), -S(b4e6caec,c78da734,80884183,d0aefa0e,82001bc8,2c376981,f40b5c13,4c8a034d,95f192ca,cb5059f4,3c6323a2,a0e09204,4f39ecfa,92c22dfd,e0bd5365,5b500c3d), -S(9536a1c3,ee4b8aa2,8edf3a0a,e2981657,df90bd4c,c62be8dd,8aad1a85,8c4d84c5,fcf54bd4,665ebaa2,9ea4d2ed,40bc8a42,34e6e061,e325abe8,2a123b06,36d99d4b), -S(3e15d13c,75ff91bc,5e928cd,ec8e303d,286deea7,d7a4d88f,6613dfcc,a0c27c59,f98fdca2,1e3dc253,44ffab,2865181d,b830c74d,2891c80a,b71a8,904cf13a), -S(8215dd74,1eb7a889,7895feae,170dc452,f8fc451a,2037af7a,fbc02813,827ed4a5,bad149be,dec24412,4f65003d,d44656bc,5e61e332,aed71f73,b58492ba,ede0040c), -S(7b3755a6,3913920c,83a2ab1d,6a738122,bf7a67af,ddba85a1,6b9d7de9,ad6cf0ef,25752fef,1ce6ae9d,4f2ce922,fc610ea4,d4351718,f8e97bc8,bd4396c7,11697dc0), -S(cdb499d,f67a81dd,db28cfbe,bccdf877,4f8b76f,6464ff8c,221a95d8,3e3ffe6f,4b08bf10,15fe6b37,98fa8da1,7438fb88,eb96720d,495d22c6,336e0225,454268eb), -S(ac0a10fb,b902bcf8,205b2529,7724073b,55fa2837,dd99edae,e256f7d8,7c19aac,7ed1aecd,d088097f,4ec8b005,892fd069,ddfc319e,f5bb3b25,2ab7c597,d775e615), -S(1e9e3fa9,fa96a4e9,4f19c5e1,105ffc9d,fd7add4b,63c85ac0,5098c839,c0e851fa,69bffc28,5927b917,dc4dc5c1,3ceef964,27dbac93,a778a01e,227906d,6abf9df8), -S(14359ebe,e923252d,f17e2320,d97a991,c16d7819,d9791f86,65142b93,4c2bc20d,3248f24b,d31f47ef,dd34853e,dc84f8f8,17403b4c,eb737d8e,c144daa5,2e5b65da), -S(13363dd8,56df936f,35f1bb71,eb2fc4b,df232e76,1fd9ad9f,db3a6d6b,ae78e837,8160695a,7428e400,9fc88172,faa6784,b3a2d03b,71f89a5,89dd85e2,f5565436), -S(6b71ab46,20938910,bf2e16ca,6e40a653,2c6c1b58,b258ad04,b1d51656,3a5520c7,2e72f5ef,4ab06562,52e224fe,1c670b2d,39630f97,f78ee55e,d1e01f5,c967d988), -S(98f0a6aa,7590ffae,731263a5,b940dd85,6d0306c5,ae98bfc9,9d164263,ec14c21a,284bef1f,a5a54c96,f5aa7c41,ac50c5c,fa88c352,52b923bb,92da72c3,d3d7d8c9), -S(78d11179,5965328f,cda22443,91871ee2,574c0886,f82e942,12e261bc,f5c3b9eb,83802a00,84e8b578,4450a423,1bc1a99e,6b9b545c,e32881c8,8487bc45,59604f84), -S(f0856a2a,2b8b110a,dae99427,9af3da1a,a74e1b77,46d4ece1,f054bc55,905aa49c,1a80e529,2b4dd9ca,4785abff,edbbc11f,7111663c,3fdf55f6,ec3031aa,3c5f0890), -S(2c5fc446,44d1e735,3e2b3374,89eb432b,f4dfaba3,39051221,4d279de9,87d6df7f,76c8ddf9,d2339112,c10ac9d0,5a473d28,cd066ff1,acd63e5f,b49bfb8,bb34d3cd), -S(3cdff15f,9953cb19,62cf5024,4b8db26e,8180090c,d6baf7f1,f60e6184,73a9336,275922c7,6d4841c8,324d1ea7,9948765c,ea399a78,51939f80,15b0b7dc,9f22d37), -S(d36724d3,91d3fc20,d1273367,97f8d961,18543b2b,dd40a77e,88813634,1c5f5d21,bc81050a,e6cac0f,ba1bf5e7,f1232d5a,a90d3b29,a0fce8e6,4dccb5f9,3e6a4d14), -S(f91cc30f,acc100f9,ee054e7b,5aac0294,e50035b2,2e7f35ee,306a30a5,1d5d6a00,328094f4,26ac3ce,71d53f82,c3deb250,be6a44b,6704886e,424e524b,c50f3e65), -S(48c715e0,da1ce36a,13cf4b8b,d5294baf,84a3fb08,b353e43e,e9f37481,ca2beeed,9d7e13c,f09c64c5,fa4a852e,206cacc3,8d398693,31368cda,1b06d242,2f8e26dd), -S(74ca89db,72b0796,af9b6d5a,57296952,1edae51c,5a3e8a76,b1746b87,4ce9de25,c770dc38,db1a585,43367fb7,979d7016,15a0a112,61064596,ebb40e63,e41ec50f), -S(36e77506,6284060f,8f8e709b,88b90125,f3c696d5,64bc048c,8dab4b93,40fe170e,b760473,d66e32f0,a716c1f5,ae462b0a,b5e77e6e,2e30fc58,e5ac1099,eb7105db), -S(a0899b68,99176eb,77c78eb6,d4a7786c,8afe1898,d34d3cfc,5f286528,409da4c5,f57441f8,734c16af,7ca6c64a,6fbe557e,11463e6,6482f7ff,d46f1b91,eb2a3cb8), -S(3503ac4d,9c9fffeb,d188d81c,9a92e506,a91fd15f,6bc67dc5,502b3ae4,d39d8e5f,dd66ff4e,40a5da17,3d3b143b,60534b70,33a5444d,98ed15ee,a6644e10,766b7918), -S(7765e5d3,2ceb50d0,b9bf9a80,48179d59,9fbfa214,4f183c63,9de26485,a87590ea,2052dbf2,718975cf,3c225235,d2504b4a,6b9026ca,731939dd,6af8ca08,9bc7dc26), -S(eeaf76ae,d4e737b9,900d4ce3,f39a880c,e060eeb5,208bf4ee,81b173a,dfd193e9,5490a02a,4ad8595a,6afd6612,48a80146,14366bc3,4c9167a,f290e164,f32eb9d), -S(f64a505a,4116a861,12914f01,6ae52fc7,5499efe2,32178ce3,d653b030,5b0cd0b9,4a8bc675,8353b7ec,e89096ab,aaa42a2a,e8af1a51,2e6f9323,1ec71644,1a09ef3a), -S(e73f95b7,b13f0907,53ba9ad0,c8b7f2ce,83ebea09,cffdf313,868a6ade,ac9c9efe,17986166,e766d323,cad73824,8eecb239,255d37ac,af72a56c,69594ffd,78281818), -S(7d2f8553,a46fd9dc,6fbd149,abd07161,1f279250,d508b9c8,b22eb2c4,99145d36,b88723c7,462f5f81,f69c92c4,b204f499,b3b826d2,1c05ceb6,a30bb285,c4bc4fd0), -S(32dd097d,96318d8f,69cea5f,f5db9476,33aace77,9059fb08,4177b8cb,36cb334,b078ae96,3cdc78cf,bd0e5bde,532a1269,a752c8ca,c8dfaa81,6ccbf4b1,2c3057aa), -S(7caeabfb,be7e30e0,345161bf,8380e160,2415178d,314caa33,b3c99d55,1c99f506,9a449ab,6cc98b09,6487475d,cae39e13,7df05d2a,f7863080,393ac16a,802547e4), -S(e5783a81,16e1e396,4c693fa5,919aff98,bbb954a1,e8503974,a27af353,3247dc86,d9d2c1b,633e2217,b66cadd9,dcff6880,be272900,e1c966d3,3726ae66,21860fc0), -S(9c7f5cd9,c274177,1f00e117,a62bb197,d0a8a18f,2ad23261,eb04c91,47561c9a,6652063a,9b2a5abe,38ab7b50,5768a5d7,e098ac86,bf127b48,2c56a417,175cb5d5), -S(fda48685,28c4f2be,58cd9b00,6fbe1121,ef009361,f0198b2,f5c56b44,1d28e9dd,3055bc29,fe08760c,ab624154,ee98a506,9de9dee8,c1db40ff,b972db60,30af98ea), -S(ecf9f4b2,2feb14a4,14628d74,8f7e55b5,886f7d18,d107e4b4,f985df5,163c3eb1,cbbafcf,84606b89,63e4013d,3c730edc,da808338,3f681153,307929cb,905beb69), -S(ee0ca18,25428e9b,a4c0be5a,8c9da473,f73c43d1,54a6fc52,176ffa4e,c05af36f,c8b960ec,91139b08,25face64,fdfa01fc,7390804,3c4f691,bf684dec,bb10cbb9), -S(744d4c0,fb5536e4,99b0397c,8cb127f3,68865b79,fbcbdb37,ff9f9c8f,59372ebb,b9ae4d36,489ca0ec,c318098d,663fe8fb,aebf149,fb28abe2,15ef6f43,8e414a4d), -S(910d358a,710c8e22,314b9eb8,394a7770,4549fcce,c98046f9,9c0a3e04,90510c49,5ba779b8,530e57a4,fec63e86,188d269b,6081fff9,d3f49bee,b0b62e29,540ae214), -S(2434ca82,89853823,57d1f537,ef02fc12,89300332,6acc9c67,ca2f3b96,691e94c4,e4608778,311bb1fb,f88a771,f6281a0b,7f850767,af4b9699,77b1fd6e,8df34d7c), -S(cdcebffe,d7c410c4,18cac7bc,cba49a59,b3ad5ffb,4c0577ba,19e25dca,c16fbcce,9745ea09,ddeb473a,a0b861f3,7d16d83,a8a73289,d278ae12,1168a6a8,d6bf5595), -S(826f49bb,90a6b195,b7de613e,ccbd1230,930c0303,d88ee0b7,a7c40b66,cf576a56,230ee0c1,c1f86c3f,a79e98f7,e63a7a77,2ad22724,ff6ae39,ea17cf43,e2e44c8), -S(d8bb1cea,9976a5a,ef1a5e6,57b70b09,e59cdf59,c67b4de8,9694701b,fc73c7c0,e76bb7a3,60759c9,441424cf,46aaabce,331e749c,80d588da,e3039162,e1a95d35), -S(6f475ce4,d1c3ee7d,130d101f,fde3f250,d1a0d884,2239ef78,83d67254,80b750ed,13c5fe82,7c76f2c6,4739839c,4d8ab9fa,3271dc83,b949d123,532cd0eb,71809e0), -S(d8d129e7,72635a5e,bff00c26,8ea30c0a,bbe3c635,d49818c,a3251082,fda4363f,4c4f8a79,d88bdf32,9b7a7121,7572da21,f89cfbbf,22547269,1362d5ed,c50b471), -S(19aa085c,e17cd19e,c610d3af,91d9a263,3d706773,1d5f6891,e31de7bb,39d306c2,aea04c67,efe26,c46dd958,e8fb2d4b,726e003,2d33355f,e7d256a3,842f75b9), -S(3712aa15,914e6f15,50ec12b0,f7dd6b2d,854d9f95,e86e7d2f,103b9925,dea23828,f5435b64,af251cc8,72c9123f,964c1c75,47457e1e,8c8942e7,852f4fe9,a9240c84), -S(f5b9a5e4,db49b7fd,b00912a7,821b8c37,a89ce6e0,12286f40,852746f0,1d4ab4b1,7ea00e84,d03d8654,ea03759a,69a3b055,60af6f38,55dd2ccf,a2e4da9,f8820114), -S(4ffbb51b,563605a5,eb7e784b,93eb7ed5,83c65968,1446a776,443cd436,e86d9f13,ff8e7729,e235ae1c,9d0ff576,5dc8763c,7bafc9d4,f3eae4b3,b7a58871,add58688), -S(9b3fe406,55f0a924,ddb0cb1,48dbf03d,5da4f1e4,e8b7307c,6b261915,2fd5c3e8,46dd956f,583120c6,91961916,1a46023d,da55bc27,b0717029,748673ef,b6aa318c), -S(86d8917,9410b427,b8008d10,3e481c35,2f089dc3,5c263804,ca86e08d,9da279ef,9aba2027,c3e47bda,aea2eb58,617ae633,83379235,7c233d30,e070115,d46ec081), -S(414b3ae5,23a76abe,6ba71141,8ac0a61e,4915076f,a0c2528d,e20a0b5c,368d2245,bccb169e,3091f7af,bfb8a251,958ffcd4,6f0c8c5a,f1662640,6c7c9993,3fb8fdd8), -S(7aacfb93,8644090,57ef8ab1,63bffd25,d8d43166,e8f31304,57779b20,b5da5998,257b5c42,2cc77f41,a6234a9c,1ae8d2f6,e91fad8a,78c39a6b,1d380a4d,7c9684be), -S(2e51b2e3,72a64010,92ace7d7,b263f897,ed629521,d45d962f,2876c266,3e42d7f3,fbd258ad,28324ce7,6bdd4b38,44517a40,e5cbd237,3bdcdfb0,862e768f,8e6dc5eb), -S(7721f122,e26e0fba,f6a33521,841be750,5a47dbcd,941191c9,432bc25f,56aa6e55,65e23e03,f03785c7,c81695cd,b49dee81,b9f678fd,55325ce9,dcefea04,f11a79b8), -S(aa7443f8,435fd4d1,e2f1dcc9,bed52a07,66f3c62,543a0f3c,5ed7f593,e7933f9e,858be190,a656bcd3,5b377138,2c3176a,45e0a53c,8a346743,e1c595eb,f992c70b), -S(23a3de7f,147a4ca1,bcd19afa,a8e71a58,27c7e7aa,c7db0c3,40d37b4c,e97a76dd,5361192f,76a37f5,d02e697f,288daf6f,34313d58,4e33344b,32cf1c0b,2c711217), -S(ab65c884,73b68402,5929fefb,322667f1,bf02efdc,d33552ec,4d743222,2b2d7352,c2949d4a,af2c3ed0,f9284466,a572b1e0,34e56e23,4c928646,5427d60a,2f092d63), -S(5d82cbf8,71aa4029,b16d09b6,ed1a22c2,6a94bc73,c1bc11c3,ae27042e,92fabe78,2610095f,c1dd2eed,adf1ecd6,a5b15b0e,5c714fce,87f424f1,5c198588,8b2ae3b2), -S(e5338bf1,79e3b22a,306e3f36,5121f94d,cb5a072d,6acbedf3,87263387,7ee23090,a8ce14f9,36d0b486,3db6f79d,d10922f4,395804b2,37035103,b59768da,c1f8600f), -S(e936f432,e5cefe07,e4e290ad,823d90a5,c2701eea,57bebac4,81b97400,b8964544,ebb65cc,15843766,77e34e80,b665567,19189319,2a298033,a4786974,5152b5ef), -S(a8f4c429,d93c81c5,7284f59a,a3a941ae,536f7c2c,e3707973,ac3eb5b4,a0ba1ad1,4e39b9ef,5e1b885d,b3a8e72a,8c069800,fa539e6f,7f6ffb0a,4b22ac8a,66c8a83b), -S(76ffc741,af278fae,39081989,d884b195,9cb7f240,d80c35f8,989310e8,64034e40,3df6c05f,12b2ddd6,262e3837,5c2876bb,e0f7b769,7d4cca13,be11c55d,cfaf6618), -S(eed12546,217f1270,505f9235,b875f6ef,1ea38bfa,6e790cce,97d491a7,30683809,6edd20bc,75c215a2,9a162bb,f19b757b,ae5d22d0,1c7a68b9,e2e0b01c,21e4d193), -S(8a975564,196e1add,526576ee,dd330a0b,bb1dd32b,85ae095f,79666907,15637aaf,5ba79be4,6db3fc66,c2f9666e,86162767,4c408e7,241ca378,47b8b3f7,ad5c3c48), -S(87728750,a68695b5,a23a86a0,50e5a015,e721ee92,da191a77,a8945c92,e356f3bf,44746e19,eeef603a,9115bdcc,b8d4146d,a928e723,e1736c9e,a352e8b8,8bb5c6e4), -S(83e9abe0,c65a51ff,c9e70748,35d1263a,5c31db10,6647e6fe,1ff9613d,6ddc6479,2b956ce9,1dc3fc78,b5d2c0e5,abe82eb5,d1fdd4c4,f2fcfed2,acbac011,4950e7f9), -S(89f0cbc1,5c7c60e1,6503fcf8,8c70dc2f,b3f18eda,3041ab27,e917b93c,a837b60c,9b25624d,1e3d2dc7,7c4a1b6f,4daa6020,2246386,b2007dd1,efb0043a,300975b2), -S(b64246c,e22786aa,8f269907,bb819041,dc564b0d,c6e14987,c5ac8fcd,a7f5a98a,68d776ac,5200e1d9,68088a72,af4458d7,85dd81f8,37f877f2,f4884b4a,3fb4d5d7), -S(babdf57f,ca92a314,6884f3c6,509a27aa,c8793214,49f55c78,7eac3531,74074127,380fff63,5aebe191,3c6e690f,76045577,21f65949,6a1df010,32726fbe,ceba0038), -S(92eade4,5d8ebce6,3685ed69,56caa62f,2f9eccd4,55f57bc6,4a75010d,20ac2df6,3b5babc7,16be9c71,e87bb0df,54aba5c4,3bd1f820,40d98f83,f2911eab,deb32573), -S(ac69071b,c1bf2a3,b01f633b,fff39f4e,3c5376e4,620278c4,ed9d98d9,5ef7025f,252a56cf,7d6d2835,6defd43e,70e6bddd,6462bee,d37b5227,d7d9fd5e,3b95fc6c), -S(f05e2926,848849b2,a7d9b980,c5e18d11,73db7422,4a3c476b,f2c44b,4d81b49d,59aea3ba,83cbdad6,4aba7857,1228acd5,eb574350,a9d1940b,68a4e495,2ded3c0a), -S(468ccfbd,aaae8f16,b91f4,cf41ec7b,f65f5832,8a3543e7,106dedb9,be4896fa,bfa82375,5e234421,19a18f8e,d182c52,1caceef2,3811a874,8d30b143,5676a186), -S(92452b56,58086172,625ae89c,48491669,e5c38d6,6280163c,397169,79578e09,6cc0e425,1da8e662,fdd858ca,e213cfb5,ae819d79,23372d39,d5a9722d,66543782), -S(3e201b8f,ce5bc832,c336c15e,2daa7770,1835c00e,3852cb19,7a9d4a2c,a902e287,5096a11b,18ce12bb,27f935b1,3e664d26,2cfe6be7,33c8b5e3,45cafe32,9f0804f0), -S(68ef4ac,e421f24f,dd628a01,56caf9d1,24bfbfb1,d6651f35,10ca5e48,5bfff389,8ebf4cfa,190aadca,b04c256e,ff0fbb04,bce8b360,3e308fca,fd8dddc8,dda15ce), -S(d2e44a05,64718ff2,85c56932,8d8fa7c5,530977d0,56fd8090,972599a8,461b5d39,a16bc6e7,3d514070,702db8bb,34f3cfa4,12099e19,da5eac7a,f87076f2,88b88bb6)}, -{S(4bd266bd,4a730879,cb06d8dc,bd8e5854,c50b6221,d83e0a10,3afcb2a9,a64cca67,a4654a1d,835a51f0,5a877200,1768c549,909212e5,78e3b1d1,df935959,93650863), -S(c275fe8c,b742a78e,7d78945d,34d988e1,202e1807,905ee89,d348957,f44c319a,88aecab2,7d47654d,df33617a,5fae27a2,8968ebd,284f5970,e0c39a2d,1e8039bd), -S(9dbe3dc5,ca9889c5,af21701e,11c60d,2eb901f,d0981d51,faa8c79,8b766a99,26878a40,fb4f091a,7c82cbea,db50bd98,8ee84e91,f58cfdf2,647a9de0,39f614d5), -S(4471b988,ed964b29,87a79324,a251f228,321523d8,1a7039cf,43af4c90,f63c3ebb,8196836,d28e4dee,9022c609,4f078448,72e70cf,c0b8640f,a28bece3,76c5aeec), -S(a7f5ebb1,7f00f9c3,d51ee4dc,ed4d713b,916b8049,17604d2c,1c6ede6f,4a9308fd,954f55c5,83d49978,cbe0bd27,7b2eaace,92e43012,bc31d63d,6f8d117f,e1e80223), -S(f80df047,a066a8b8,e1c6c6d1,12af4a5a,92894eca,d7946929,264b81bf,b060db7b,b3295268,6d708b49,73f0861a,3ba7256c,709fc322,9983c28c,6a76aecb,48032947), -S(72a6521d,60423431,a29ef70,73467d31,f654034e,3618c2b5,b9ae057e,b6c85b2f,f2cd61c0,58988546,7197e84b,6ee01d64,d200a135,542d5a0a,fb3ad4de,507dc900), -S(e1bc0481,d40b97ad,c4eaccb9,377674d9,ff106f94,9b3ac081,965b5332,5c981be3,a717e82a,d9ee2fd8,c07e3c96,a224c449,bc16032,3d0f0f1c,5e5b0f88,47f3a7d1), -S(e44aef3c,f9651799,f07b2ed8,b9e86780,fcaf26e1,2fe122e1,edeee3bb,a45cd461,c2a599d9,cb14b881,53a18c84,3831c475,4245b403,840e8cfb,6442446,d412785a), -S(3db8c67d,1964077c,bff351e9,ff770afb,5a7836ba,8e8916ae,2246c183,86e17177,1c02f899,1cc2b1ab,94affdf4,a302042b,db88b31c,5a516b4a,6d63a667,10e7ac32), -S(107e06bc,96acffed,cafb1205,26c61c9c,7a67618c,d1d4a1f9,24f7ff89,febb8316,aaba34b8,7ea1b235,720b79c2,b84ad3db,af6da2ae,3447df19,77e0a08c,366b3cc1), -S(b8f30382,716e92d9,7607837d,b162b56a,8b50dfe4,76f5f700,832dd55a,1e686a73,90a4b3a3,d11e9bcb,55d76467,a194f32c,e2fef47,1fb2408f,b71b9326,3c722688), -S(a3d1dd0d,8a5181a,b06639ea,f4f3111d,3de0ebd0,5567b9ad,56df821a,59191b04,65b8e7a4,fbb854f4,3699e509,4a9da6eb,f277a0f7,a38dce11,8dc924f1,ba916726), -S(44f3f1a6,8fd1c5fa,9de45857,7f320273,69cfc6ee,5e30822e,cec0605a,dbde28e0,400f764,2566009f,a7482bf2,7ca5b0be,1621b94b,ef42f693,417412cd,835c922), -S(d2eafded,346b24ef,633e925f,74178ac3,5e6f4d32,173797f,1f51e12,2ca65f7,6d30ca48,b1f675ae,1e1978ca,6c05f542,2e2864cd,a58480cf,517960e4,f373d79a), -S(d07404c0,67917364,7b2e946a,87c5cece,20be2c5b,2ba551e7,864b2b30,8a7695de,d685ad61,efc4fae3,fe60574a,8a20a6f1,9243100a,4bf945d3,de002f81,3b91c185), -S(38936927,ecac3831,2417ee88,59318fb,724e758e,a175bd3d,e2247b2d,1a037a5d,da223eb8,71b3f213,ffe0abbd,8bf8152b,afccf3da,4bad091f,38ed1c5a,b90bbb9e), -S(2e0b714e,f9bf7154,cc41d846,9fb99eb0,7bed9ad,3ad4a60f,b3e88fab,974ff918,8680512b,4a6dfc2e,9bece0db,435d4420,c745b611,8feb15e0,7f1ce001,6a65fdfb), -S(fb42c1da,8d1b62dd,7949a6ee,1e8605a7,fc774863,eb4c7e70,8826aa80,c5b22aa6,272c0d71,127c514c,8b2905d3,d962080d,b5644bf0,25ae95ab,5d88b15d,596c7eee), -S(5dd9e606,61ab076d,d7ccb699,caec20ea,49b5645e,96662119,15f679d8,1dc88e70,e17753cf,6bef65ff,b2739967,e64f7402,54562b4d,9e44c297,3d1e841e,ba2ca74f), -S(5c8ac07f,466b9f4f,3d6f463d,54f16e0b,3661ff55,8a1ad864,bc86ec2c,29bd8356,f849f526,77b36737,586b8782,27a927b6,300ecb2b,cf25c53d,1cc18c02,366a9156), -S(ba773918,50f9faa4,715a8b00,bbb3abf7,c78f17e7,917172b7,958e0439,7b974887,3e38618e,743539d3,469820d8,c1e127a3,cb2cc6bc,a386087c,ea7296f5,46ef4418), -S(eaf36e71,7c23e7f8,8f1af63b,fc7e56bd,fab55922,122e868e,5456d556,eb3051cf,843239de,1e94148a,54a00e92,a649ac07,e8fb0883,7de8a3c7,405bcc0,26bec993), -S(fd76140a,9e0504c,5df9aaf7,ce77174d,d64a8131,2cdcdd5b,8b82985d,db980f2d,7da81b12,d2836ce4,ee81c288,9db2408e,38f7888a,29282a3f,22a32cb1,5630c5f4), -S(7db855ee,a3c28e7e,45f51166,f32a3af9,3fcdc75d,acab827d,3844cd0,b4e88251,8cf4f691,9dd33bd4,d95aa1ac,c9ecf926,4be5b588,7453e77e,9f69241f,9498d929), -S(dafcba5a,e148fdc,aa431fb5,db8f4edc,f43168ed,5e381fa3,e5789c89,82f2a90d,a6c718a2,92c522a7,8dd15fec,e3ddcf50,10327f8a,1f601544,dcfe0e66,41404275), -S(d7de414e,7ccdc7d1,e934b10,17980cda,fed701e,5b3c4a53,d8ec0021,bb6b7015,47ca5491,2d5fd9a2,37daa64a,6434d6eb,5a8e27bc,665d3cda,d3164fab,f185125f), -S(7391420d,d4585846,cdfbacd5,63c47521,cd3640b7,4ba43c86,3c5c09db,d389133f,243bf979,ceb34758,84130208,b3a8eca7,bf695c38,5c60685,6785fd65,b1114e79), -S(a387b4b7,6c49ea0f,9b5e20ac,79053b7,a7391c3c,984c7e0d,72116ea9,85a11f0,fe7097d3,ab64e202,e61cf2ac,27e506f1,78bb534b,1bfbc8a1,9c435da6,b13776bc), -S(49df7215,bd8ab08e,21c56507,b6e57425,bc4c443e,ff0a49e,ec4ce0ac,4caf132f,9f6eed66,1066c373,275d82a0,4908193b,5477690b,5796be1f,533f67f,b9fa18c2), -S(ebeb0f66,1a66ae8a,fd0b3442,45f78f6a,cd414431,13bf03ac,3c6f5641,b5a62dd8,fca3f129,76d11af9,81f6c175,5b9015d1,91dc21e1,a91098,3528516a,a8a22a09), -S(367a8c75,e4fac5f5,55f2f48c,23d3c344,ca4bce60,b188be03,5461d077,af8a5e9a,8064dcb0,e3c46a0c,3cbfeba5,20b18f1a,4b7171f5,7db2dd3c,829d9168,f9275792), -S(d3e2eab8,ff9af1c6,5a881738,d52ee173,7baff4c9,31937318,287cdadd,46ff98b3,f7c729cc,808f4760,5757fe5d,c150ffb,ea4bd6d2,78e3860e,56b45add,bf54875d), -S(86c329eb,3adca5dd,7e840133,9025cd69,461367b,781acf0b,fb2f760b,6b56df9,6db54fd0,401af8d6,bf94cb4d,c8230161,ddfeab22,2c6802ef,1640334c,bbafe470), -S(ac9cf2bb,fbbb0be7,8fe03b3d,5b0aedf1,3d36ec3e,d8748a68,ba873bf7,3eba049,cafebc22,ede77a8e,fd3926ab,dd69342,b3226271,9a7719e0,540afa3c,c23d60c0), -S(54f1d996,ca39664,f03ede34,3dc394c3,aae4b65a,e75aed69,1427e2fa,85995d22,971bf54,8445fe60,714cf038,6c801979,e6eaa1c4,d51aba97,24b3491f,5b490fc0), -S(a01cf61d,b77a9519,6b8d0f1b,10f087cc,3689ef3e,56e66f4b,918baece,8480e8d0,d6da0432,2822dded,838373e,70550728,1a1ddb83,375944e5,4559e360,165d6b81), -S(9c971dbd,7bd6933,d4d4c918,ee7c7236,45fab1e6,1f50f54a,5474c711,8334e8e,767e56a8,e6aabede,53566eaf,daf22c38,b2f949b6,4dcf006e,b24469e,c2ab6e82), -S(db08258e,4dfa75a8,940c111c,1691e148,42a106ae,11e6f266,8a6bd70f,fef3624,9bd0de5a,f568b6e,1d05bc6f,e6999245,3a223e91,61311b7,7e06cd6c,faa956f4), -S(1f546fc9,2f784ca,638a1c8b,74664baa,d2da0745,199aebbe,9fd1d65b,48bcaf91,5470251a,9b9d5a79,be198076,541ba922,d7692ebb,f65871d6,e9daf078,52428dd1), -S(a318a92a,e36427c7,6c8387ba,d4420b29,a8b0f583,76d6e049,e70b9a3c,55b5d799,b38888d9,574e6cf4,991d6608,ed6918a9,92ef5a1e,90d405e4,da8280d6,74f93b2b), -S(84c29d90,417579d6,6124a754,aa77b711,4758f383,20a395b3,44b0e547,d8779b2d,2957cecd,8766c432,49ccc288,c6f6b005,b2726bcf,9bff51e6,d676ddeb,ebd340dc), -S(4109a1b3,c740a287,5b06f841,def2cc2e,47d82029,bdbdedb7,7a225298,e3f010a6,334cbba3,6526b308,ca45e487,d10cf54a,fe229d66,e3538833,754c7058,5f9f368), -S(99cb215e,9ddcfba6,bc703e59,c3d3abc3,9b0824b,ca0a5cb2,35cd2a89,3fb2be6c,6e1494f4,2df30735,45ac89ea,ca3834ad,553bbfd8,ee0231e5,c803661b,82a16cef), -S(2bf5a599,18959366,e7740ef9,8e2159c9,28cdcda7,f38753f3,9e83923a,5121b490,7a70ee9f,387e09de,6a8608bf,527e9d0d,75903644,c4efdcdb,916f7cf0,bf35bdf8), -S(234f1de2,aca81510,1a9e8659,41851280,8d8801df,2d63ed83,e7c9899f,6881ccc5,d43dada1,7029e6ba,56fd9c99,29810f3e,c8bd27a3,5671781a,283abb97,12014be5), -S(7a691d3,2b6d605b,c04723ca,a6d7219e,39d73fcc,e3b4e4ce,ddde027,eb31b918,9e869d3f,d4802e57,34969854,12a84c77,42dbfb65,f70d2d4d,a7ddb858,f68c88f2), -S(963764d1,75a0cad7,8e87e2fb,d3f32dd3,e45e57f9,ccad6560,dc58e548,8bbed05e,d5faa558,ac6a9a20,74c5166c,72c15cfe,b509828c,24a1d967,8aeb6dff,5eca8a7e), -S(9d250071,90c38bd0,64f0cf4a,dd0809fc,95c02956,9d199840,e6d947fb,271573d0,5eedad5f,5930c244,b3fbec61,425da0cf,6d0eef25,87e84f42,35f08429,9e38d8a4), -S(83b30514,e1691531,5eb6b9e4,eb1affa6,533be8cc,c8af829f,5829321d,cd3aeacd,7eb7fc6a,e43b73e3,1ff48193,947eb01d,3029fab,e51e4344,a278f142,9ddc9752), -S(4365f9cb,8ea699f5,284e21bf,fd4184a9,685c6b9a,c07b555b,eae2b2f1,838d9cd8,4b0c0ca,4fbe4088,e1c55eab,f80858c9,6c5d3766,7af397ee,ffac81cb,3e2d2394), -S(7bf3588a,9d51278d,539b7e72,19e32b94,336441aa,3c56db9b,d70d1d13,4425ad3e,442a5e17,27706843,fe43b75c,ec629876,2b8a81ac,26f71371,ac78110d,67d9f54c), -S(bcd1ea95,621c195f,b37f0ea,aa7c1688,35e3ba46,e1fcdf8b,c6d4ba36,9dbd46cd,799a70c0,422c82ba,e3790abd,22346df0,8d1e80ad,9194f70,f94f9d09,50b8719a), -S(9eff139a,7e728eae,57480c55,b5a5752d,83c4b92a,96b72c98,ea7fddd9,9cfaa8fc,656a5a97,1de87e12,afcba7da,f6ee5020,7257f604,5a909707,b55a83ae,ebae5f62), -S(16edb231,17a09c6f,bc1b0142,c06d9f8a,ce125101,a48229b0,a7605a87,f3fa59db,1f41d18d,29b720e8,54cc7876,d682efda,97d27e31,3f66eb89,7e23d85b,e160c9b2), -S(890e1604,5f35d432,fb62b4b1,aa8e8aca,b08a5aa6,edced104,841ee569,f8b0dd86,7970b632,a25643ad,df338a59,4f974cd,701da359,8b845ab,bcae75b7,f2168e19), -S(630d23c6,f5586b45,59d68f49,6531cb74,e2075ae5,3ecee2d,3c1c8ac2,b01362f7,5a9c6335,dbc506fc,d8abf476,ee5f5437,290cdeb8,9c3ace9d,184658b4,67478c74), -S(9348ad11,53e90953,65a13cf5,6cf05d66,a69e509d,ccb1be8a,5a985472,f5ec3909,3632b1da,48e2ce33,97d25cd,6fa6d55a,9fed786,9a7b9bf,d2765af5,81af7206), -S(e507b132,8614fd05,e9d8fd9b,5742cebb,6e7301dc,defeedb1,5f79022e,79acbbc3,e09d5d09,2eabf8d2,d0186df3,5007570,e9e85f22,269e0342,183bd375,a5e326db), -S(81727248,d85e0f46,a8e4b09c,ee17658f,557e1dee,a7c9c12,49012f6d,76f5432,f1654495,339b6da1,981e8e87,eb95d1dd,5b62ba06,67ce8a2f,889081bf,2aadf), -S(54f7d9a1,806fc37b,668a97ed,286ab04f,a2a96f90,aaa92118,4bc0034d,431c5d18,26f8efb0,5bdb0263,2e7561f3,9f56c5c3,2f41c8b3,7771ecd,897204f,33c1da14), -S(75b272c5,88900750,4b139b59,f3188477,56aa22fb,b1981bcf,74491b05,881a4be6,1b7ef1cd,70dd43b2,851220bf,b3989bf4,66e76fc3,e9262d89,de46327c,30a73c31), -S(9880a12a,10a9692f,b542943a,ce6513e1,bc95fb8c,618331d1,413657b7,13b2a811,38e33a55,ef745420,98d92ffd,17a7882f,b2e9dd69,40deadd5,8dde4a,8c31dec8), -S(232f85b6,f3fb87cc,fac4c06d,bf585c3f,c5ff3d67,114f1187,17d68ab2,af6e24ce,44981280,9c5b77b3,ea4d6b1b,e1872fe9,c295596,839a135c,443a37c8,d0a1f405), -S(e7e0e5ce,292f1386,3f186534,200727a3,46e60312,76ec0831,3fff6810,6d378912,404fd06c,68a99234,9d86e1cf,c2aec52f,bb101169,6940c961,1c052d86,ce87cb6d), -S(7ceb4d25,1844992,86b50e20,efc3bab3,a98cf466,e22c4018,eb22a97f,51a2182f,4cd70a08,609fa1b0,d55bf37f,2be739ff,8af001a3,190b7b4c,9687a3a2,949e99f9), -S(bb22eb38,cb29566,57a046f5,2f97d3a3,83bde5ca,e0e64fc3,6c5d28b1,be701695,574027e6,92a28c07,9fa92945,cfd36c73,8ae59c35,c869d17,d460f9d3,d12f7ba3), -S(e9803291,3c7e0c3f,4e0213e6,a6488dc3,f5c0dc6c,9246b655,5dc0adee,978ec5f8,b3bd6f23,bf63d3f6,ef4b4e45,6ea7d58f,47136aad,da5b1de7,765dae5d,b4b6986c), -S(e18f27f7,f8a95e81,fe58a13,329d12f1,4118d924,2bfbbfc0,f64eb2ce,b233c15,66b93d85,a1c7dc3d,cdfc3970,ff0f61de,b6b0adb3,ad8b0db2,fe766606,3c4630c8), -S(e6243ac1,f0b1d402,363b4b37,8ca320a6,68595325,a1d0572d,38a54476,a107a2d6,5286e1b3,54a3e264,4d9c91ff,cbd141ce,58c8a6be,5b609924,5821dc49,d1e92df1), -S(a77f0928,c24f4ee9,14a84684,568ca975,322ca71f,dc78f389,9aaede60,9a3df1a8,1cc82bd5,7d6eaa18,a05e8096,441676d8,d66c1584,af2cae0,ec118bdf,bc32272f), -S(e79c0aa,51e9fa1a,c6e330aa,b9877118,ff672fd4,46f49920,fcf14f26,d74bf10c,6d952340,708203ff,109a0d,7dbedf52,866d204d,8f5c9cae,bed7c724,4d726ac7), -S(6f5ba3c7,202c796,c27d342b,9e5f62e7,b3962a71,7fda573c,87d30071,796e592f,174aa4c,789ff3a4,1c5a42ad,a3bfb2de,ad3a5351,cd9bce90,f983a9d4,e897f053), -S(701c7dc0,9edccc89,530845ee,6d76dfd0,ec06a842,49ffa8bb,1f5eccee,c8aea899,1f3a2d11,a53081ce,6c326977,911ed535,2de2df6d,e3ea92fa,7946efe1,a2afc215), -S(3c82e97d,f06da304,13439ede,3a56a48f,c4fa7c6c,9ef2a74a,cd80e58,3e3e4104,1ec4e9c9,14dfe93a,13a91edd,5f7f63d5,fe60ff4b,bb271624,d5ea48bc,7833dfd9), -S(88d3451f,3998286,2cc3b867,afd91cab,6ccc737c,4cf1f41f,1c0d702f,a2af97c3,2e3d51f9,141c94a0,1c1907e1,c5328653,a67e80a2,80883f2,2caeab79,70203d05), -S(dea9dbff,93f8f6f1,714a49a2,e9154fa,766b9627,e64049d7,4363a542,f30b0647,deb01f8d,91c3f7f0,ccfe5fba,a5525b4d,b10561c3,aefb11eb,6e540844,2813b714), -S(7e715f8b,68718d16,ec601550,f80a7f91,d1f1f3a5,ec972755,66ad93d6,af205104,9c79a5cc,3226c625,d734b73a,f34bc14d,a5d5007d,ecb402af,b815bf4f,18df8260), -S(6bfed43d,a9196990,c03f788a,9b27d023,12394f38,78bc6d64,8923ec4e,3db64d98,672d59b8,c2c40ba6,4c88e516,d5602983,7a9b328c,6c28701c,80d47927,9590a913), -S(177bd160,1c53637,28e341de,4e7f8a22,9a561665,c1548ace,7e6376eb,dc790009,17585c2c,9a90c5f1,3a97fd24,b7cd0358,762f1217,e4ce2bf,832c008d,d004186e), -S(f1b16245,4181187c,f5251139,8382026b,ac7c4355,ec7cd347,9f83a66c,db63db19,5d261ed7,3c9611ab,d983d74a,9ce05bbe,cb32b858,32d00e87,fa794482,41fa70dc), -S(aadc4097,ce6fb92a,6b77b5c1,abfdc345,85982877,5c37a522,39518559,363d2fec,825fecfc,6f11154d,89559a63,56308d34,5dfe2e8,a439ed20,eef0edaa,3d506a62), -S(ba354351,d81b0113,a215ed8a,3a900fe9,3484f35e,36988664,8c830d79,699932b5,c18c12fe,9b2fa86c,982ad09e,5d29475d,7a0b7f93,865e8300,f215affa,48bcfb66), -S(ee1f269,ab870c07,1ad7d7d5,a84b5c64,140a3bdb,68f0a5de,c4a80c52,9bc7f6a2,67f62848,f082c3da,69056b00,91ddcc2f,7687f630,7f4044c8,8196a368,d441a44f), -S(9880ef57,5b111cc2,c51b9b19,d3c154fd,30d8b967,312e30f9,2f210a9c,13b8531e,af790a63,c44bf477,8884f95f,91652c14,f1ee73ba,7c1facc3,8ccac2e9,8382b83b), -S(996a6793,873cf119,f77cb23,1c8771bd,6226d90b,d319c2d7,d9793a30,4a7686e4,983c75e2,f0ef1d60,dd60ac8c,d3df6e09,ae1a8da9,17b1c63f,f59e17c2,c19a7d38), -S(35faa9e8,7fefcabf,3aee306b,a88cb110,1514db47,9e559e6d,f8b995d3,1616395d,bb7560b9,fcdb7e2e,7522e5cd,7bc42236,79d1e546,a7f7c0c9,44186043,7dfde05a), -S(70d1471a,52f0fb45,50d2c644,b7925895,5e27917,13ac9a68,2b5351d5,333b3fcf,a84cec71,622fddae,72f4f995,2585ea84,c15968eb,666573bf,254d2144,e0a523e1), -S(ac990fcb,477409e4,442a7635,64ceb28c,26adc45a,b5b99441,e9d7219d,593ab4c,3f3ba91d,c08bf75d,5e764b72,d048fff7,fd6ee3a3,758bf5be,d9a7da1c,6446e15c), -S(f8f64b95,69be42f6,1567f537,d9e60f6b,f0608f5c,d8ad8567,ccbfa02f,34b26208,d818300c,ee7da0af,1542dcfb,9a62ebd6,86c1bcf,d9e5f41f,31f79892,fbaeaba8), -S(c24cb8c0,eb923c9b,d12db26b,9473982a,73099bc8,1f0ce101,49d153df,e77bd5f6,7f47cd6c,123cdb2f,f9772b09,9f44cd9f,643929d,bf0132c1,4f9df2ff,cf4ac056), -S(5281bd2e,f6089825,91e8310d,4d626c4,4e68ef80,b9e6abdd,6a0af7b3,4b957f1d,eb9a808d,97ae906,b029a24f,b600712e,3cbd406e,27380c8e,bcf3287f,fe1e2cdc), -S(d525c063,fbbc8ba4,dfed492e,cd056ce4,fa60b04c,25c850b0,70052ec2,6f592be4,8e5b03a,9268a809,a86f3842,10a4dfb8,1a5d4659,c2695723,db7982b8,698cb778), -S(b0a5dcc1,3b377072,9ef8ba6e,b0550b3c,968b4f1e,2a2ffe0,54a89eec,ed3adbb2,49865cce,282b337e,14ab3f17,4a07979d,38649ee1,951f8aea,8a6ba657,8bcd4356), -S(ef3b5acd,4bf27694,cd96f70,7708eb1b,26f517b0,37d44194,ef3aad38,98d53812,db292747,53593713,1c0a9be8,5b020ad,34f2040b,3b60bf65,638f4561,709889e1), -S(dca55235,2326841c,625226a2,6844d317,adbb5cdd,a08f8931,68920aff,82d300be,f48441b8,a104131b,bc1a2487,eb3760d1,8b60c53e,70b693d5,b5db49f,485ee525), -S(53a47db,565ec4e7,255ad4f7,7fa28644,2ecfd91,32a0e8ec,6e4f119c,2d090044,1ee6a228,b1615640,83a62c49,f3f92c9c,9d6d46d4,6c7a277b,7ef7705c,4a20a6b1), -S(8187e675,78d1c19f,c1624a5a,386fb1a4,2ce7df06,8487baa,f20b0975,6a40ce91,241bde96,53091ddd,49423bef,e6a1ca6b,b75e312c,46ff803b,bb709a4e,25a691f), -S(3ebd8f13,d92881af,1a43223,335c7eb0,7958b7b4,e5af5cfd,f320228,64eb7937,72b3ee1c,bf91271c,84603d64,a8feba9d,bcbe4626,57c4d084,d2d3c8af,e7489c58), -S(90de5cd1,b27da158,a73ed3c1,f23f9390,9e281c65,6d50f8d1,b70294a4,9f4bb4ee,1619b365,238cc8c,be2b62db,ddc24381,4ecf4095,8617ecfe,6315f8b7,a1d73b3c), -S(e44c5ccd,d2723f6e,c44ba386,3337d911,15a73547,c2dc77bd,bfaa6e1d,b4ba3d62,f150acd1,65fc084d,b8b442e8,8a6fd033,5a8383df,9b2639b0,3248a1b,72828129), -S(62eb6bb8,67fdb48b,f474318,99536489,437a7086,8f27287d,6ad56996,31d6c845,1014f43c,517b3a80,d2cd9e4a,7d76693f,61afef58,4ee80ff9,8d20bcc7,c077f7ad), -S(a44ce0ca,a242039e,3defa271,59976e2d,4bc9f1b,10e07b83,4aafee6a,7ae93066,511dd603,d264403f,19da6380,dd470cd3,2fcf656,2cf00b3a,d6a209b8,b244b070), -S(1f1be63b,414713ea,7060e264,ca58dee1,76677033,66002c72,fb8beb2a,a661539c,ecdfdf49,a771409b,2cc03f7c,8640cb98,49c00a82,1d40d1f9,586763bc,35815ab7), -S(30a76480,5c483013,7bbce984,10a2c250,4dc2250d,ed82f853,7caf58a5,b52bd8b5,2edb011b,ae585fce,da2e20dc,3d840c5d,704b8ee5,8578c573,d3363a0d,83168c7), -S(3d6072f5,dede706f,593d93e7,73e3555,c7ab31f5,60a83985,a575294d,1c73d135,d8348521,802df34e,ffc3956,498b0f25,91ef05cd,b71da7,20ce9b3e,b9de6db6), -S(12e42941,44a1bb18,e7944b3d,846429b0,cb9010f4,b42a31b7,e7642b73,520d2ec0,bd7a8a89,f5e1d98d,adf3dd7b,9c8b2bda,5e49f178,cf51796,9bb99903,43901cd8), -S(93b9a4b8,bf35a92c,1f008623,ef3c864b,79de76f8,5d52c4a8,67d24e5c,970d3776,10d1fa77,43bb9211,76801b67,5ed9d304,8fb25b31,65a0f544,52709615,965a7b0), -S(29cae9f5,688107b0,d7cd3686,d30c0dd2,1f65bfae,11172330,7d21b8cf,9d95a49c,dc8ba474,da42ca9e,2325123e,1dbf93fb,c25469a3,381b6833,437034e9,2b6a20be), -S(d1ecd9ae,8af12732,f9423f23,f261caa0,c75a7e,58e0ab83,7fd47568,d3da43aa,c24712cc,49a9a669,e0e46068,60a8c0d1,969aaa66,a436f3b9,1c530e3c,6c0a71e8), -S(fd43cd42,67c4d07a,d70df093,863feb4c,5f82f94d,c81c504e,f95dfce4,4092104b,d68e7968,e003ab0c,ab98beb,796dea02,e854ce39,ecd79ed6,53e001cc,3be14c78), -S(d758723b,587c3af3,52fd7d50,9ef63ac9,efd9235e,a8c8d8d2,41de2898,73d5fe94,43094c5f,1c773577,29b9638b,d180a70,b3c9ac41,8e078dd4,99f5d2b9,1f02edd7), -S(e8fbc8d6,51f9828a,2ec3ccb4,9b7fe22e,18604125,7c975ce,3c01b362,d2897e36,1c306170,f2e1fc7b,ce0d9ed9,fdfa39a4,99d6cd36,bb04716e,e1ac003a,d7573242), -S(bd8878bb,f050eb0c,bc7775ee,a3e991b9,5e72330b,fcba7b3f,cb7dcea5,f1464f2b,c3bbec0d,e87c5a17,5370e6f2,f98b7adc,3538a452,e04ba2db,3e193ba2,d9d1ba5f), -S(e47e80c0,bfd82bf4,8aed911f,236a7d96,4f370d11,c5c10912,3828e3dc,e87e0b3,1856149b,230697d0,1fa39446,9434270f,d0932196,aa7e4551,faad127,b0d22d60), -S(224963b8,57e650e1,58be4862,bb70d566,c2fbc28f,c6892eb7,6f04135b,7a91761c,28e62c6e,887010e9,7eaecc0f,b67e5630,eb2ccdb2,f95d0be8,51c43db1,54ca6e61), -S(b500417f,b75ea406,cbbd77d6,48ac1e45,70703605,8990b340,85856564,a64af549,daad3ad1,9579c990,a7e061fa,f98fbd12,5678de87,ca16c708,7130dc85,abcf1bee), -S(a06e6152,bf4d9aef,d18fc0e3,6e0eed5a,a35b316f,7db75007,ca5a175f,3a80cdb3,6faa9900,6bd783ed,d8c207d5,95843ea0,2819b277,7db69ae6,908d7ef4,4e04e781), -S(179f9602,2ccb2620,3e94101,c9bc95de,5eb6d3dd,8a04f18f,17f2ddf5,1b0df5d4,dccee7d9,30f31ea6,3903f801,d4712ae,ad5459a5,b0ff2987,b3b1f454,650180a), -S(40312ffd,1e4508a9,854c3f94,ffb878fd,a5912ba6,5ea241dc,ea82cc66,e586de28,e111c511,5399357a,eed01d11,18ec409b,febc525e,53cee921,d1dd0455,d01854d0), -S(a29e24d4,c72bd5ea,98630030,a31150b6,5a1c9676,d661ba8b,19d95d5b,ccd7bf31,a906225a,120eb05c,3885e734,75765949,a4da7e4e,a6aaeebf,2f23a011,7aa8df9b), -S(e2e4adce,eb40ffbf,f2a31a97,a34e5f4b,9dcaf149,76747838,3fc0bcb0,43139bb8,94ef60ec,26dfc1d7,dacdd451,2f8c0a0b,ccba1b04,7ae3c197,46f3c234,54a007c4), -S(2a11ab6f,7188858b,e0c8c08f,22b4bd83,3c864a74,4c43428e,2c467d4f,a71118bf,27f83304,ae9e599b,2a212050,c8c363aa,34ae58b8,13912bcc,f6df669,f01a690f), -S(23cfaf4d,57e0e9ec,a8d180d4,568016b9,4f896063,c6fb4e2d,7cf909b9,6ae048cd,62b11d6c,2c3f30e7,655d2c86,8c7fea1c,391d2982,5fdc92fa,f2ef3e5f,f2d65587), -S(cc112ba4,a6b684c0,6f95458b,18f1d41,d0c90022,1fb6af39,203efe1f,f32a07ea,7919e449,eb1720a,49f66e8f,fb3bbe76,4a5e23f7,798f47ab,281d7cb8,9409465d), -S(4d9ad572,bd2829b8,ab98f048,88ec4369,b577846c,59e70414,7128c4ae,17159456,4570249,6405ee85,4bcf1201,9b56cef0,136a4cff,cf90ce00,52711348,a459e1e5), -S(dd32548e,826e2aa9,faca198e,f911d0d,7ec33ac3,41f625c6,34c59c0,ff3e3bb9,5526048c,fcb29f30,ac84ac24,5230b0ca,a0e68e88,ad6c3c75,544bb137,4b1fb47c), -S(c4ca7cdb,93519cc1,7762ce27,249e21a,e2bc5dfb,727a4e23,a38f2938,e41e57f,8233f977,3aeb917b,c65dc1d5,a539f62f,c8403779,f1edc4b5,781e92d8,fc8bc802), -S(a1e1f0d6,2a0d616c,ece08d20,fd529521,c5872f8c,8cda2bf1,a679af71,71bc46ef,68a2a818,4340b803,c7641034,fd609333,180501a,612d3b6,c66754c8,16e5368b), -S(d099aeb2,a5fae253,6a953441,7439e745,35fa8236,96731b6,cd327332,8771bb26,c526ff8d,f32deaf,b7080667,c9d74257,f294355d,4cd10414,e8e38fb2,b3722eea), -S(87fbfc7c,ef2301a3,b50c3bdf,993c52a,b2c32ba2,893b8d60,19f224aa,9554900e,aaaa988e,cf77f228,ee4f42ba,a7ef4a64,ab475e3,3d708ee8,e2826fbb,cc3b92b8), -S(4b440dc0,d6673ff7,cae6cb6c,5ad6d54d,fac23da8,f8e1a570,82fff0b3,eb165493,35841c69,5eecaa5,1499676d,a97c197e,b60fa733,281823a4,2e0bbd8c,ce44b2b2), -S(3ccc6802,cc5fd5fb,82bcc9d1,4e2a2765,f68da87d,7fab7e0,d1c05c68,515fdb2a,3be7e4dc,fb8c734c,d9f0254d,afde26fa,1772f094,43420bc0,aab9e29a,83de67cc), -S(e98bc0f2,d6f9e71f,deb01296,d12a7a0d,b617e5cf,fe2bbc9b,ab166eba,e1a59b85,2fb5ee36,2c01c58f,9a113e18,e03a9e49,5853f5fa,a11053b1,73ebe019,58710ade), -S(5c0bb588,69cb2007,86f2d549,f4fb4146,5656739f,15c8ff95,afd057f9,5db895d2,2c69dc05,b3b5edf,a4d8c3f2,41afe00b,b67a29da,4f1a1301,83c80876,21ecb08b), -S(9c8ef657,972b5330,caa9b64f,7d7c817b,7c0b1047,ae2984f4,3d4f4085,3cd01267,98a3630e,ea6b3bda,c9e9df0a,807eabf5,baa9b920,524a7aaf,2e1e9f8d,8173917b), -S(43b18341,11a7d2c1,d5341b95,4972d28e,e734cbbb,e352460b,75fff2e4,a9921035,3d32e375,40e33c0a,5d4eab42,6849230,22a7c560,3d47e789,30022b40,8fc99f96), -S(89d86eab,b52a84cf,9e53d7b5,270cf9d8,198f032a,e43a286,e18fbfbf,3d0e59ee,bb7b7247,bfb01ad5,fe143967,e5cfa75c,d00a54d1,83322fdc,63a7e29b,5d7f47db), -S(567061ea,2b03428e,d8430f6c,5f03b469,cbb265c,ceb9d999,30509d62,25805515,ab9917,15fcc760,c9aae0c6,5862333b,b886ff7b,b423f80a,92ff44e7,f55f0259), -S(50e830fb,6efa74c4,5460d96d,bb9acb33,df2a3ad2,83602ddf,214d66d7,967bb35e,b5914d4e,24073b29,31937f67,58d69c46,917a70a8,213617fc,4f669622,401b17f9), -S(2bee6cda,ed042f5d,c28bd7b2,a9266c1a,eb502ded,379d4eae,21c8810f,7f8dfead,6bc759a,a1a950,e506c504,86392bf1,4c1d9e8d,c212192e,6f99d274,c1b82754), -S(c4482ac4,508bfd79,b4b6592e,d72b5a6b,f58f1e08,76194a5f,9829cc18,a7959fc6,e99ac34a,91d46cff,e9ab0b74,883fcd24,cc93eab,abfd4873,14920417,1bcb7b54), -S(55bb94a8,70858f43,2753df21,592479cc,32cd6533,f5c7cc6b,73517cda,1814a57,93bdc1b9,8b64d43f,6fdfce00,b8ff652b,ffdc2c75,afc4c95c,ed7644d2,86dd4224), -S(2e17cf48,bbc6b561,3fb740f4,52e2f03f,64a01a9b,bc770df2,b0a4d8a9,71e93fc5,efa5836e,183e1d1,b8e02309,5526ab9d,fb1fc046,92e1ebc,56a6e3b4,4f425c4d), -S(86fa5013,f9928726,79276993,ce380d50,ac17d961,24b48c6,b68f6565,6e39a418,d66a981f,95bf103d,3ee373b9,af27ccde,8fa454b2,1277360b,995a02b9,b7e43b24), -S(6990a5e7,d3d4da2,48f4b621,4d8d3d04,78b9bb36,6647a0d5,3cb66412,120bee3b,5a75c630,d1551aa4,ce9a8020,4ca405d6,dad9291a,e28d0fa5,e14e8df1,1ff79727), -S(1a901e6d,2bf440fc,97075337,b6188f4d,51aba0c1,4207ff29,83ac6eca,9312ab50,6a40d2c3,c497f8da,cbf7b079,7cfa1eb3,80fe0d6c,f3b74a88,7ef912dd,3d8c38f1), -S(37d9f2ff,3f14bd91,3871eda1,c5719b8c,c6e92717,dc97b308,5b0b6890,eab8284,84b05081,cd3c21e3,b36d1766,f133284d,d4abd71f,dbc94baf,33d297f3,a8a238d2), -S(8a430121,8acbc3a8,44436a0f,c476ed74,3548a445,8deeee56,55717e7a,1117166,accdb0c4,aaed4b97,658b77b8,af83248c,85456cef,ad368565,4f73b013,3a258e25), -S(452e5c3d,9c95fa1e,f5b9b508,8a2bd2d9,ad1b6871,5b07d4,d096e99d,22c7fa25,ba4d9d3d,49092858,c6a2b44a,56586ab6,8cf1d7e8,f92a4d35,7b1b91ba,509066bb), -S(dc5d9da1,efd435cc,70c5ab24,994b0fae,75e9a628,a71d1794,ea620d18,83facee,e16e5e82,91f44b12,e6512645,d9ef73b1,4ce928ac,3b4fa30f,bb2e958d,28f1263a), -S(ea6aca7f,b52088bd,7094764b,bcc2c0b6,9ffd5859,e1fba329,4212b0ed,7fda33db,d81cf674,4ffaab0c,71e43cfb,3c1b7ff1,480024bd,1691eaaf,cb5b8174,af824cfb), -S(2bc369d0,ae283c1f,ca38ee72,8a154d9e,62935f97,45f3f043,51800368,651ecca9,b469499,33f679f9,5d75cfd7,94dad8fd,b06d91ad,8c019dda,a819261f,1492eafc), -S(c4c52452,80983e50,4a599a12,782f006c,c7a5fab,5b782d18,b68a7143,ef1a382,a23e7df3,e1443d5,72278fbb,5ce63ff8,b7ac020,1544f21,3c9fc2c6,6c7a7b69), -S(42e4ce90,1240f01e,82f0f4b4,6ce1a1ab,9b26d339,b7a4e128,886031e2,6e6d08cf,61ce91e3,b05dd18f,6089cc3b,9fab7541,d23725b0,49bd16c8,9e468bfc,5af82be5), -S(288a0ac9,72a2333f,f29dcd93,faba3852,c749763f,4fe88a79,601ad6fa,7440836d,fd15dbb5,26ccdaea,7a02807f,f1edd91c,28409802,8f84eb5b,18cbd5bb,1bcc5daf), -S(1f9655aa,5434b9b6,e4b76058,6557e2c6,77df18b6,1a732003,c9cfc21c,97db70d7,98366446,9229d5b1,67bb328f,205260d5,96930a73,8f562c73,707900b1,52b15632), -S(a509bb96,95d4ec8d,93fbdbd2,7280b68,597cce37,a0d71fe7,bc0eb915,41ef6e8a,b28d1ac4,7f548df2,4de2ab4c,271a69da,4b0ae5b1,a4a8c8c6,1ffbdb21,74863e1b), -S(10a2d8da,bc8ca5dd,88b84e39,7a4a3119,61c3470c,9924491d,bf206432,a95d7d79,aed65260,d2eda695,d67a1abb,97d24e96,83ce4a38,46c46d19,6ebf3e1f,5ceec78a), -S(222588c5,3ef96af3,af198f26,34180c2f,13941afa,cf3ffa45,29bfbfdd,3de12d38,648de7b5,76a4d19f,6ebc5785,1c218a59,76feec4a,7b2aa840,6d3917f9,ab364ced), -S(39f06a75,58e5f736,fa6d85ea,6e55f841,8bf722cb,23dfc3bd,3249bf99,471f680d,6e7cbaa2,923201f6,800a817a,af7a74f9,49a8bfb5,70a8d555,d9588c4e,917cd6ae), -S(e6e0f39b,9cde4787,dfd22c28,154c1f0b,bb2a2cc,f67547eb,18117941,d4cf0b7c,5c91c032,21b8892e,bfec7a9a,21ac78c7,2c32a7fc,63882605,5c2901bb,3b99dfaa), -S(d041c732,d1728f5e,1ba5bf55,9e22c824,275d74e9,f58929e1,4197e556,b8855569,f2055dd,9cc15a6f,95874965,3cfe9399,7ea79f3c,b52ca46d,1f887620,c15e497), -S(35bcebd1,45c3cb47,946deacd,9bbb8a9d,b791f087,39a457de,52ac3a65,a2cf459d,7ef44f3e,bbe42529,5f5abbd6,590f1f06,19094a66,21812331,7d025414,147fb9a), -S(69dfb692,8e0a7fd0,4f26d73,436e955c,52a01239,9382c703,e820f214,3d5153ee,874f75cb,aa5ff884,fb3fc309,b15b36a7,df29ad73,efaf66b9,e4d578a1,1b1936c0), -S(4cffedd4,2e6412a6,5f225b6d,1901d551,4c7192bc,7c09d454,be730b24,fe126dd9,db4e13f8,a050b220,81d998bb,98e11bdb,2afeff60,62b69b20,58894e77,f3272ffd), -S(71087039,9e0a995b,baa637fc,d1a58ace,c3564514,6d203182,60539468,702d145c,4a94877,6fefab05,6380f77a,29ae7d8a,bc1bf472,28180606,a0ebdcde,8918b10e), -S(15caab55,27c3b93b,5a708d42,4fad0cd1,11b0ee7b,d80cf28d,1407e82,abcad580,61b771b1,b8290ba1,34850edd,993dcfda,61321cc1,7874b60f,ca774ceb,38c53658), -S(38dae820,1c973758,7bdf9b0,23044555,d0bd3453,702806d7,e49d7196,2efece73,b5cbaa7c,f83b4dbb,28ea4797,dfabaef7,95167b09,3ec173f3,fa4e5269,48cbb5d6), -S(359f78c4,f840f5ea,8cb0b0ac,67dc7f57,84f6cfa4,fbd3dba1,4bf658ca,190ad431,39d7df87,8c9470e7,61f9ccdd,da1bfc8c,8b34a003,89df27f6,354571fa,66a608c0), -S(fc0ace9e,607d11b9,8945c546,2f210a33,586397d5,131cefc9,7d7b6737,aa4cb19f,61cbcd8b,2131e124,292d0d69,e8543867,846dbb06,90ff745c,5ca5bad3,96596a6e), -S(1256fa76,bc6da2f,9ebfcf03,c05afabd,bb43c4cd,eb0c1af2,cfea3267,3f5127ca,9788b8bb,223f13a5,909bc219,cb582232,8f101016,db9a5799,6fe8e51e,a7e4aa33), -S(52e87225,4890364c,d8b2c5a2,34fad84a,329056df,d3131f84,6282f5cd,231c552c,b3227c4,b8932f7d,aa787ae7,c5ee5122,a0452862,43489ed3,8b9dd191,499ea46e), -S(d7c5c4d0,12f6c325,b356a323,1afc6f4a,13e11fa8,e40db671,c3d9683,20d63a41,31c65dfc,f30c4d23,3a0020e2,dd6f2829,f101da64,88589bab,11d50c5c,89e5e04f), -S(71334288,1d40474,5d7da525,c10fc11b,645bb0df,c92add65,dfdf5018,5254b1a6,52245a3b,e4cc60d7,8a029e4b,1e482311,cb1ae091,4bdb5cf8,ec6db584,2693ad53), -S(f97b9e11,1749230d,b6420cad,db097faf,fdce34db,cfb77f89,596086c8,32158e8d,5ab80620,4b7a78f4,e8b98f62,4b2c6622,9746d840,cb43cb04,bb737403,5cb57d96), -S(ce121ae9,b5128a22,917cecce,c5daa168,bdd61bda,8c17818c,ea678b04,35d73ed8,dd63e534,1131922e,6e5de85e,30d23e9b,78c24cd0,bfd68c9d,14431ff7,3cc237c5), -S(c7344dc9,75ada59,ae0fb974,fcb7e68c,d36d99e9,8bbae0b,de3cad18,fec9fc98,c617af54,e38e7c6a,733bbf11,2cfcd97b,58298ea6,d5d1e738,db85ae7,fb6d8d4c), -S(4b1e37fb,34bc0a0c,f0fc8155,96ddb468,197c76a0,fcd61b03,953d3489,79f37359,abfb2758,4f6eac6b,3a7e3230,f758d775,8cd92608,7280aee2,966d87aa,a5d974a2), -S(187c41ba,25c3d7eb,9a0c319d,c82b1c2a,5e80f96a,1e0f6be3,53891e25,d9d2fdc6,3a211ee4,4ee64261,6f515682,f30ab58d,9edccef6,2f9c51d8,48ef14c0,b1aaab1e), -S(69e6d0e5,494e7ab6,5430360c,c88cd478,fd33c196,d5984d29,cb012c14,e7c0445a,ea292c37,99f914b8,2b99707,b3e22251,646576c6,9669e66,74551217,c0266006), -S(acd53be0,92b10fda,f199b0d3,95e1461,cfbed969,303d65e0,fac52b6e,a9e6ac4,3e08e524,f1f2c044,dd581c81,9cf92a88,1a003981,1a08356a,28674c59,5829bb0d), -S(3673cf9a,1b30bf54,4b12e80d,e9400b57,6680f866,d4f40a36,ef7e364,f112de90,eb5a492c,6c7c18c5,b97a1d83,3c48a3b5,8c764572,7559d19b,a49f01e3,204d22a9), -S(29d36d36,efae37b6,96083387,f15e2300,7a1a8897,6387984e,31b8688f,789f6ab0,5a65924b,cc549712,992bf77b,514e8f67,b5b5b677,90654d14,f2813e43,45144408), -S(1f42155d,6be7d164,a376059,36d253f5,b4657286,c70d386a,ce5283de,a3dc6491,ce04e68,bd5ac22f,5ef07b0e,a0034ee1,1a6eeaa2,19d3f7de,d82a5296,84721309), -S(3152b951,db4f3586,994d7e65,fb855285,9401434d,7f9f92eb,5bea66e4,4783bc01,bc8aa531,f83267a4,84fd6485,2a13a155,ba18d89,9a2c66a6,ded6639a,ec856ad1), -S(311b8ed8,66830c54,754cdd74,a9d057f0,34566b1b,43e40d4a,85236f05,3b41808f,6f1b0365,2443f54b,3276d30e,23967ced,42476347,e9a13c19,419f1ac3,10bb3066), -S(348dd77c,cf08f8e6,d3ec8d2b,ef0ab154,f1cb1908,1a497b49,7c44ab29,c2299dec,32774af8,4e29b1ab,ca10560e,b0909ceb,5815068,d4f49fb8,e5b1766f,fbc23571), -S(632e0270,d07e3855,446017ed,d8753402,19e325c5,40079385,1f321378,b22d1427,ee608d57,3c5e5d6b,a78f90a9,58d5ec07,4068657e,e19192b1,5dfaf3a5,54f930b2), -S(750bf219,84a046a3,6a2dc2e0,351fff5e,25cb20f8,1631c91c,81c8c10c,3e251bc5,59388fe1,6b5a4f6f,59fadb9d,d37bb50c,6993330,79be47e3,344f2175,47756114), -S(1957df1e,4a617193,1f1d0f7c,fce46d02,3f0b3f49,53b593ba,bc882368,bc7ee3c7,62a95912,beee20d,43455ec3,69e0b4cd,f8d017cd,520a831d,b045226e,c7302c05), -S(bd846d21,7e08ade1,833ad435,4b5af61c,f987e071,319344f3,6ae78bb2,7fd3dd14,eb6a2269,48ba3378,4a65d1ef,5b643c6c,102b09c1,d3ee4dd7,13d8761c,a1976a12), -S(871fbe02,37350222,fe698501,e9fb8a96,985b4254,8d4c8457,5a9c1388,c3f24d35,c1660e11,5bfc3e2e,29e3c8b8,461f479f,64f60cba,5e7bb363,2cd92127,dd78d69d), -S(e7aa1f24,b4be5505,1321b35e,6aadf2fd,9cbbb45d,3cbfd0de,b990b032,70a58a42,b5f3e930,45efa4b4,54ca308d,f529c526,487e98c5,9bda3402,531d9ff9,c4f618eb), -S(879ee365,67d03ecd,7a06efcc,b7fb2b6c,8e756969,5f369c07,bca2410d,3f909399,1242e4e6,d7da2997,aa102242,16bd3e4c,905452a8,90203a43,60667fb0,c1d5647), -S(853bed4c,db8d5a90,792681a3,f654d2,c7947e70,1b94148c,204128ae,5296b2e7,d5a0bb9a,5c785ad3,faa3d26f,732ea3b6,ff50805d,344c823a,8c8f5f79,60d11dea), -S(2a40813e,c0c0fccf,8488c8ba,add7a231,7313a0ab,923797c,2abe6285,971a0d11,9552f927,f6e501ee,ecdfc1f2,1cf4001,a39e458c,23d5ceb3,c4cd1c3f,8155343f), -S(6a77953,3f265be4,d6c0de74,4137a9aa,cfbdb479,92093a61,94b3249,2a50f5f2,fd6eab4d,7fcf58e1,d2fe6b14,d34edee0,752bf837,f9f1bad2,a25e5be9,df979a1f), -S(1bf253b1,d971644,ae6bd7cf,b0beede5,c17d16c4,a50ec5c,70b050e5,159f544d,34a466d2,6e22ee07,a38928a1,a0ff40c1,d7600771,e4478c73,9820bd84,6abd0615), -S(8bb4c9b6,99634aaa,a30e6792,3d543572,2fbe69e9,b0c8f4f3,febcde8a,76700ae6,b36ad35a,7b47e2a7,1e35d002,49ca67d5,80c6d803,3aa7b3d3,340606ef,d6b0565e), -S(796cc3ac,1413160a,7f5f4c9f,4b4b1c4f,99acda5,ad71e8d9,e9bb772,dc4b01b9,1a674e53,fcc8f8da,a40badaf,4483ff63,eaba8555,2d1f264d,dfc138db,43c27c06), -S(969fbfd4,3d17cf8c,256d3bc,a7de453f,4fce7840,10c2eeee,6c3c3077,5e08b378,8f38eed2,1b64ecaf,56cb0e5e,ef83e94f,394ce1fd,9cec89a5,e2814ddf,127a3f95), -S(590500f6,ee062164,eebad106,7897f85e,75d73696,39156e73,369f2811,acf60685,71060ec,51b9d51a,aa8b90de,6b1f7d08,f446e262,3bbdefb2,4664f98b,c1becb45), -S(635f3674,4654a3b1,e905bcf3,198e9747,d6c516de,ead4fe98,c2f8a86c,4961f5d3,415b4c90,a3681e72,b8ce95dd,804dce01,b1d6740e,9d53078c,9b8144b6,cffd69ce), -S(68d94350,a15ad103,aec6b0b2,792233f7,b0d83120,ee5b1d9b,b481e84b,d04d1a2d,790350d3,32dc0cea,2977e09e,fce1c669,978a2588,9a8d6082,1f564e5a,7213606b), -S(c96e7e8,ec77ee02,335ca492,7f15b99c,e0f451eb,e07b4506,4c05467f,461f01e6,e9a31a45,b9424ddb,9adc82c3,df3d628e,bb1e9979,c9a0c650,77af2678,a6f95980), -S(7917fd53,b5be089,fecb576a,25aa257,c915f9ee,38bfe4b3,f86ff29f,488d680c,b09ce7af,8c77843c,35c5c621,65b527eb,fb28aeda,9a36829a,de905dc,d6f70ab0), -S(f55b5dad,a5205283,88d574c9,629d16b9,7f937bac,c6929255,55fd4497,38a5ef6e,34201d75,2f3869b6,f8db8a88,bb018f54,cb0a6d3f,9f87e522,e22e2db8,800acc7), -S(a257bb75,eeab4ff8,269c4124,db5a9cf1,71779493,7537b46d,52c72467,f9cec60a,f08014c8,6b355789,7730b437,bd9e84fc,22ca7740,a5cc5e81,618499e4,ac74bf6a), -S(3715ebe7,da86335f,b386a73b,c8b7a4c1,4f6e688f,ed72bbcc,83a92728,69cc52d4,976fb0b8,6a119539,90c05a68,49e22544,484dabac,577bb642,a69806a5,39161aa7), -S(c57384d7,29b0a7b7,c9814a4f,f369cb75,1a3d076b,df00dd02,e87f82f5,3dfd6817,4319c981,2610010e,6283ee27,a72f9473,5c10c4bb,d246bbe5,d6078473,b80d665b), -S(7d09cb55,b1a3d446,77dc5ada,4cb7944,c844e82a,45954ba1,ec2dfe4b,b1f49ef8,72571169,2db1e3d2,217e2e24,992882cb,fa11e4e,56c82acb,a1db0d0d,35c5238f), -S(d0a60225,5b87b479,4f2ddff7,a7b32c3f,693065ee,dfc78f35,f8ee1813,30a5319,4fe22384,42e5d371,46e730c9,7b91587,bef5a036,535e609f,de2f6f07,865ec3d1), -S(ea68a147,c69797e7,813b5279,daf2b824,e12a5ab0,69b18f91,f7cec706,c9107264,218fc72a,8e0faed1,bbd55ec5,d1b84912,a0bcd7d,a6367c4a,e6f68d4e,5d218841), -S(d1848858,d2436d03,396c84d0,3262ec0c,e4898a61,86b66e5a,f4e8143b,1713c810,91cb6ce4,c502af6e,eef8be3d,93261cea,79f102c7,12c798bf,8228143a,bc6f4ec4), -S(10883dd2,d74d3c21,a50a3b2a,1243efbc,876f94be,4f749173,9a76b7c6,c3ae13a4,376dc0b5,7c8e454a,eadb8a1c,eb53cf24,374961b1,203175d,f682c8fc,895304db), -S(4ce880c4,f0d3f822,47cef7,7266f02e,efe9d1d7,75f3e1ce,f6bdc7b5,9a1b91aa,8d8f082c,3e3d305e,91eb4032,adb695f8,51cd3ebd,78c8f6b6,cfe87cd8,6dc645b8), -S(7f43f40d,99228e89,29102200,49f40ebb,89508aa2,2472ad89,9e14d63e,69df3cb0,64bfc237,cfd6fcc2,aa1d8d5d,d709aaba,542db811,c4098d,68f8a123,39291cac), -S(91a6f844,6bf0d01e,298e8890,98866445,96e19b74,802fa565,91ea7f7a,3e01bea4,425d1750,17f81fc4,939abfc1,63aae7a1,a9e57623,3853032f,2bca878e,e53f4bb), -S(c1296478,5ef73db9,27acaf97,7c459535,15ec8dc5,ddbdd62b,d85d448b,747b25d1,72d82dba,36b200a2,4921a696,ddaff7c3,16f6027e,516a13e0,ef3c6c12,8187d956), -S(5239834d,63ea0e88,6df2db9,8496d181,1c7001c8,c845b319,309d8bad,7737b4b2,32e24dbc,d6265e8a,902264b4,345bbeb2,40363c6b,731ae6a,a9fa6194,ddf9ca51), -S(e08691ef,b43e68f9,bf315a12,7d5a93be,effbe597,f8c51e15,fcfbded3,72be397e,f304ec86,55f6255e,527f0c4a,80db724a,f4c5fe8a,e7a8174b,128d09c4,1f38bb56), -S(8ba2d25a,18b66731,5f03025e,a79c4177,24ee484,ad281e2f,a34d21ac,ad49711a,a9a0d35f,e6508408,219f5bed,f8926a97,fc070ce8,3e7c8a9b,9e319cd,842f75bd), -S(40a6b491,c6c180fd,fa4e81cf,ca69e9f,b264a519,55796ab7,1f5e1089,79c8f243,fd51d9a6,35be3859,280caf2f,c494e4d1,141b5faf,c54a9575,ab98faed,c8f0d8e), -S(176e36f4,80e9f1b7,bfece37a,55577811,a39e4390,9b12a8f,75b4ed9b,a3c5a7f8,5253aeec,58dd769f,12583d34,70248112,7720ac71,1e9b4273,b4a567c6,f6eb91e7), -S(72ee3556,e5b22f02,9eed97b,ee54c7e1,e3a69fe7,f2e83e13,401c7ee6,dd4b2b95,9b728711,1ae6f55b,1aa1a43e,271c0a4d,e0768689,62a2166c,ffc996e2,d5d2ee8b), -S(7a1aaf5,616ca51,374d539b,d67c7373,191750f8,fb5c512,5d23ae01,3297db5d,430fad10,6e887fff,ce7f8e99,97cd20cc,63abf2e4,d8783da0,f9551a57,591d72e0), -S(b7c2c82a,dffc0544,8a350835,843cebcc,7c854fa9,1dd50429,f0cbfabc,738f60e8,ba5a3066,1ae99c9c,65017efb,8dec5279,ad99b3d8,fb93e1f6,2292fb4a,16566ff0), -S(872247ed,67ad35b0,6fae570d,ec2d5717,f1aba1d0,39400e84,b4bfb997,c124b13c,6d6020c4,cba3bf3a,34d6c831,84ebd4be,5a19bb63,dc2fe3af,458ad74b,bcae582a), -S(cbc1502e,b44ece8f,c641d32c,1206aaf8,4eed904a,8b00507e,338e6017,d7decfa9,105afd03,4ec01247,27bf7159,57ef0b01,3dd37776,dc40fd7,5a0f4385,e26620ca), -S(15768fa5,72722a8d,b26efaeb,61ce7f71,95c0e10a,99d5fb09,fd1ad9dd,bc597590,8f61c181,98218dc2,8b8e0730,ba7aff7b,c5dc3730,30a27caa,d1b913e,36df0a52), -S(52301c83,5f809de1,7bdfcd79,fe3e9518,a1479df0,24a2caf,423b86f1,c685cae,3d171f90,5f13860b,778e5708,c2e3914a,c911bfb4,f70a4af1,2a1b00be,62efe3bf), -S(8fef14f4,100d0f24,b9dfbd35,12d02e0e,f4365406,8630c899,aab5bbc9,ebd6cef6,dd67918a,27d6a6c0,812153e8,481e6a42,b05ce8b2,dbed064f,b82aa417,1b788850), -S(7a4d8983,ce4101db,ecb3dc62,c228d75c,bfcb3283,d575d73f,6bec15c1,8b5cf1d9,26ae5767,13a0c2d4,dc6d4ec0,d3f8c038,48516436,ae5286f9,698bb2fa,913752f6), -S(aeee0e3c,a620b586,c34232a9,e3bc6b8d,f5b72be9,b1303be6,5c07fcf0,f3507c58,d43e4b08,6424e81f,c2b7f809,d17d9572,83adadd1,2bc2226,a190755c,82d010ae), -S(7c97458,6753cba,49ca2e69,905ea7c7,7a6f28bb,f3c7f390,d75aaf3c,3d1eb924,fbe15867,a8e7aa97,4682180,c9083321,5edfaab9,a7addde5,7e5b8037,acc9065f), -S(9428c393,31d5b775,ba3922fc,43cfb7ae,98a6dc54,1541dbc8,bd77816,1aadbc06,f1be710c,5fcacae2,4e7afb36,353b8417,35cee21,8d73310,4d58a19f,7ddce278), -S(45aee6c1,d86ac7f5,b8434541,9c37ced3,ddd54bda,5d8582f,1ea4d2a9,767dd73e,95962f5c,45c6f3a3,22f430c3,919ee03f,cab243b3,f9feb2fb,9f8b00b6,983a84b2), -S(5ab3774b,b840b2ac,e1595d53,d51c5d92,3f7b617f,1bf07ee1,a091c798,20a6cacb,125f6498,1d82a4b2,ac7b1471,a42da473,da38524d,def91d11,a045af83,89d9904), -S(28966b11,43e4d01a,d8a7d161,a3b6031,9165518c,880fdfeb,bc51e0b5,84c3b9cb,1cf95f95,e8422d0c,cbe87d43,b831ce39,b1f79026,14cb1538,a4eac1d4,438b2c7a), -S(ad71d209,83a14eb7,f963d5e9,aea67d3b,f00173c6,b7625b3a,9fc7417,f49a3a76,a72f2b57,fe593a09,2ef5263a,955598df,fc2266e0,ecda8cf7,573ab085,9a82792), -S(f918d962,ce0cc947,2539b1eb,23482e9c,a69b6254,1d0ad633,5c35adeb,cee0bdde,41446862,e8c749f9,559c002d,c42deb6c,bd2240fb,b5b0d4ec,94e0d142,e6ff8bd), -S(f0706622,6367ff84,f7cfbebc,f389d1fa,e9f97aa1,f1acfdf2,d8c6145b,e3a8a159,53af7a59,6fb697d0,2d01d8b9,b0c75304,ce1009d4,7f3c20cc,94123aa7,9c91c813), -S(800e414e,9789e121,2c8b6f71,33027b74,14da762f,8956f347,4eedc170,4e9442f2,7d1ebac5,3088ecb2,7bd8a881,78318e1c,d0ada6f,9b8f503a,57283c6f,b2039e31), -S(2fc35a13,b45daf44,8370dec9,a43237ec,1d7313d8,1113993,7e103ef4,1c90fb78,ee6b54bf,97a32d23,3755ef16,85b1f212,2e46531e,164277c,8769a6a6,2adbf6ca), -S(1bb58cc6,8606fb97,5ed32c09,f668e25b,b4795ce,84ee0e98,5dee5536,b07929a0,9e82d8c8,b37926ad,29954971,8b6dba63,229e6887,14e03042,ac3a5fbc,a8e9fb0a), -S(2479bbf1,e9ef8b33,b1a93153,47392063,19575393,3b0b760f,ed876af2,a98c285e,e58fe58d,3ca3e0ce,23bed9f0,258214a9,51741872,e5198064,af43e106,70567e66), -S(b396e44a,41e53514,411fdd39,6e1084bb,dcda0750,ae66145a,efeae86f,87994254,6536d014,1d2b6a6f,a0425f70,c7374e3d,4fb6324c,931b004e,995ae706,2762583b), -S(7c1808b2,bb1b46f3,fa79d047,ba65032d,7b2757eb,a9b1f241,2379e419,9d4242ea,bbfc916f,cd41f3f,e269d5a4,38bfc9d4,fec0dff7,739ede5,8785483c,c4657faa), -S(92e5f9c0,13a482dd,6789661a,2eaaf396,7c0321fb,1e488f92,44e8ab96,cc7273bc,e2e815b0,f9f43539,3a265354,f6880193,791a3bfe,dda916ca,ea12fda3,27e67eed), -S(6a7ab088,8ea54626,9422c715,e9b9bb43,cbc565b1,ed885200,1e49d8bd,4a79e84b,dea9872c,2c07f8c8,461d943b,cd6328bb,6fd23a5c,937d5f3b,5a87a921,94a5807f), -S(75b11622,ec6cc4e7,6887ced9,dccc7604,8bcaf51,4be6b6f,94b1d7fd,e35b5600,7f654a7a,1be8680a,d94efbcb,12a4ae65,2b0f1859,5c14ec92,df83e72c,cb98705c), -S(ca26ae7f,2b6b1e1a,1ee255d6,68d85ee1,88c7d6b3,87ca8374,e07eb9ff,8bce3df7,958ac803,5fecf72,a2e89cd3,d54e151a,575eaa9f,2e4c1742,a2d8ea21,98c0d35c), -S(e6109fb0,a6d50ce2,c9eee96a,3f5eda11,31af4f00,8ea9b2e5,eaa6619a,9b023517,92a046d0,653d61de,97ea073b,7be72083,1fa16ea4,cdd1f4f4,ba9e94d1,37e9636), -S(a99f3ba5,30d7e13c,f05c77a3,27754420,50b3e1c8,eb92da33,988b28c3,20caf85,8b73170,71d3533a,37968605,ee80b458,5c77688c,70aa6aae,1e322015,e9647713), -S(2ab7b1f,4b81ed62,9c358544,6cb81e01,77e9b0a2,43a4c81a,58e636e6,1df8f5d4,940c38f1,605f9da9,78c713f3,81d578c,88babb13,b08d7a53,f131e60e,fad6763c)}, -{S(217de5b,a47e8de,cb9d8dc3,dc8fcfd8,203c514b,b9d7bb5e,fb03584b,aa1baaff,c77bddc0,3af15e63,912e51c7,19bd8186,67f999ed,9bd801b8,11bc289b,f12864ed), -S(109382da,7088d834,bb181d52,fa1a54e6,39177311,fae56ebd,eb3a4b43,f3e95ea8,4b9d8ef8,ca4cc192,e6b60506,d9f7ecc7,a91af4c0,6e976b79,a90ad5bd,a03330be), -S(ff8486f2,d5296a82,16567549,7a46c099,56a1b1b6,15577e6b,7e789f4f,e032e31,7348e2f,b0a04014,2e23e7f2,bfac58d6,4e7b8087,2297603,dfca65cb,acfb7be2), -S(ff0252f,e7993b46,9174f525,27a6d39c,4f7dfd3e,234f7543,4aed99e3,edb8b04c,dd53af80,f6148d42,b5c7295d,150830eb,18d5c213,aa44fcab,8610ab7e,495d079c), -S(ad7b6b2d,faa1ef9e,125ddb2e,27fd5034,a576e565,c3cd7ec1,7e329e7,ebd22f52,9e1ca583,7cc8214f,1a694ced,2f216007,9b621ac6,5a2ed803,cb3bbf94,2e68b739), -S(1bcfea06,6ee96a7,63e7592d,3a9102f1,204408c9,7f191791,6b941a31,f2a257cd,c4f83f96,7e80765f,77b044db,e3488180,5fdb1cdd,294f765e,7f60cb7a,a6fa34bc), -S(95afe13,a5798934,5b22e95c,fa65a072,4e3e2914,88528290,8e99e098,2135041d,f94764e7,99b95b0a,180fd6f2,8b77ed34,699de7ba,ac4d5c74,24bc79ad,abd5690), -S(a0c4fd09,b3c27bcc,d3a52cd0,5e14873,7c49c2c0,c07cbaba,1a4aaf88,417ed9ec,1e7cf587,2ec3b0d2,f24b2b9e,531d39a5,ec30924c,44578b3b,ef82e55b,f432b1a1), -S(837f8537,d9347072,8ae81f1d,c58f6118,53be68f8,21571f83,4ea71bbb,34e7772b,7f16e8bc,fc9d7784,9d089ef0,77dd953b,508e5f0d,393ebdb3,27e823a0,c75d3b56), -S(c3637c50,fa14a7d5,307ef422,2444626d,179fa5bd,7a6702d8,29971cbf,d456c7d7,dcc3832e,901ddc80,874a82f7,e586c7fa,3cd79be2,7fbed643,ed926c90,d9b64b5c), -S(ff4d8382,9f7ef2b,b6fb2dd9,76787ed6,7cf062bf,bab5c78a,a26d5f2f,f8b2057d,64c4f671,73a6b641,7d97aa9a,fd6d3715,930c3a9a,fcd2dfb0,55aa004e,84cd26af), -S(76099a6,6bd40c1b,69009fa4,7e3237e9,4db5d6cc,4409b9e1,88c3a053,1ff1fcb6,5c7ad308,bd5ede4d,bd9ab004,38e1df54,615ed88,2b073aac,f7dadabe,f0d803e0), -S(f9f4f60c,11b4361a,ea15dc8a,19e1db4b,5f249f59,61003300,98babbc5,c74bcccb,26c524b9,1339e97b,b1de385a,b9f96636,2be8408c,65e6cc23,49505309,3aecc82f), -S(3dc564b0,6c5899f5,5e2f451b,feb11edf,90c1b843,523b51f2,686ef705,ce9d60b6,beb5613c,891141ee,a6eaef14,d5f0fe89,dbacb245,95d712e,b157ebcf,5d5db03f), -S(8ba520e,fea14cba,b5cfb96a,f09e8798,36aa60ed,ce5064e,ca04b802,78068ac6,74c2427c,42793f35,7ccd3f57,9e97e85c,38ec37a6,c4838c10,f0e315d7,aec33ec7), -S(1a32f327,c37e1617,2cbbf255,67636e65,c3a515f0,47f5332e,8a125ad0,84259bec,ac94889b,d1ba74fe,41ad4eb,5de079b6,321c3da,b76f1a6b,52382162,c8a22ff9), -S(a4fd9780,b897456b,b59da53b,7a0b00f2,54bc7044,7d0492ca,a96ca1f8,7dc3114c,e09eedf6,25923e98,2745d544,b4891cf,f443386a,e41a624,284bbada,38769bdf), -S(3c627056,5962458b,faf569c,9fd19018,1b37f5dc,4643bcec,4fca288d,e08db385,e6cf1f81,30178785,f3347f66,2cb81068,25e19f7,72da485b,79e697a8,fc822b46), -S(db75d23d,794297a9,778c28f8,6da0ec91,95e75b53,98dbe0ef,be88aa00,a64faf6d,1af59d51,3dea8f8e,8e36c811,28d113a7,5a7986a2,b6471f6,d17efd0d,e7922238), -S(9c16da05,b9020404,2a1ff95b,9b0457b9,fbb8b1b0,fbc23587,7d912b17,e11a0b5,caa3dae2,8c1f83ce,c6b69f1c,e2064fdb,4c74f239,e5793a9a,5428f5f8,bc995b2a), -S(587dbe9,ef3d647e,d0e0ed18,c1cf96a8,a1415fe1,8627b5fd,f12f8459,c1d5645b,b6869014,4e9bac2b,5256f5d9,d31fe1ab,feb3a26c,90abef50,e89a8f4b,4e461cc0), -S(1de4c4af,1aa3668a,13341760,2101a007,26268248,7c531efa,93a87d13,7aaad2c3,604efe65,d1c041e0,fc12c11b,c093c8cb,75e550dc,55b2ac,92371101,c4c5fadb), -S(cda8f01d,3c1a198c,27e29fda,c3fe8d6d,72de1d55,b36a787b,538bbd3c,be8c9709,4fe322ab,a45b3dad,db173c2f,ff700152,4faa90ba,65917b97,cb4f29c0,ab65a2bd), -S(df64862d,2c032d38,f99aa05f,372be0e6,3818b94b,9d17230,a45c4d40,dd558df6,860c2a10,68082744,f4c252eb,89eaf5ea,57cc76b3,745e35e2,a3dd077a,a3cff1cf), -S(d9895b7b,6893b227,e838bee5,9316d1e3,92743663,e4a7f917,ed308d31,e733d171,c8099481,d8badc36,11e9a266,89c46662,4a9c641f,6e954a9c,e57e55e8,7a455434), -S(e71e1d58,c307f1a0,d6060ad4,710ca427,ba47f2cc,c5cbe7e,5844e4f2,2d46e567,d34c97a7,68b60ff6,e79eb12b,94fc84dd,32522c45,99274a54,83a22906,b13c15c8), -S(5e36de9b,62a156fb,c10e9d01,5b0d2e90,a3b0b0f4,78fff430,2a58a8dc,aa42739e,40186760,c68286d8,cdd1a40f,fe0bba94,79bbcd2b,151eb361,9fbdb0ee,ffde681b), -S(9dd460b6,42869b10,740abb12,cdb7b03e,ff9b7dde,f6d88577,1bac50bf,3d2de390,66c5496f,fae9452c,af09a7a0,2c969ef4,f075da7,9132949c,e8b08a03,cace8f56), -S(313642cc,cd17e982,b924eb23,13e0634d,1324a802,bd51cb3f,80d90d0d,17d7f916,2d59ba09,e991279a,c18aea2f,bbdc40ad,23988b6f,d6082749,f3f306a1,94ec89ed), -S(6d3bae15,82708fe,61e09e8d,65318130,686af25b,3b73c60f,def2e585,3cf7c84f,441d216e,b80b00fe,15f2bea,42358150,5fd7726a,12605a2,9bd0d0d,ea5077d7), -S(22f1087a,d2f9b4db,28df386,b93700fb,cc331c65,7cc995dc,990cdf88,afaf855d,8f2377e8,9c562acf,78517ee9,917b6b29,88063caa,bdb7fc38,d7e25fb4,23650e68), -S(973d0afc,7dcd4ee2,9f7dd7fe,b12ec147,156aeecb,9218d651,f6fac991,e738f6af,fdc111fe,32d3559c,9df48e26,f8d7a5d9,ac14d12a,c78e5109,e1baf6bb,6f030a), -S(bc5a2618,f46a724f,c295af9b,5aa75cc9,4cab7d6b,ffb16709,c35e5d0e,8115f320,79f1764b,40dec87b,fc26f74a,36a040c8,752f111b,61827d15,58ea5238,580a8336), -S(fedcacf3,fbec5575,5881379a,54db4451,4a6750e8,b1bf0d5,296b17dd,aa396ff8,c7518849,85cdd0a1,3245d3f5,30685653,3e0782dc,a550d6cc,1c091363,879db1c0), -S(6fc31e9b,d5fe8f58,f2ba7559,8caeb21,f9eb8b9d,394a3fd3,3cbdae74,3b20b01,d17a98cd,3f8b08de,b18a57ac,fbd75eb,de187cc3,98b0d772,32acc3ba,41537557), -S(5ce3ac9d,eaae3874,36b13398,80d3f5e0,9ed594d5,70f8cb5f,ff5893f,11b1b419,8cac7f2,f451e966,a87b294,f0df6e54,3a6251a0,b0862c8b,2d6cff43,fb1f2a19), -S(db689f9a,c54e2f83,aee53b19,d7511624,6195610f,8a4bd546,73ecb7c3,23568fbf,2bcb293c,4d303a00,149f4c2,e4d46cbc,708e58e5,3b1f26f4,9004001f,153621b0), -S(6852395e,84e3b9a9,a99f17f2,bba96758,5d597b1e,18c3ee9c,1ffe50ac,d83021a0,96f4be82,c57402f7,b1f18258,109c6ef0,3ebb2163,3dd6c91b,503c34f3,af250703), -S(baa0ffe4,337a2053,25a06dc8,d502f954,9ab54915,2f757ce0,7ab0f19c,975759df,385a0223,5c82a31e,23b4c721,46ca49e1,f1d3d9ae,5a3ef424,da7982e4,d4ed035b), -S(8652c41c,8898804d,f377f192,9e64fb8a,e2524fb3,721fb7c5,b7f389b,f51ac7ac,1dae8810,fc3c450c,1800a806,83fb3cd,18fb5de5,ddbfcc57,72870867,ffcd0c8c), -S(e57beef4,8ab71788,262d1016,d7caf2e8,24407aa,bd32fcd6,49772c9b,dab0f98b,7557bd67,a381c515,a7d2bb84,f5a67dad,17b91f52,6d60127c,23279479,81552aa8), -S(f5d671c,3e5cafc,caa2a98,93e0ea53,b5cae255,1ca13144,f5cdb793,897d74e3,a455177d,a1c343f3,72ff895a,e0234780,f9509169,ecbcd4fe,9bc7e2b6,77dee746), -S(ad4ea4d9,4cf266a0,62f747ac,a3276163,4757ce6a,2cb1b655,1cd91232,36568664,6e20396d,78a8e653,5d915f77,a1b07f71,6c72d5a6,73c51381,ee2cb69d,8b8177ff), -S(3d000a68,de2bec93,9ecd8fb5,d9ab77a6,247971b2,7c33db,522ad3f5,b1348b89,1a923b11,358a52b9,2bcaebec,f7a60b46,b51922cc,b9c239e9,4713e3b3,455a565d), -S(4b1bb516,196f7c6f,d6b917cd,b8cebb6d,56c4c49d,3f44312,b6e54b43,b51f3278,2acf44a,efb6d3e,95ea394f,18e9945b,e3c79e8b,b3825d96,2b96cc7a,58e357c3), -S(c7edf142,aa3e3fa9,91e92b6b,4f5f40c3,1e802f21,5383bac2,5d90ebf0,74260f,9806dc46,c4c040f5,941e9489,3ff82abb,a0bc425d,44625765,ae4cade1,95a683b6), -S(71f0c9f5,7d2e0048,afbab0b,9058074c,3524ad35,1a9dc2ea,430ea159,eb702966,82a5a7b7,b4e5d028,d748774d,f90b9d52,d7086e37,2be2cd8,916b0d5c,2ecca118), -S(ae7fa0f7,275f4f18,15ec6888,4f358fa6,170f459f,442aba2d,10a8ac0e,829683dd,66c93784,6576d531,a6ba8641,772b6917,9638293d,cf4c2866,262f2221,f8e8a12c), -S(50447e92,2eb7e2bc,f96bc492,6072be78,a4f7d17c,6267f8,da513c57,7e624f4,c4536744,c06a5831,3f75787c,4b854b13,c3d3a4ef,ea09e584,93d10567,cb805ed5), -S(b693791e,4d20ab11,bc3d81f,28f5e509,fa45e1d3,9ac658f5,9a9dd7c5,e7cba800,a078ad71,af8d7312,c1b003c7,a17b7263,6f25e195,4813c05c,b4a05d41,2893559f), -S(4c8c48f,73d8a610,a6cfae50,44a31d86,40f660ed,93d306ed,7942d01b,44c5bdda,c747c2f9,400bddf7,5a96238e,17686ec1,b04a96c4,5031e5a0,68523d8e,16d1143a), -S(87af9f94,4296132a,9f23e471,8961a373,d49c9efd,ae7ca312,d3e28180,66e4c1f6,8251b125,4bdc4711,33b7d9ca,7a079120,bb04144e,a6720b0e,3de93705,32371017), -S(ddb8044c,82842cc8,a2cc1462,c803860c,19e7e40,79a4bae3,9dd7271b,85983012,6bbd6d35,264a732f,824c012,6f076c82,6247b61b,e4248260,99d6a5ab,5e208971), -S(17c12c2f,344e5da0,bba8d9,a5a145bc,d1e6a77d,cb95cc88,bcdb18b8,1accae3e,90fb2afa,a634d199,b11d426c,e974f87,e6aa765,bd98b848,dbec1af,e023afac), -S(dc115062,8630d468,d4c06d0c,6d693470,63fa22a,7a76538,d1341c45,4bc8b0ef,3542ff1e,2359824b,29d0390,e8379bac,43d8e9d1,eb5714b1,91dff000,3748bfe1), -S(7cbbc66f,84023a67,7966ffc,231e9613,9e2db2c6,2b7d2d7e,31d9e785,8ebd8feb,e5911b68,73f2e661,b67d7a0b,3aca2582,db9946ae,b925d302,e1e1c3cf,d9a1975c), -S(72cb29fd,5baafbec,9bd0abda,6f8c53fc,918e71e3,d932eac2,a86f5fd2,49b4095e,d14bbe6b,8ae0ba27,4796d5b4,fc6d6ce1,9a383389,a08535bc,9ddb3220,a04227a8), -S(fb809bdb,a32038c8,d017352f,629fc367,ed1b7eaa,97632e6b,f29a6ef7,6b90a6b,5d4c4958,a28fdd6c,c8a698a6,b7c35773,fda9c700,2776ae,b90986a7,2d65ac48), -S(fb20eed9,22031d48,de92ae40,7537769e,600db346,6de8d72,64610094,79581323,c129d99f,1e32672f,2913bc69,e76e710c,399c0256,63056546,d2332e64,fe6257cc), -S(18b7710e,aa95f5b5,79eb6c9,7d95e653,aea6ed60,3f1f3f0e,f4d570af,621a396a,c1830f7d,bc278840,9a54cb6e,f48966b1,40a4ed2b,54a1f0ed,2754142d,7bd02495), -S(dc781435,efec9436,4d4d3af1,58216ad1,c392a4b5,9adeac05,a1ca9a8b,4a196c60,625b2205,45678f7e,36dc1a54,3e9f9f05,383e3590,cc5b7450,c774226e,fb73c05f), -S(6e16acad,951b4ffe,737c6884,8a59e094,a35f9450,760693d8,9804934b,25d2be1,505091c4,8e00b8c9,bcb50e5,c5eb45c1,d706f95b,cd292994,29425b0b,f3e968ad), -S(3dda4d71,9579a27a,a6980e32,95439374,1af56e38,bb51f165,618af16f,8aa2cb36,c4a0dce1,57b2fca8,2f6eac0b,a800be12,3711694b,4b711742,cc37297d,48d27950), -S(33b53cd2,ba2f15eb,db59dca7,d096d50b,2815cd8a,d44fb218,a750dc1f,63c08130,2088291f,30e861b0,3e566d7,149b961e,d513661e,5eb44cf9,1ab808c4,2dabad38), -S(3ff3ae48,c88bd212,f35fb6d7,b06ca581,38d4cc40,24f0c0c9,f6368164,de246f9e,c177b65d,b99236bf,2161529b,870bb558,a5553f62,1da1c2ea,73297623,dcec6133), -S(1d9f4e25,4ee26361,f5837220,3e4c212d,9f46300,44574f4f,ccab16ab,50023fde,1fc1da4f,8567e4e1,fce5151f,648f31d5,f5cf22b,5973bd56,73b967fb,1bf55e1), -S(5815c873,f3a0b76c,56e79769,54540685,1a853fcc,23b62c5a,6a74df64,c90aa0c,d2c66c1d,b75425eb,8c74e822,d902890a,2d7feb27,f95cde22,648ed311,5dcd756a), -S(bffeb15e,4f70e4d6,b16c0027,eff0c9ee,594b254b,43523788,cb54e8c6,57309213,12261851,deaed15,c2eb62bc,92289c40,5714904c,c291d736,470271a4,24d6034), -S(66b01b20,8d891037,bafaf962,98d6502d,fc05adf8,24731d49,84e59425,9cc9a780,1ad93ad1,984b9404,e2439450,c728eae9,c9ad5c32,7be6299,216ac174,4b838d43), -S(db8a04c1,cbf6dfad,3ccc65b5,19fccf61,a9132332,b6786ed8,5cdc4a32,a7c4969d,2a366e8c,ef249745,fd6a3412,2e7f5403,73bf3ec4,21991101,ef7c7650,a5838337), -S(2cbd46ae,663bf92f,87d280d6,9ccfcc6e,37fc8d87,c586e7c5,891e57d9,9815f71d,40312f04,51f4b2da,ce2dac4,f6c91fe8,209fa78,60bb6247,dcdc1a1a,da4bffcc), -S(4a5fa6b,21e4cc49,83620a2e,1c13a4d,3aab84cf,4e4aa616,a4e0b340,dc1db441,8cb91277,671abe8d,c0252252,665537fe,6037a7ac,8aa142cd,6cae37f5,606313da), -S(48b756e6,3bca3d84,475e90e,23db898d,cf319138,a2bf14c1,a820e9f,768cfb35,e4b5972e,d058b90e,f38087dd,82c619a1,59a42a00,aaf7dfce,a89f679e,96d48d77), -S(6a5157b8,85721f0f,42fb387e,b50f9314,fed50fde,59bee2c4,2a12973a,2fb06b13,7d51867c,834fb385,7bcf64,c2d89094,6784d2dc,e635ad9c,6e902525,ed48f51c), -S(2788ac60,8c691e57,e062972d,398be225,16f625d4,f952f37,2c9c38db,eceacb43,6e469eaf,32db4014,12279b66,181003a3,1d6101af,5b3c24cd,dd4cf420,d71fb38b), -S(7659a365,db31c14f,ebcdc3f7,d8483383,7eb7255a,25b38956,fe013449,89176796,9db1f7f8,cddaed52,178c6d1c,ab762acb,11fc79ca,330638fd,7ee34652,35934b3d), -S(317436fa,cc0f540,dbdb8acc,e9c35266,fc4f01be,b65f3457,9655f1ff,dda3ad7a,deaf8c78,33c26e4a,f1eaf83d,16226488,ad2dac5,639cfe17,2b92f16d,95ca71e7), -S(a92f4493,84a1acb5,fc26ddf9,36b59373,bdbe563d,eb05e446,917a4414,f6e0359f,dfe5c80a,b676487b,b334e9c8,c67cff03,905905dc,a0dad7b5,c3604de,cb456d90), -S(fca66bb2,e3b45c58,2499e52e,d0c12034,2796ae4c,466391f8,ccc81f80,cc8b91ab,12c840c9,b9b20dbf,8c24ba00,59db5469,99f9f2e0,ecdfe4cf,e1f8195,31f0802d), -S(d773f231,295c4836,6c012e24,a825c921,7a1b1657,dd0f3ba7,49a541e8,b380284a,b4ef8d00,66b260a7,7b01a0fc,a4e9b8d6,31265f1b,94834e5c,f778dbd1,ec03e892), -S(af63a268,5669fe68,f3c25538,ae3cb24c,ea5aeabb,51bb6318,ae8f3bcf,3d49d198,ad7f1474,606d40a8,5e4606ee,f95c3034,f64551aa,fcab48b3,3de68f1e,eac43a08), -S(6329c0ed,27a5bc0b,b02eeb67,e79b015a,2d58ebac,9a0270f,559b6bad,f75073cb,a5ffb0e8,12e1f2a,b63c5c30,745bcd8c,cc0e9825,3ea223c3,850119e,74cda400), -S(3d4b56c3,5b51c6be,fb380e04,7e3f05a2,2d5e90fe,55cb584a,aa2e909d,a80b2a76,ff0f8a0b,f6742113,c99401d4,a4f2132e,1e6f41ce,b21241c7,986713e4,4215810f), -S(d84552b,5b70fced,a8053aac,63d2cf8e,7e6abc35,88a467c8,1193eab1,63adc404,d2f36d9,e296f0e0,1f01ac9e,30fa7db7,46a97608,2208d90b,60e4fc00,816a9580), -S(b46206b7,984144eb,a6655c9c,8aaf0658,6083971e,5f77da3f,96b260f7,8dfc4763,ef70665c,b881d9fb,c296ca88,10fbd9a2,17288e92,c0225f06,e072bf53,7830df3a), -S(b38355d3,a0b1cbdc,343c0a38,4c7f0653,b9726bdd,1a3bbd34,2614fd54,409b0864,a7cfc80,895c9ae7,36aee67e,aabe29ab,61223e08,deb06542,62393dad,eb9d4ce5), -S(a423de5c,338efcec,58349f16,70e8ea11,bab0c78a,be0d2442,4ddcd2e0,294f0bb2,e9a2e0d0,90e31783,f2d1abd5,a46e4649,33e3f111,b6f1d3c4,d7b8c93c,5975b2a2), -S(54ea680d,959b1824,15e66f4,622b6a2e,1dafbd8a,1756fbbe,d622ea43,e443c673,5d57314b,44923737,9e116877,e6f74a31,63a2ee66,44c74e42,b8617855,3ca7f009), -S(2bf96fdb,32c84cc5,7a37a941,8f5d8de3,67373eb5,a9e401cc,ab2c86bf,c4a265ac,b0a83c7a,e9ba4985,3c78bc14,8a891c75,3c259c16,4c620a73,8ab2bd3d,7b291851), -S(2425f73e,f25aa0da,588e5a96,51e91bfd,3953fb43,cf1142ed,28341f6c,c0d94885,acec2cca,1798f9bc,2b844f62,5212c411,52dc665b,c6e99704,19108b38,dc9b7cd), -S(d387f2d8,2b130fc1,80f940b8,6bca2c6c,d29fed99,2c3129e2,e1155d0e,415a1e98,af31ff4c,8312a574,9d0a9860,cfba0446,2cc8e2d1,6b516511,1225d4c7,7d388373), -S(a34c6211,815459f5,679b5518,5bb311ea,efaff5b9,cc0175bf,ecf58957,f616d49d,c88078a8,b1d1839d,c1941e5f,300f6876,63be4a91,9766063f,bfcb1e35,d81b4871), -S(cf8a62f0,66e4d06,f2cba109,8c3267f8,a435b03d,c1900e47,3eeeb3d2,bc3d7909,1e3bd7ab,5445163d,2bf834c4,2a425414,af72694a,be85a1ed,e8c53910,df5ee50b), -S(c9f930b0,a80350c,c66d2de5,ae6a8165,9a2f80a0,6c01fdde,3436a7de,5da09d2d,79ceccd4,8a9c6cac,ad77a4bc,255e7cb5,976d29d6,a3d814a7,e504cfdf,66b3af2), -S(dd05c586,86b98f5b,7ba2c17b,e3507e2d,83c31d80,eadf33d9,291abbac,e525a4bd,cdce214c,5525efa9,5e3f7dc5,8ef4bdda,d0429ed9,c59a8aa5,d520433c,eee8a34e), -S(d432cb8e,276f7e79,36f455d4,6ee3327e,70e6ae4b,a04c6ea4,9dc02557,a40a30f,d2c4a0c9,4a6ff7e5,c254bd8b,d24862ba,857b3748,9ecf2cc0,74265907,2b5be899), -S(a3b51478,dedaebf9,a5f59c9c,d7b4bd69,158c5c92,9511c5e1,d4ae7a84,b57a5d9b,e766b796,15010b2c,83a69c19,8c524b3b,10780e8b,e4fc62f8,a2ecabb4,f6fe3f51), -S(39f79580,7530e55e,3b985e2b,763fd21,78ff03b9,56b02a42,faaa87f,3100002f,bd3d83a4,e01de784,c2d106b,e645ea4d,5b6efa85,a52f17fd,c82bfde2,79761c93), -S(a3382f,9f706246,7ff434f,54e1841f,a18d8554,c3011852,f4803343,15c6a360,e4b43770,354c7ffe,29685ebc,64272360,8447cbbc,279b7e67,14bd9479,5298a156), -S(6d09fb4f,a6228cd0,93dab47d,99435c7e,9c6e2524,34c59792,bb2dd18,448a2bde,1f047149,31b69744,d6f7d61e,43e44853,6577fc6b,c2335282,109119e0,d5978db), -S(2a55377f,875e99b3,8d7c0afe,eb3e7491,1f8e41cc,8acf09d7,e9bc9763,697dd91b,14e2693e,81e893e1,67045a2e,a2be9a41,faa81fee,9e864071,f672c629,119b10db), -S(da913380,16f20888,9bfb4371,82ec0b6,1efa4d6f,14eb6f3,808c6b81,2336be7d,1776f0c2,f3cad01a,a0582732,2d2136dd,7e6020e,237a1329,6377b1a9,a3f411ea), -S(fd413737,14e6b895,9a289039,3370617f,37437de7,5c3061e9,4bd5d61,d1dcb42c,56b62876,86af6b96,a73e041e,2c45a439,468e5e18,2d91d9fd,1222d732,eaf1dbf4), -S(d39cd710,47956112,3e7679b5,cd14f400,8e1b6524,8d16d1,9b4313fc,8af4b38f,ef65114d,7e747603,b9ae1127,e1fbbffa,f488462f,3aa38844,dbc26e29,abc314e4), -S(617a173a,528ce0be,77371444,9ebf2d76,f9b58ceb,6ac21d58,885f1dc8,693870a4,52715ae3,ce098246,c6f08660,6e9ebf94,14266165,a354d81e,fb48c9a1,13688e21), -S(1350609,6f5c3382,b280837d,e640c142,65ad14c2,d06a95a1,4838014b,12569784,ac6f4d30,443fe46e,236f331d,980ccf92,d8fc5928,48a75841,c7e9f328,6b25f8ef), -S(494ca163,2000b61e,f513c04c,6f0c2e72,565fb1d2,ed371c25,8de1713e,d467531,611b3bf6,6b9efbfa,f6efd046,c426350b,cdf5536f,4134cfb9,1b4a3225,b2f096ee), -S(3fb9cb47,b84f05fe,72df9ab2,32bd4e83,da049679,ae09a93f,4081cc49,660784db,d9628fcb,1f9deca8,79d19c37,59845e55,94effc2,f0364775,9fe3838c,2674cec), -S(496f829e,b09f2d4,ff69b9f,d4e058d,de547d2d,8cff573c,3728cabb,eb59e58b,64bbf6ef,fddfb044,6e20d42d,4b34b3e4,8823839a,be3a0fb1,2654b8e9,b13a89f5), -S(dfce1042,841252f4,d1524b2c,817f3ce8,85821df9,913048e0,21aba64e,eb10799,118a24dc,eebd2a19,df7b2b0,71fd3073,e21c68c9,2aaf61c8,1fe1afd3,13dafc47), -S(2c1b46,91eba809,95ae941f,70cd60ff,a8988faa,e115c265,3c5b94a9,1e26a0d3,6c50b88e,cdd60794,32bae140,90afaee3,cbc38f76,7f7c5463,c244f9f6,54375ec8), -S(f8d91c91,1fbdf774,6829c779,cc7eb877,498b42eb,fdc8dfa4,3c81eb58,2983c45e,b80c785a,d936896f,504215e0,92eb3365,344d9a6f,763e1361,a34fcd5c,9b489f7), -S(cb9e013f,95b3ef75,2a9a15a3,5ff471c6,6d25acf8,66e89c79,f963666a,c299dbeb,3b117868,5c7e93fb,6c920f4c,25e48118,5f3e8f22,552b4e13,10dcbcab,e0e31d2c), -S(6d3a170f,6be4f0d,6c915593,7c0c7e8a,d43def0a,54876947,a36ff7e0,3103aef8,6fc40770,541ef68c,1d8e63af,18d99209,9313c6b6,6e1fdcfd,359c3a88,900f96bd), -S(ab498e5b,49558ca4,2099c7b2,14c070d,8d61e649,73fed001,11b526eb,c3ec6474,189c85f2,b1b63783,877f008d,b2ebd590,37dbd82d,865175b8,5b6376c,b2e265b5), -S(6d969788,f5204548,d2eae98,87cb5e1b,429a8fa1,8f44cd3d,32f36699,a9ce6671,a08f674a,8de23cec,d0c53cb6,29cc24ca,8c5dcd42,4ae8a7d2,8d43f2e7,57c70317), -S(3b5f696b,5d15291c,75f915f0,f043a622,1cd58678,6c7a0ae8,4533c0d4,d4ef7b58,7aee88a0,c4dd59f2,303c8b80,ed337b67,da3b33ae,fdb66c9a,3952df26,443bda02), -S(4905bed0,798f2ffe,24decf40,d3695efb,deb8fb3b,bd734395,3b027e71,9b8d057a,4365db64,4c598c10,6e4e4e91,f67f44f3,bb62140a,b5298f79,2ce32668,69ad25b4), -S(e1cb11ee,ecf54858,85575261,b749e51,db6cc08a,347fcada,da4dae9c,b6709ad0,a02e375f,da9346e9,f2473432,d74debc2,f70f5727,94027b27,6a699f0b,6206cc83), -S(53e44395,533e62a7,3f97e7b0,d449283b,7151a653,1b13d03b,154f458e,c839c5fb,ac3a2b9,c9c3f174,ec24deef,e16d8da7,f04e7776,9599207e,5fb71eb1,4dedde61), -S(5946135b,230ce11e,d28d5222,ae55d780,dc8d2fde,53342755,76546af5,d493426a,198b96aa,f9922a55,5910b8e,b8bdafcf,d700b230,aa926f90,625ebb56,4a8e488f), -S(4a238646,f0d38511,6d1b997b,6085d90e,b79b1289,53861526,55e60f79,6d378304,99da664b,5f5174b4,1dd056a9,9189e563,55d04622,17d5ca49,c61d01a4,48c94c47), -S(7234b856,dbebdbb8,f20c1fd3,4b719188,7d4ae91,3c596418,2a8455ee,d8fa34d0,2a6b196a,2eb98ca4,fa3ab40c,2b96ca16,eefa888a,5cac8676,d4f4680a,3f9c2b01), -S(dda23494,413dfc0e,f09cc4f4,8e5968ed,f9366e4e,6473afe9,eaf26c0b,7c50a347,ed097195,60b470b0,399aa60e,7210d398,eed8d9ee,1f410b36,71e2485c,c7e218c2), -S(8a8c177c,4617c43,3fdcc6c0,8685bed7,3dbe567b,31773907,acf77cdb,d95ab7f0,27adb686,1572821c,25b40be6,524fd3ac,d801877a,f689f4d2,aade7949,fc3b2248), -S(c40b2617,dcf23ff6,f1bcb76b,dd96a198,7e6ba559,1b14b267,42d5439f,653eff49,eb18ff9a,61e73c26,3ab4eb64,aa53a301,97325c38,2fbec2ee,407af143,7e102468), -S(eaa452cb,813053ba,da8be243,c5bb6c76,f3a2e87,97a5f83c,af7d15f1,e07d8088,15fde99f,89d0c428,979e0b96,83cecfd2,52117580,1dc8f7b9,ebbb1fd9,f02199a9), -S(5fdb7a4b,1dfc0d2e,42c10078,25da5cd5,a3b90346,daff2152,3b9b75e2,d1855fba,3dc00aba,890bd133,6ac4d676,9aed62df,db9a281d,2412fb9a,8e9aeafb,58bbc5da), -S(6f7cf42b,f4b09098,26538863,6c24770a,2c7789f5,dd1ffc5d,5382bc1d,fbb6df44,5ea4dbe0,dcc4a01d,4d7e6660,3026fc41,f0dfa1b,893d4934,5d05d75c,6faecebf), -S(1063f63e,51e3aad3,bf91e892,8b1b8fe5,1b941177,6580c056,60361280,63fc7629,6565cca5,5de4a54,777b24b6,7753a880,7155d632,5bace707,dabb9062,3bdb9b37), -S(f0d88838,9ed3ef56,688985b6,6077fd8,63f2e1b1,67cca7b1,e135a7a8,343e6b55,1764653c,86deecf0,ec350009,1f320d07,db1ff9a9,dd497488,386b2006,e12d2ad0), -S(9ccec5a2,869a95ed,ac9e3dfb,c19c552b,5f04ce3d,5478b16d,c28b6fc6,8b8ba0cb,838b79c1,25b010a3,624be75e,89dedc5d,9b6385e2,65f4283d,93a5271a,f896d0f5), -S(22427c29,2f19da5a,3e4a0454,9b3b35f4,901e2ac4,e073943f,5c41c733,69d5fdc,493252b7,a0a13723,baf56860,949490a9,15f2ced1,cd5c4207,9ac64efc,c94c518b), -S(78041b80,76e8935a,986a269c,68fb1bca,66d1f84b,3cb75ae6,bdfc7428,7ed74b9d,4a73feac,2a7058a2,f193e338,607c4f39,41aeeabc,d1126f0d,f4917623,afa180df), -S(ddaf719d,78d58c3,ae253ba,9cb24640,7c589367,af122d0d,a9a38d25,1d1aa757,8f7e649e,ab08bb70,f052beeb,46321ccd,9f8fba5c,e6e81dba,40b7da63,d3aa8c63), -S(3e28ec5c,4d9fac25,17b857e2,2d1e2c3e,fd9d507e,3619a21b,9d957588,769e5257,fe8b4326,fa187a9c,fadb417f,94914cee,b689f1e6,86402e88,d5a8b8e0,d9ffadd7), -S(2c659f7d,37d2ac1b,e372dee0,f6cb4997,c7dd990c,e8b1f06d,79b49aa5,a8a83ca0,c90bd67,dc1faad2,ab4086be,f7a6b310,39592bf9,3a949f0c,5793ef46,d9136fb8), -S(d4afa87e,2dc5a4aa,d001b27c,87989350,1afa374d,85a2002e,e5111bf5,d7da03a4,39d697c8,614df67d,295d7fff,20a0e333,6045bba4,6d565962,91665f18,83816707), -S(12de6449,860786cf,215f9285,a28946dd,668b0ed2,f8a0012c,c785f441,3386271d,39d68f4b,42aa5ca9,99c1953e,c216418a,7a1b83bc,c534cd8f,f50dcb25,2ed08d61), -S(19e539ec,986bc292,c0993b43,e8f03988,81fc72b0,53d530d2,812c971b,b53e35a3,41e96a03,31462b0e,e38f6a2b,774e154c,22ece598,7400c199,4aff2beb,340dcf8e), -S(3a6d63f6,e0083404,c768869c,a180b659,3efda9eb,f2a38385,7bc32e84,5e7a9f63,2897d84d,a8a13aa2,e2b96f22,d97fac13,5e65739e,ce341c1f,1e188d0d,6b29d765), -S(6fbf7d9c,5238b959,1e29dde1,cd092621,86a3f216,c8252b7d,dae85433,b08e642a,7a52157a,6c78af5e,2b9c21e6,64aea1ad,36bdf11a,459e2fb8,205fb818,d6f635df), -S(6bfe3a73,6211e70d,78be3665,fcdca331,a73d6a3f,f2cc9e50,df5b87a9,737b6d1d,1809c07d,7c997a60,d2bc187f,7ff527ff,8f162fea,10475684,6cd95920,5233391b), -S(c6f521ed,441c39dc,23c11ed4,5399ccd1,4b83e00d,524c8163,8cb0c0c7,ecd3a0c8,dfccf249,6223886a,e520ed1c,d84f4663,b44aab90,85ed836f,756a3b16,72775f4a), -S(be39757b,c2537f0f,c4c67c93,f2dc2830,b464d3c2,672f3d96,8051db68,57e6cfd9,30047462,b2f2ec23,2901060e,b05f6697,78fa42ff,ff05922b,2c253927,4d350a9f), -S(8cf591a1,9c98e274,a83cc687,ee992acb,3255320d,e3cbbea6,57fc790f,a2b84d0b,1f2d8a14,66b75c5a,34e9ba8f,6e96bc0c,6ab5e9e,e704919b,96a8d2e,87e29f81), -S(339c0d5e,5e28c33,b298bbfb,73ab7a8d,89f4b1f2,6ee853a,83d9865f,3480166,b63bb64f,7c99b7d1,15430fa5,125552a1,201fbe11,c1b90f69,a539e6e0,a8c2bf4f), -S(7ea652d7,c3309dcd,70f21d5a,e0fea7fb,81790527,c75a51f9,a37beaf2,ce867e72,22974b39,a028964e,97e00cc,7ec3491d,fe9e010,be520d4a,f2e8139a,1c602296), -S(23975673,c1723378,ecf11bbb,90d963dd,ae855472,2321c50c,eaafdde2,2a825762,2d1cd4b2,3aa66041,8fcdafe9,25ad8486,5912b905,b77588b6,deb97db0,effc7ee3), -S(52c0516d,6bef62d6,debd0879,9c96714b,85ade01c,1748053c,2e4647f8,f28e4594,deeea364,bb534e70,b74aee1f,95f528fe,e0b8c239,b6a0c228,1d4b5538,41f0bfc5), -S(a19f26a1,f4fa9b9c,42ca111a,a2b9492c,b95a792d,d23fabb7,e76ad6b5,6117a9fe,10f990c9,e9554447,ab030a5e,2db24dcc,80f17142,aa450d5e,930851fa,8eaa9a40), -S(366786e5,76b32325,1e44e4f6,e5d71c50,5361f771,8e355e3a,558beaa9,52d4a1e9,e76bb0e,ec2325f6,144801e0,d154bd6b,68701212,7233da5,c0daa306,2217c839), -S(ef26121f,f99a553b,ecafaa00,95d9e06,92fac8cb,40ba0331,1eef3b0f,eb291181,5d32068f,a1e9bfa1,487c6993,305e766f,82855bf6,b91339e0,f8804e01,6b6b8691), -S(5d81302b,9d653515,2e54d2c2,10d8dcc4,3a28393b,1da7402b,30410551,21f19b41,5094a844,9dde9d3f,3113ef85,9a0bd7b1,d1756646,bb793080,3007b2a8,f9068fa3), -S(c15513c2,652f8de6,ad273db,67312b3a,6c6c6ef3,7deece21,2703ea2,234cd929,64c2fca2,a392d4fc,ca8402e,146da89,593a1e7,25e34bd6,9c577238,30c4a449), -S(c265755b,5f628680,327c3b04,335a4b60,dee266c0,dd3bec93,708a20a3,c3ac9c1f,1367223f,dae8a304,b32c97b7,505ffc23,21d94115,579a8ca,638959d1,34dc21db), -S(d4acca04,42a53b23,ecc67ae5,d81d147f,ed477480,609fb71d,f0fff78c,20adf544,8b0aa74d,88f9fefa,affc2acd,d36479a9,ac814b3f,8cc3d01f,749ceb0f,9a90f052), -S(2a8cd5bb,2be61c60,615aba87,6df1508d,37f61b15,2429d10b,1f06599,dca26b94,8e6cc5ca,abd1c09d,4615cd80,a582bb71,156be2db,4876720e,6ccae849,5990756e), -S(74d6c1bd,65f37304,360b58bf,c443701e,f2be71f0,b366bd38,f29b876e,954f2f40,4cb209e0,6aa2459,4583b12,8572d25,1c88a2de,6d54057d,19c270d1,bf9c8077), -S(4baf4424,d78546ff,9b28f46f,ab97ca02,94ca48ac,812f13ba,7cc47b4e,ee9eabfc,b4910b45,5e06246a,c99febc8,af1cb0be,807127c7,28e29c16,a94224d2,b633065c), -S(c69cec47,387ab1ac,d20dba21,54625cf5,d42d189,3cc782c3,234e204c,9b7f28ad,514a7b5,fa667f36,bf4df18a,8ced613d,f8579abb,3e90c470,66c40280,85f0de84), -S(7300a33e,7d50b348,c28b4769,8cf8e011,ba6388fa,54a2dce4,7f83968,7b05d5e1,d0ac31f8,1958f36f,9b403154,b6426faf,73078ae2,6c4675f3,19b3bba7,c5c7128e), -S(e989b465,c21d3a2e,60687588,73333148,1e58b3f3,e0bfbcb6,efdd60ae,204e408e,a2d6a205,ada25071,c981db04,f857b005,9f906977,5d607958,7c1479fb,5e44e121), -S(c6afe364,f87a2b1f,92633e44,6b7aaa,74cb626a,79d6f325,263f1b7d,e5af90f1,87197fb9,861d254f,bc8be0d3,afab0831,9064dca1,7e8e1f66,ca55accb,f2d905f5), -S(8a026fc9,1dd4884b,ec8a7e66,cec8b7d8,7b9c78de,127dd3e5,40324032,78f70d22,34cde629,eb1fa38c,d533eac5,fc39bcf3,ae67605a,1ab75537,577a577d,1a75d079), -S(20f33fe4,41217692,124914c7,1750ae1a,86309797,7fb7ccff,93786b98,9e5cfed3,3bd39c87,c3897ed5,52f4a1bb,d8791439,5f1d10b,d827e22,30090b30,7ce9e6fc), -S(47e43518,4cf5e087,3a1b378f,cfa19adf,42abbab4,e0aedc37,2a7b0d0,1033c0fc,aa16a1a4,cadbc035,d774078f,231fe564,53c2b736,858d913f,b90169a5,3951f31e), -S(8fd41b49,adca1b48,574a559d,eb783fd6,6a8c61f8,ddc4950f,883e79f,585351d6,60409c9f,d705fe6,67d796a5,4c0dbd78,41d1b4e2,57f8747b,f69c01d2,7cac9bc5), -S(2091cea6,d9c5ac79,3c3dabda,89bba911,8d96dec1,42f77c5a,83e85c75,d67a5c91,493384b8,83d83be1,b1528700,6f466ac1,b9f5873f,4f99e8c3,b6077594,b8ba019e), -S(ecb086f2,36fc71ff,e455f9ea,3bd542d0,18d6c2c0,9564813c,5da7fea0,81568b68,24603a60,7f05cba,4d10fce,972241ca,f05b491b,dc2f324d,8fa93ec3,99359a2a), -S(364a9ddc,759693ea,cff66ed1,74e7c450,3197a2a8,a743b2eb,b7065e5d,307d4d52,11184aad,92fc83bb,11752b22,6d0290eb,725b5e4a,a2e6e25c,2095ab26,e34764c9), -S(3465069c,a194aadb,e5ae30df,f2d6eff8,1dd3acf8,7a01f6f7,38e24347,b2c6ee70,ded48ab,ac058655,e27a52ec,3ad5b9e9,d1ae3c39,25f0fcd6,b6e8ea5a,f490d15b), -S(ed1ee361,9b6709d7,cf029876,d9ad4ac,3c3bef69,c58476f6,ec719730,1f29eeb2,2c775e17,43f8422d,83b76860,d8a244ca,6a0abbc9,590a3249,1fe6817f,f395fc46), -S(194c6897,27039b42,d9d7a7a1,fc1cc4c0,ae1c16ca,9bf576d0,bab0ff09,c6d478a4,21e309ff,77590d33,9c408879,315c64b2,cfdd06c4,5b744238,1722e974,8f78734a), -S(6e9c1ed6,3fa52d39,74bd11a5,f32c382b,a6ea80c8,109a630b,39cfb9ef,50e92ca,edb9e34b,eb734475,ae167b20,900e86cd,134a2d6b,568db142,22122a54,32ee140), -S(b0db1eff,53cad7cf,ba686559,80c0b90f,6f8f1747,fe53912a,17d6ed61,c696a010,a3f2b2f,110e29e3,8d6a4518,18f04f79,6392b2a8,2d2dafb,6f0a627f,d9fbad48), -S(185fcfdb,db26b6e2,a1ebe2f6,b28b6cef,d02132ca,aa2f53f5,af734cf7,cac6e6a6,754e39e,62471511,e8d077bb,43023072,a52e9fab,d987066c,e5327cb8,a12bd843), -S(434df3c2,cd69896b,fe2ecfa6,6a9c0107,5d12283a,4a34fa68,fa2cd077,da271328,fc13d680,92b22495,fd846672,901e1679,8ec01444,5b25c11b,79ac93f0,423ae41a), -S(c2d222b8,15409db,6a5624a1,5aca06d0,56591dd6,10cb3b4f,bdde456f,608e6849,63a0a035,f5705e5e,17c95f7e,a0a93926,9da8894f,7b4f607d,b47fb04b,bada6261), -S(7c88c681,13468659,d7d89b,477ea11d,5f0443c0,cfa3baeb,6404a383,8be05b34,34b1e4d4,4a29b75a,8f6ba2b4,cf35e7b9,a9953269,30cab213,3f21325e,6f772cb1), -S(42426b3f,833b995b,825bf9c4,ee753d65,ccea144e,8cdf413a,63520819,2f1c79d5,8f188fd7,890baa42,520f957d,a12376c6,23c894ed,e48dc7d7,a8ca9300,77b9df19), -S(560c13fb,86f0a75e,24a24647,11be1c46,d7671f58,fa9c7340,df201d92,5c574518,79f5167a,315097b2,ba5bc761,34f19125,671f67b8,b9b64a07,ee8414a8,f0194ba3), -S(2dee64f7,6cb69a16,aa7245ac,afebd2d,6e46bd1f,4de9af60,fbbdad76,a84f3854,7196b1d2,fa453e67,7fe7a5f5,73e51022,9a7b7539,af0fd02a,b487cd57,46f970f0), -S(31ac84c,e896a814,3a978d7b,ed2a3ae5,d0ce9783,6717ea8c,1f44999a,d6baf5b3,24096db,a006766e,b9be4e81,9d53fb2e,c145b7b5,13cc77b7,8d175cbd,160b86e9), -S(af903e81,1b36c12f,b263759a,7905c2b7,d5bc640,ffba9974,86eabc6b,b639af8d,efa986f3,84f8ea74,2a1be187,55b500a9,22fd9ffd,5a54515e,3e5ce3fd,76d59f48), -S(cf6257f,bca09ea8,34d9da9c,b208eb8a,9d7cac38,5b6dacc3,9863adda,4eaac68b,189b50e,3b68290,ac0657d7,9e885421,e90f270c,3bd0528c,fdcc1857,9f403351), -S(32e61b5,f46e796c,ad8bbd01,41004e5e,81a2b2c2,8446352b,749f1840,9ab2e076,2ad27a1d,ed77dee9,f0ee3ba2,fe97d752,3e974514,ccfd3988,a7f0e1c2,3ac6059e), -S(5079d7cd,fc1f0f4e,decfcfd3,ee5c66cc,beb84197,d1cb9836,e04a7ee8,5e76fb94,5cc95d46,ffcf5873,cfffc0df,6e8c2599,a358fb46,3ea1baf0,225b7fd5,f6a3bf80), -S(b62c8158,5be8295f,29472b7b,b1cda9cd,bd61f9c4,23a085eb,1a31257d,fd72cec6,1d9fbcaf,7fb9e15d,eb992ddb,d09f91e7,f3c9dfd5,d4f1601a,1c303f1a,657c2b7), -S(1c74344e,8088b2d9,1d93f5fd,87a92e9b,9d97a160,2d8bfe33,d8b90b9c,af944f28,a8d98144,3354526d,14d03ae,3a2d2a3e,ad88c0f0,8d9cbad6,666f533f,3cf56656), -S(12cd5403,87768461,8098cc27,ac7e7ba4,9d697ab0,188aa938,483f06e6,7c94e95f,8c0b02f0,1d3836f2,7e5a5028,bb061a32,3389ed3f,fb1a606b,9113c205,9004994c), -S(36abd4f7,7f45d01b,2347a556,ed4c01e7,4c82611b,7e1afe94,13c43e71,29d36406,c160f21c,f4befb28,60ae1ae9,e7da4b16,242b3c6e,f129e309,7b3738a6,95fb9223), -S(199740c7,91588e9a,3c5fd265,19624ff8,ecd4335e,1fdcc482,749821c7,b0301fe6,a316790b,5704bab2,1b6dffcd,19b15604,c30b6057,8543ab6,a3f52de7,ea459c79), -S(14dc3eb3,59ea830a,b8827de0,59db6f55,4319478d,b4750e16,80a21d62,d2d6138d,82c28f9,a3ea5004,7253eaae,2c62df4e,fd4b92fa,17fce544,3c04086d,9038f5ee), -S(6d288843,e16918b2,5895f837,9f75ec44,36ff7559,8a26bec1,bcbdc683,3979c2f4,aa99f61b,59f3f7da,6efd2945,9e09fe0b,54cd2de6,cd70c538,99def857,4e0805fd), -S(9074a3f7,709dc3be,c191f276,a425278,e1d7bbb,a33e080b,cee68373,6f49714f,3eed8639,fdcbdd3c,56ea731d,dd99f99e,77a59ac6,970318c1,7d7c0801,f71b58f1), -S(b9789069,f400101e,6120d9e9,eb95ac97,203bb7b9,701578b8,364764af,d9c4f9e6,afe1ea3b,2634c97f,75e0cc9d,29d9aeb1,c035a048,a68aef3a,7c21bdca,e55c7c6e), -S(55e06b0e,ffe9047a,dd0f2d2f,567b0dd7,d67a589f,50cc684d,88a779fd,c60ebbd6,d0d2b49a,c9347ac4,b8143fde,23b6ab2e,b25b761,4dd862af,3a0d1dda,a79175ba), -S(c81b2c54,96a1db4d,aec6ca5f,b8b0cda0,68a7a049,6fed0d3e,3dea861,27337291,d11e206b,26f9daa0,731b4c28,f65feeaf,8e78f6d8,cf3bc973,873f6d2d,7d2f0d3c), -S(b202ab85,678ad74b,c007535,1016a995,5795ae15,3dc85df6,2d7178b7,e5e37cfb,e6f922f5,6c6944f0,2e643a19,d39c120c,4cb60a44,af353de2,ec653179,9ef84da7), -S(ee0deb59,e956cba8,cb9ca8fe,7c86da8d,33e1287c,616fdec0,1ba68ab9,3de8632c,63af5457,e9b6af60,9b1dc6ad,a19723a1,23e710e7,d03fe98c,5f709c1d,2456181), -S(e7e8f3e3,ca10115e,c7dce3e0,5dbf95fa,f39f537f,b8af8d86,773d9684,8417b28,158c1768,814f518d,a0904747,b96bb7fe,328f8e45,df9c2c35,9f192789,2e7d2441), -S(3b8e4edb,ab45ae8f,17670b3,ddc01fc1,7733143e,208498af,931234dd,c992c51a,e846f581,2a049bbe,94d59a62,dd43817b,fd635e7c,8eb9ca19,80b6bab9,96211c4f), -S(9117c67e,ae125762,75694252,bd88c13d,5aa5786b,2b01aabc,319c600,86b4c26c,c86a9fb,5ec90f3,a2ad0be0,d36061f1,e572e1d0,63034c81,5285a389,2f05bba1), -S(4388869b,17025257,4b754639,a7da1513,1cb9e2a7,b93ffd3f,2b254d7f,430cd1e8,9ce82f3f,4780a2de,f60d4dc1,cfe83ed3,9eac907f,4cf180a2,b829a0e6,292ab6d7), -S(98c583dc,d55186d0,54f3858b,ca84df9a,ff66e333,3fadd076,53cd87cb,66dea0ab,7877ea9,d3a5acb5,553d45b2,55e4ff92,47842b51,4342cdf6,667f83d8,a41b6155), -S(86c393a3,e24b29d4,b26ba9a0,5ce4e1bd,29214489,cde00c4d,1f4ec788,43409ef6,700b9044,8c95138e,a0adccf3,137fa827,702571fc,e1731223,ba1b4ea1,4a37d06a), -S(25d6bf73,6966cdb4,6fb06f43,83c64965,d462e118,258c36e7,76d4e193,13c0cf5c,99a98bcb,d518d7e3,7964dd4d,d677a735,8a886225,28df1cfb,f6d0e999,259e680d), -S(4e3dc2f9,cda6d077,bab34d7b,3dbfed33,5c3f85c,b350f895,5c8811f7,60c61af0,4f35e49b,6b8137e8,58c6b2f3,81ece9dc,de81b5b6,27e6274b,53d6a0e2,c5e01652), -S(4ce8d8e3,5f1a301e,c2dfd13d,43ad1f20,ae756b0b,34ef7bdc,a8f30c70,194f3f15,7e2508c8,324b8e31,2a603176,b1fc0a33,dec501b4,23e73c2c,416aed6e,2b19a3da), -S(2744cab9,e7999a7d,901b91b7,4d221bf8,be41b064,396be42e,46c80536,c5218267,db9b4ff,80782ddd,d0701665,43d94eed,ba19234b,c1881bb,47362cb8,8d90a0bd), -S(90381b83,5adc54a2,d7bc1e27,2f7a0738,dbce1103,db2b21c3,3c45242c,1ac591c0,a3c25f2a,333d8cdd,256f6f6d,d5a7e34,3332e527,50a12a2b,fb00fb37,3213d22d), -S(abdf4e8b,2437703e,6125dfc3,a33d41d8,b7ea311f,fd9b62b0,7546f6d4,8ed7af05,77a66284,1cdc961c,ac1b0990,5877f7a4,28213472,5e95684b,461bac1e,de6bffe7), -S(9f31c9e,6fe48e14,1a9bb99e,75486eb3,5896f990,e247bc05,cb648452,75cb645f,3ae168e8,b4ffed16,bec4422f,43385c17,a83597aa,692b6097,e48e542d,98ea4932), -S(2801ae6b,2083f345,6840a79f,23d638a9,a878d689,39651668,ce82c0f2,e77bb8ac,66f4fca2,c2fc9926,36ed5d9b,5b070607,f0e75d2,8474a8cd,256db66b,d4cd0d39), -S(c307afc2,d2de5ab6,3b5c5d6d,4d25c03,6278716,37f20fc2,175f6631,55172255,6f287265,4d518555,1da8c16b,9d0dcb2a,f0843b68,a3a756c5,5b6716b3,b151da1), -S(e0d0f3c9,866512f1,f78f58b1,8e573d98,6c5d978c,a5f6e73f,75509808,b2b90e6e,3c766220,204ee2fe,9d65a7c3,96e37c81,cd2de736,bfdb6c89,48f59394,38df3cdc), -S(5dce8200,28630e45,1b754c65,8946f4fd,9e4b15e2,e40116b6,acfbd145,29ff8a3c,af743c2e,5f578bea,2c9a6323,32f8fd0c,be7d385e,1e84d6e2,ccc52574,39ff3e41), -S(cf6f6b23,5d10351b,73664b8d,4e2f407a,38fad688,fd90662,29459b13,cf84acdd,c20ede1f,ca2792dd,c5a0d88b,bd8befc1,746a137e,d25defd0,c8b1c5e4,7f3bde93), -S(e73f238c,62efe49f,97359a82,467cfaa7,a7fa39af,35223bf,dc2e82d0,6162b6e6,14ad9128,d74bd306,b91df3c3,c846f203,dabafc11,49d2e8c5,99841964,954b51f9), -S(2aafc65a,f573533e,8d8e1ab3,19c11cde,60a02481,32296117,1455fae2,4f5814eb,a083c95e,cfc67a96,1f3d8b7f,ed66e2f3,c3f6175d,512a38f0,b6d974ba,cbaa4509), -S(f278ec4e,b0d210e3,24abe42b,d1d376a8,244d28d8,614b1260,e48214c6,8161b90b,507cf667,3bbc53b0,d507ff6,cb4a1c79,745b483d,487c6934,4fb4401c,275f4a00), -S(29bab26e,23fca95d,beff49f8,e5b742ed,2b32eece,f7f4d696,4a88b4de,d2b773e6,2e1b3d56,7afd6483,7bb7af1c,7be68427,bbfdae5a,43907e0a,d1f4d3c3,7ce44428), -S(a3a41ab9,8d2804de,81077a4b,73fb3832,f90edd3,40118b32,44a08633,1bd21c5a,5e292792,a0cc3fd,1df5f1e9,7c639cdb,f33b0f21,cf536e64,a2354757,ed523641), -S(3b84dce1,5e9b6ed5,b40cd906,c22a08fc,5a637d96,71c91615,d4038bb0,a3e6affb,7d2729c7,94a19c44,18851c6a,9b813735,f53bba0b,111eab88,b29fa27a,1d189b24), -S(e1a1de5b,2893e1b3,fd7d434a,d22493d5,1479e56e,2bd1699c,30fc8ee6,58c6c13a,c41ada21,d2d07fc4,f26035e5,b4d1deb2,15bb4f2c,d050b300,2d075f86,516a2ce7), -S(23b7c994,1a9a6b03,50707c20,3363b025,665fe450,bf5a89c9,d0dfa7fd,84ea303b,ed7e3e90,c09805b1,46f1f365,45fd2899,ef75f01b,47d12fed,275936b7,e2682da6), -S(56cce967,aeb8e65d,7f2897ff,e881e695,d0260f40,fa8facfe,38c0a050,19e5b160,aad07728,b298e06,ff562b76,70ec1717,c80f136,3ef477ac,abfb3b78,fb655b77), -S(8bd02de,4abac82a,3b50d1bb,7c721a38,9cdc2812,2dfe48f3,fcd30969,4d0f4191,5be841df,84a2251c,e69c2f39,690dfad8,92620119,7ba36028,861f6c6d,d32a93bf), -S(43b066ff,fd91b621,fc9b062,e0f9d362,bf02e492,f764381e,ba49a4f,2fad5662,3fb10c39,cf37eafb,162efc89,f548c8f4,eb5877d6,7e8587f9,4b8b9ce5,9aad7164), -S(89ea2a07,bfc99034,c3e9e7af,ebf87fe2,2d9b23e,e62e038c,321cb2e3,dbb8c7c5,c3069964,6a19d602,7f3dfb8d,9008556d,f969f576,61e562fc,8356c3b2,d3159a50), -S(6c382393,553e177e,164c1f38,d403df46,d05c856e,a41d7d71,3ac0cbad,1f202019,2a716067,37801041,46212c8a,4e6f7716,4c57ab39,df129e77,f31631bf,3206696a), -S(aea725d7,e59c8ce,b646ffe5,d4791760,988e4cd,d23e38cc,cbf610fa,f7066223,e0e7929a,980ca7f2,2fb46dd5,4e1b879d,3e77358,f42208af,d1a3a003,3ba0e593), -S(159ccc54,b888fc90,1f75e688,def8712e,5f79491d,5d47712d,ba3b0c12,ae2f4c84,c1ee2b1d,ec27ac4b,9f8ddcf3,74cf8696,6b353204,690b4467,d752edad,53ff5804), -S(aed9251,982bbf59,d7cc815d,fcdcff0e,76adfc30,61a042bf,1cb5fb3b,60acedab,6e90b10d,a2b23e6d,9a2abdf7,830906aa,d286c9a9,65f28a32,ab9ced92,5c966725), -S(4d669885,c053bf77,f1126cfa,f8db351d,3642c916,1a01d76c,8fb0a20a,3a54adec,6bbbcfe9,ac74987c,2e50e036,74e4ede3,5ea37b79,ab8154a4,396a15de,dd02865d), -S(1240d1a8,a04fb12e,813feea6,d0a6601c,9e6caf03,64df94e7,d2a5b522,5994ec2f,bb502ef,dff84c2c,17dd34c8,909e5a4a,cc1e6e64,aee237da,b8485004,9d09c5f), -S(7ccdef5e,4543615b,a07a8dd6,419926d4,47fb6eff,312d638e,3f5b0363,7d00a96a,7ca83bd1,3f056f7c,c46e6f2d,41ac1e9d,846c5f6f,570d956f,4c9f91b2,8e95a5b), -S(5c30be59,1bdbd093,321d2fff,ec167539,d794e22,d4b2cb53,d33c608b,cac23f25,2e44eb7b,d6a6a544,99b28ea3,865db2c2,f53de940,17e8a03b,e34ed7c8,fc70b64b), -S(fd59cf82,8f64f7d1,10c7137c,5d091b3d,7fbef206,1d2ce5e6,addf2157,c83c0578,9edcc796,7515edda,bbf4e048,5e70bd50,cb9dff87,6753d41c,6f22241d,824bd7dd), -S(5be3a507,ef4b75cd,75158a2f,aec4a5a2,d4cb85b3,92e7ccf,506661b5,5c77e277,92e45bee,9d914f7f,7e687de2,f7eb0004,5e9f9628,3e9332cd,97f5fdb9,a21a937f), -S(d1c94e0,473992b3,307b9031,93785bc1,d2c2d14b,ace6ff4a,8fc7b251,e629d3a1,9cb04ad2,8525fd34,d8fc59c7,280c72d,74fc9f2d,6ab1a5a5,c186f7bf,fb14a940), -S(7db048b3,4c03dca3,7c53df3e,6a94d789,f53308d6,a57f347e,d32d5b3d,4ab3ab03,4a7be537,189997b9,1f420593,add91bdd,fe7fd47d,6684dc21,afbc443a,68a879d6), -S(73005a1b,1ab1f7a1,ffa38625,e0d37dd1,8b54f49,34d38e64,832a78ca,c51b7e5f,6f8b689c,50fe7da2,27cc8be8,cd066588,30d4a2b8,1e80365f,526f590,96508640), -S(34cb6623,26ea9b37,c0f47c45,acb2dc87,92471834,84f9357b,e8d4894c,d4d3dae8,ae989ad4,96e480bc,375d3df,61fb2ae3,a18e6100,cbe1a40f,d090c5ea,8ebcc0c9), -S(ef5c4b6d,cf92cf9a,cd00cd86,63a44223,a49120aa,bc439f72,e6a6a7a2,13e206fa,be4790e9,d1982dfa,5e037c81,ddfdd6f7,802718e0,ebfaacf4,685a1f2a,ff9c5c38), -S(32cab877,84d37189,5ea4e2e3,22586a8d,30b86c1,fa5ecb76,573d5106,bf5f16b7,bcd4f788,20807923,7e5f1487,8d05e2aa,afb2049e,aa4c1dab,8985e413,f758de56), -S(bb183eae,900fb0ca,80e3f021,64e2291,4e40eed6,ceb4d7c,89539ad3,132d628d,94bfdd19,e0bba445,d453a0a3,e95423e5,c7c027cb,fd76df3c,93532317,fe9381ad), -S(605387d8,51ee5aa4,f39288e3,a656addc,72ac4251,5ca1c4a8,509341b3,5819c1b6,55ce59b6,8d58b114,f8a6ce41,86f8a390,9698aeaf,e1576bc1,af37713e,70a550c7), -S(2d971b20,46f30b55,9e8c1638,fde42108,60172bf2,cc088ec6,2c845f0c,4050043d,762ce259,e63f1da,7bb80d4,b23a0368,dd0ee680,aeb90a54,a0ea814d,904b1dd5), -S(5c89b962,e56d242,53a98bbf,14a8e0d9,c9a0a908,635f7717,ec2f2a0f,6a5c3641,28d38188,1e14e248,417dc0b7,5561a875,6163e1db,8517cd4f,f888df08,ab7f2974), -S(3210dcd3,617fd3e5,3da2e0f1,a6d23c20,ba27c0b6,920aea90,bd87a732,8a8fe963,171d81cc,64f4e8a9,ef43aa77,95a1821d,4b672eb3,20555016,dae40ae2,2cf24cef), -S(f00dca15,e2358867,6c9a4b9a,46706b61,af249336,99572f44,ddd87ea2,33b8b6f,3e2e529b,3010ab9c,66c73021,f28b018f,57b270ae,aabd4b4a,a2ec2a32,952125b4), -S(9d69dde8,d344fc3f,74e9c43a,eba9753a,fc22cf58,df6a430,b86b560d,c952d62,2b667455,844a1c5f,1ad56133,99e28380,d8f2b7dc,76f80817,a72ccc87,3f376e4d), -S(4fcfb13b,7a0c8f3c,1c2e943e,806ffe11,850cf942,bc5bade,5b4653c8,9f6a1cce,21e53c12,102089fd,1f010e1b,d009ff34,9d5e4d63,f299d613,d4492763,278ff580), -S(9173a3aa,b16ecd8d,5c3f2889,ddb1ee1c,2a4681fc,35926b42,7411899f,ed851a03,532556ef,794276eb,779b339b,9131f8f9,bea01f29,2018498c,c77ff751,dbc2170e)}, -{S(761cab41,3916a1f5,e131f337,e9023519,6199f789,87ef390b,3f2d8bfa,b0e9bbc6,f10272df,f7e91c40,3565da85,17fd3011,bde7b797,526d3c3,f00fb28e,f26dbd91), -S(c20afed,99f345eb,7ef90636,89598022,d06191dc,7e376b44,71036b03,1e6baa02,471f7c90,681c42fb,b2157f8d,629fafd4,87285270,6a4ab39e,c57f0de0,dece8837), -S(c1f66d62,532b6a50,fe1c1712,e2ef2258,4c03742b,7eea27fc,efad13a3,de1ddbff,49001db5,c9b8b3bf,7206526a,3a868c45,1b45eae7,586c3bcb,4685810a,52a62978), -S(684aaeac,cc13fd4e,d3dfa9a5,ebab742f,c5b9ecb3,81b49fdf,afc37edb,3b165ee5,78c2a82f,7e8484b3,9f808983,402c64b,4329c656,49bbdb29,1925baa4,89992ff1), -S(9a5a9331,3591b8b2,b3381f72,7dfa6c5b,343b9e3a,1b1c9c4,c6c9859d,e82fa566,d23e49ad,5099ba1e,58d800a5,c2e658a5,8be77b8e,ee9ef143,c541921b,671bba35), -S(37cdb6ec,c924c1c7,7fd0ae7e,d9baf38e,b46ea5cf,a161c78e,e4673968,f3eff2d2,fe025569,9a9e1ece,42619791,55cb0241,a3d16834,ef35500,7fb55080,53b161e7), -S(7228ef6c,4acd1d3a,d377d924,46fa894b,6f29926,564b33f5,6fc4968f,f66e8ce7,d4818780,533a52fa,13043159,7b22d8f0,b8ee64da,703b9422,e903595,c78b8a11), -S(78555ce1,101d40ad,88c9eb43,292e8d8c,683dac58,fc8779f7,db22d3f2,e2855ff3,9fe09f2e,660886ed,98f70203,c3308dfa,77476e27,e22c68a4,e43107c2,75501bb), -S(b078bfc2,cb4b10fd,31ce86ff,35770aa7,9979973e,26595e95,913016a9,850b2be6,1bfa79b3,f43ca2c9,93572d28,858a0301,716dfd04,eaee12b4,4e13bf79,a73fba72), -S(c3425e34,3ccc9b6a,a260cf78,7a5e15be,5c698894,2370f66e,826fa1d4,8f60a8b0,55f8dacb,54052f3,a8e42190,e5031fef,34c0eb5f,83bb252e,ac7e6eb8,161a0ab), -S(a8360f0e,4d5fc0e,81598e83,6384a5c0,6c871ff0,d1303179,e5c1c0c4,18a2b7a6,1497e874,db0af96b,35a5bbb,e3097ba8,b6fb1bcb,4d30be17,fe7a5a21,97d0dbab), -S(e02a7309,9807dabe,ee04fef8,36624471,fadbabe3,40507d0e,2abe4468,9c384458,59e707a9,416dd50f,fd07ad54,29d686fb,2402e768,3995c25,2ec4091e,c221582f), -S(fce6ed5e,2293286f,a976695e,8871c763,20af09d2,14964d31,318e197,ef80a398,168b9d4f,c9521ae2,51228f2b,f8de1d2f,8b5b183c,a918ec66,3f37f62,497ab2f7), -S(69616788,b5161a84,80f1b464,5f950703,af731632,ef807400,eab00ee8,581adf57,ab0deb81,73ae5e6a,c35a53bb,829acac1,51db1254,f73ebe70,f99d3cf9,7b3499cb), -S(2c1bdd6a,699f2e02,66d68c5e,22d8a504,8eaee31f,b8687858,555d03c8,1633ad2f,ae63f080,98a21f05,f1017956,c9bb6746,7b2d21ac,f3057151,9fcadc8c,c97d270d), -S(b1e45413,b39af497,da71e953,bfd13826,91ef295,da20be6a,2ea82d57,dedf0c32,a3343fe1,563fdf86,22f93d5e,75892e58,cb927f6f,7d3ddc6,68f87a61,96fd8ff5), -S(f1a182d2,994fa6ff,b6a587bf,a8780f4d,69b2259d,456d10df,2e73eba,4aa83567,a3ab08e,99488c03,939bd170,b4c1a7c4,c0cb8e18,1a713c1a,26f0eef4,8ab805b0), -S(840a512f,e5bbd665,83520649,efeb9284,e25fe4f9,9252dee0,b228d360,c8e6631d,899b91b7,2be1b494,1f5035b6,5c85dcda,4efa88cd,83995cf,42674fcc,486dd4de), -S(d920a9f8,b6ef812f,c021d511,ddfca976,436dc216,36792eaa,736be182,fc5ccfd1,ff26725b,21de311,d3359297,97bb6efc,479aa492,a366a1e,a4de8d9c,f0caf4d8), -S(2766bfc0,aa717b82,e7ad53ee,1604c5a6,2fb3bb6a,c7e4d6d1,4c71165,49b3b2fb,7a52c07e,70feace7,6ad0f704,e1d95215,b29b58df,9ba733d3,8a76f349,2c20b5bc), -S(a503f2de,116e492d,2b8e9cd0,e02cbc7a,56ec245,5ca27f48,7d25b316,65374cff,36a0e6c0,4e8092d6,f07fa375,c7874ac5,5c24119,7a096489,766d1d8b,350c260), -S(c2601313,43856496,92fc4795,ba6eb8a2,f6d052fe,5a8a37a5,76e036ef,163b6f6d,72d27995,ee8bbec0,de1059ee,65b8d4e9,9c828bc0,665c76ba,ff333ca,6a619635), -S(43bfab90,2f3a90de,ab1c7fbd,92b1ca9b,577c51ec,d0a5f1a,de461c84,98eed5e7,42cd4d0c,62858547,4852a2f0,7003fd0d,e37253f6,757f4c67,c2e2b22a,2aae375a), -S(3a6befed,24635ded,c7e2a341,64615858,d3b3029f,99a3f257,fe23725c,6a6d0e2f,5101cb68,d4f1c0ed,c4e33e61,e3f3bc1,99f81564,5aa9b81c,ee94e739,667b37b0), -S(67805b9f,4f6b6813,16940582,7197df9c,ee1b9307,5b4ec69a,61ea52c1,788deae9,a2f64de7,3019d67a,5db36099,b40aab16,d87ec8c4,56285e01,49e382af,81b68ba9), -S(e079dea3,f48dfbbc,ad661a6f,1c0a4627,17343004,cb18e5dd,5a7bb32f,a0e9000c,31706c43,77bd9a87,a27665e,12a60711,bf6b5bf8,acbbb29d,33318a8c,df29c11b), -S(f530e1b8,197ba44e,b7e23206,98a43b13,f05b84c5,5e4dc48,aabc3b16,68fd41b7,12995e58,aa0dc86d,15c483e6,5d01cf7,2f6a6cf8,8b53a983,92f4dad,6bb5202f), -S(974519bc,e9037b7d,84517dc8,a0c45ee6,a0e86ae,947b18c4,3dcaabee,7aaf246f,8fb156a3,cde52064,2f03f5b2,32c66fa3,12946f83,5ef77ec7,8739ce7f,4d45e6a), -S(9cde11c1,233c56e2,37e93006,cd42d785,acb74be2,e7051037,1db72065,5a6ef178,6cb6983d,8e86413b,36049815,3e2c8256,16520a1a,aa7a0370,dfcebc03,9c5da20e), -S(6e67fd2d,25a40ad,df954c26,ea452770,1fd49aa2,e7ba7cc7,17bae4b6,1fc11385,a6d2b87a,5367518a,6705af46,20ac9da2,f4c84c63,bfaaf895,449445ad,5ac0bc1e), -S(aec9f1e1,d101310f,a682316d,bb6de79c,bac5a3d1,133051c1,2a681a97,549aa904,305ed459,4670a52,de8066,9c026bc4,993b7b9b,559fb9d6,75ebd333,2608db68), -S(784d5905,e805d9e2,35e0828b,ac0abb12,7d1efc7c,d1b2f22b,304e142e,10132562,d8a6b329,f29221c9,344718c9,35b6cd3b,28aa5ff9,440cd4e8,6841c5c7,1c97ece2), -S(15e2a17c,6ddd8302,71eb8b67,e2cf6b96,2c75f28b,b5d32ef5,639ced1a,b3d6253c,55ef6683,ca7b8cb0,42ef9f48,fe5788f1,4ab256ad,f6dcfc80,d212db66,a0ee89c0), -S(4b003c6d,f6935da1,cd9cdd9c,4d4ab700,4646cabd,b7921125,98265bdb,5e2b5b36,4e621d0f,55d22df3,89c0a5d,13e3717a,eebcebb0,30d94de7,8b205a14,da58654b), -S(3fd57470,cc7d0704,d551224,5a10125e,d94d393b,3a8eaf0f,b18fdc58,e71eb1f2,2612769b,7528f3bc,9da5a240,f603010f,272b5966,c59a7bc0,a9c751ab,8f72f7dc), -S(aed36630,1d7f9738,dd439355,8174e535,de668758,b5b9ce90,3614562c,58c4fb0a,499e8a8c,befd7d93,a191d702,b39dc61c,1a7f6cf6,85432975,cd3fb006,e62a1bf6), -S(2ba768e6,da7c827a,f5456916,f0015e7c,15baf2bb,ec1e8c6b,936e37e9,376bb32d,850c242a,ae59ad30,e566e244,4b0b58c1,2b5f297e,7e200e29,3a8dbb83,9c5be04f), -S(1ba79c71,f162d72d,65821a17,6d97ee10,9913fc3b,8990d45d,5d6b2e55,4a180765,62258299,6d4376ca,5659a7ef,1771e26c,5a672521,5e69288c,ae16d819,4a845b37), -S(fd54543f,f7e27a72,e3747953,368085ed,945e6e1e,8b16032e,351fbcf4,643efc6b,e2619d2,ee6d935a,cddbc0c7,1727a9d,f5aa2a73,ccbe655a,44a1ff7,b362d55f), -S(ddea80ce,6f9e0bda,4d39337,78136c93,5293885,f0564b23,3c98a5ed,90ed0905,8218bacd,e6049f51,b3e36832,145230d6,776f0158,7c275d36,e8bbab59,c47c40b1), -S(d3dc0b5e,bb26fb78,914b9c9b,30b9b42b,69f20e94,fa8dce28,9f243a64,e53fe5f4,942c3ca8,64d9a7b8,cd21a3d8,32bccab1,c9c9b297,b53a8336,45aa4356,8b1fbb60), -S(30a0cb,8e510a1f,6ee8bdfc,f46d2dbe,be3e43f5,dff3df9c,75f96c9e,a14751ca,f43efc8f,7f47e83d,c940b8df,ab9d413e,bc4abf9d,8f8eac87,b392dd01,7946fb0), -S(1a0fe79a,4028b017,138c1649,dd58de09,7adedcc8,c57d4aab,2bd35b36,91566b2d,340eeec,d2028765,e00dac93,ebff2589,ea9bca7e,f7b7857a,783e5855,2a0cc60a), -S(ccd61837,a08fc389,25890e71,b13fd588,58995bb4,49e9b3d,bee6fd82,12ed1d66,92e1236c,7ba39599,3e71d1c8,44cac95a,9a61347c,b98622c9,92fcee9d,2f593ce9), -S(3b706e43,fd96a62,24853ff7,99df5f89,8670c268,263d27bb,1be885c3,be98a8e7,4319b438,ed6d33fc,c9f4115c,1a91a954,744dffd8,804281c5,df713334,7fb2cfc5), -S(d0441778,af56e7d2,91b83760,e024646d,abcc74b9,7e86a390,e060113f,4a01cef8,300e8744,ede079ea,eb52dfe3,f6373d25,6bb3efc3,26d80965,d65d1307,6780c1e0), -S(bd2769fb,3257a88d,4a5f4ce5,e7fcdb59,7e665429,ec9ff117,54c5bcd0,dcea9509,df765e2a,fc7006de,2459d6e3,c7ee3823,bd8bbda2,dcbbad18,7994b09a,5059d9ef), -S(18cb57b5,eccb921,50c8d8e7,5bbbbda5,ce182f40,67197079,3fe97b50,6c51893b,35b98a01,7f4a620a,172f80e,871e95df,b3dc4d,b30f317b,37809f0c,ba9f2b52), -S(81ec0ee3,4d91b585,b7153a61,2201fa41,fba04c7a,50ea2910,ad33917e,b1e524f2,a53e216a,d069520b,b7d4604,9fe3ef35,74c7bba7,2cef5177,11b6810a,a36f7ace), -S(f9a54c96,729a23ef,ad5e51c2,b8870b51,c68843ac,656b1107,49b23f66,fa013e87,ec0e8e0f,1a16aae8,c2f954cc,ac50fbbf,ed9efed2,25ecde21,dc629c0b,415fd93c), -S(c92adc3d,c2b5101,e9ad2ffd,ea2c448,3a39f563,c767e737,a5a34d1c,e84f2bfa,3e3f49d2,10b76661,71d9af9a,51f72edf,e6248022,cd15afe7,f84e6982,a5525720), -S(d0239502,2a0d5c8,f87f9b08,97daddc5,3a9300d2,1e7aacb4,d72dda9b,4564f418,4fb09e9a,3cdb4551,e56c2a0b,9e59f056,c500e390,e47b5d28,fefbb11a,4791678c), -S(593acca8,29588d90,13a41f35,8dc5e41b,678c7411,164c27ac,895fa933,d1db7978,af3c448c,bd72faff,8a52768a,23c9fdf0,68b5855c,d9f022e1,6eb26ac7,454709c7), -S(6a168acf,7b4f3a51,e56d8924,68fa3a96,d0ea4b9a,e191b860,5a6b96b7,d6834b05,f54540b1,f84d6bc6,4dac1240,ebb61fe0,1f160fb5,c00a1b24,8cdddce7,7db419ad), -S(5fbb8d4f,4b3b8d54,a51bb96b,7f58672a,5d2d6145,dd864799,804ef496,17ed6298,a87435cd,6fc5fc1c,93c4b38d,d7b2e565,88e99f,cc32597,9fe0de65,e8af034c), -S(8942bd97,115688a9,ad84039a,3dc0d80b,bdba443b,8431a530,60560745,876c5373,9366058f,5895e83b,9db6bde7,7da94b22,fbeee36e,b24db502,706de359,a81f74c8), -S(3f7a1620,f93be626,690308d0,ce5a3dae,8eefeaa4,63534032,8c3adc5c,4d68643c,9fc70963,c9b068f2,f6f8813,da2691b8,de3d3b07,c7bc1390,8f8c22dc,135d0bbb), -S(29b4db5c,7224201a,9563fc36,eb7b29d3,d6b0b640,b812591c,af21180b,9eeef26f,c8dcc8d9,8c411723,1db961a9,ea3eddb,46a21aca,b47d90e7,e10167e1,f5fcb81e), -S(f05c4970,392d0487,d8ebe570,fc5292f8,685a4895,5a9c75d1,bbaf2a95,49d0a557,f012d939,5ac0d2e2,f694bdac,dc7535,e126431f,34b8d440,b9aaab34,23774ea0), -S(fb2c83af,6ceec5db,edc822b3,4f1bc35e,90bc388a,5a45ae9f,7c256045,d8daabe,cf9e3e2a,30fa7ff6,30e221d5,7fca78,d4f59145,f4e1c063,2798c471,93a3295a), -S(b63db89d,daf39301,f1243a9d,72ba57c1,31fa2cf7,fd0e486a,c39b8190,a48a3f9d,cbb7ebf5,dc68b80b,6fcbd4f5,90162683,cd8fb0a9,17142da5,aba30eb3,1f83205), -S(c3fd72ab,c247874a,c682a44a,938c3d8d,a7ee950d,722ae51e,ae24d6d7,1ec211f9,23b0ca13,998cb9e4,216e26d3,ed9cd144,bbd2bbb4,b45b1514,e5110fd6,bab1bff1), -S(83f1e25c,209153a8,7fd7f4e2,13328ed3,97a93191,311219ae,c36c76eb,f35e2a9,b93a7947,a553a6db,868451be,96988dc6,7a569d6,6237c110,97f132e0,89c73398), -S(1dbec6a7,32838979,b4e7f03,bf791b5e,614800bb,39a56f68,10af5c09,f10c3eed,f06a2e63,c35e3168,4508a3f9,39bcd071,1892b16a,762bcd6d,85c590e2,92bfa06e), -S(56e98c,c2b21625,e9149fca,61e159e,140f9808,bf781c0c,3159cea0,f7bb51ba,c5e2636b,6bede1c3,a22a03b0,818ddb73,5f073c85,105876c1,4d8f6650,92a61563), -S(a6e497da,d0347dc1,dcf24181,efdc40c7,fb18f480,64803a6e,ab9187bd,deb4d305,88983af5,21f10582,3dac18f5,c6badc0,19e724a5,b748159f,1fa20863,9db7d6fb), -S(bd7df6a,1415e150,9759e259,7abb9edf,cebf8e42,97ca092,60200e4f,53ce53c0,90029a06,2b77274e,7ad517a1,44e3355,f08e23ed,a9161e25,e67511b4,9f32d6ef), -S(dd7a6f4a,c529d120,64d1e89c,b6106d06,8d17502,7f6ffbec,411d38a6,dc327745,bd2caeb7,19d6aa06,c97697af,1eca622f,86cf7083,9e425ac5,b7cb23b8,761d9c48), -S(5220c371,8714884,402f11e5,f93dd80e,f8d10333,f9b054a7,14a1d3a3,9664db0b,3f1fe980,d62ffa5c,d50e3ac,d88aa07d,4c9a91a0,373f1541,cca46699,6c0d76e5), -S(177ef38a,cadec4d7,d8ebceba,53a1b938,f3db0579,7c476cc6,19fb208a,1cb582f3,4f33adb1,bcbfeb1e,b9d91df,c6ce7da,6be73016,6148e3c0,eccbede6,dd3a6a3f), -S(3b99ce03,762fbee2,81bff40e,6c67ba55,fa97842b,b175673a,7f08e362,1d6bd97b,ea6ff097,77f095c0,ad161d60,20f04381,b49cc469,c2e54ffb,1f91ec9,d7523108), -S(5864b293,f81ea7ab,688bb9b0,89f9f1ce,244fec0c,b1e2db6f,9c83f58d,5701f79a,7f4f8900,b3b2a552,e452093c,20436189,d88d4493,12883c32,8ad48678,69aaba61), -S(9bd29db0,c45326e0,3ce95b3e,8a1d13d0,ed868ec7,bc3fbacc,6781a4dc,90695798,7c3fc6b9,462ce670,c1f0a604,52c8da1f,47644c51,e56948a0,a4f6c6d3,34e98b4d), -S(3a4143af,3f07e795,2eedc5d9,b3a8d87c,a52a16d9,9839bdbf,b5b80770,38e03b17,aa749ca6,9b2d316e,650384e7,19d775fc,6a1b09fc,be5f17e8,741fa129,1cc73a34), -S(8b668df6,eb568b1c,6608ec61,b88bbffe,3103a9bf,c4dafd5b,16eb611a,d3d626cb,efcb4ac8,ab30efc3,94db1c4f,2f0476f4,81789d34,2db7244,a8f34266,13977aa), -S(d1b68e26,5936b365,67c11adf,259e8bbb,2a190757,86f2fbba,a76d72ff,7cbfd9f5,57328a80,330997e9,8c8598b2,33ba682b,e6baa6a4,69acad09,6ec3ef2c,be6f6304), -S(84281721,6eb15d31,e2c6faae,1b2140dd,e9ff5419,c0555ff5,d0edfa8b,2d878506,75b6ef23,821def9a,912a7c88,74da9c7,6e4fa036,14dd8fd7,9acc639c,ade2cdc7), -S(e2da1bba,3a895d07,fc86b9b3,dbdd657c,b1ba523b,bc498ac0,eeacdaaf,22e4d77b,aeedcc86,52457101,86cbdec4,90850961,9cf09530,15faa353,f22605fe,2acb7142), -S(9cd8c718,34088f1,7f94db0e,50148e4f,81fc4c44,4c9fa34c,8bfb384d,f9c5e24e,440ef0f0,e8e641ac,ff1b2264,21975338,f711ae9e,e6c7e4ca,54d0d177,244c76d9), -S(6bcf2ff,b6c2e3be,54980550,1c8eab96,e27c814e,9b60ac42,2557317c,10419180,88af1c74,ac893eca,a43a0e44,89ed9ea0,c9e3ef4f,d8329de7,4b09eb36,9e6c8f83), -S(79fa7473,a6699efd,f0f498cf,11c40195,c1288549,d069d451,b05ecab0,fb94c8b8,53a59b8c,fef24cae,6c5f324a,19b8c30e,ddf7311a,b76d5266,ce747a90,1f46f568), -S(e3d80881,849cc86a,4d087062,dc5277a5,388f3d16,3c34503d,d6066eb1,69a5892,b6841ed8,c06ebd0c,e99bd851,afc6e2ac,5752d2c6,2a75a30a,ad1ceb1e,c7a2e70c), -S(5a6759a4,cd2529aa,8c656064,f5c5993b,8c4a90c7,4bfcb2d4,604900b,bbc55edc,5670533c,ecae979b,ed06412,7c9b218d,2f880bce,fc3939c,2db3f572,d3d3977d), -S(2c96f255,368c227,46539a06,303b328d,d8909991,a83cb991,204888d4,f48d38e5,3f8d2f14,61d1f778,83c16e42,dfbd33ed,781dd563,bd5091d1,8dfcea20,4e1eac82), -S(534f93a0,1b8b7cf6,28b721d8,af045176,45667ad4,8bad934f,4df6cefa,5327e4f,25c4e7b2,6716a3,718b9e8d,f9233f46,8e8ecc5,2e851418,13930bff,db89c0a7), -S(b21a8e26,f727f4e4,7d6091fa,1e9f3630,688f031a,fd2a7dba,6b1d682b,a87d6f6d,5bf9d718,9dcbb1e3,84051f7c,df28e4a8,2dddc440,fe8e4602,3f67b018,8513a4ea), -S(7d6964a7,3b5bd658,5bf9f92b,b4462e90,39801914,7042048d,8a55d9c7,13e39477,c4f5059f,2aa5a3df,2556d6eb,9172df43,7229a33,c3fc199b,de7395a9,41651c48), -S(5f5067af,90544909,996efe0f,250ed142,de02bbc0,315427e7,27942762,34d3286f,498a6c71,c77a4aaf,7a5db357,3a3379f9,3c9e0120,8ea82f50,936708fb,298cb60f), -S(1a6b6f9e,4d46ea18,2a4edb33,4873ba99,11e28cce,c0607b65,b716623c,e0372e80,84b1b569,5d3d68aa,5e6d514b,71ab31b1,c7d7196,ccef7fc0,797382df,bcb1f968), -S(361a14d7,c66fcb1e,109248e1,568a9ebc,de67e87,40388cb4,d2c1c0ba,aaf5516,2f3b5f71,3c150080,4af382af,e76c7f7e,f42af72d,fa83a83a,b6aa6688,45577afe), -S(b49601f8,50bc8d0e,7bc1701b,82499b2c,4a334c0e,2d8c1960,c7247300,af4a48d9,b5e2a9a7,ef215ca3,de3b39d5,853f4f22,45a4bd92,70a6f193,4c141a1c,841a7ae3), -S(3c509b32,d8095e48,f5a3087a,6bad9223,c891ce6c,fa781f2e,6c8e7d2e,8803e4ff,5945b1da,102127c5,c6dcaa04,dd00d591,57adaa12,2a3958f5,bb4b393e,b82196e9), -S(936331e0,14fc93bb,1f6a13da,3280d955,3f388e73,1ff74be0,ce36f738,901bc8b2,1862e7b5,6e58670d,5f212886,f91cfd1c,be3572aa,2edd865e,1ec2f254,9d784710), -S(9401e6b,c6183186,d465447e,adbdf85f,45e53eec,b1966dda,1493a387,55092e43,fad8a635,545c84fd,76924675,a328bdc2,61add731,fc63d3cc,57e4b274,24cbc2cf), -S(6849a7b3,6e018d2b,c0f9cc06,539ab30e,43c06fc8,6138dac5,751f0fd1,f1a4484f,ea62553f,a9fe03f0,a8bbe82f,c3974335,8bba3744,8d8c950,fabe4c5f,f20e2bb8), -S(e1d750f3,b3ea7a80,b3a42a39,487c6662,e2e73722,91d06ef8,c38b60d1,e0c22abc,8c59f043,5c12d792,8542f488,2202b79c,e792de21,809d12a4,bbd28675,57d827d4), -S(dc2436d4,268fa173,9fefe9de,81c06975,eca56d51,adcac9c4,2d7696c3,4c4fb4d1,86203b1a,313dcdde,a15f14b8,d3fe3894,e45d829e,14a00991,134ebcb,3a2e6673), -S(58892b5,10923690,2c82f057,45e55487,aa469535,984e350,1888218c,bab6e269,5a93b8d0,2633ec94,a2976bdb,238234f9,dc5ea84b,e3da3a7c,e4cfc628,d7cd9b28), -S(457138fe,f2e48bb9,73975346,80cfcd2b,3b8eff0a,a46fb460,9b6cdd96,168d71e1,f7cec976,ce010d6a,c9b558b4,3a715772,dd707c65,a810b900,2bc9cbc,406523e4), -S(b17e576,69ae6db2,88e6035,da4513e9,d5faf5d6,fc7c66d7,d68cd290,416c4449,2c1087eb,ef93f7e2,3f434394,e0146ffb,543f0e72,9c14c34c,8b22fd26,4f1aeb0), -S(f5ad8e6,968da1b8,ad2e400b,878edabb,77078aae,880938fb,59407313,68e9d809,17f5aab7,a6e19529,39294470,1bc75cdf,3527373f,dd6537d1,781a3e16,338e4b61), -S(f3f4b339,4f876752,7e3e0087,80bda1a6,9cbf9027,cbe131bf,c5b238e4,3e4cedb5,fbca590a,86e7d2d3,c784f04f,b8f5544e,8af59e82,d70549e4,dccc2d26,dd5f74fa), -S(979a2c6b,c24a9fb7,36d1ef74,f177f574,a0ec8220,5a2c3b5a,1f62ed2c,7766bba6,e69b9eb,96c2b65e,e91a5274,94368caa,e1480cfd,12711762,2212257a,cd6ce5b4), -S(b6301e9b,512e74be,92695c18,f18b57be,fc0ff988,87ee39c6,31f067b9,13f62c5b,96d8c690,7b48e6b,c7826af1,486c6ac9,1a3e1818,f7310562,86c995d6,4b0fd835), -S(1b1bfd50,1d5c0b5b,8e778ca1,fcd44b9d,c60bbc43,59ea8cb1,6c69f3aa,3a37df80,995d106b,920df44e,3120dd3c,16875e6,d5abe7aa,62c5d956,ee6baba4,cb77273), -S(b2fdd8f3,9a5f8e84,d75d8bca,d8d483b2,a8477bf6,9c12d250,188d30cb,e7ee289a,b0d183dc,4d971b81,51c6487c,39282272,2365013a,c27e3ef1,c2384ee0,2ca97072), -S(d6e43ada,76252428,bac311dc,5b49851c,79b7cfbc,dee6312d,ea051a88,8819639b,8dc6ead4,53c9781c,d297bee2,56c158fe,9aac410b,d7c392ee,367cecc7,5f86f5e2), -S(9de1baf1,ed24b6e,ee76aae6,566b3da0,2124f7c9,d526c3b2,ad15bbc8,3ec90c3a,e299b84a,acea081a,66e41b0c,5e9c84f0,2ef3bfd6,36c5a99b,4b8aac35,b7f71d9d), -S(9d6a8c3e,2247af1d,394ff76a,ad61dc9e,11da8d15,465bacf7,5075a348,681abc7f,880080f1,89cbca1d,460361e6,5388d177,da4d173,b9b3120a,af9dc8ab,2d7602), -S(6a7186ff,70065f7d,540fd40,f3e8428f,3ba6f0ac,678fa642,653adb41,3684a613,1097de94,8a2e3d94,dedff154,11d35a2f,2f75f9a3,2d65d9ac,2f47d174,24ff9455), -S(64f47f87,f05e4b03,d7d15938,1e81691,e337a08e,57169533,2f34ae8c,901760af,14cc2fce,17eefea,4981f14b,1a24a60e,73f3dd79,54ca12a9,64e1065b,c65545a8), -S(37112309,3f6bf796,11d5492,5978ab39,7e4df483,8f96b51c,39ad10f6,fe648431,45d08953,42004dc1,2cd39ea4,e1365116,b51b9ce1,b88a11ac,16295ca5,ad0f16dc), -S(9b2be865,6be732c2,9fd73a9f,7ec74827,6fc9e5c0,992ade7b,df5984e8,c7c67b2b,1cabae89,b28ae0a,6b58cce1,d9881a05,b9ae4847,5ffc3c63,eb145fa2,cb7182a7), -S(c0206346,71a326f6,5aea417f,a13ef7e5,c1054c57,ff7aa6d2,8bd7302,89243e22,ba986e12,86eb62cc,ab595158,7731c1e5,2e420b11,af4c4b9f,7e7068b7,2e8532ee), -S(cb278985,452e2fea,ec881f24,3c43dff,bac7e2e6,e8af62e0,f1a568a0,f6c67de8,b0d0c6b5,aabda249,237f86b8,f3d4aeef,ff32f9c8,2b349791,a090d5d0,4484a496), -S(9a092478,40008754,1cb7db8f,63d00d68,7a991df3,59e71657,984f3303,2b90c577,d8e49ebb,a2314b8b,2da2a1aa,49dac713,15942701,d264ff9c,e57a8abc,49d54fdf), -S(43e63cd1,d6d96399,724cae75,d5ae4fc5,94b12170,5335a3d7,b12afcee,155560f3,36d2c315,93b939f3,e7791fb2,56ea0cb,ff0374c3,be8eae7d,ef015e42,e595f962), -S(bccc009c,4012a2ae,58ac20bc,90ab1c3e,662fc7d5,57eef6be,120b5da2,25aeb10f,2a30dfd9,7b558c12,ab897ae5,5e3cb4de,3df9ffc5,326004e,8da8586b,364ae92b), -S(1753b47e,3e777908,376103c5,266147d9,2334fc29,a3ee15c4,edc9c8a5,38319f92,eaed6e86,c94a0bdd,f85cb9a0,d32cde01,c6ca2bbe,85607b56,fb363111,fed28447), -S(53f163f8,fdde3cc,39ce973,2c909ca7,29c2c5c7,415b50cf,c03a653d,1a9cf505,3ec19406,c26c6cdb,7f327e0f,1936c0e,bf85908e,49ca6085,5c5c2276,b2511473), -S(5e0545ae,f6d3ce1d,90300f33,827fe4b1,ef9277ef,17d5541,597d6ba8,6f4da13a,5207724a,a83bbaba,cd52b920,e5a6c116,552b010f,21cc8c63,d7fe518b,fed12e32), -S(e800d78b,a04fb045,a18a5f94,de52eebb,640b2ec8,a2159835,d2ecedfc,4bdb3b5a,5f3c4f8c,6bb039dc,150aa758,b4957a30,12e2eff2,657172e8,4e76328,45033b0a), -S(448d9559,94569d0f,9fb5ccd4,baf52bcb,5ca776fa,f49a3b7d,e9698fa5,50c5012,f0a64077,c97f82e4,be4d23f9,17b82f3c,6284c71f,82adc6ca,fee176c8,8b601613), -S(a2550ca7,bfbbff9d,4162360c,1274baad,bcd1c213,1ffd1714,7938fb26,cdea3b4e,4f50424b,1ebf6486,c6c5df10,4388a22d,8cdc707e,9485c87,851beed2,45c7f3eb), -S(af94b7e,f5984caa,2a14ccfa,2acbe4f2,70a0cd31,2caef778,c88b847a,be86b9e4,dde4f647,ebfccaa7,d23a5ac5,28cab9c5,8462a761,844bdbeb,e3498494,cbc16b95), -S(d434b5a3,a3c096e2,19f9e18,11f9b7a9,61ef6eff,a09da242,b595b824,5e8a4843,c068f8e0,30ac02f7,69555f1e,5656ca89,71bab03e,d5e6f865,94b3e4d7,37087350), -S(fef398e2,961ac682,8ee348b6,274a1782,7739420e,7bd36925,3a66e468,3fcfad86,ef1020de,b8d58a4b,be7b39e3,5cab7ef8,4e3269fd,248cb80c,85e83081,8aaed35e), -S(5052a736,dcdc83d,35f65bc8,d1eb40bd,7d8645f2,93bd88e6,aa2c5643,4fb77af,4e203bf8,1632f8cf,8c54c1f5,8f0342c6,612399f,348e7ca5,f9d3fb30,3d8ce1e0), -S(4fb4a757,246defcf,3b8752be,a32e819,c11a239b,97aaa45d,7bbdd92a,53a6cc45,9e6e2cb4,e02bb3d1,14c59aaa,c20150d9,3077600a,257934a7,935ceeb7,994f075), -S(518bb638,148f9d12,f0c9fc04,693745f0,656064a2,4d448224,b60d55ee,a405efa,f719e2ab,16fcc1c7,d110d68,3089a1a4,4fb5823b,db814a93,32456534,995c84d1), -S(8a8fc859,6dcf731,3b700deb,3bf9ddd7,f2732bf,e5928752,236df0e3,a9fe4c4c,896502a8,3c112e5,dbc87e63,c5cb73f5,d206e980,c017484b,999513f5,d5a5b4f), -S(47875c9e,86043157,3bc346db,d8076123,274c32b8,9baa353f,56b4efdf,8a5e7226,45174b75,7eef6f4f,70dc9371,40e72f14,832b9b5a,b44c384a,4c4b6063,1df05942), -S(48644f61,57f3099b,5828bb5a,eb886f51,1515191c,5be0dd69,32ec6618,c3870d61,8804fa4d,b44ed648,e398c863,6eac7c25,ffa3a188,71e3bd6a,395f92b2,259f5db9), -S(d5bbe7dc,9efee9ae,392b735f,b2e250da,a03023df,df0d07e4,ec84f829,bce69ec8,b542595e,dcf7e1eb,11b639dd,65335588,5c3d2491,f4db62a8,e099b7f,9c808be0), -S(ef6037f9,cf9770e7,ae5e9eda,9369caca,c7cf8101,d21c4130,cc119219,f2c3a6c7,5ccea6b,22073857,adb52256,1a37375c,b5f4c574,8716e2af,b26b190d,af69a43b), -S(a5b3fc5,2801baea,1f33f9df,270a1967,dff54723,7d7620f3,70a522e1,983ef747,8399a63,6032cb17,3c648480,74227374,dd19d172,57c74c69,eb7bd6dc,52d071f2), -S(a206b95,e51803ef,40ff83c1,8a6ac2f,553b181e,55d03f13,2536f947,7bc426c6,9149110c,5ba91d60,c25c522a,e5aad669,74a34a40,8ddc9dc8,29b5d976,f2c65867), -S(ff9c9766,f459a87d,c07235c3,3ba55ea7,25a33791,bc851645,d289b53d,1ce6291b,51706cd6,de0d2807,81b1d8ee,9ba5ce53,f6395264,6e509654,def0c037,6015313d), -S(ad502070,787ae242,9f4f9f55,418443e6,4386ceae,b20af7c3,7282399f,9f748994,b428a363,32d4f518,56f81274,d7fc023d,b03bbb08,5087b4bd,8c083c0d,77e1c7d), -S(e38920e9,3a1f1b82,f2ac5f01,ae02fcf,7b9cdcd7,d91fe7e6,14be6130,918746ef,cb55c04c,44e66359,db9a17af,780f0040,e34de88a,d10fe04a,a44da778,dcdbb26f), -S(4c0f9c54,ef982c9,be46ea7d,a380897f,c13ea12a,13de7de8,249c7483,88b30747,5f5da3e8,338e9907,c1b71021,b2177b5e,d90db096,15c78ca9,74445d49,dd5f68d2), -S(c9de9ee7,3aa50f40,b5b7b02a,9cf49627,df5196db,e72d2c58,738e5a0c,61725cb7,75a8ae6f,eb47b5f9,21aecf2d,a4bb8e56,7d4588db,2967c612,a53e1c4d,f392ee8e), -S(ab394e81,140e69ae,af0ba047,a6843253,e9875e48,b61f15e9,fb58d3b2,c61206f,a70db392,a3c6f12c,971b61e9,d92dc2d1,1bd086ab,67475e5d,6977d638,110adbc1), -S(39938f5e,24111c15,253646df,b02b4957,84a578c5,2a982a51,40d36d65,8b492cdb,a5e4ca99,a95aaf09,c3dfb75e,5c9591da,c6711e81,ac5d8fd5,891342b7,24b71598), -S(8b6785b9,82dcc8c3,2b12e79,582dfb2,2ea222b,99f3e5cd,dad2df89,8e621571,319495e2,79101993,ac2fc1d5,1770e668,16150e6,ba4fcd20,65beeeb9,169e6f96), -S(5b4e3ad,d62b1ca5,12bead13,113db6f5,52632ae9,163a4724,6fb7389c,e2775815,b8117dc3,5bb1939f,31c93f33,160daaa4,3114de60,df3db6a,a422a677,51d3fa6c), -S(bb1f0da3,ebe501fd,761e2b01,2711effd,70cd1390,7340b800,65c938b8,c938af6,3cca83b9,a6349423,669abf1c,77ca35dc,5c3c6c1c,e3fca31,6a85d66b,7da7c2e7), -S(deca6934,7ed75676,cc85c372,a0612ca9,c3a1ce69,ba67a7db,f6c92972,3b5f4e25,152adde7,67f4877d,2a9df65,8f86b090,2f2550e6,92fecdf8,9574e808,ad4fc510), -S(1e864048,c9d2a9e9,22bdc2b3,6e21065c,6dfbeae3,77712c02,ff015c61,8f65ab9a,cf00e85d,575641e8,93cc385c,7fa70aa1,22530e4,8f111035,6a50555d,ec004bfa), -S(71af1234,457ecaf3,51fde7,894858c4,90f11cb5,90fd0af,2a854597,50a33ffd,36b78c67,2aa4580e,d9e562c1,3dec5d81,bffe55ca,e5dbb208,5ffe0407,b7809ff8), -S(928ea175,c5b56f9f,a3a76080,f87389df,9b541fdf,fa409fae,8583b5a6,25f20421,5e9effe8,4fc42b4f,4e7647de,a1ee4770,2d436ae1,595bd2ce,6db80fdc,30fe2f1b), -S(28f7f51c,783ae428,73e4067f,34cf5bce,b3e53b66,d319fb7c,7165cca6,63e7d152,86c5d540,629a05b2,1583a470,3e9ecf9b,8f5573fc,ac3d04c4,9132c5ba,f6068196), -S(1d7b9551,af89db75,d2e93d25,49553373,79896eea,2d3cd7c8,fd2b9375,b5a95df4,138bc305,58a1090c,8b85cb0,c15130b1,ad375c45,57437232,a5e6333c,9dc0aaf9), -S(9b03def7,22f1df38,dad6f052,e054faf,9852a74,508808e8,38962518,3043bbc8,e9a6d8be,fbd144bc,bb23fcd7,6620164,82667553,d55a8a98,1b9f8f88,d4e5cec2), -S(c158478,636792dd,e24abf46,926ba57f,4d00f7a6,78efe168,5711abb2,beb3bb62,b772b20b,be7f1d8e,643643da,98b6389f,a28a7846,17207748,6d276d08,5bb3f6df), -S(de68187c,c951a366,ebe2de2,8f676a04,266aa791,f3705229,37ef2e19,fa1d6293,f9f28e1b,5ce0f88,66a04e,b967777,bce1cb,76ee297f,4942abbe,88b8461d), -S(1aeafc3b,f66681f3,fdb82d3,f128b12d,58432fe7,f18c92d9,dfcf272,9cd04262,aeb3fea6,b9568a8e,4152e022,83f60cee,7a8fbf42,ac3c20c7,7e339dc2,e6d5a246), -S(1222eef8,39569e79,d101b6fa,c63bc546,ad9f51e0,e27ea0e0,48da9453,4d8d4bc7,9a4790cf,4b561d6e,3143b80,86911de,49acd2c1,3ad7d975,5dd845c8,fb3bd86a), -S(568e3bbe,91d1ea0a,311018a4,b75dd711,45a6bed3,4b3f7d3f,77c1892c,a7e74fb8,24f9853,51477a98,daffcb95,5b157df7,7a8b6005,84a67fc9,7d427b29,aa74ebe0), -S(cc9f0cda,6a3b96ee,5c74785,dc4a5b97,31d0ef4d,10f97401,6935db23,12164399,bb7a50f8,6b530d0a,73162e59,4334dfca,5d1329cc,b31bc05a,3fa68c7,15c76818), -S(bfc084cb,45fb39b7,db0d16bc,fd1ba13c,a133b6ac,691aa545,bbaca6ec,dcc4bfd0,a528dd00,195c6409,6a9bfcdc,95db1c09,b1e5e0e6,6944616a,2334c297,1be07f40), -S(29cd9485,268288a6,4b1e6491,ba211ac5,94289ba1,199d1eb3,a1c013b6,f5d305c5,95283c31,38a01ae0,7cc119d0,58e8b81f,d5fba6a8,8bb4cde4,11268613,86e20a81), -S(c9aa4323,afeab574,a25023fd,a5775e33,8d216391,b10e1d10,31042e64,21f5667d,31f77398,3699d879,a5d713aa,d9b7f2f6,febd54b3,1a69afdb,d3f52232,a72338f3), -S(3a7d733c,9a73b8d2,4acb08f5,48031cd1,b26845a5,837388d9,68427a97,4cbd234f,693e8214,6e219fbb,b31e048b,8dceb28f,d5ea9b51,cf89a40b,d4f8e935,dffe4dcc), -S(2ee63f80,ccfe610f,7e6db9d4,af8defcc,b24907a7,d49d24b4,c3b5a976,73ee9968,de2bfef,b99069cf,fee3cd66,7eb2875f,3660870e,f61c70f2,6ac6b942,4314af97), -S(e1942251,ebbe37af,412340d9,2900a06d,9ced681d,48d81075,d04833f3,9f72acde,85f78728,4017fa63,28a3aaf3,c6e0750e,ac989642,8ed92993,4cf27e41,d3c37035), -S(d1a6911e,72ddf575,d81589ed,b8995e40,b0843840,72dc1df9,42ba5695,8a759b,71405cfc,f836adf5,b8e8c77,e376a7a8,ba0d4478,a30c6600,82450ba9,7264228a), -S(e02062ae,8b2a4522,4ab441bc,7e9a00d5,4b97a9a7,cca4e2bd,8dc743f1,931b81b5,5b6371d4,345f08ec,cb6db1d2,dea7b9d0,7b49ffdc,d50e9b63,23fdf855,e1cd2243), -S(7327708d,b7d3f037,8bb261ea,7db74eb0,222d891b,e14de28d,2defe3eb,a1f64a93,e71c99e7,627440fa,ad4bd9fd,3fe1a69d,5a8c109a,5165e54f,20113643,3d8baf66), -S(cd57d3f9,a726d2c7,308132bd,bc7401e3,f89d1449,57057bd2,14edcfc8,4e25e560,9e23e46c,3760b31,5c117006,99c2cbe4,319e483a,eca1641,b1a29e81,37633b6e), -S(87dbcc0,91c348f8,593c6807,1d0df231,9421e732,58e76672,e03e4d63,d4073660,823edb4c,fe506e04,49403b68,e4a69101,cca82923,82589a99,a9fd3908,8fff07c1), -S(e3499c7a,cea737f4,8359512e,98a9e5b6,2d27ca35,accb8c2,cc65c7b3,ffd28b8,3a2c7591,f0c91dff,e01a243a,986dea24,fbebc8cf,dc0387f5,78988cbf,ffe017ce), -S(5ac29de7,70553d51,284cd610,b360469a,fcc4ef23,bcee5936,942ef27c,b805779f,2a32b97d,f3e8713e,809d4f79,55525e45,65a60581,5fd582d3,82d7088b,5966523), -S(201ee48b,86a8a93e,8e12b084,2fb9cc37,25e4478e,b9d6d10e,cd1f220,c4a128ce,390e0cef,e6b561a6,6f58c07f,3569e8f6,6a467d2c,cc548281,cbd656f9,f7fbf73b), -S(8f64a6ee,3ffa42d1,e55aaea4,9e00f260,fdd33f21,394aa31d,c17a4328,87ff50cb,867a0189,2f55cc74,6e61a5bf,46796ebf,6c0e2932,b8f9d1df,a5c48af7,e491ef83), -S(5e38512b,65607ae3,f843e223,ec7f95ef,5af4bf35,edf9068,96fa76d6,c302b75f,7adeb25b,bcd0bd27,646956a4,c4a659f9,1db48f2e,532a84b5,7cba0aaa,23e28da7), -S(c812dbf1,732134df,1c459c81,f15cbf3b,4a97f959,18bcc0f,48062b04,bf133649,d22eb1c9,27d57ff7,e0baa4ff,c3b9f74e,116c8a43,ecb10cb7,32745d9e,61e708f8), -S(3f0d8071,56f38368,91a263a1,5177bb12,720eb46b,d6c9abff,5bd2d2ba,ce377b39,348f65fd,f87f7f2a,1dec49e4,8e009fc3,8f916c40,857586d4,e6063772,704d70f), -S(da9c23d4,e4fc5a12,f80b9d65,c2536366,c75a86c8,fd4fb92e,fa5e360b,5ba1993,eb01f616,fb20b8af,522a108d,b81d92f6,3b161963,bee3427b,4a49353b,928da25), -S(d266b680,fa8f6b70,4f8ece54,e52094f8,be493a4b,9a4f396,dfbefba1,4887e18f,564bb0fb,f63b5054,6a930ebf,df1afd93,7f0db851,e460c8f9,67afd274,b735681), -S(b9859cc7,2b573a92,b2752b85,692bf02f,be1f176f,1cb8be2,e954a00b,33e314a5,fb216130,8bba3bc5,cefdf81c,c21981df,2dbf0a83,d98d259,62c879bb,4ce6ab87), -S(8e52468e,486dc34c,c53cc59c,b8c9360,62935ec5,4563b9e0,8daa0a95,f8787f3f,2e3d5c59,90f228a4,e7133352,837eeb62,892e28c,7f8233ec,48ff18a2,d6564c9e), -S(438a2203,af978f12,d28fb3c6,af10ea2,13a954ef,7b0974c7,2b1113b3,e6d03b65,d8f36c0d,d6d4782e,d7194631,7b0a5745,6207517e,379c29b2,ab30cde8,e8ad33c9), -S(1a4982a9,f06bf158,9e395e10,9873ec13,1ef4a00,6a6d7b83,675c3906,1d61fbbf,93e2882e,676591ed,8acf2e3,ff22284d,abe2fab2,bdb99175,5ac72631,c5002747), -S(6ebec1f3,bdd0f019,3bb9a7a9,1d59dd92,5019400a,575dcdf2,33156bf,3e88a47a,c341309d,b462016f,afabbb56,5d763ba6,9c8f2f98,42812afd,fe0e9941,53283ba1), -S(599dc439,687d0dda,a348eb2d,337bd2d9,76a2be69,fdf5e064,1ba87e91,61f45351,c8433a55,411fdd17,ddaa9a86,bd2561c5,8b891c41,d868e764,13e5f3ee,3b3ecc1), -S(5a63cd59,aa9aedc2,91a0d50a,c7d01214,c3788f62,7e3c60ea,84d09ddf,2eb80840,3851bcf3,51ce55f0,4f92eaeb,99b3036d,a06d1f38,2a759217,50e4bf39,7d5ca685), -S(86e089a8,9f1c1644,a2e94b4a,722c6f19,9bb0403f,9a112b59,66191e31,e750f1,91ca06bf,fd48c38c,272594e7,1a113083,f6a4b275,7f279a75,3d70b984,a552e391), -S(2f2c3b0c,dc0feb58,620ab813,c8182510,a2a6f14e,9127153a,358c50f,31238370,7ee136f3,35f076a9,5b80e0dc,a8dfd8b2,691ce9df,5ce0f1b5,5dd9e3db,e156a360), -S(4e2e8b40,8602701a,2d1081d4,e41f81e3,3d9b8465,9959532e,93aca00d,9a70f005,5ec80478,d44bc01e,ad4b544a,20cc58fe,2990c0d2,4d08fc4b,2f9e0a5d,913953a7), -S(98c30f9f,4ef0aed6,17a8fee8,92934d56,10267d6c,e14832c8,b802ca00,320a9c7d,765958cd,15907b0c,dc0ad9bb,217d647f,6c85da72,49260d4d,11ec062f,9d818639), -S(f2b87023,7841e053,a20f2df1,efd265c9,f58e9132,9c280502,61f8c6e3,d6ca5afc,bdcbdcca,67fdf622,84fadc6,4ed6e727,5e82d40e,efdabad,c3d1dccf,fbd32dbb), -S(650f0256,1031a2d6,7549959b,7c358191,cf3fa7a6,30010f57,1006d2a5,20592377,2c4d23a7,44aa3b0c,6359149e,c170866c,b5874045,900b2010,d5a80dc1,e6b2892c), -S(76c3e87a,c72dda23,7ef119a3,9a128507,eba08e31,9f1a7512,5c4dde61,6523fe40,822fa37,8e7c8f19,e02954b2,5faedcda,6d2e0123,ea0b10de,70361487,9a0ec110), -S(472f9e0,9adc7ba9,179a6e8b,22985721,c994c51e,109bdd04,eb2afd6e,fe471f8a,11abccaf,296e7c8d,98e1c3f7,50069ff7,9552ddc8,5e5b55b8,4980ea03,4012072b), -S(4cbb2b87,1f8b975a,2ba257f4,340074d0,7fa897e6,7000795d,d5312e35,cb9453a2,4e31a79c,d842f6da,9e45664a,2878070,1dc87cd2,eb2cb25c,2a7833e5,4e2736e9), -S(ec70b3b,1a95b593,431ac4b5,5825e6a5,2cb88276,27165195,83924921,30805ca2,6092c54a,165bd710,a0e1f36f,18b4e4d4,cfdcf6cc,2f222599,761a9efb,e4d7807), -S(a6b1dda8,e0dfb484,60209710,69cc5398,4e4462f5,a305af62,6b7ada3c,bed5e1f7,e2c113db,21680a63,8f0ea442,52421c0c,41958de3,c7b4a24e,f39546fd,19be201), -S(4a18e595,4105c269,25468ebc,a0c9accb,1710b854,d618cffc,72eee0aa,c0e3f296,1e7cad8,cd248d4c,5dbf0207,a32b67da,2db8c8dd,4798a17b,52ae6445,728e7f6f), -S(eecb1dbb,e2451a48,53054f45,4cc640c4,3e38f20a,3957a192,c2f5827f,9384d11d,a889250,f8bca4ed,5158a55c,197459eb,50b7f10,f74158a1,75180856,b4de62b0), -S(8949f6e9,5e3143e,653889cd,4d57fea4,657aa42d,76e6297d,d20ceecd,d5def67d,e08d4e90,fd929ac6,ac3e87c8,5554e0f2,b584a31e,1be841ad,827c738,3cafeb54), -S(e85b17a0,dcdf256e,51a605c3,1859773d,a0e52a36,6312eb19,9a789246,beb7441e,3505403e,1ab0f77b,984f41e8,a8462c0d,e9d5b500,d0a8f59c,fc83a75,ee063720), -S(c7742a95,6b5c8298,bd1600c7,b756f777,bb4ab2b1,529c8419,d124d402,2b902420,a05ec2b5,8af28f9e,35a86b,4db0634b,5b7017d,7947a023,3db01ff0,64bdecc1), -S(5432c05c,814aeb02,c82e651f,7d1f7b89,e294a76d,17e5ddd0,9ec8140f,cf5a62f2,5902ac55,ddad39dd,da4b35d1,5b84f43b,c13420b6,35f28bce,a60d55a5,78d3afae), -S(39075a61,15bd6870,d1406865,4c8801d4,b9aef508,c880618d,397f9bb0,6674b17a,8bd2702c,96604b83,4114c489,367c3d3e,5e6efd50,c15b8bb3,4b2cb686,b08a49d9), -S(df43a136,af0f754e,599659ce,63d0d48c,73993927,6eef3442,e505c93f,acd025bf,1378d4e4,763c6c79,483597e2,f90824c1,830c8850,fcd32c69,52dab9d9,cd0802a5), -S(840a24a8,314f7e0b,9b3c33bf,7f6cec77,3052a0c5,54a1e180,23772bf5,1d7a4a6d,6e1be7af,f02c4536,f44db655,b859383d,5eabb37e,92b4b896,7ec1acd3,859cb1ab), -S(55d1fe11,49cc5e08,5e9ff19f,9c0823aa,9ecbc1c3,62385bb,e5d33d8d,8156628,b1b96f77,c27f17cd,df4b223e,7343f140,1849d049,4351b2bb,27aed7e8,79b686f5), -S(a8ab1f78,3a7fd00d,f5f4a814,31eed1d7,b767417a,691f28b8,38238da0,cf8fd509,2d747fa3,b164ec83,de89aec8,746781df,f7fcbcd2,67230a85,4802491a,e213a3ca), -S(3cbe8f71,c37679ad,d61e0453,3a1ebb71,99618a3b,9e8139a2,cd751d97,d4a212c0,9216bc42,a61a9734,750470c9,1bdb3fe4,510a5f0,9fa5858b,29eb7b8e,3d19641c), -S(cf1fb09c,a6b5ba69,93303a5b,695ddb27,3b527ffe,9a83e88f,9b5d45d6,b0a8f94e,cea6959,943f7e1d,f1e85391,e08fbba4,b9d84b00,6cecdbb,16f576c7,dd89c814), -S(1854629d,e22365db,5382ddd8,b6840e03,d1e12236,d31c7d10,12e8f83d,3ce1b71a,b25fdfe7,4fb81669,a24cab4e,eece5fc9,689ea40e,205b614c,4a0f250b,8f778b15), -S(6d1ebd8d,69fe133a,2e6628db,70cd4f,15d066db,2b0f42c6,2fc70dde,eb2e89a1,313ee8d9,750c0164,ef561df8,6125e72f,cb5c2233,ea36f971,197c7fe3,acc429ed), -S(29ebf614,7a918ca,371b5121,9efa033f,ff2869fc,618aec33,a4fe7aba,b916e46f,f1d5c067,382d76f4,74c159c,e88ea702,f90ad2c,5b268a7d,14ede7ab,40e11a22), -S(8e2bcc39,f60c4c62,591cd482,8125d08,4d26fc92,2e6ae30f,51882438,93dc5a40,44e3fa3e,64e14ada,e4a0a616,10862503,2e109dd1,c863814,368d423a,f96e9e56), -S(27e17225,1f6a9557,39aaa058,bedd91af,1e920758,cc0724ba,42f44f4d,45e99efa,7dd22a7d,6dc604c1,fe2850d5,41b2392a,b3c3d60f,2e712cd9,179fc5db,5fc179e8), -S(4fb44a50,574d591c,1391dabd,7f40f7bf,14514f65,927466b,2c643f36,d85063d1,fea4e431,63c1123d,9764b70a,cd843281,e108f04a,6fab19e3,da059f51,4c2a73b9), -S(929112b5,19251a93,bfd2715c,6107e5ee,d3283e0d,1849ae37,d110fd4,8eaf6be4,e382b859,a7de2309,a4dca649,66d0b744,9ffe9ba,383379be,d12871b7,19c653a2), -S(532c823a,a090cc4b,128938bc,69adb5c3,3653fc33,fa07d598,36d25ae0,808c0b70,61ecaf31,30a852cb,46de2616,f7bd24ed,8d9e1ad4,efadf570,d08a463d,b127b455), -S(7c7ec9a0,aab8cf1d,36b9447f,d7d82549,d425c217,d25cbea1,3ddb8d5e,e29a38a0,5441d917,1898ee1e,3cca969c,acaa074,62cd236c,a5cccea6,9436a086,e08142a3), -S(a81c85c2,54e52aee,1de1ee45,b79cd027,e1cc6414,4fe99ee,8ad8c572,82c0bad0,1be62473,54bc2bfe,1dc85c68,684fa9da,1ca55a58,6dc4ebc4,3cdb050d,e7acfd7), -S(38f16bb6,da377f25,aadc90b0,7fd21078,5028aed7,85dc0b07,5ad9f04,4b0ffcd7,9563c6c5,531b64a5,d06a5181,d7515b61,4a74f8ba,6226b559,4220282b,b8654273), -S(ea7a49cc,ec294031,87fb5f88,82deef27,2dad9624,76dcacfe,cf128bad,732e1686,49de39f7,5d9a4302,221d9b96,90019013,1ce39a7f,dea1c801,cfc0a2c0,b9a16995), -S(85019851,529364d4,5c84b63f,7f119f20,f3245547,2aa84b42,1ccb239d,fe536868,91b58064,2fdc0f39,284706b5,5b8e4bb8,4e112d5e,68379d94,465c3ac1,8e37cc50), -S(17e41364,244d8f16,22059363,be73839,75ad528f,f1db3390,ee65b106,beb6fe40,e90412d5,5e1b6590,e0d5968b,88dbb0bf,393ccd6f,96748e5a,205ff1b3,2f18a0f0), -S(5b49e7d9,fcad56b6,8b85d934,1b996ceb,6a555ca0,78f8d12a,e58e79f3,1d91caf9,32af7ff5,de4445e6,4bb895c5,316b171a,d911d8d7,81b16115,1e9643ad,4ce21885), -S(42baec78,86aff012,13d9d182,6e031b20,85724be0,268790e9,968d01fa,63e0e366,8298f68b,32e5caab,b8e641e6,720db67e,4150ad69,ebe90143,23f7b981,1ace8d4c), -S(5201710,64afee86,14c28123,5279e1a2,cc2775cc,85a5751e,158c66e9,2fa55d51,d12195c5,a0a08b,7cdca2da,fae86d15,d37427e0,1d266609,dc9c1adc,d5d8039b), -S(bc353c2a,8ca16349,fd021e60,8befb9a,f85c9ebb,b448d732,13220154,a02297c5,88850fa3,a61383bd,133c6fd4,65d12756,37878fb8,84bd3c31,3c4f92a,2b620edb), -S(9490256d,3acd97c2,848b24e8,8b8b2a8a,8635417a,1f228d6f,dccc3917,9c0fa397,4f4ce298,cf1dd296,b7704f9,b8f0a0d5,be42923,80bb917c,5fd49c28,55d3b662), -S(a963e733,ca168104,47ecb136,bbd2047a,97ba8f49,9222736d,eda1c7f1,75c2fff7,5385ed6b,93e6c27f,568566a9,5cf31059,de4ac850,1809319e,ce216eab,c8dc181a), -S(fb44e6f5,eca57845,76439098,2ab24ad,c84efb0,715c3b9d,df0b7b2d,a165702f,a62de478,678bee62,891c5241,9c8e77b9,d573fa6,95b0a2bd,fa5d9d61,c4362e43), -S(c1de1705,6bd1f0f6,8912dc20,29a41689,efb21e22,e24f3fc5,ff5c4498,f4fe7ea6,6297c6c2,a30e8e3c,43f534ef,475c3b35,f2a9550a,c5b9c733,63e117a4,af2829f2), -S(8c78a7cc,e7084890,8ff122c9,108980f8,b2a2b9e2,80e5536c,34b5e13e,61f8e133,459a70a1,5929d848,f8def6ef,ea8f42c,905fddb,3c0153f6,71a17b4a,b7c2c1ad), -S(5204d397,bf3ca5eb,988c1ccc,d23fe613,25202fa,88421157,cc7e7fa8,91b4e612,c02a009e,f89c5b88,b3f3a7a5,40d30ee6,75f94247,60e23fd4,8d8ce1e7,6395b7f5), -S(3cab1091,a0dc43c0,b90c60ee,44d31ecb,607da086,fa6da814,9c378acb,99c67ec9,3bcc5297,267a2da7,e228c7b8,c1677407,93feea54,bf31e3e9,f8e270df,e8d1fd19), -S(e0475cb9,9ecea30e,94ad6292,5ca5c3e7,77c30673,9d9d55c4,464a3e85,cc2f10cd,484818b4,d0f72e79,79427904,9f9aa4d4,8aeebcdb,f7f55a4d,97ddb03e,4f6018c6), -S(1165d67c,11327a34,e702775b,40a9d7b2,deaa423e,7e4d3dff,869f4a9e,3fe6ab73,63c55abf,6943f35,171595c9,63ab061b,a1c9f605,c2ee4970,767ab1cc,1bc691af), -S(f0ca20aa,59ecbddc,cdbd3f3,6c8830bc,9bedd29,b893ff74,48cc523f,bec962b2,6b2ff156,557d16a6,47453361,c4bf9f4f,41bf1e73,8f0c5536,a3dcd50c,ab88a086), -S(a3b01fa3,8e743e32,b623f2a5,cfb7300a,75457d46,6499dd5e,b1453d16,a746cdc7,19fdddaf,28030237,7310920f,3f982394,db89f510,a4a73b08,cacebc6a,2d417c78), -S(37ef5196,c8e2d69b,cc0b26c8,2bc30b9d,650a7ca1,409c77c,11e0a338,c5065ea6,df890a8d,8cb2b669,dc74c96e,19ffdbf5,abd5d898,46240fb9,18c297d6,1275ea86), -S(d99abce,1ecb8415,eaaf50bd,66f4b5f1,a5a4e5e9,d6959735,629d624d,adccbc88,9da9b4fd,2558c726,c44d10ee,f72c4699,80069045,a8660cf7,58de00cc,67be856c), -S(f77fe49c,28595198,7abfa598,915684c0,2af76675,5e2648a6,36f5c955,a78aed61,a764861d,3a8dfe39,92b2e897,ad4bebb0,8c7e2b55,e390efe8,21ffb60a,cf5e4be1), -S(88f6ec1,2aa65721,3f672e10,9d406472,7b89cf88,74dad08b,a4b54747,2bb767f9,8b6253db,a124b7ba,43fdbac8,55f8e9d5,9da23b49,e450c8e5,675442b5,f822b8dc), -S(a13a7136,640d1507,9ed90b77,12a9af52,e53e75af,4583a149,f78c2840,f383fc55,435fa5ab,6454ef1f,ede1b33e,475ffe8e,10dd5a94,4f96f340,1c184642,2672b310), -S(20940c7f,9d4abc67,d42884d0,346551ef,1b2aa54c,d8a1485d,1e23758c,e207a7fa,de5eb4e7,b619e600,3cf9c0f9,7e944f55,ab57fe23,388dbc73,66bb2120,e5aaa793), -S(298e00ed,855dd2f1,c0aef293,c55d859c,3db60fe4,b026f782,1c07d534,cb087e0e,9c45f376,466da662,583ec25b,5bdea3ac,c624731d,4bb62b2,2345fbb1,bf721990), -S(5153ac16,6b837bd3,29d98a22,56a576b9,821376cc,f7e48cb9,24e75f59,ffb6d7a,3f5ebcd5,d5ec2073,f1e43334,7ab4780d,f19a2806,d87a6477,bb73ed09,bec6bd43), -S(78c909a7,c94bcc00,b5518df2,bcd3ec09,9d5d2db0,d15321d5,b3135953,e8e1d195,735e4b40,519f4757,32042f20,410d8699,d1af7a33,94062791,b12e19d7,85ae42ea), -S(e4a4b24f,d9f7ac92,8a888507,c6d21ad4,fdaf62c9,2bb920ec,3ef96d64,a70a8567,b62c1cb7,b0e49cd9,8001dad1,52a2206d,6b397952,be03113f,7ff764cb,505502e1), -S(ca3b64ac,d4aa25df,3e7d4b64,6d5c8032,66809507,7f7f60cc,1e3138a5,2eff4800,92972d13,2f370aac,680f2a2c,feaf4e93,73199207,7f51334f,37553a04,5af089cd), -S(58e22f4b,a636677d,aecc727,d58a6ac5,77d85e31,2d41d56d,1c09c859,749798c5,cdcca924,549c867e,1a11e4dc,27bb00ae,99e0a356,5b6b37dd,26acb58e,f29f3bf0), -S(94dac55d,da61410d,926841a2,4b5ffb24,e44e3ee2,3d42efbd,8afdf3a4,3530363,4095385a,529965de,b01b9a3f,f9647b29,8f3d2119,9bdac924,5aa54df0,7e8d621a), -S(639ca66,8d7940b8,8f41c4cc,eb50b60,203b6884,c8ac9c0d,c33bbf59,926d417c,447035e4,5c9bf80c,71f8aaa3,9f9356c6,672f0db,fa01a4ef,5b1b7400,dbb70a21), -S(a6a9f38a,51d8e82a,7e04f667,e8cd638,af4cb7aa,c8b0ffa9,255f472c,c5b30250,fa935a10,4796943c,1880e3ed,d9c2504c,7e6e4bf,46036119,9458e23a,b0b025bd), -S(60179b5b,cb4ab099,b74f6a9b,853a50f1,582362ca,fd28b288,e2b339f3,27671a8d,5ef8f881,54b7b4af,ba287388,6c09d1d,c12d7070,6b960d0,b0453767,7e5d283d)}, -{S(60b01067,25cf781d,e78ba725,40508697,3f2ff6ec,1511515,6e19384,1fddda7a,624ccf87,f0ec21b9,82efbc4,6d4db878,5d20fb8e,dfe663fc,46660bb7,98c96eb), -S(74164670,d214bccc,23e32dd5,b4e7f093,c95b4628,b7b3448a,347980a,1f9b0323,827aad3a,23a648ab,e0ffef7e,d8a6d6,800e07bd,7eb1b5da,50b5dc2,8994a20c), -S(66a60beb,feb1eb8c,39857b37,158b48c0,93a90cc7,8d8aa58b,af183975,b12fd461,62f95a56,2db16e47,5ef65451,4cf82fc7,1a4379d2,cb4224fd,695d202d,8e85fbf0), -S(77272c7c,cb0ca53,17e660,adfa236c,e062992f,a59c7164,71d89755,f99ee448,a6a2d5ad,7ee9dbd6,d8a9d8d,157860a9,58e3d766,da5b82e1,5bbf83eb,7d987f7d), -S(eab2ac49,209ad561,d3beb05a,5152d5fa,f1af52a8,12ed0d40,c493d611,bd78c73d,c72f5b65,dfb7f960,a8bcf355,b80918ec,a9e8c3b3,985602d3,7ac0cae3,54645f6e), -S(ec184bfd,27c2ed17,25026464,4be6e557,db93ce3e,90ff225d,fb0cabda,cc124952,b4ed4a46,acebcbb3,9103f99e,cb65e208,2aa5990c,eba9fcac,cafdbe55,6a08a516), -S(6f5e0f0e,7c32165f,183f7834,3e12c845,86745ad6,d02d4f29,bf16ffab,31b1de93,76bf7f22,105a881d,6d190e20,bc7b5d89,ad0ee9ac,c1df6905,7035b6f7,6a9d4f61), -S(b3d820a7,466f3cb,d955acb0,c8baa787,e7f0d63f,52f9dc9e,87c6138e,60b9279c,6d769d76,91c1e61f,41b9cdce,949828be,7d17c1d,ff0c5041,7e2e3b79,fb873753), -S(ad92580b,575d6831,d2332a72,f3f888a4,713cd659,bc439870,7c000318,8e7ae426,eea9afc8,471e88c0,22463a9b,c8cb22c5,d0df87f9,201aebc0,519fb7e9,e2307073), -S(54b8cdd7,3204abb4,22d870a6,c5afcb14,81d4f117,a673e60d,155baafd,f3c5d4bb,6aadeaf4,94823ad9,df8d2429,e42a1d6,8aacec78,bf973785,a56120c8,28d23bb0), -S(ef2bb94,f14272a1,e235da4d,4ce4b043,2037c8dc,7ad8d559,958dc767,e0e75f5b,3af91f78,54bae661,9702996e,1defee92,2c0e8c3c,5fa4d37b,261c20bc,14fbed93), -S(13b87d2,8125e63f,1259b1d7,4b79c395,25bed045,256e8b00,84024bdb,48196b7f,139b380c,bba0404,463125e7,a455d454,ce7d811b,c7c14e10,90cef0ae,67d8281), -S(34ab008f,50e1a525,8cc77331,3dbf8510,7f3fda60,7ad5dfba,9aa464fa,856394c1,19178d3f,f5c51bd1,4c6d424e,c42591ea,414de041,7a3f470d,7c35dcda,77e57860), -S(7d872049,c080936c,54875ebc,49a00c41,b837b71a,18de4e70,adcb8369,95c2dfc,b572a6cb,58a2337e,2453110b,eb877a02,bff2bea1,d542714a,3a115a59,933eaea8), -S(72a2644e,2e6d7182,9f78274a,eefc9f15,9861b031,56d20d69,db62b4f8,57dd34ea,82e158bb,dc2d6100,bb5b300e,467470fe,606ddc1f,e662d3eb,3d51d9df,8383263d), -S(de81a355,37cbb00f,76aae7be,d3ce5362,c51426e4,ca012ce8,5d5f0fae,791c106c,10137d33,8a6532e,95917e92,31e5c14b,10551f6c,7bb1cd4b,5944e772,22c0f0e0), -S(f8499694,38918109,b0eced18,766add3d,8e21a5e1,a6eb640b,e4794e21,20400de,9d081c04,cf130095,fd00af83,32408bf6,ab4e262,e5150e3c,9f43a3a3,704b3d8d), -S(a5786625,1f866279,36233299,283e5dc3,838a5d9a,6fc30cdd,cb75ea90,9f3b2e94,57d57841,f173e1e9,e2959908,7e535dc6,a848132a,d6fd98b1,ea2a16e5,ff8c60b1), -S(533053dc,a24ceba7,f528c93b,bf62d61f,ec640ac1,40848f7b,9dde2ccd,f2465df1,d501e49e,3291919d,3c7a280a,1501258e,325e478e,343ae766,61cd9cfb,b856a316), -S(b85608de,dcd5543a,a90fc566,9fd94d52,b041e434,2cffc394,1cce3f40,12c23ebc,dcf01862,1051bab9,d1471d26,99f5727e,705ea2bd,8e5ffe71,df7db441,236df5c1), -S(bd1a08fa,d7d7fbd2,b46565ce,99fe28f9,635e0c41,a8b6aec2,31d949aa,a70d52ca,1a26906c,f77d43fc,ec656be8,5db770bc,65d05482,d6449f52,e23e1e70,6ac2aa15), -S(ee4e9976,9517bc1,2c7adc6c,fde381eb,b385b1a4,bf918268,5f175db9,949c99c3,738250e0,5dd8e427,95728575,fe5733f2,6b083705,301f9138,d736fb24,98c34679), -S(bcbbc6ea,2007057a,1be80335,3d086450,c48e432b,6f80ba43,bf03bebb,c48f9379,10fd6383,b5857977,87d8696,9525e0ae,b1842c23,974353f3,4eb515a1,5ff52435), -S(5c717940,e5e9546a,f9ce9d6d,c260bbed,fb678923,db861b41,1f275f0c,b18b6e02,d9144751,3ab535c0,603fbc12,adf52285,560f029c,266cda2d,69b29090,f5179f68), -S(7137b160,a5eaf92e,fe5f5c90,c3d34063,333f8204,5dd83371,31f624b8,cb7173,3025534d,6303c9a3,6ae38e66,57acdd29,48bfec24,d5ba7709,be051fb3,4537c2b8), -S(a6e79e0b,54c083ea,a6e37b9e,b54c181b,ce397786,c294abf,5d1cf475,fe34c030,aaa6aac8,4709fb5c,ac6a498,c0659da0,e2506e5f,e890c06f,5ed5081c,bd737c71), -S(9a143958,23cf2096,d81677e5,f804bd5b,790ceabb,4b15da9,b35c01f8,c6b1d81d,61bd3e2b,642e9948,50179f0a,947820f3,f241e53d,8222ec73,3ceb8bf4,cb7f08fd), -S(a51aea0e,4039ce66,b3e80814,4582aed9,d0ac0be2,95105a8b,23179025,4a2b0429,7cde7f91,96e8f417,ed7a075c,c25cb694,4e996997,3ce13a4a,941f670a,f523709d), -S(2d79629a,1069878e,76cda780,b9291c4b,45b78b7b,ac98fcd4,3ebff7b6,cc2ad200,cb01aef5,1a5fab94,ec29d73,6ff2370a,df866d45,d977fda5,2b7fe32a,e1d9a3fb), -S(6af74994,feabdaa5,fb0cb613,2f346490,bcb1a70c,7bf58e44,2cd46670,12e050d8,627e7f3e,b4e66be0,672b8bde,f119177e,f878e80c,a7b5661d,d6a9d19f,19729e9d), -S(c367583c,7d2d5d6f,3f00083a,1218645c,568a85ca,8fdc708c,7e8dce2b,c72c3ceb,baa36c7e,1c86d194,ee03efb5,c5e11b47,34bfa6,c168ef3e,fbb78f07,51a7ebab), -S(36b2293a,2dc956f3,47ef5874,9504821a,c9197e25,1716c398,f5c9dc61,c63fd5e0,95c93401,be8f3500,d971ca82,ec97def8,7d58d64b,5e4753cb,4f2cb608,72f2950d), -S(78e80bca,805183f1,76257399,63e9cf9f,a1bf2b88,eaf4147a,17d83057,bcfa32a8,b42e40aa,f852c738,fe1abb8a,e5dce499,414c2113,eb59cd2b,2a3f6c42,fa96812), -S(4f5b3550,887d9ad1,1254333d,7203aadf,d202fe5c,845b3c8f,3c0094fc,e4a32628,a4842bc8,c793e4ed,948dbbd9,cb68b7c9,3bb86827,fa9d7c3f,acfe78bf,670eeb99), -S(8f880914,9dc553da,4ed0b371,70850bfb,c305fce6,d5e7be9c,640be999,8df19b1e,f020f82a,eff490e9,fc7d4d7b,519e780c,21f86f87,5a547693,86524483,ec776674), -S(ed7f98f4,90be919d,d1f570fc,cb565424,c3537bad,d8d80e61,87b51f8d,9ebce164,d374e45b,c81bdc9d,63c824b,1bdeb2ff,5c9a3453,93540ab7,884053b7,107d8066), -S(754d2b67,65625067,14865f65,a89bd0c6,6415aff5,644d37b7,e7437e03,372d70f5,e4b5855c,14ba6a3,360d1519,98358bd0,ec2bd109,ddee46d,7a95050f,5131a9ae), -S(d0778425,311ac57e,b8ffeaee,2001b9fa,89d6cb36,49be46aa,365b81cc,c8bb903a,25e3a484,5f1c15e3,ecf6a654,69a78893,3c414b8d,c92587f9,fc8f54c6,eaf065a0), -S(c7c18e4f,7c8772d4,37e3e861,584d24f7,f428c06f,23730347,2dcfd4d6,80352ff2,6f5a02d8,1c6ff6cb,32e85004,3375c865,57f8659,83e76e0d,4f42a69a,b02ddd52), -S(96c4e50d,eb86020e,b0bfba2f,ba3da698,c7bd031c,78959022,341aa1bd,a19b4a1c,8cd7476a,78098ae2,ca166d9b,c8aa79b1,ffd9f8f0,943286ff,d563008f,6f3cfd5f), -S(3f462649,9a5e5ad9,f5ea71a0,9b4e6b7b,fea33c80,c786715b,15200580,cba306ba,32624f0e,9a3b0413,fa401f8f,6f32995c,74ab592b,792247da,970b89b6,90545bc4), -S(a1495fc5,2c642d7e,da16d1d1,289f2eef,f4993882,f2843128,6d17d34e,5949e2f1,66ce7c4d,611421e8,7f049ceb,11e9f99f,9edf2592,9da6bc45,91ffbfbc,3c73c87), -S(954ad30c,15a6c5b2,deb98983,ba7125c8,e216f1da,5531d258,513b7731,4fc86c0c,39378c22,527387af,e75d630,fa69dc8c,44586372,96e4526e,2e105fd1,af7ba0b9), -S(5692830e,c3ab78cf,6721b604,31abc539,ab14318f,cdd4d6d4,1586772a,bce39a98,5d1d9619,c335acef,22acc9a8,d32ae53e,9b227ede,50ca613d,d67065d1,252c56b8), -S(1cab4f2c,73e452a4,de0e2591,1ed22364,803a060d,ad957184,3c81258c,6a4c518d,27617c5b,d52b5d06,8cd9c2ba,df266f8f,ecdeb4cd,41bd6e0b,a2db6a2,8f4c7f3c), -S(9f1834c0,145eedf2,53211dc2,3339283e,5e7daa72,fbf6b69f,d5642a63,c551bfed,c1838a49,b3289127,7c3365f5,9f69d34a,27b48c6c,8897e9ca,f40d8753,d467d72f), -S(58988653,8035c13d,2c538f0a,1c587f2f,fc08405c,e6a1d7ad,828aef75,43b4ae8a,c4b901b4,beb24774,598bd2b7,d3450791,f2cbb37c,939594b6,593fa592,dee20590), -S(d248754e,c643d300,6d81c5c8,9e91b522,181921bf,627e813,1acab8bb,cb97b2be,76b94631,6668e319,a057648b,2369d781,c2abc77,6aa8805c,43734698,671174e7), -S(f849ae76,ad1bc714,4c2fe13c,b0ee81b3,f9abcca8,d940a161,74a69c0,b2cbfd0b,239aab7f,c1b6c054,a34deeb3,56da4e14,e15643a6,63f40642,b2a43350,80c2883d), -S(561b12a6,2e2fd36c,ca92d85b,14baafff,864e99cf,315d8902,72f81dd3,27d1f04,c4199633,801df02,b34ba9e,13462533,7bd975e3,ceb19673,7bf37bb9,daf30808), -S(8821c52b,c13c4ca5,bc7712da,9e769754,c4ab00d7,83dbc018,b1c5b383,9c41c245,63edc442,6347d646,5ea5c046,820fef62,89a28c47,df834a71,cfa9f5d4,6561444b), -S(382b0dc2,c54b6fcd,dd8ff070,6edf8f4f,2ce34daa,4f7dc15,d7f1ee0,b0ba78a0,31e1e109,35d8c994,3ed05b5a,57d91bce,81ba0f4a,8da1454,98a18e70,17f2fa39), -S(3b4fa983,26fbd82b,59a938f,1aa9d30e,2da395df,f8ed1aa3,c75f0969,b3b85712,57653c2a,8a11d192,4116c658,5b413feb,e8c56142,bda13d6a,175244c4,4b13a396), -S(5ea8db07,47f4f7a4,db0f9494,3dbf8b3b,9b04855f,93737d30,9c7ab27,8c2ba4cb,805b0db0,1d883e3b,a8f82de5,b6bc6c3e,3b05b3ed,4eb16d34,db8df937,19929403), -S(21386763,58a655e1,e878aa8,984bfe61,bbc7f1f,c16c1881,40e2cf21,63431d89,b62d321c,82082b74,4f8817d7,dc464804,c1d3e9ac,220dd1e6,a94f17d8,2250d06f), -S(934eaa8c,bbd3fad3,44cd1996,86b8a7c3,bb0ef384,4e085e55,83030bc2,bb52148f,4613cf3d,ef424be3,af392f4a,6fc474c8,3e3f2d1a,394431c6,5ee6e224,4396774e), -S(99a5472b,e9d06621,7e18be06,d9a1c1e6,a649a5e,61f3726c,87b21a31,7aac5f48,1e5a68d6,de4b2958,70cdd340,8b3d66c4,84eb4002,9d41c1a4,1d30bc97,beb14693), -S(3411cb09,5d5dcb10,49e8b927,5788779f,11516882,cc09ba6c,dac69bae,2c63362,6a3b3241,e6c3c802,dd5105dc,a1b82a8c,6bd31e57,aaaf505,fc41553b,2ac08b4e), -S(f7a6f695,824a413b,8a916cd3,c3403950,38ccc3ba,96803c71,6a498b7b,384d7fc1,7acb457d,3cda4738,bba35848,8bce971,d584ba79,e7432224,6619c0ef,9cff3ed1), -S(d4737f3e,6bce15f1,7ae3a133,bca08f13,434f25e6,8fd36a62,5672e6cf,983b1084,54a81a40,9f08a597,ba4e312d,f8789106,19189132,40f97ae6,b360d510,4a0b47b), -S(5b1e76c7,3f9c8353,b7f3c63f,ff2e48e2,d3bc05fa,857ebcc8,84e582cd,83845327,6024ce76,eaffe03f,951ca26c,a1550d96,f468385c,157d9a79,eb9a20fc,fe841e2f), -S(d201ad7a,72d692d9,e87a7a83,e865965b,48e90ae9,1481a927,34c90133,f725d589,310661e2,9fec5d37,96484ee1,bc6a6f76,e8da9e1c,f10fe672,6dfaf737,d78119d), -S(cd1f2c41,55b8119b,c5b9bc31,e5817a8a,b2268a8b,a526c005,1a3e23a7,abe8bef5,35b8f656,8b84d979,64b29050,77f01e9a,c2024236,29614688,df077aba,1b639048), -S(89c74b7c,e763801f,41ef6dcd,a452fc7f,a39f621b,39fa1061,a2b4bd4a,9649c9db,d5cc7a8e,722df783,82c168f1,91142df3,e15c161e,3a8471ef,236afa5f,a98a9f93), -S(ffcaa11f,317a856f,300df9be,1dce6c40,88bd5c28,b08861d3,87f3492a,d1004bed,ccaa2565,1ce602ba,72c899ad,f5f9be23,910ff5b5,1e3fb1b6,e2eb975b,c43c1492), -S(35903c6b,58659353,391a50b7,1a9c8186,a4dc7ede,f3455ee4,8ecc1470,263e1b8f,d44d9022,a5cfb61,4f56b02d,a83b67e1,4c3eeb78,caee0a4c,7f404471,77ae7ee0), -S(f9138261,2bc1de8,eb9d7062,80ef2b2,fa7fcd30,d157130c,784d7698,dcce5183,4709a971,d0008021,37a9ab87,27a705bf,cf1aacbc,822dab5a,d9334bd5,bcc5fd5e), -S(244ad0f3,26371ef6,f6c29f9b,7ef567ae,98a2abb0,cfa1561b,e9dc7f15,1e8833c7,53c1198c,5ddb33ac,37af979a,f40e321d,e87304d8,62efc794,2c944260,65de386b), -S(cbfeabdb,c93dee73,6f54f500,b33c2d0c,8c66b5af,68dde61f,c820ed3a,1ad2347a,f1416c9e,bc04c0a,792a1288,a20d0544,b7452aed,33f77b86,77b806e7,567914bb), -S(714246f7,3eabb0ac,af298c16,1bda9c3f,11f8fc8e,78b9616,2591242d,f0e870a3,94d8e600,cfe23c05,c9ec81e5,2c9e440a,af477c70,590f5470,31ece7f6,778edc56), -S(d776c80,63f8102e,805317ce,8e0b31dd,7b8b094d,6137c865,184ae51e,e07b924a,e66f3ab8,998ee226,f1259e4d,25d98d35,918b2cfa,abfe56,4a10c8fe,663101a1), -S(ef99b2bf,80bf084a,6483e319,9b4b578c,800eb85a,8634222a,197700c8,92a05310,94fc3ef1,12d050f7,e7d34ade,e89faf30,b651e10a,6931e4a7,ac2ecb48,fab90ba8), -S(c84a0ac1,8b659ffc,ac9e2dc7,57248e23,3d71fa98,90327e76,9441231,666f3790,e0973e42,73cd51dd,7233ca34,43dac778,3cd53c25,6816be1a,fbdd636f,936f7fdb), -S(b5572cfc,61db791c,d8b19da6,6fc11df6,e8776505,c016e6ed,96f17b97,c2edb89e,608ed024,b606b10c,5785811f,8c333fe4,95a726a2,ebe56680,b00b513c,aac4e0b8), -S(68447029,864934d5,92907821,5ec5ab99,3e00bd52,fe4994e,42978327,bf35a6f,31521acd,69c57644,ef35bfa8,cec803a2,e825c740,36a9a3e,fe831364,d00fd897), -S(fc9ee8ac,9fb265a3,7c26358f,8bff851b,d2a7aeba,2dc2a19b,153f649e,97d75605,cde1f563,b971ba67,dcf3d759,2752221a,babd8ab8,1d8a5a4f,3dda35ac,44c01d5), -S(7e86c9a0,d024eef7,91758bd6,899eee23,ff032336,9221f3f4,2b604ffb,33c473f1,2c15df40,6cad3479,841ffa5,14513883,978af93e,42aeba3e,c8ad64f8,df60da24), -S(e2b33d9a,8806ccd1,7d34a916,c4caa169,ffc9673c,e8eacde,19bbb286,85003732,5610c3fb,f0a6b39b,ec5c8cfa,db9296b5,86c6677d,61220ce2,b1d19bd5,9f44f72e), -S(ed6b2e3f,eca9b628,d98e663c,a3c72b0d,b853c8b7,a9cb9c4e,9247b8bf,84b2f3b3,6e45aa3d,f766a732,fe91f124,9148a96b,169e3b88,7dcf90ac,f972e91c,b25ae9cc), -S(78ed22a,c278758d,625e0439,3e273e7c,24acc72a,3975b497,ecad1314,df2de65,a2991712,373d669d,3afa81a5,c1e043fa,24df04e8,cc8fd13,32025186,f459913d), -S(3f3e7509,69153c5,378f64d5,7fce5aae,689f20a,8deb05ff,72077c72,b116996f,63d56b8b,92e77496,b86bd0ef,8bf803fa,f1d040d0,cd42c975,c7a08d7e,fd5056f2), -S(2540390,ca25189f,381b398e,3fd46acf,d5918215,a8bf9a17,d25179aa,fe75c1c,1c6f1725,5cac59d2,ebff7c4e,322694fe,96f5e2b7,e3927c9d,56134007,fc6dd9ec), -S(ed668903,3dee44be,80e9792b,b95408bb,5d38b016,d75490fe,2a22b118,56524fce,1a5c61f5,e738180c,cb533faf,ec9d3def,913ec31a,8c8463f3,df097f81,36375093), -S(a1a86dbc,2061e047,6ecbc303,2d25c159,414a6860,fcd818be,202a0f28,ef803224,ec9fbcb8,31f6720c,1735e505,276acd05,d957ea94,5b3af60b,6e1a2ccb,ede5b706), -S(c6064cdb,4feaaf24,89c35475,54279d3d,f1e96556,e97f1ec3,449fc747,ee8d0a2e,661f040f,ab90e5d,c9931a8b,297f2e61,9a24468e,432fb2b8,84acd0d,5cee7dea), -S(25b5f3a1,656c75ea,4ce2fc9c,bdbd2f36,78ef6e4a,9c2270a8,8b8dad5f,6f55fedf,8c48ac45,dbe199a6,5c9d72c8,7c1940c5,f17f59ca,d0c67211,5c2af898,7b142ec6), -S(b8e77df0,e23c94f,6f982ac4,37540690,441135f0,948f019,b79088d6,9eed91ce,3105acf2,23c01ac5,556b665b,d6b1919c,dde81dbf,7d44e18a,17bf67b2,833265af), -S(2a19c0de,d617ce9f,ff906686,a72bef9b,3ee2200b,ce71aa87,e18c2767,32421500,281d0c8d,dac57006,6c8d32f8,cafa5f54,404a6676,78ae9a0e,a0d19f1d,d0d24a6e), -S(5771b96e,c1a30ad8,d2087016,45df9b92,759c312,cc542ab9,126d3207,827e68df,ab4feadc,4b37a329,bf86e4,81786a0f,e1648794,689d0fed,183d7b48,fd53f760), -S(183fc4c8,62788f1c,7b7036d2,96bf7193,cdc93d6b,533b8c9b,ea28a9c2,9a5a9c10,2c019a73,5cca1086,e73948da,5d15f816,cbed1945,83014a64,24a586cf,501ff5e3), -S(31ebc0ae,656194c2,ee49f25e,28af673c,c65b2224,467ff0cc,920d3780,2dcfee7,d2db8690,89c5f10,b76d2d8f,cfd707d5,db7b3cfb,38903b6f,c4ebabde,47edd669), -S(a843fb7a,af70c96b,e7812f89,789b05c0,63824134,33476cbf,2a2b31cb,5a8d77fc,d0091386,435d082c,38fffaac,671129ab,f5e3461b,dc8295f9,9a064ee8,9371f70), -S(76c82448,6820236f,39701ac0,5290315d,a6f30e30,91d086e8,b3c934a7,871c038b,a4cc0e55,c2048935,c5c11b51,417950e9,dcd4ac6b,839b850e,efd2b890,17f5b4f7), -S(61653255,b4fecb8f,7fe9e6cc,179ded3f,955b359d,cf59cc70,1ee85750,b31a1d63,e197d8c5,d2571f03,931da039,b59989ad,390cac56,4982952b,a17e4d47,56f57582), -S(eaae448c,9a862f27,b55784b7,b3275e1,2d99d369,2aee475,dcf2d3ca,edd500d6,3cf4149b,351205e6,5ce2593a,282264aa,127953df,7da3cf9e,976af775,6be084af), -S(858c766b,faa67e75,672ed7a7,f0bf9b58,14217fca,bfa31b77,326d98a8,f6c7ec83,4d019482,93b2a3e1,d6f16dd8,8160efb,d15e29ae,e4c6b7f8,329127b1,7d0251f9), -S(cd384125,aa1dcc88,fc2c237f,2ff68117,c9517217,5b8c4f9b,a677ddf4,c2ac23a7,cdbbfc3f,d65180af,6a52f3e0,79f169a2,1dbaa8c6,bedcc4ff,be67635a,a1d51e1d), -S(5387bb96,b91fa67c,823e41ec,8dbece4e,cc1b6182,d50fe91f,44a02d74,90088659,bb7baeba,2b744ee6,8ff6ca19,64457de0,62a5e0a6,57edcac5,d6019bdf,caa25e01), -S(31ad9536,a6c16f44,c00189db,ecc8c527,304ab3b3,89bc7425,47fff91f,a088c01e,f48cae34,98357da9,5c47a41f,bb07055e,2061d037,35abe3df,8ff2fac0,cbcc246a), -S(18741256,6398f4b5,d2c34711,fa0e952,bf4de5a0,338bee49,a93daa3a,fdf29a47,5f96f31f,870511f1,a390a0bf,f9d9d383,2a7e3bb5,e8c515aa,f6022437,add8f159), -S(e1e5b96d,cdc60b81,19ca3138,9544c7b2,bfd587ce,6f42188f,115f4ac6,99e60793,cb5d9f4a,6475154c,7a285cdd,b0c115f1,765e357c,f51d8388,c03bf829,9a6720ea), -S(5184ca38,33208dd2,c04279f4,de77916c,fce7b4c2,1d45aadf,293842cd,56fdcd39,268d16e5,59d8488b,a076c82a,9587834e,87ccd65,c98feb69,9ae33005,299d2ec6), -S(d11c12e3,6646124d,c2602f0,b68543f7,e62ac955,8505f479,236ddc03,e9e6251,9d429bb2,d1378d9e,8e986f9f,a3d1349d,607df6b0,c48de566,d537c48e,10aecdd2), -S(d55753b4,93da41b8,f01da15d,ad5e71a3,655de4ae,b56a6fb5,9df058b5,f6636a9d,ee5270ac,db3d0e8d,6b46b948,9740311e,24925894,114d6c4c,52dbbe1,c4118013), -S(3f23ae1e,39238fbb,249606ef,d47502fb,30255e87,97148a90,5e3bf259,92429eae,845208cb,c6420538,410d5b2d,aaa28712,a2b77fdd,5241833f,124dd025,38d515f1), -S(837d504b,7f244155,1003c511,4e905b7,2bd9ea37,c690d9b7,381b2084,9cf7dbca,db355b5c,25d9b17,1167d31c,c5011a6e,2069863b,eb12164d,311e483a,21c2ff), -S(3d7e0c2,dab7f97,866a591b,f8187705,e31b7b3,bfea09c0,502b7a0e,c0037b5c,2a71d18d,f997d233,5a405ecb,d1ba09c8,8b282049,69215d7c,8a390435,8888a41b), -S(99f2faf7,8cdceb1a,70fb3076,3c19d54c,e16aba42,4e75be22,89f0e521,c73f3f23,778f4a0e,25c3844f,5aaa9082,cc985aef,dfe6e692,ab40eac2,9ddf668b,b28d0bee), -S(32dbf023,d57b27e0,5be2989,bbf1637a,7b3133e2,84d434f1,df8dcd56,70f9ec15,91d820ab,7a4f2350,49814592,ed2c46d9,fd7da87,a392b5e5,9dc309e8,ccb863ba), -S(2e413a5,b52d61f7,1290f182,9d24cb58,38339ebc,1b6d46f0,3c55334c,61ff64ce,474be10f,a3afedac,b9c6cee4,640424c,d7d3d6a1,437f2d0e,79e0b20a,8bdf2553), -S(955e7565,6052ab57,d05beac9,fc586758,780b8979,75642db,cd11fbaa,8e9deb7d,9276041f,cab762f9,929a6f54,a619e6aa,9613a794,96d32fe7,2e02ecfb,2a22045b), -S(1d6ec4e2,cc1a1dd3,f116845a,3173d350,c9607bd2,4e6db8e1,64220217,9208d805,2b6ff084,f5c42222,e29ab094,6f82b5b,f1cd6f3d,6d01a2ba,4d0744d7,ea95d0f0), -S(6ba994a7,9090acef,e756192f,91e97d07,82f393f1,c59f3b7a,786beee7,63ff0ec0,5c800150,c9464bb4,57190378,88247938,e26e54b8,93d25b7,6ef7ac83,78733f7f), -S(8b914ecd,2e19697e,83aa0196,70e1f955,530364fa,4f592638,b241a7a4,e07bd8ed,aafab68b,f3587e6d,8a078717,27e91eb8,4d327ad1,6fb89154,52a954af,e85f332e), -S(295e4ed6,380b91a2,a6628b5,820c11cf,ec407294,379b718a,5d4d88b4,3a2f9fd7,4e617c6f,b89074d9,818815e7,2a13d34e,58702106,f1470e80,ffce03d9,ddae9dd8), -S(efd76a5,217fca77,80aa7871,3dfb886a,f0b18e91,857ed243,2af704bd,87cb6187,e8f4d552,5e1e84fe,b89793f2,12a508d2,4b7ad2f2,903c38f0,d6729be1,6449cb1f), -S(44acefc8,e7148bbe,3c634bde,b8e4eb7b,618a135e,9c1b0ec3,6b160975,87284364,5eed55e8,8ba8ba5d,afc804a2,3cd5e1a,c161e4b,69d9bea9,da22b9f4,d130563b), -S(1e7d7ba1,475ff038,1fe4f0b9,71609d3b,d315d10e,329520f,3832418b,541b4174,887863ef,78a7ae20,acde554a,dd436aea,3f61ffc1,24023448,ac8f66fd,5e206869), -S(6fd945fd,d8043a74,c7c57341,a0581ea,c009ac76,1eef33de,277b7205,a7a248cb,6bb15fab,559c4d8f,32fae6f6,fb65c15a,222b022b,c8c57c06,b60f7b05,65f2760f), -S(34ccaf74,39ec22bb,2287400e,663350e0,1bfa2682,2fe851c2,faf4aae6,941bd5c7,91782420,76a254e1,a30b3ee0,29a19110,4af5fc0b,dbee533d,5c62a90d,2d9766dd), -S(554384e1,90581b4f,1bb6d971,9632e002,4476c913,30cdab94,5d8b86c0,491a8362,190ee656,95a73bcc,4faa6dd,9cd0113,ffae600f,fc13cdb8,14b2189,779aad2b), -S(75bc28dd,cf96c6d2,55981f0b,cf08df49,e48b162d,baa21046,89924a39,5db3386a,cd49b1f8,ead093ae,a554b9e4,d2fdcd18,ef614118,cf0baa2d,c83f2c37,92c23175), -S(4d094d69,15e92b69,b36d98d,8bc0e31e,ef6d49b5,d3d11b63,95bdd831,47cd679a,2aeb7bd9,98bb35ca,4554ed6c,91d92042,9945f775,8697684c,d0c63887,cb625264), -S(38b35099,7cde0af0,61ef1a3f,ab9e038e,988f670c,b06b39f,e611a5ed,227831ff,f0531e87,deba2ee2,117bb773,c933b780,71b2b8f1,956dcf8d,af99ee52,d69d67cd), -S(96bceef2,da234989,f4deec66,5a73ec91,6b284242,2a813a3d,f78c131f,4ba2165b,dc844f47,7ac5ea55,114aa18d,65950318,8b6592db,dfa62c75,d191e7d6,bbd70de7), -S(5badf11e,b896ab6e,f49de6bd,7b6adfef,840a0261,b173d89e,884bb453,5d7def8a,939707af,ad49890,2268485f,697d95b1,8082c75e,7b9d379f,4f7143d,27f830f), -S(ece21ae5,f5981e,e05869,fa9e581c,12773fa0,2b463515,55ded999,ce8acdd8,7771180b,9fc2d3f4,ce5d2ce0,a5e15c0f,4c29d135,62eee682,f80cbf26,fb812c9d), -S(650d7149,30417468,cb918e91,6234ff3b,1bd46f06,b90184cf,41d9112f,e472d26d,1f746358,4fd816de,89c86e9,39eab19,62a49305,775d8a86,6eb1ad35,edf48961), -S(f344bbd2,7ae90f73,b6f9a152,603dbcda,f14da6f8,f9ccdadd,88631de7,286b95a8,ae254238,b63ae9fb,89bc5be0,3e36a0bc,3bf15159,27094287,b9278988,b77a8ea), -S(982c94e3,a9dacddd,c1ae1394,cf93f8f4,91fa9261,ddd81e09,826b68e2,992c01f9,7527ad8b,39813588,6000a328,84b4f108,a4d6791e,2fbc86f0,b0038c40,ad280ea5), -S(b9885add,38946d2e,170d4bc2,361e44a2,859f2166,8577a099,f9d42c4a,170ff9db,edd69b3a,21836af3,a68c9e76,a7d62c47,3ee0042,3606ea6d,477126e3,b88f04e2), -S(4b34b984,4f57ae76,8bb666a2,b610b4f3,dc71b651,e23ae7ee,7eb2faa7,73a99e4b,4f4ea965,ccd9e929,b1d2830f,3bfe37bb,53be8f2a,a7c3a67f,9575d508,39cf2580), -S(ac8b24e5,9aa829ba,a7ebc7d1,4a25b14d,f770f0f1,158bd924,50b6e448,5af3bd7f,b25ad04,4954b659,8b8edcda,bc3b28d1,6b42a286,82602977,87c95360,ab2242a1), -S(88ed52a5,29858067,59b3ffe8,c1de8453,29d9c427,b7825931,57d8c927,43f1732c,d9dddf46,92f3d20f,7a99a3ca,a855a272,9143ceea,28c887fd,c054c6f,bfc25ba7), -S(f189d8af,9c34afb4,4dcfdbe7,996375ef,d8b9cac0,86230acd,e6972b19,1e1bba41,9a652729,1209b68f,722ff77e,38af6ff8,8595be0e,e1433afe,787716f4,8c69cc70), -S(6eb98d26,50dd58cd,8b7ee6e9,663585f5,77ccc3bd,3199d34e,2589b2f3,2deecd91,1c794824,bef31b44,b7497bd6,3966ca73,fea5ad7d,f640630c,37800e59,ac3d4afc), -S(75f5ea53,2e89dbfd,cbebd051,c129cfae,437e70e5,ae3a2d89,1b20588,94184ad6,faf379ae,6645548b,573142c6,8665eaee,882de32c,dfdc358,c778ccb2,dbca8107), -S(d62f599a,f29209ae,c7818548,f833ffcd,4d232d6,e297df96,4329d5a9,e7300c4c,61bbc3d3,79088b3d,ae30ad32,da25aa41,17b63b17,84bffd34,9cc7a5dd,9635e587), -S(2dd9167d,388f551,839fcda0,8c0b2f99,5bfb4fac,2f31dfdb,4cdf6822,72389b08,de646ee4,2a53c47f,11214ec7,cc46bb0,31ecd599,5d02935f,d49d9e0d,61c8bc4), -S(5e244f2c,87e222cd,70d4c4db,4020593f,ede6e3eb,fadb2d7,c260a12e,61349323,336b3413,ed5f1f7,f82db066,439e329c,323b5e68,26bd57a1,1038ffd3,2b236d0e), -S(9ceb7373,d13b017,1d1dabb8,4d22a756,52ee75ce,5943238,6784f06,4fa9dc80,80bf893,e4162d17,c7792fd7,d89e283b,7a6f3e88,fbccf0ec,251f09bd,93e46714), -S(aa4de7b3,6d1990f,5b2f2afa,4fa71caf,bb852321,dac68f81,c65cb997,306bf020,6cc882d6,577e5958,8d5a2a8e,ac18f0da,f29cdb84,bb1f6ec7,19b53600,4621196b), -S(dc1db767,2e425cb7,b1dd376f,37bda82c,6fcd98d7,c9dd1831,5368c4f,2e95f5f3,fdcdbdb1,926c987,81c0944e,bd13f28d,97fb9a79,2b7d4b96,8be1cc0e,a1c20b75), -S(3ef39100,83392f75,8a78325a,44dfdf2e,5083d8cb,396d2b0f,1e4fd37c,47cf799a,f057ff96,da3779fa,f9c66fa8,cc59801,44ed2dda,561370f,4c3e1800,d0dabbdc), -S(681c2240,fffaf870,ff80b853,ee1aed59,c2c6d435,d0319354,7c4ef991,1e2e4a8a,16eb0138,56342438,57d3af9,12403c06,6cc48eca,92fb6614,b839e46f,8b939450), -S(8d013629,1912293d,c39537c8,3ebfe514,3e831e69,c844a076,c227926d,e5f9a774,b422e532,e989ac8f,1369c95a,63bde2c,20f02ead,254699d6,bf3d4a76,375c08bf), -S(bdd10d52,da3d9deb,e664ad2d,e020391,665f32bd,7b236e02,adb6ad1d,7dfccece,201ee4d9,76d70c3e,cc06784c,a33b84bf,ebdaedaa,1df478f6,70128198,f1b8f66c), -S(2d34aeca,2ee9102c,bad92b30,2802386d,6e7af432,8aaeaeb3,939e3435,98715d2d,2c372a9a,4a4f0daf,a32acf6f,a40acacf,be6c668c,1306b93e,b27fb43a,a82e0083), -S(717776bd,d8c65a1,62ebb2f1,cea29ecd,9a843d5b,92f91278,3cf4c819,b26158cc,bec109f1,29997d51,e032f8f1,f453e222,4e2466ca,ae89fbd0,37a119ee,45588f), -S(a03bfc10,6f13c570,be92a85c,f72cde29,caa157cb,8b434ed5,c958f2dd,3c69ae09,8d76f55a,959eea82,c18d7328,2d5fa91d,d747fa13,67e64b0d,3d0b0a94,e58ee0e4), -S(b3516031,30e3198e,4a158cb0,108c8187,88c59939,bc813423,3bc51ca0,314832d4,3a5a4dcd,9fe0c5dc,bc17a082,396a93f8,36182c7e,2e26670f,d64ac6e5,8f022c27), -S(a927baa6,f7cf01fe,1993e1ad,c435edd,c806af66,6c9d2168,44a86bb2,2d7a8951,489734bb,4fe191bf,4535c812,a0e2d3f0,fd8020f2,ddeabbfe,c740fafa,7ccfb468), -S(54df921b,5848a4da,22c4dc63,c46876d9,53368446,e6106389,55ff00ee,61d75a13,25de0b92,52968196,18d606f5,d2c54e7b,fa6c1980,bdacd4a7,54a9b2b0,4015d8fa), -S(5822acdf,704948e3,c9112d0e,e718bcda,98eef3e,bb927d14,a1fe1952,1d64361a,c8bcb245,d5aa9e2e,7d527508,38db01b4,e2487197,a3ba351a,f2fb4b3c,19d03895), -S(a58c52f1,ca6983bb,cf2e8bfe,592b8d9c,b2a78dbc,e1f77931,14c95253,6a2d65c9,43626050,9c114db4,eae66452,599b145b,4d16b14c,cf7ce807,9a9c531b,7f3cc46b), -S(2db642ec,2bd88fed,7e624eca,e8022f7e,453cbfe1,1a6b00ff,726be4d6,89a72418,e3e73ef3,403e341e,e032ee00,e99b1f26,e710571d,81ac93f2,5855a8f7,32265440), -S(45b76e7f,65d895ec,24756195,187a4612,7dc9b31c,5e3e5376,e3af20de,b7e69a8,b2997f75,7cafe61e,f8a67043,a624e55,c10dc237,2f4b9d60,9692b269,7c616fac), -S(accc62eb,bee83904,c01a32db,e4af9b0b,50f3064c,bafee18e,eb49bcba,d53a41d3,34054eed,c77ef0d5,e865ea30,f505ba8a,ffc94474,5722651d,294a2520,fb7f4f0a), -S(1de2f5de,b1658f6b,6d20878b,9adb8a4f,6535965d,63bee989,fe23e4ed,a77f07e6,96762a16,fcb2aae6,ddce8f55,39c57f57,fbb45d09,26738e6f,82085d3c,ff0f20de), -S(5c51b67b,d4c0df54,ce75b09a,c399c293,4fd7a991,607a0aa4,a0f6629c,645f57a5,d1082c6f,66cd1aba,86df3edc,39b2e579,6e6975c8,ca018310,385173e8,5878914c), -S(8d7421b3,af8ad663,e7155f89,25bc9246,af7b3bd9,3c6a1097,afadf84f,7b041434,bdfa5121,e17dff19,6c105c34,b9d0bb18,8514a9ba,7dfee6c4,45c7855d,556409f5), -S(5608f4f9,f6d1a0de,64f22794,7fbdaefb,24b797e9,1f6db6ce,f3986d65,f0d4836c,1e03f309,f4c0f432,eae951f8,6e876f24,35364778,2249c36f,cd7115b7,8248a1d1), -S(24fced9f,ec868343,e6d6482a,1017853f,6687da3f,cc8e19d5,240a0991,6fa61791,8884a7a5,c742149f,88af0fdb,7cd59bfb,d318d8d7,60015afa,6bf0474d,eca7c214), -S(d9f8bde9,8bb83348,33783e9c,5d8ce8a7,85b9e335,6921bebf,281c97d7,bd000fe8,59d46892,a3d604fc,a378aad4,9645c747,2ecfae56,8b362e15,c0acb755,af7103c), -S(617f21e3,af5d65a3,a504fe95,34ce6bcf,71384bda,272ca49a,1c36ea32,d367c4d6,daf8e0b0,4bed8f7c,2d8ae9b6,afed54c0,904c6010,9d0c07ad,5f57178d,2cc037b3), -S(e1bbf189,83052820,ae65ac4f,e5a6d4ee,5b57c3b4,c0b2cc06,9f84b25,adccfdfb,3cd52ced,d7f04a93,86f4845c,49af86e2,c3a86984,fc4c77f1,3200017,ea68deb6), -S(83f82dc,7c709587,b883f1c9,e6cece13,2cd510bf,3664aa79,220892e5,dc2dc8c0,24c2a1f4,7c4b96f2,86265605,d9348dcf,8261737,56c5d91e,2d1beb4a,a857525c), -S(5ccbc6ff,c4362b4e,3d3a72a0,76ecdde1,1c1b07f2,680ac16d,63cca8ed,df924085,d54095ae,f357dbd9,5c12ad03,78f428c4,beaf44eb,23724fb6,cd0726cd,e1f04fb7), -S(c83a798d,c8b1ff5e,41ce6563,f35e741c,a6020a80,319b5543,1f81726,818307b6,c9cbf8a4,747baee8,2e156cf0,4b0d7762,2638e8da,7731f4ff,60bb9ad5,62b7588f), -S(c15d6466,c7f0bfb9,ab8a0013,300dc6a0,aad45c60,c2fcfbf6,7c9ca24d,7d2a21dd,cd5682ea,b41b707d,9b787315,8b4e347a,7ae682a3,cb950e1d,abad3b0,c8c42bbf), -S(e9606086,63b9bbe4,35826c1f,3830dfb9,f8479216,5c57f28b,9fd28d5,7a277a0,37fb1f6a,6d3cee79,ee2eca6d,c499fcb9,e2896942,f17fe885,25d2d57b,11c8a198), -S(f8a3fb79,afc8a94d,d69998a0,f4889dec,200b4b72,d2900c75,59371ee4,412df0d5,d5e0f5db,b4281cb2,ce21fb09,9176362,90351fdd,5961db25,ab677dcf,d4fbc0cc), -S(17f3cc7c,64540e31,ac6db6b4,ae67d100,46b7665,450cc011,dbb558a8,56a59b2e,9d815416,553ba751,79955382,12e988d0,eb0e0493,f880c217,5b90f423,5763b624), -S(6656be68,bf528239,51d7a392,ef22b258,42fb0646,8908fa1e,fd91d89e,a54f6150,741d5373,7da163c5,3e160d5c,b3f9f118,273c59af,75aec2da,bf788e8e,e870cb69), -S(67ec8648,83ad9ca4,22fb181a,2235ee66,cdb74f0b,f8e5b808,c37ee314,35598cf0,8da1ae29,4f37153c,1ad165b4,474a8f91,e7bdae4b,54b227c6,57e2d3ab,f3bf3fb9), -S(c9e8a673,3680fd41,83005ad6,97c78a4f,abd5d048,1f9bcaa,7c8eb209,68240412,fbad52cc,a0e510d5,e5c813d8,13ba4559,716e0787,4f48c20a,f783a807,c1848eae), -S(dc11b6a8,9c6b324a,f2d67e4e,9f59f32f,8898dbdb,d612f157,e0f24cee,d2709dc9,8c20a8a3,c273c882,fc6a59cf,ce74f115,1d0421d4,bc84a11f,2def142c,f2a8b080), -S(c5ec365f,7c0aa7e1,94fb5a90,ccf8fe3b,3c90e413,f3b24947,d8246024,7a2cc2d1,c5b39d08,b23bb1a9,c5886e51,abd1fb2f,d55ff334,81f020d0,6796d978,8801de79), -S(fcc03866,bfbe3215,9cffee9e,bd6874bf,10a5055a,5e56826b,37322559,5381650c,99cd7d3e,66e65f1e,5eea297b,f957c699,b844cc35,cd19dcdb,2d3a5653,f45b59e4), -S(7c96526,7ade46e5,693ecf09,cb052ae8,2a4bbcac,d07f136d,86df45c5,bf20521,db8e1dd7,3c961137,23325d6b,fb728dc8,f0a85141,ad1a00f9,53100aa1,5519d444), -S(39d11c0b,2169d3fe,4b5001b5,a8da1fe3,a7b14ae4,e329b931,f7db92d,86acd02b,46fe1f3,65805c5c,3b731dcc,d46ad37,1c2fb6f3,b446e466,ab80aaa2,5200302e), -S(3acaa37c,4acb28b5,6af7f970,ce279372,d2b998e8,5ef20932,492ba5b1,7b79240d,6effcb72,4a7c7dd8,b8bea6ca,322a8540,f38cc5df,a06677c,181c45d8,c4e4a4f2), -S(fb631a1e,25daa546,47492d26,fafddec,6f38c08e,e67e67d,af1c57f3,ac3ac79d,90b04e04,c685e4bd,4817c367,22892881,fbec8c09,1e5aaaa9,7fd6a163,b68f2eac), -S(3edc2ef,2c609f0a,c77ec4c8,c035a537,3d4ec7e9,6addfd7e,87f040d2,df98aaea,7e549063,ba715cd6,35719b86,c0b6eb30,68a71420,7f480f93,6d78f0a8,d9251d20), -S(bd4f2218,7a9f5164,a864dce0,2bd1a89f,d283e62,64255b0b,21d2f6f2,62fc419b,d5eb78a9,d2337e68,3e3a77ae,b37b170e,69f1400a,2383b339,64dc6726,7c5db5e1), -S(434d9881,70badfd9,5ab26ab,90933eb8,89bc6a88,60e6f412,1e5dee2a,f82341e8,c6af879,cbd7d5dd,16c3b06c,810d0263,2853986c,ffb11fd3,aa2be2ad,db55c4e1), -S(9633c8b0,653d8010,e785ecb3,d710b43c,37ddd97b,20f26c4,f9f41581,cdbd991c,13b53adf,b4841e2a,2590609b,46b604aa,3bd6e758,4d443db1,6a7ada9f,9a49fb71), -S(ba656a98,c63d18f0,c4aff8da,3bf05cf3,e3781cbe,db5d9083,a8828fa0,c2fbabfb,90ad3738,f28fa937,cd4149d7,90f8b4a6,d4989c5,5218023f,37742c3f,1814896d), -S(cca5c935,ad4a690d,893b3bb9,cdaf2e6,102c44da,d9446615,2a39206d,777ca72,3c060ba8,b14da1ad,41991c64,95e14465,9361c724,d895a0d3,a3694d45,56c7a146), -S(b22a22de,c827e8a6,dc630b1f,11229bf7,ce8a5030,608392e9,b03093cf,47afb358,b10c49a1,4b30449c,200bca1c,4a0f3df6,7d978988,1be46597,c1e5334d,5b5a2e4e), -S(b4253d47,beae6a36,1dc45090,c358275f,fb8e0696,11e51b3a,1aa7c2f5,273ef8f8,c0f4bbbd,e98d0960,f9a59809,83d8c4d1,35eff1c9,2ddc9f2a,6ee05146,eadec66b), -S(60d75d74,1a85d65,b9edd2de,8a03f6a5,5ac6d000,d39ca913,9fdbcc47,fc3da6e0,fb138bcc,da55de59,d496b784,9532d99f,44935e6c,b08be8dc,beefbb7d,74e1fe7f), -S(ec63d10,e66db9a3,7cb5b88d,811f2f6e,aecf51a9,e39374ae,92df325a,aa560a85,1066615c,d2fe8397,d2dd458a,f6ff36fb,60547398,29e6d6bc,74525c29,8c3d3c53), -S(8df7f52c,8324b50c,fac3e27f,6f230e9e,e4926895,c8f2785f,560ba5ca,98b9feb9,6832846c,a78a18ad,3747b1fb,d8cb6a94,fb3b4977,3db3c0b0,c873507e,f1519480), -S(f17e21f8,e97bce5c,2e63285a,f9e361c9,4a2e6b45,f437c1c1,a1310988,b63ea49f,12690d42,bb90b05,2fa4b1d7,d517f7bd,f6721a82,e0a9059d,caa5ed15,a7acf7b0), -S(4b0e0297,729ceb7c,4c6a4caa,73d76ee5,9d8f8547,9f582fa8,ec678339,58c023af,73f6affd,3afe58da,5ba3e0c0,9a043e8d,100f1275,dd9b9dfd,42ef4f47,a1aae067), -S(203174f8,fe8427ab,42bb517e,67e9c13a,3a39700a,158c3581,a0c5bf76,79f950a6,ac630f01,6b268772,72e422cf,b74a3a1e,dd1f581d,bcf2a1a0,54946a15,108c70bb), -S(ac34d445,cfa711d3,fa7a8c5c,bff5206d,d6dbd22e,737c5b21,6e6801ca,362c4b35,91a0a6aa,fbeeda5c,abeefb76,f1bd4b23,e850e1a3,9886344b,282dd0a7,f0b6985c), -S(81ffda88,a45f8b82,e3e249a7,457fd1bb,34ebd35,58619855,6ff7ecce,73dc7998,eeeb1a42,125877fb,640b160e,4930ba7,3f1e22cb,51e33946,3935787b,5d6e353b), -S(1a281d34,5b4f227f,2a6d4139,db2e29a5,7493b1e7,f099edca,ef68b3d7,dde37dc6,63baaccb,8a5c1de9,f1aa33bd,2fc19189,619a71e3,f9b290c,83fe7643,bcbfcd25), -S(ed9042d9,ad110ff0,6be64aa4,cae0422e,c9a8aa79,4dddc1fc,52df6098,8de1ffe3,9ede1c43,5d6b8a7f,61591d37,e166485,3071c894,f18f85d3,d8f145ce,98208b95), -S(1f5b14e6,1453557e,f3ccc7a0,1e2864ef,43dac2c1,ce737ba3,ffefdf2a,3de9622a,c0d40622,5a4f8b24,59ae2d22,69908c81,5f901125,1e46a683,3df83659,f2a474e4), -S(218e8943,96fa8e79,2f29b53a,de2f9155,94d95a50,1eb1a1a7,c8b01b32,75e8c117,2701de34,af2aa192,79dfc9fb,391532e7,56824da0,38c60624,3771dfe5,aeabbb96), -S(d6ec122d,463c0f2d,a994bc46,a968693b,f282ad19,6a6471f7,6516b5d9,2fea7303,57f84e4e,9d439701,19f58c6d,426265c1,25734ed7,c10db0e8,e5b87ebd,d584981e), -S(3ffb48a5,58fd6f85,b1609710,1be54107,6182a7f5,a5692074,48d82dd3,e8027e40,aa410f17,7c08cf25,a7a9e9eb,33f2b83f,c83989fe,7a737e23,e0aec6a,6eae2ca5), -S(c8c69bfa,450cbd11,6dd51750,a5fb2f0b,59b4f489,cf05c670,91a49f13,3963a50b,879d8a2f,a1c26933,5719a389,d504ebb5,498318c7,acf103ee,348d27e,cf83886e), -S(86097033,ad0a0d7a,982e748c,bce06089,2c6b55a0,17bbcdc9,d26166cd,b0fc1e81,9fcdd6e5,17916ee5,ffa48a50,a0df8ff,98a06,82059d92,43a2194f,fc89dec6), -S(37cd256b,7502a789,10296144,bd41ade8,f4a158e7,68b6ed2,723d3e57,cc5bd099,5eef9bfa,6e5e1bab,8d8170c6,2ad90725,afc38eb0,db145f59,35520a7b,7518dff6), -S(70aede0e,f89ea93b,702fd3b9,4f81a48e,aa36cfbf,f4775426,37b0d00a,80abede8,b30aab37,206b8c1c,2f852ed8,348cd387,d676f6e1,2baf457b,97fc49d6,91490f33), -S(2504fac6,acad5f23,81cdfa76,65fd1859,85e3b32d,d1767394,85d63f07,500c963e,7a455f78,9cfdc25f,d6ef9c01,8e44e6cd,2702ee9b,fbbad8a6,7ee228f3,fbc56d61), -S(b8bab480,d143bcd1,838f7f2,d13b7a54,8f7302a6,14c03cf1,3e4fa971,5478c280,8d1939f3,abd45a47,686be62b,7c079fe1,2cd2a3d6,78478afb,d21327e1,3599611b), -S(19370ea2,2e6937c8,b7d600e8,cfee9b54,e1b527d0,85d3a17b,ea2daf7f,2e6a410,c721f3ea,af20344f,98692ae1,b88c7ce1,8655a4a5,9c2c945b,aeab2756,a5ea546), -S(5e19f6c5,10bb512a,798fe39b,cb37ea2c,da70c76e,d7d1c828,9b488e9b,84ea224,ab34bc16,50a99345,772aabb7,f47f0b2,f92fdfdc,4ce7c9b4,f5bc14f,5b946b39), -S(e97888a,cd62f21e,76f5247e,fe64291c,e69b8b1c,b331a2c8,292bca63,f3dde54e,286dded8,ec435a9,2155fc1f,18688e5,e69ae21d,eff79a6d,c534e18c,3e7b114a), -S(4361dc3f,9c039f2f,750e4172,88ba8d7,36158f28,d5e0869d,44207ef,f587a8d,b05b54bd,2097d8dc,c7ded5ea,ac07e6ac,a7974500,8337891f,4b5d6c71,672cf759), -S(8e679eec,8bf365e,e5324330,3437dccb,768a3955,3c3135fd,3c168109,5ecacce4,b6dd115c,d19ecde8,4e7a2fae,be358448,3d6277d1,19ca2aa8,3bb68ae7,f5e94f49), -S(e2d80539,947ebd32,8716ce6c,74e5f09d,eabcf539,2e84dfd1,2e33219f,de8b77ec,d4515668,586e8753,74406b32,65c9727f,92e71263,b0f77447,14de6f0e,732fd175), -S(a2527f0,c754ac94,29bb5dc6,18efc820,d88c8490,df39cf13,a25b0136,37196f9d,bd16d989,90676eb4,36e735df,94a5a5d2,28aa4185,24766ae3,2c7bb12a,e9aa0508), -S(bfa67870,6db9cf88,139ce56c,4f5165c8,38a5830,d1673a9e,b4b0a218,a3a66319,f6eb6944,dd30d6af,a360a7cd,b360f58a,c17dbe8a,7eaeda38,f3b1eb2d,83c02e0c), -S(1d5bf7c9,9255f96d,b91a0f5d,82a3119d,f3d491b6,859f55c5,59389e90,a2f533e0,132b1468,f460932d,7e0ec514,8ba77405,8b8cd4d,3e47acac,e52ec9fa,618139db), -S(44f90837,9b8aba17,44415980,aec15cfb,4edbbe4a,23ce6885,9e4ba880,8a67025e,9c4f9d97,6f1581ac,29818a6c,58c70ad9,ebb08f3e,83dc1b3f,667528bc,3a1968c8), -S(f100be57,1d4ddee5,291e7123,cab57bd5,c5ecb8ca,6c8a90c4,d2f01f73,87b175f,8899a16e,3a7ad5ff,f0e3aba5,fea86e1,974dac4,d736be38,6c2ad93,8020a6dc), -S(e26927c2,f3cce898,33a60369,2513aec4,ad0d8f63,2bdceafa,e5f6900c,716be2bc,c1154830,52dc4674,238758c7,d7af495a,f32a4d01,e0c316ad,301606b8,d3136383), -S(e3a3fcc9,8fcf1ce8,fb994b68,f92b2fc3,c114f2cf,321e89a,c3ba7886,43b0f2f5,214f38cb,7020f57,ca4bd953,16960c9a,250feb38,7519bfa4,abe025aa,dddd072e), -S(59ec03fc,5195e0d4,a8df03b6,a96938bb,d5fa5a40,161f5ce,2480e205,dfc0dc3e,71421a9c,b58aa65e,180c97e7,6a90454e,d5d8a2f7,739eeb09,be7fdd80,47a4ecb8), -S(a53cb7d9,3dadccdf,18d4d01c,6217f39a,be621089,821aa92,362db85e,71cfa358,1f989a47,77a2837b,f797c249,4539069c,a24a23aa,8f1e5b35,fc401dec,69d049c0), -S(170b9efa,13e1c948,a5ea39ac,e688408c,1cb2a57a,a55aee52,e4fb21ff,2f7329cd,f092c60d,c4f8492f,d718aa74,fded9cea,426b4,7277d724,710ac0d,53ba7039), -S(e1d16c75,893035c0,63eb41c8,36bb8bcb,770f752b,718a02ad,24e688da,79ac3a14,2d58df,7b7bf0f1,60a091f1,b0b209bd,ce5516d4,53f8b799,5707721c,66ed2681), -S(d45a1024,78595ac1,abd9a582,a3afdd8c,5d33c7d4,caedef2c,747450a0,fd2d675c,8faa7ee4,3923474,12012dc8,cca109b3,dd19efc,52ae73b7,508b23e7,1826732), -S(d3f355bb,b2ecfa66,592ef13e,fe983e22,b2b90538,ee2f0aab,ee1fe982,62c336cd,ee99b839,7d4b97cf,a7851de9,366d24d3,70169091,81b5a10a,50fd53ef,bf549812), -S(6ea90fb4,e58f1eb6,f27dfba2,acd645b1,1c7cdb0c,dabf2d49,4fdbb4f0,8ced2c56,74934a84,871dc011,3e18d5a0,aa3207a5,e588a3cb,e8a3f350,4a06bb73,8ef93abd), -S(de4eff0a,ccb612a9,a79d0983,94e8a883,da348aad,74bbbea7,d477e45,c2b87436,9b30581f,b903cfe7,610429f9,f6ec1ba0,df63038d,db8117ae,ec67d7e4,1a28b9b), -S(4ba09b19,f129b3f8,db86d780,4630c6fd,9c22d620,677c66db,ce60b69c,c3bb4772,fb31e85,ce50ea1c,13af1c7e,93d9026c,e5f39474,9e91d049,1b459970,c169aa77), -S(7fb3c3ee,7c600ca7,6a2bc674,a497bfd6,67b0124c,f532d5e8,55aa2c90,c4b4826b,29b970bc,b8f5eaa1,616f3695,5a1b17c6,60b15b1,219388a6,b47a55fe,6cad1eb0), -S(ac29cbb5,dd2a95ea,5a3b6f57,8c2111a7,6bf2b060,267b467d,5ee8ed2e,554153dc,89d4c22e,acee2b3e,7e7872d6,5d1daa52,54a1a00a,f6b0f7ee,16d84477,45d01c81), -S(fe956021,e67458aa,c6fe2cea,730f272b,19fe7de9,18c98a40,ba475dca,af3142ad,52c6b42d,6fc03eaa,3ec7da94,5ed12ea3,84e16d0,590840df,6b714a59,d4bb814b), -S(336491e1,dc3fd4,8d63944b,2578a415,5727daa9,6e853935,a77b7077,d61984da,e9b8db61,51fe90fc,9bfc0635,5b9676f2,cecd1321,292d2a8,c6e30e9e,6b1478c6), -S(245c6818,aab65e40,806f8cb7,721b7dd8,b0e3854b,7daeff8b,da5827b6,4d294df1,4fc22df2,e7b93b96,b60f2ce1,a659c1ab,1a06c7be,18e5c80c,91e4dd2d,75bd8ec), -S(8c89eac1,d9ca6c06,8229986d,6d22bc3c,817dbb6c,575ff654,36653101,1a60de8d,ebcd4867,323bcc7,f8dba216,4d827a48,8b4763cd,aef0daf2,5a1c1437,d6379ce5), -S(afdaa93d,7ea7f666,e737a379,914d1b87,6899cd9d,5202e985,e365d75b,806453aa,e3e9116e,8abf33b7,ad036291,2a3dd016,2aadd1ac,902a9448,30248a60,6760cdac), -S(d447b974,fcecfa15,1fcf7ed9,8762283,7ae28f74,be8a2a2e,22c3bbf1,d9b23071,a3e79560,f79524a2,e206e9b4,1cf961c6,8f6f898d,43694114,a3f89495,6ecf970d), -S(53525693,be8fe724,c970f4c4,2b46141b,321e79a,4ffa411a,5d947bee,ac235674,5cc74ddd,7a74afe,2026885,1fe180c8,dac3246f,8c4ba44,2032d584,8afa9f4c), -S(40e60cea,6008aaf9,fee64781,b5adeb9b,f23d2db5,94f9fad,b7394481,da971273,fa32f2db,263c1f7c,987671f5,68c714dc,9d3ecca1,2b20655,2b23e5cf,8a365b65), -S(de59a6fe,1fff672a,c4655e87,f6440e4c,bfec2fc9,135f1049,efe173fd,d666acaf,205e5ac0,8cb9c3f9,9023b6d6,795488e0,61ea691,439a22f6,48bf0da7,cccccde3), -S(89f718d0,23f80ba,df0625ea,260f6ca6,dcf8fcf6,e79d35ec,67e535b5,e9cd06a8,6acf9bad,6dcc053c,f7e193d1,a4c432f5,32211761,aeffbb4d,1d53d737,6b3353a3), -S(fcd5af97,603e0558,76f24ab2,eb82de83,3c8cae9a,f19ed307,f7da1da3,f1fdac3c,3b7ea3fe,bda44592,abe9240b,8b06cea4,3a8a0ab8,aa862c85,36a17b18,fc911ab2), -S(208419aa,670256d7,94712f59,bedfe025,ad9ab43b,2037783,4e4c8f4e,9473d6af,b6171d6a,20da4ffe,f46a49ae,7233206f,d9ce1ebf,89ba01ed,9b86896e,43c9fac7), -S(d7ca0446,88d411ca,c3f3acf8,1bc3f3e0,a9feb9ef,94bf31d7,8a15563,cdfaece,3a361b1b,2ab89d27,6e120d38,7c31f97f,c4d5880c,6ace1813,b4eb95fc,37db069e), -S(30b96bd4,b284e36a,f790695a,e2c8aac7,672a0496,2f9c92f9,694780d3,92b60bc0,6e2c7f8e,d1e0d081,a34ea062,591e1854,6f79a9c,60daf218,6513e4e2,621d4852), -S(5ca0493c,3d516b44,46723477,fe8359d5,6a2e01b7,28afdca1,343de88e,92411590,60bd34f8,7d4bc12d,4179da44,3595b48c,17f34f19,b03750a4,6904a242,93af0e93), -S(de3486eb,22faa1c9,ccf774f0,e17da3ef,3ab5f7a5,ed6ba58e,bfaa2c1f,cb5c0e58,af8666d7,57c13f3d,3c2e6b02,1dad5ee1,ee4f4c82,97960b5e,84135309,4188936d), -S(8075138d,59a9cee9,5320cf41,cfad010d,90efff9b,ad50f2d,dd3ac7d9,234b4576,ea48ad8a,6a8ab6d3,5cea84ea,365b6a33,d3d593ca,9d27c5be,2df2907f,8bc5d91c), -S(5328a0d7,17f0c7d7,9b8838a,abcb0875,77eba66,eeac756a,6a365657,d4d710ab,7f33d5ca,84206a66,a9aba1,2dad6805,9aede27e,2b38d755,53756d14,9b4b5a1), -S(9fecd234,d25771f0,aee9dfa3,2286697b,faf4d34f,83eb7135,a581b225,791ce0e5,3e364215,d2eec5a3,632f01f9,9699255b,e90303c8,eeb0e8b7,56cc239,20b2dae0), -S(7084b279,e89d0f23,967a1635,96a1090c,4264504b,c2895b07,fae5f128,93150c02,481d6078,35628b54,783484e4,d4f299cc,fa3e6f5,bad67457,1037797f,b3fb7f96), -S(bbd3583e,8b7ce417,88cc23e4,eb0c331d,c8970d1b,7b186ee8,9b4cf45,c83686e5,f94d7cd4,392a9589,77ab3956,a91024fb,b77a608e,91147a6b,4be6cafa,69b9193c)}, -{S(a707efc4,89165c75,7edcea3c,ce729b44,91f04142,3fc6ea9a,704f52df,c8a0650,f2e7657c,6c618494,c01c5a90,d06b625b,c9416d63,f7b8f809,dda5076f,74fa2c92), -S(8282d8a0,cb008916,33654a11,fbfe16e,8d2dae0f,ca06175a,5183ebd,de06ec8f,44128945,d39e1b71,cbc914a6,21c95329,b6ac0b45,1f1921f9,725ff10a,2859af90), -S(100ee34d,993a06d0,cdcfeab6,3eadde22,7be8aa84,a9458fee,61448911,1bffe20c,c891d347,c63acb,c72a2a8f,c0d8d41c,2c32a9eb,5742ab35,e76b573b,3817b9ae), -S(9bed0413,465a899f,37770b6d,6e847223,28049001,73efb872,aacf122d,4eb12f1f,745eb015,938e3ce6,d38068f8,90ad253a,b0b1bde2,de636162,c0442b66,6e9e1e61), -S(2896ee21,34276bc0,131a10aa,5b0c9b39,ab5aca5a,3ceed61,cf2d27a7,5404d264,cc51d26e,ad555071,e57bf3e2,dafd77db,4f58b6ee,b844ea86,5da39b09,ef3ecc6f), -S(b95886c6,e569d641,b8e32555,bbaa562e,1f07589c,5a8f3810,d4bfeb4f,e58711f1,3fe1536d,551770a4,cd816eb6,46f2b864,77d565ff,3091d916,af8597e2,d8988b6c), -S(b32e3e0a,3ca6518b,6bdb2a9a,e3471248,5387cc5c,ffa32cca,976be3d7,ebdbf1a1,45d998f2,828248fb,2f97b503,8de02b38,493f5b62,ab8b0d7e,75cb96f3,305680f4), -S(8a760935,8c3682b2,fe8f5b8e,a9c76c61,f66ae677,48294bed,9d3c64d,702d3c47,77110a33,eb7562e7,95032a0f,5027d162,28131575,323c8f9,8aa0bcd0,9328992e), -S(ef709552,f80148fa,dc1f7007,174bfd85,81b03db8,189ca3da,96b3e749,b1843ed2,b8e9393e,c3cba6ac,2cdd2d04,6235f7cf,14965616,3722225b,9010727d,94b610eb), -S(5071af8d,2e37c4d8,11225f8c,543863f2,3d5ddfff,be2576ca,42630f38,1b967483,37248038,487113f2,74ad07fa,7dee36bd,295971d7,3a30cc58,629dfc68,cf65533e), -S(88c9a5f0,e76871dd,3afc4ef4,5643419,95642dd5,c8b1e386,b71c2471,c591a3a4,a77afc95,71af8ce7,60148b15,1e1fcdbe,c48d3b2e,580b9786,9d80196,2ce6549b), -S(fe643b36,a0ef4165,e591345b,5963d37,632c8fb8,97114b60,c4ba6f6d,c07f9033,e3c7bc7b,865c1d,4c496f36,9a79e6f7,1f79f6,e6929f26,63615855,e9509ef4), -S(d35bb10a,a23d2bc4,d2aecca7,51f1cb24,2133fc16,9f008ce3,4a29b93c,7ad21f3c,57265f67,dec367a,7addd6c3,fb23fde,f04f42f9,a291e291,3f2128cf,df041f07), -S(e3c8d76d,1ff5e0c0,21668bb8,f425487f,b7bd3a3c,eb3df289,5e4806b4,177fedcc,abbca449,95abb588,3e0a6959,6c8108c4,ddf8a50f,6c43e507,59f85556,be49efc4), -S(b7e31e11,cebd568f,658eadf7,ac57f265,fc94073c,9a779f21,5016e5fd,705f2580,da4dc770,742cc6e7,38d05ecc,6deca283,9c06125f,bb911cb6,16f0fedc,84dc2815), -S(bc486422,ae3e277a,d24fe096,120decbc,4a735e57,8bdd72a4,b3f9006a,859276d5,ac246a6e,a145a990,51c62762,dcc47fc9,ea9bf93e,7bccffd6,c82228e0,49686165), -S(79d0a8d,61039dbd,1787b140,9d8109f,3832112a,8e1ae97a,346ba122,c9f66eaf,9bccd3e9,b9b2c673,c465fed7,b774bfd1,833621e6,87727a5f,a8959528,9ee034), -S(c58bdd36,646e3dd2,ae3ab0d8,8c9b352d,c319d1de,c132493d,11f2942d,1f7592b7,ab923ba0,2cbb4bf4,35212358,66b0a420,41677486,3d67cac7,ec5e891e,b2415f6c), -S(3865f065,42ea6eb2,a0741658,5afce76f,d87646bc,a086ea6f,5838e9c6,55171a85,8c7b87af,c049de66,8578c89b,e5a49c85,64ab35b7,afa39588,6312d680,837415b4), -S(10c1b93d,f7ef0d97,4583889,d07b7680,b6ec858d,b45f9a2b,c36a2f68,9d77a4d8,3ac497e9,15b7470a,f9bd9c43,1ef3741e,b61cf7cf,a2e7fd3f,e1886fa9,4211ae45), -S(1ecd15e7,3905fd66,a86a96fb,16118d4c,a6da82d7,672f2361,fd101a3c,7203c90e,4974d5e5,9b8ce7fe,30671eb1,7bcd4d04,97c57b78,a4202261,28eea45e,b3b8131b), -S(808fa8cb,40e6440f,ab60ef45,65caadc8,f86618cd,e1c0d900,587dea31,f49a589,511ccd1f,ee3a53f1,bd12f1d1,13098694,34579292,74d13973,b0aa29e6,91d889c3), -S(e1035b36,290782dc,9e578522,ba51aea0,6621e7fe,8d5cc9ba,af0d131,ee00a6cb,ff12d04f,1d5c1bfd,859178e4,368a3a0a,f73e125d,35049e60,342186c6,ded5a753), -S(daba0ff7,a9f3cf3a,2f05cae5,b2c6a881,ff9ad5ad,9dc1f853,ebac7384,5a48e230,d4ae471e,2ebfbe0e,dde343a7,83d9fbfb,87c3d179,c72da83b,8524479e,19bc23d8), -S(106e3bdb,beade62,e8ec777,bc4044ef,c6a04d9a,5a3b5396,44ff98a4,33c94b92,1d461e65,eb1bc8f4,d3aa5773,a5cfef37,2e55dc46,45f8be3d,f53adfee,6e7e7d75), -S(82424b42,7b95dd6f,5c9bec59,b1ab98b0,c7fdb4dc,fcd1f8d8,574f4b89,6c8d359f,aedc4fba,825c48c7,4c466738,1cddd6d2,75748661,89499c96,297829c6,27945de6), -S(71213056,13ba1e9b,8b8e6727,74b718bb,2cea1e65,ac944db1,9050f9be,e6c90c84,98c54a0b,8f0a6d3,d7e821b5,907ac930,b79e683a,3ec49a39,f5043d28,acae4144), -S(6dc2c201,78620ac5,d99cb81,8474e5e,de8ec3ac,2366bb8a,19685ece,bde25a8f,2f1dc21b,abc65601,fc706aec,50b9aecd,954bf039,e3b066a0,54fca082,287b026d), -S(e7239283,2f6a23ce,252e2493,5726a774,497319c0,9f0fd327,59fb594c,6d9c8257,165dfcdf,2b117b5b,73bc5096,26b47ea7,c8d5b8f0,24beb2db,bc0f993c,d30418c), -S(5d44ef96,eb90df1f,488375e2,a3e75459,34169a9f,5bdc7477,bb7d1bc5,1b3f4ef3,87da9f1e,3346fbfc,6372637f,da5c1e13,eb561d61,ecc68e03,8167eb82,d2d05bda), -S(bbd86c11,dce2eb2e,d7424033,aff54543,2f2aed92,5b433436,f93ad8fb,57816732,f415eb1b,e921aa07,6b7b52bc,773c7e9c,f89ef076,95aa86df,92f4b72,38507c8c), -S(633050b7,3000259c,42bb380d,815b2219,14e78d79,e2a7d979,29ca8ad9,cdc40fdb,efe2db3b,16d1c829,ba0add4a,c07e7ad5,f021ba2c,9e53ff12,c93a9c36,4021779a), -S(70c4392e,d4a1652b,ff89db4d,6b1eaee8,870e1957,f98f0271,d7fb430a,85c76bcf,4d0917aa,96368ba,45a567f7,c05505d6,a349faf4,b51c06a5,848bb8d2,1fd80f0a), -S(7abb4651,6baa8c3c,47fe60f3,6ac3f91e,92d6e09c,cb8401a,a2a3095e,107df5c1,d8445036,8eb5e86c,37ba9b12,f812ba0f,f88d166f,fd1ebd98,67632a24,8eb9f388), -S(65c27141,24444b72,188eb222,650e99cd,13ae852f,e515d452,eb757225,17f63fd5,5bda906b,e1dacf0d,e65e66c3,23ad6dab,15582561,ec4faf17,35de87e4,a53ae7c5), -S(416ebda3,baf7eba2,877f312c,f86c6517,9f422d8b,8379fe9f,29b5115d,f1ec3364,ac46579d,ee0a19,bc5d3749,142f42db,6e934f90,eae78e80,d96df9e8,f932907e), -S(3d94add2,7a320b3b,da7f03ed,ae29d1d9,cf022b47,b7a0ea03,6081117e,60cbebf3,8fc54299,9bd420e,96f464c,8c3a56bb,2f1719e1,20eedd6b,37084251,f406206e), -S(4f0a9e32,76447fe9,2fb48cfc,c962a0b7,b7c391fe,16c41c8b,21a6e563,53d7c218,441e9d39,db107e8d,d8f0a99e,cf791c,2fbb37e3,2ce1d821,9011a8c1,60345bba), -S(17165596,c15ddb64,83b4d45e,8be57fe1,2a37da06,a47ad7d3,a190e88a,9d58e0f8,ed06f5d3,167dc12a,992dee28,ef331ee,443f6c9b,7e485386,7a2f4daf,c0aaf64a), -S(62f6ad56,5d8c3ede,f50452cb,4af3866a,9b40b729,ff1b66bb,c566ce9b,b07b37dd,b790cec2,a2fe6264,5913b5f8,4e2f2ab3,bb45537e,e7783908,1d8928a7,484ff315), -S(c3b43bbc,522390ec,353a2a4e,47e04008,475731d,1fb4c67e,f91eaa49,8553d857,82e45f4c,81adc79d,5a7af4ab,36cd2628,416f1229,994d6e69,d260734e,55d02eba), -S(3a943612,ee8e0359,4559290a,7d55a549,f8173b03,b04cf28e,8abcedec,38c5a81b,d63e8faf,90666215,5f74a6f7,6509be2b,c5aa2b83,b75b18b6,1c1da05d,f6c55ad3), -S(5f2291b3,1aee7ded,21c3f1a6,77e53e7b,e101be5d,a4fc29f2,680cdda2,fcd94be,fc0b1162,7dac2084,c5ad479c,671564f2,b2b13e60,f101af4b,5e7959a6,70b1fa0f), -S(4ca0b91f,9c0cafd5,b9f577b9,f1b84515,70b0521,6a4f0c9d,77c6c106,99c1036f,b254845d,cfd558f5,11d5125c,68f1d65e,7e3bb173,bdde887f,d9b48718,b45d9521), -S(6ef57d2f,6f1eaa88,afba085a,d5882c4,4d823f74,f65d16f5,4bad3bc6,940d9985,52f44465,be358f70,3d0fc3cc,3c3373e5,56be7d9b,6b0486b7,6daa8519,f2ab521), -S(dcac3acc,a1fe2f5d,e231a6ad,74da4a52,7ebbd474,d3742cc7,8f0ef74,172017fc,e0b7be39,4d422b45,be66848d,b8fb6d9d,25ece5f9,28d2b97f,db0a491e,145d0340), -S(da9601c,352fae24,9d92bcf0,6403a08f,5b85ba77,a26dd30e,851027d2,f2def143,2bbf855f,996b6358,30481f7e,794c993c,e8e5afa4,6482602c,f12ee666,ca5d24f), -S(c1f8edb3,fdda602d,ad4a53d6,5e1be6ed,cfbbed8f,12e593f3,470d0485,e4c4a3b9,51003ac7,1cda53be,7be5c073,e530da8a,551d69ac,ee40faba,90cf5c20,824f28e2), -S(71ee3721,ce03cc75,27c837cd,88018278,f2a6f05e,a70b2b4f,323f9fd8,1f8a8bd6,8a9e0467,a7ccac5a,f5adda8d,7380c84b,80575e31,90335247,41abdb94,c1fec726), -S(eb5604af,d835b055,ed67f5b1,fbc145c7,d04f8ad5,f056f13d,2166e6a1,c2eb8c98,85ff6263,314129bc,1902d56c,f76395ca,9d70ff24,2bcb8a0a,b612d46a,b6b2ef3), -S(7cd7eb9f,5edc9246,e33d0734,e2c63c09,f23fce37,cd6c084d,c5d370f1,42f58f21,50485ab7,7ee6dcc6,4d1291fe,b08fd861,f954f35b,1f64a4a6,ad4e30ba,5aeff269), -S(25674f3d,532dfc3c,10d33f39,215b9656,4ee87199,c86fb142,89ed917c,a557be9d,74d20685,274f832d,8406633c,29611fd5,f288fbff,15f6c9ef,e21b911,f26664f9), -S(106de86b,33c9c46c,f0846a80,89a6f140,1e614599,91191ea3,58b877f3,9c7c4e1d,7ab4fadf,4b78c6ca,3a11c0a1,4b47738c,2ea53040,73b3f4f6,7cdb7b9b,74ecf74f), -S(b901102c,4a27cb1d,bc8697d5,156c4efb,8f4a1eb6,7d1af30,28fe2094,5809a195,2fde128,5755900e,3d87ffac,c3fd368e,f84b284b,e30e6122,c518ec69,96b2b56a), -S(9b4d7f5d,5cc3b009,45bab53f,400e942e,6ee7a1f0,915db960,e3a319bb,2d573da3,81507aea,a3fbb6ea,75f42bd5,bc044ba6,60e89279,a0103ecf,2d99a03e,5fc447db), -S(806cb351,48bc2e18,c2261d6,22bd1113,ac9037e9,90318085,b9c46082,a19f9b83,187da40f,a8d49de8,5a6d2f66,831b8b33,5f575c39,c7c95eec,a9a30d17,dc03966d), -S(16633996,fd30bf59,f28de170,7ed7e8c0,95971754,ac04677,9e525b3c,9541be27,27ae75ff,ca485585,c6277177,7f727dd7,bce2cf00,205d9f49,43a74278,b8a361ce), -S(166f9fa0,b7930124,38912819,d2601bc7,e24b246b,9b19f53a,64f69f24,43c421b0,6289f5d7,ec71e262,822bf209,5855a7be,b2b248b6,2dbe3133,221e1ebb,84a3e7f7), -S(a656c927,7129451d,6ee2d455,9acb3c8,b15fc7ca,302adf2f,3b250a8a,499e13bd,b812bf3f,fc2d1777,6363227c,6ae339dd,39120131,187bbcad,2cf2f792,877a7993), -S(8e3275f3,4a20d2df,b236d99d,40a704b7,ff23eb63,2746767b,75e6a9e7,b78245c2,d2f08f58,55d400b,fb3f069,1124915e,547744dd,f0933f5e,c8e8e5a5,28236533), -S(9c53d1f,93b60aca,5f008d87,852a7425,c043e9e8,b0d337a,23304b51,bf763f10,460cca10,cc2768d6,8d19adb,c970d4ea,55a27d12,f2c0566a,6dd433b5,389e8059), -S(12fe0ee4,5cf521c0,a36ab1b8,970314bb,f0cfd20c,ac2eee26,bcae5b77,661fa370,6b75c75,103adb98,dae0fdac,e2b8e40,aa3eddf1,bff77d7,703ee2bc,c6eb0d4f), -S(2e317981,e91c4238,b5760ecb,90e4ddca,ddb18a97,2015eedd,30794744,dd859a40,33d11a2f,8c17c132,972a8a6c,3529a98c,50694b74,fc501db4,382f7423,772eaf76), -S(492b627c,d368c638,b9c13232,79bc34c8,f765b14,c54ce0bd,6ce655b7,20370a84,1650f188,b118104,9a18c474,a4e3fdfc,bd68f2fe,747c7cc5,fc45982a,e2533aca), -S(9c95a6c2,6684b3b4,e31d87f4,53918faa,a0d45e7b,45bf74e3,542038d3,a80a73fe,7992441d,5497a94a,14e2d0ca,acad069b,2b802584,ccc975b9,f895b8e6,58d8c580), -S(20a55d91,38623cbd,445b576,264b4129,8614bbfa,f1da06c6,c41d26b7,8639098b,a214ac95,fd6a325d,b26f0d1a,768d0168,c035568b,76758a38,a6f8feea,c8405b12), -S(813c3b1e,32812e27,27677a03,1bb3d63f,7562d127,8b62ab37,abbeebbb,51a9ddd9,13738be2,f0f657c,e6776e38,d40196ed,2dc669e2,1c281765,286830c1,4587ca2e), -S(bf197179,9e604d69,79b752f4,28e07c65,2b3727d6,837e140e,f812035c,4be106d3,8cfee411,1fd9a907,5bce32d5,54ebe54,892825fa,22b46af8,633a5ba6,d957cac5), -S(26f0847a,8e057fd9,9a625d21,df2e034d,960d610f,39b50c5b,a7398ea2,10a082db,ccd4008f,f47d05b4,47c98456,7fdbf173,fe3ca96e,596ca4d2,6dae40f9,f40d4fd), -S(716b7bfb,781d71d0,93182b2a,d72540e3,8c83a6dd,e6bd94ee,f2ae8995,1db45620,69497305,986fee26,2e2aec0,57e02e1,d396509b,7c3cea00,77d0c21,5101ee46), -S(6f6730d1,5f7377b9,6cdd97cd,91a4fc40,92539279,124bc3cf,c62bdfac,897e796,3c193854,3c7e5dd3,57ce219c,fb20d8a2,c87ec1e2,45381004,ebff0add,646fb0bb), -S(65f8ae3e,1365b723,fabed346,b3953fd1,463b1974,44972c2a,df37fa00,ab3337e,5acf164d,a3730a6c,125f9e2a,5416e7f2,a233ec0a,2c87f24a,a0cfbcfe,63f222c2), -S(b15b96c3,8bcb453c,756aafba,5726cac3,ee4b455b,ae346a79,87e42815,5758de8d,c7274128,ba2f8816,18540ee2,e9dc7de3,587b6a,ff76cccf,74dbe598,42cd691b), -S(804c9c6e,10622728,19159f49,eb579ec2,2e59cc8e,6504ba29,cf725469,3a3e60df,8f765c4f,f9a27d7a,415c918f,e501713e,20b67dcb,aeea39a2,c873a4d1,3c8d4dd5), -S(9754b3d6,438231f2,326ff09,da4554c,15888498,f2129ea2,931c3dea,341f33da,97c5eadf,adf25ec2,b3ee40b,3526a522,104a8d02,1028a5c5,57366571,e83ce032), -S(17721368,b5c35e0a,2a8ca72,f83c02eb,d1c006f3,5a3dfbe7,3adb134d,aebc69ef,b9ff7e6f,803294d3,71c72dcc,73e257b7,f2762f8f,ebc30af3,e0fa3a26,3732096b), -S(aa271646,f30cc43f,ab736d0b,2526a8fc,20318e53,785070de,35197dd1,bdbaa749,e6e4f4a8,d88785e4,de06845,714c5c31,d9c55e8b,dddc6a2e,4519555,15013462), -S(9a496db3,832fed07,8ef217ff,31ba0831,21376977,426e649,79609b23,9e5f96fb,6e37e2a2,3aabccab,452c0cdb,ed0a38ac,10e707bd,5858e9ca,610d74d7,5a4036f3), -S(c3c856b7,ed01305f,a067bf40,c78f1f4d,49af3ac2,963eebc8,94c5ce1b,13482630,956a1d62,fde75fd2,f9f0754f,f8f8041b,d8ba58d,6da21e47,39150268,5b1380d5), -S(94776b33,9b5f04b7,f3c6211c,cb925dd5,8945c761,b74df28a,79c58460,b49b9f52,97dc32ee,c164d32f,2e896312,ec07cd5a,dc51e89a,646a04ee,16bd0268,bebd08de), -S(2aa84c41,ac10c480,38c4b277,18145f87,15f992bf,ae4f8d82,1114b83b,c2fcd505,c9e4571e,be171081,cdea3858,c84999dc,e21cf638,6c03308,e9e5a36d,67e05aee), -S(5619b104,c7f5ff8e,7f3c9744,4457789,5e4fe608,b44147de,902226d2,14a614ac,73b45ac2,d6c678a8,636d68af,f00c1222,354958f9,e41b88c5,53480ecb,57a7bba5), -S(6ca32160,74987f30,c4542eae,f66abf56,2ae32531,7d70ba81,9bcf4a6c,56d29223,d81408c1,4e899b9f,62fb4648,77f5217f,9b32f028,f50be839,a1fda23e,3d6ddcad), -S(2b0de06c,802d4478,de84b508,f9c73a7b,8f6d4773,452e4599,dfc4f8d8,428ab718,805bb316,34a05f0b,919e998d,d3cc22e5,8fc684b5,371e6167,7f1e01d7,c162915f), -S(e4d4d1d4,bc074de4,884c510d,261096e4,ddb6206f,acd67c86,97f8846f,3ad11e41,aae414a1,40cd804,900653e3,1d92b947,efa2a206,f90a322b,8f8e4dd0,66667c61), -S(68c0473b,d83936ba,39f896e,ee7f6e7b,bece7d4f,77f3dc1a,32ddeadf,198df39,988095d8,e45a8ff5,ddd149fc,b8835bde,aa95a392,5ac1e282,5ef7c2b3,7b8bf708), -S(91f022c5,40ae514f,bbcb1400,67bcdcc8,d0846305,9676cfce,e5039e24,d4b52151,c57a96b1,f77156ec,88ced4f4,4401e955,10a00ad8,bfd828e6,4d9c3b52,b97325f3), -S(8e140056,3ab8bcf,a634adfc,bc9dd508,b49348d0,61d0c0c0,2b63e6f7,c56f08ea,754cf682,54a57e08,bf607155,cfa5ba1c,7cd56a1d,3edb7e82,8b9bd54d,f5f23d0a), -S(41f4e6a8,691d2e66,8efc8ad,aff3fa85,5d55f8a0,127990a6,27c33af,a2442d81,ffff7626,6d75962e,e49c042c,16086e89,13dae3c4,f75a78c3,77ce1856,ca49e3f9), -S(7d76b7eb,82d0e161,b1a97b9e,e39defe5,11d7c6dc,6fae0255,318d7bfe,5bdd197,86bad87a,21b0bff6,780eaaa3,6a30b7db,bafb4740,369841dd,da734af4,2815b2e7), -S(3a8d019c,ca085837,288e6cf2,18494433,f55c6e5c,f58513b3,6ac698c2,8d5e8c52,292ebbaf,921daf15,c7c93d5a,4fdcd646,2238f650,4cc930bb,b9327d6b,9ef4499b), -S(b8daa085,7c7c7ff0,7ee79541,55dcbfbc,749c927b,fdc74422,a281f3b9,c4e538ef,41061f31,f0c411d4,8a206fb8,bc842900,1c82c3b9,79fe3cf9,397000de,6cd89f03), -S(315b3e39,74d7644d,75a453cd,c2de9a90,423512c7,18379b38,cccde80e,c95e9da9,e8e82e5,17289192,fc9c9fa4,de1cdbea,477cc013,25060dd,2a766bdc,5381f282), -S(cadff522,8a3a947b,8e122ffa,234baaa,e7c23f13,59f18c63,49b1cdec,232c9048,bdba6e3e,15e09ef8,2f06fdef,64b20c6,f6656505,e3f06551,9bb9e54a,a671bece), -S(ffb3ce58,e72c3c41,a0dc7203,27e4b557,c524e4c8,d724f7df,7742cc52,eb74ba38,2fb99e81,f1927389,bcc94dec,e0ead426,e8631a22,a25140f0,cdb88ecd,34ccb2e4), -S(56e4455c,369dcd00,d8987d5a,46578fd0,44b9532b,2e86641b,b5260502,5ac0b9b9,d54ebdca,e2f22f40,76af78e4,448b6c6f,8d06899a,bbf5ab52,a616ef2e,dfeee9c4), -S(7740cd7b,fb64a276,30948a74,c510e0de,2c63692c,e1c9ff2f,86349bed,bc856421,c866667f,b04e9b04,638057df,8786d549,bb7980ff,bbb87799,37f9f345,ad013106), -S(ab9df6e9,81b1462d,23595e7a,6749a2ba,4fd1c579,b73435dc,de879f02,c85381b4,8258aad6,e81b1e62,b16aa87d,cd0db00f,53d46ae3,ff92a866,f50ddbe0,b919b9df), -S(f5eca856,ff675ad9,aded3baa,83465964,714a277a,58d5dec0,f08e85ac,5ad16ae4,9b8e6768,f6dfcbf0,b6789239,5a2cd72,562cb14f,4224c3b5,61c1993,f49326dd), -S(9732548d,85f535c1,41792440,bd369270,827d888e,e8f8ca29,27f5cef4,b29395e9,564e057b,e5fbf2db,cc698d28,34749b9a,6992b2a4,604ef4d9,5a42bf50,282aed8f), -S(8bfc3830,eecc3177,b6559a01,7391f883,493e045e,b6e5a173,643bd4f1,b4c42de3,7820a218,61c9ce19,5d9ae658,aaa74aad,12bd7db2,4c5e2aa3,1ff6cab9,79fb751d), -S(6ea9bded,744eed27,4aa346a7,3542bf8b,4e93e14e,5e57965,8a5d6a24,beeab56a,a4fef266,b9743c35,935cfec3,2495d6c0,c36f6ddc,b249c256,d17d5646,55278afa), -S(ff15c8b2,ce43a5a0,27817821,e556d021,356ce795,bba2c632,17d6205e,deee9116,87cf8fe9,3618a6ee,63608a4a,99bb27c3,8905b955,2df4bbeb,4b21b9c9,f3884cc7), -S(eb61006f,b575ee16,865ce8f,5809ecd4,28187875,91d924b1,5cc15e9d,a8ebe9d,8e51dfa3,c7494b58,f4447e3f,90eaa595,106fe0bf,d31eda0b,961f758d,3e01e0a5), -S(14d141e2,5ddb4621,7d99580c,918d45ca,51a9a51a,2d7917d,a39624fd,dbe87a6b,ea964fec,b49ac43e,45de4592,6ce9bc7b,f693f945,f6447649,bbccf4ef,3e011ca7), -S(36241c8a,b9b7a9ad,217c0a81,fb33281c,7b48afa9,ba1d2897,389f02aa,19cd964f,a38a1e69,2747117e,71654fdb,fc427acb,39531231,4594d08e,5a32336a,431f3b92), -S(8cd8dee1,5059932c,3c94501b,e15565c8,7e04d705,908c4c6,a2311085,5e5b261d,e949fc1f,7fe429aa,cf0c4b01,1d88e9f1,f5705ec4,2953a49,2c4f31d7,15c04380), -S(232136c1,5e76435e,333ed3ee,ceeab24f,f101cbb1,75bdb37e,5b8dea17,fe5b34df,bfc5f9cb,66063be2,7c090421,e5cb603f,f7a5c860,f9c460f4,220c10b,512c792f), -S(178316ff,4abed117,effb70ec,531f4b73,26124ac0,adbd66d9,e5a5eee6,7572e1be,5d88cdf5,90a3af33,ff5def9,1b5c8bb9,be36d3a7,a331a6f6,b4533685,ef2dc1de), -S(9341dcf0,d1b0c5d4,40004663,c56e57e2,a792cf05,a51f000f,1d192cde,6e81320b,54215ad3,3824b655,72204f8f,a9603007,8280621b,8162cbe0,153ff094,31becede), -S(e5399547,ea95b6fd,d1aab09d,b73e616e,593ac82c,6c4b030a,56b775e4,abdfcb04,c69e3608,b7202138,7b1f2a32,d445c809,1fe67869,7feca054,d94aec0c,14fee6d1), -S(da3a4d99,ae069bf9,9d65e041,69db4dc5,d9ab7482,3ac1c1d3,85d37290,807dc652,f4096d3b,ad811fcc,48faaec8,84633cd7,a7f5552f,4c7d695a,7224b0,ab05353e), -S(a5b6bb89,4594a91a,679f8d0,252fe38e,d0f8a544,8d05108,eced1e4d,133b79ce,d6cdb4cb,813a4fe3,7ebe9b33,471f619f,9d45c295,6b304491,4162417b,d0b206dc), -S(12d9cc50,8d90dc59,dc92d250,3a88424,e720c0b5,56912ba,57b8f00e,c9a4a63d,56992d51,780762a1,312f2bf5,51b657f0,5bf34f58,19d23288,2093e478,b074c818), -S(d5bf7f47,77538811,4921894e,2985b8c3,8cddb376,c9245c5f,6f1308ae,3f228620,693c17d8,40a58ab9,50b4b374,18caa8de,e0a49ce6,b471bade,43387523,30fbfc64), -S(83f06119,88ca1f4e,75490777,e864415b,abad972d,d5f4ad1b,1a295b4,205c1a99,e893d1d9,2416da8e,5fef7f76,389c59c3,94725241,4534cc86,d8518b3c,6cbb3d07), -S(fe6995d3,78e80a54,f3b1e8a7,3837904c,2d26430e,c81e5b0,11304e56,50f95f41,26a96933,8ad90a9f,4a15db70,28df1628,2214f822,6bd38a87,854dcc2,f4d490ce), -S(12af3d09,265b9f8c,fd5a74fb,62358ad6,a2cbf782,25b73a88,c5e56d29,508175ad,e28281a4,36b0476b,37588e2f,7fcbc4cc,bd88d96a,3806022b,75a4b5c0,8569cd6c), -S(1bebbb1d,3141cb9e,3723fde4,c0f939c3,7e37b67f,346fecf8,9ee9c789,7f25d89e,4f2835f0,4b875fa9,bccdb338,32ee53e,80360b6f,30e139ae,227961ef,426e0c06), -S(ddd3bfb3,173aa6d8,7d867d95,aeb66535,173c9a6a,4f34cc67,cebfaf7d,1ce4ed4,d7cf7542,c6e93a03,e3b37402,2c2877a3,65387e99,c9956071,beeab06b,69ef4d51), -S(81ddbe22,10125e0,32b5826e,651548cd,ba44a5aa,e131c0a7,2b1f48e3,7fdea8c0,80f9dd6,957aa45f,6ff32756,f87bb9d0,fb145b86,ba0b6890,5d15814a,f42b8ae4), -S(f4f5f53b,fa60b009,9317ea49,5dec1044,54352b89,5da6df0f,707d80f9,7d698da5,454cacb8,999acdb,5cc3e5d2,efac913b,4b967755,3ab998c6,8531b2e2,5ade652a), -S(b232f345,16c572e,f7d89d46,679a0458,2bdc84a2,39f35292,855ae063,fee9a1fd,8e480fcb,d3361e54,a128da49,6a2285ee,829ab82b,7a1530ad,e0f7ed1f,87ace8a9), -S(9f5a306c,c0e7f392,523ed44d,c2a74f62,cd8912fd,292feae4,493a9a90,53e43be6,d4a1e25e,46cbe19e,88b342a5,a278feb,9b9a0523,4636962f,b9697931,c47a848b), -S(4d5005c5,4b079a57,3ce42e6e,87cbec94,cdd520fb,16ff9d49,e715096a,a5ab8301,afadec78,c911fd4c,1248210c,622f17f5,7a34a6f0,1fe07abf,89ad8242,a0340732), -S(6b5d7335,6b80d4b9,9ffd3d6f,5b8376d4,6526753a,2367f046,5ed19550,4e732cb0,c0d10b3c,d9eaccf5,1eea0088,fde2ba55,17f85214,2b46fa6a,99b35a5b,811f5435), -S(896c9047,90f3a428,20715852,9b710560,bd18e038,a8dfb710,fa2bc910,ce25ca9,71ab7cc9,ddf7fe7,ea77e985,d438e0fd,34270829,1c57745e,decbb0f9,b161c4f4), -S(2812d428,7e3c5961,808326d6,8e79c93e,259c3f31,e02449ac,e2b72484,8ef7539e,eec93ec8,b2cd2b18,9ccf8d1,ec8d490a,4ea565e6,ab58eb78,3aca8f5c,b92df37f), -S(d7de63b7,421827c1,ee84acdf,c82a7e72,1eb42aef,7d91fc66,f725e8f9,dc42554a,d6dde944,ec65a85,ac0386a1,eebdc69c,b8793ee9,417e4e1e,8db8087e,bf1b6f22), -S(8dbcc742,a5856bc3,e29b009e,46985a7,67800404,82b06681,3c63a27a,667ca60c,f414fcf8,50b82712,cfcb7d3e,d92bdad2,958f75a2,9f5e69c0,67b3cadc,10da9293), -S(8f046e5f,7ec21b77,3df1015a,19a7aadd,bf5ad912,b5020ff9,b574fc9,7d442f4a,4fd50026,6f8a63cb,d603e3d6,f3f81aab,52e79e94,cb0f7159,fffbdcdf,9dba202d), -S(fc7c51d3,7e6dc2a1,bc542bdf,dab38775,54bb6787,dbe5ffab,471d79c4,8d2a0a58,a7297795,f7f9a558,abc67243,900005c5,2c619c52,bae08a62,5de66bea,81acc475), -S(e36ba16d,81996e80,36b3edcf,67136ecf,7b5dc68d,526a34b2,45843fa4,6a078f0b,25b39a4b,1b5d6240,30fa90c3,558a1eb5,df7c44cb,698f9d76,40432983,faa3b003), -S(c1c817a8,43140681,ff908319,a24684c8,dbbd179f,ac49cf4f,428688bd,3eaebc23,18e43b3b,ced5d5e9,530c05d4,6156fb9,fbfd60e4,58048825,c2d0dc78,e9575594), -S(787e110b,665a8db7,40c2ae0c,206ddfde,4491768,9aba8ca3,de737283,52b70d8a,7e22a27d,976262df,22c60307,ad61f435,b4b27dfd,85657f25,72899d2c,5fd005d9), -S(e1106094,464cd775,85b9eb8,cfe44b13,14b4e87b,54a609a9,c43dff38,995f5e27,8dff0b9c,d97f2779,fee262cf,629ab48c,483e8c09,c05657fc,6b0c83fc,3c64006e), -S(16f72b7d,9b9f8490,2989e9c1,8d067f31,b5e6773f,fc03b2b1,bf026b3c,a45ac92f,6260cc27,6f616934,9492c169,a9f97bfa,b3ad1e16,2b6a529a,7b637ed0,828f6a16), -S(1566a7af,1c3cd035,29859976,8dcd24fe,3dfd07a3,c688d048,c45f9170,b790c791,23319b6e,b9f84cae,f9c6ad8b,1c0a9c2a,6574b84c,4abef9ec,29754a1e,b3a67e2e), -S(bac2ba4d,96be7dfb,425e1279,8323068f,2a42d0c,564e3466,92a89730,7b90b66b,29291264,4e71cddc,7e78d20a,dc026e90,637eeaa7,36fb11e7,25d2e9c2,17b3c8e2), -S(b26a1e6e,1099aaee,14f3ef63,28ed7ae2,d195e04b,1d55e394,d0e11fb3,56807252,2f3566f,f7aca2a6,7e3e8e6c,294120df,86a92193,c2a0a79f,fe22c549,3385334f), -S(9a7a18ba,1cadb917,b68dc78d,119954c2,1b5778f5,a1445238,8cf7f481,7f49cf0b,14e484d,d3fe5242,1737094f,53861ee1,27a1aaf,2da7392b,f03127b0,d0d86a41), -S(49b26479,6efdf6b7,76f70672,d40644a3,e390ed50,1baaa862,1340a08c,649f907c,ca54a985,c3ff23a8,bcd6baf0,ab223fde,65b358d7,cc237b2c,3360cc53,fb7e62cb), -S(a27af3f9,728319d4,248af74a,a3e2d249,947ca87f,3e2d3293,9f574e9a,6da03f9b,226685a,8ad2073c,e8e32133,b2fca804,918d1247,ec1e3053,328e59db,70ea26d2), -S(de13bd9d,3544853f,10768f3e,8cadd376,f36726ca,5b27280b,de12a8a0,1d38f876,6fb4310d,96739a32,3b48e9f6,f215a0c2,f270d272,519e0085,ee72f325,73adb0d0), -S(6680238c,5ca916ed,5169ace,3c2e7103,3a3a26a1,89cb2cc,4420d23e,b9a98e5d,171affa,b6f370b8,c06f85a,928916c0,f6b45c1c,5ca2349f,4469aa25,c8f9b6e7), -S(c1787989,1e100300,1facb000,c41efa43,710267e3,554e0f65,f954a1f6,191388d4,68698007,38cf474b,e577d109,576c6984,cc39da19,371dac87,ae462d2f,2129abe5), -S(f0010a2f,63b6d832,256fe7ac,7b885d1,abf60db2,982b8cdc,31a8595f,23f9328e,cb3a3e15,ec21bba7,72a720cd,3f9bb93a,b0796aa8,c5ee119a,f862d5a4,e547238c), -S(2919f01f,f25e9171,1db684fd,a25c8a89,caf84f01,9caaa483,704e736b,92219e2a,f374dc4,8115ed9c,97efbf21,936cb5eb,814f40ee,40c8f97c,af29f3ea,d46c0603), -S(b110c17b,786e9b64,396003dc,3e0c9bd8,8cc4d060,e7e442a9,8bb3a1ec,2edd6663,6eeace13,a43c6cf7,33bcb313,e5cd7781,54c61fce,e4864924,f20bf45e,5cfc16ac), -S(1a41b8c2,f0bee447,3a085941,4479767d,b2c026c3,6ce0283b,337fa021,87e98435,88a46621,939d903e,9bb60506,3684ecea,7b2fba43,4f5f437c,f94c42e8,b4c274ac), -S(764fec0a,7ef7ccc1,ee478e82,dc122574,6bb18158,cac61402,fdcdae83,8177407a,b0090a4e,fb7da4aa,a54c24fc,75948587,3e1fc957,a475167d,5bfd85,7dc16f7d), -S(e9a521e,49b18a0e,1b226b11,d0397f47,8cb04d92,c8eb4cf4,4e70a0d8,c27a2f8f,b0fbbc19,7e70e9d5,765d85a4,1acfd3d7,84f06554,4008a89b,440f78ac,63a7adc5), -S(da01400,c935873c,1bd0a05d,2eac5595,c6e18682,2db4112b,b0a7af7c,f0b291f1,3fe8c281,26fac7fc,b629a6d8,9ac945a7,566f3414,d46f5e3d,3995ec40,e6aad876), -S(ab69b97d,a15898e2,d77440fc,35c31a4f,7f4930be,6a132e6e,66a529b9,b60b2796,7c80faef,ce1cb7d2,77900d17,e5887c0,c80dc0ad,b9c33fe0,5decf40c,f0c77e3d), -S(8001a2a7,3938254f,fc3a518b,2e9dc61a,bc7dcd1d,90e55812,72410380,2a91c2f,985191d5,787d0cb4,809923ed,b87dfa5d,60c18938,8e4529bd,2353fc42,9a061060), -S(5a93eede,e37ca03,194ddab9,2f9c7cf0,ae230a82,d489a9bc,87ac7180,93165e41,15c6cc54,72f571d0,c78ba2f2,8519115b,16a2256d,17ba055f,5731edfd,822220cc), -S(f0853089,da262598,d86771be,ebd4b38,c7060e9,ae9474ae,f8ba683f,1b70bb1,6508e3a5,b709d0a6,c6505be7,cfaf6744,3b741d9a,5f9adf06,7eacbae6,23a56819), -S(182a85e2,3d4af778,e652cedb,1cd6fabc,81bdb345,ec7daac9,f717249a,5d6aa519,a509c2bf,1df249a0,e477d3fd,e924146f,c9e7ff78,9f625174,587164d7,1dcc259c), -S(dc1f61eb,da442680,5dcc73bc,b6c59288,383301e,50c62a86,a9274a72,8c49ccfe,4d99f11c,be55738c,a2b889db,dee2e3dc,9d3fb44c,8cfef36c,5357396d,97c52cdc), -S(88d959a3,31bc66c9,c6aac8f7,ecc91ead,83591749,97c60a8b,7b11ddb5,fb8253f8,53eb97a8,b3714975,263bf21a,4ed923d7,39276e3d,b4cddcc9,574bc96a,f4083855), -S(53fd6fda,a8e04a9f,89fe1adb,90704589,8fe453f8,1c069b0b,5d5a9fb7,d77d612e,a8325053,95360123,422b6419,109fd9af,397ecf9b,71a6d322,b91c9c1e,ec236b4f), -S(fad9c66,bf453615,ba53a597,8e60eaf1,13e07192,1e820399,6bb850bf,237992ea,8a3a6b9,3a127d70,a36eea2,78668168,34bbb025,902cd3ab,aa499d38,8e24d657), -S(e4b96c12,223f45d2,d7bdd8e9,7ebe545a,16d23dce,1a090b3a,5ed6c9e,65512a65,57fa0c7b,39a473dd,20571bef,80a7c738,cbaa67d0,cfc7f64c,ba0be2cb,123d49bb), -S(7750e371,3b25a5eb,923c460b,967d9dd,1f00e791,cc3b52,9d3ea331,fa1010be,eecd47a,496d6a13,98e95c1b,9ca629eb,49687962,5d690434,ca41279d,a65c605f), -S(93487b6b,25ec86d3,59ef5bd8,e2cd397e,d618c2d6,98d9a6ed,28f3817a,31ae6053,f66a87b9,3dd96064,489537dd,1f9e693e,af0219bc,2b0f752e,4f53b9f4,92715fea), -S(f58b9a95,4d873bdb,931223d5,4867d818,d8c4a2fc,773a1552,35c6b182,aa8ffde2,752b711f,735bbdce,e772dbaa,89f7a95f,d81545c5,5ed25c2,8bcc40ba,4d82ff20), -S(335e471e,8756d394,8cf43e2,b32d2f7c,46147d2b,c467f089,58fb7541,89e4913f,c9e5bf5a,37b19ffb,41d39f3b,8f69a8f0,8ba01a52,559d684c,5eec3549,7413f3e), -S(e6a7d3a6,6ada823a,8b0cbf90,af3f0788,39ebeb9,85017182,74f29f58,1b9f29de,ff850986,71962405,edba654,1857c858,ff948c7e,4bd2c5fc,64afd2a6,c643720), -S(785e6bf,d3c5ae31,932304d8,27aa74f7,783277ff,fb27df66,e1596a07,705b2de0,1166938d,9604a7f8,2485ab74,af763876,2271ee5c,5a7427d8,2d8569f5,25f0008a), -S(228644d,5c0be7d4,59dd5aea,e4019421,83ea6770,ea40cbb0,38b3d1b8,f0d4cef2,1c489d4e,a1595fca,693bf7fa,d6672701,a23ee40f,b9278b1c,566d4faa,5d799c00), -S(a5ddf933,8e477ab7,fccd9344,ad45609f,7be754bc,eefba823,20f1b8e1,3ae9c15c,3e115120,5de4a550,c0f65848,804ac964,168481f2,12b2156b,544152ff,c9f39306), -S(668b35aa,b4799dfe,dca25a50,6c32ca97,3a5e6c3f,51676f82,e572602c,ec3e8a2e,63f33101,d9be94e,7d8971e1,4deec0b6,3406a621,77d5a044,bf43415e,c35a9234), -S(fae3a6f3,f9aa47af,a4babed4,7f366c09,da8e7074,fcda3f92,c74c1bec,c73aaf64,cb38f70f,61bfaca7,76fdc581,a468b53c,69d21815,11771cfc,698a9558,209736e2), -S(2fb68357,285d4ece,96ad8a3a,9c6f0f27,468c9569,3c2e1a9,8864a64c,757c754,b74b474c,133e0a4f,a8ad5032,d08acb1,531640a2,6dc09af5,6af1c862,91c06e87), -S(9f073149,dcbde92,8ba24d3,c00e54c0,c334b958,f124cf91,467cde94,9ea9848f,21e1474d,c43a9d33,43c120ad,a751e9d6,ae6c9ea0,986fdaf6,fbe6bdcf,23085d6), -S(bafcdee0,c0ad4fca,3bf95576,403dc2f7,e28884d9,b8d5f77f,4d7049ce,965ccb4a,4578e9c1,67b07364,f70d8cd,d6dda3ed,28b87cfc,b8d5c8de,48034eb9,5ad3da08), -S(7d909f21,b79fd78b,7b65abed,2da2b831,c7dd1794,cfd32f92,a4fbfc0b,3b666233,c6f2f069,f4f7aaf5,fb263dbb,389ff7ff,86a5f5a8,32c9311e,cfe31af2,38313e5c), -S(5d4ed232,4e24ae92,2f3a1aec,5a8de0a3,e7eac523,58770697,cb45c7eb,4e6730dd,878a1b35,ce2f6880,5b4786fe,eb49480,c6bed243,8e2cfa3e,4636af5c,649056b0), -S(8a97e97b,a3767b06,a9bf75f8,b7d62a4a,b22903ef,7d7717bb,7165155a,b375b959,6997ee31,72cc99b2,8f447052,b75b5615,db7a5349,f1445c6b,bf04ecf3,c8ef9f5c), -S(905aa389,b32cc33d,f9d52e49,39ad4799,8cfd03ad,bd4ed3c1,7810c0e8,8e1e064f,7102cdc0,1d6ea4c2,a426ba6c,1d4565de,c4d0f3b6,458108e4,e0539069,ff2f8a78), -S(510c5aee,f28f8345,2ff713,eb0dcd89,6d788763,af8cf565,dedd4ad2,c32f60cb,ad1f4e3a,549ba056,c3214148,504cd177,adff0933,bfaa07ef,dfad12fb,74609537), -S(66ade073,7a0510e2,40f13ac,db8337f7,80adad8a,9bb68b56,7f5d5d6b,da7cb44e,a5ce9959,f57e1e2d,8cdce9c1,33f6e684,2975a933,8bc8112c,3d68ca88,e668d19), -S(cf51bf95,42cecae3,59ab97d6,1f35ca91,a28bb48d,14ffb958,b4bc95ac,aa5b4e48,7db91cd8,306252b1,aedd7afd,ff94b28f,1e8a39e9,abfe26eb,9189cf0c,37fa5e), -S(fc409559,404b55f,27503803,9a1a36c4,bd42fa53,ab520417,94623180,57ee0622,79b14cb0,5b5f7e30,bf1ef45,cbeb10ac,a05d0819,fa9205ba,3e9d8952,afc74574), -S(832bd5f5,fd0d8771,80e65a02,6ee3c1c6,f44735c8,ce69677d,546bc2fe,fc0e44c3,b2430cc3,7d68fcd8,b35ce76e,229592cc,43ca6ba0,4c2a001d,67ccf5a0,2bbee37c), -S(d66e9431,bdc39c9d,d598c3cb,2ef18d8b,508ea830,3fe5db36,9262c476,66384bf3,b628d1b1,fef2997b,779b5f95,28fcbd,e6ce77ce,c752d83e,cbfcc05e,ab05f670), -S(1dd1514f,85d214f,4c2480a2,22cf00c1,f1ffe62d,ab452dff,6cc7f61,6c66f74,ec70290f,1eafcd75,d87e84d,cb86c460,1413175c,9f18756d,e92d6517,2f688fb6), -S(8a6b21c4,44ebfb6e,61023622,52165611,bfcc2531,1d0d59b0,49f25eeb,9894dcbf,95f6a81b,177faaff,25907a4d,61a7c323,4d7ae932,2b9f862f,a11c86a2,5c894699), -S(48fa5a8e,769fd471,122e6061,d7da307b,2a700a46,bab0656b,7fbaed37,7b997112,e4bf13ba,4456de5,b2c07597,c5b82111,ca05d178,cf0afdc8,9afd5df9,645671e9), -S(8aa75f18,7362cef5,91c58d4d,d1e196dd,5fdd9c7f,91685fe9,d4bf9025,fafbe0a7,81df12ad,b9c543f2,467c4c04,83c1358a,af08fe87,96b01d2,5e26719d,d8c06590), -S(fe10a4a2,c81f5155,e8f23469,c3b537e,b2f45237,8addbbbd,8a224a33,2c7cce6f,95abddd6,e81a6b0e,feadf6da,6bc37e93,f96f8826,efac71ce,8b36762b,dba0cca4), -S(4c29b630,af2a77ff,ed3773d9,a3d66cdf,fb100d67,8a7db0b9,1f37f6b2,249d1a6f,58ee018e,f5055aaf,c39a21cb,a68f4f46,6d6a25ae,e07440fe,2f00dbe9,103b5fd), -S(3bad5249,20c3ea2e,fc16ec86,4502804b,394f3273,5d42e047,c0cf694c,b4350adc,c553a54f,7462f2be,c8fe478b,cbdc4c2e,f693d8c7,6164f513,7e7a7a12,4c6ccd23), -S(8c087953,8616060,cf0deb02,1f46d60c,d1bc3b4,a8bbcf6b,39448603,59a2aff8,5f24e4e3,3416655c,cc35b47,633c9231,bf15443f,132c2df2,ed3d1534,52aa732e), -S(7e080d31,fa764a8b,92e74bf2,c69ee7b4,a7b2c2ec,6495814d,8901908e,443f72bb,f34e979e,c41713e6,b98d122c,a7c0fe5e,89624941,d2d6b44c,c65c4244,3f6a9094), -S(a5acd6e8,50f9b182,162ce14,3b19874b,b9ef6d4d,7c042eb2,c4dc4e21,eed6baa,85d55adf,7220b662,c5b88d63,2f1e7b40,4aba5158,2b93a22d,b3e9457c,b68ddbd1), -S(5149e4ea,600a6dc3,de6c91c9,3dd43a5e,a5e64245,1e791841,39f31749,7fc15a0e,7274076a,9b177600,85446c25,ceb68e34,217ac3c,e4c8c232,a673b0f8,496311ab), -S(e6548b3c,46de74c1,40d9480b,b01aee17,dc6dafa8,5843ff8d,e4a75878,a6ab057e,11704026,373c6c96,30da7f2b,7713a313,e64380ab,4f35d290,dc789f75,29308f6d), -S(80a85ade,2372d7f9,74bbdad1,c6e88df5,4d671f8,7447884d,ef186155,d223183b,24a1858a,5fb6aede,1a36e16,7d25b3a9,2e2f6639,64d60349,7c13e9b,3c14c7a9), -S(35ff436b,571336e7,963ca450,fcc41caf,83307da3,65468dce,28014914,7760b8d1,565b63a0,546379b6,585ba675,52fbe796,ed68a9b8,35431a74,e8f4b989,2027d8b7), -S(12a46621,fd5f9ca8,f8830338,4c150e2c,1df12e06,1dbff329,d3157638,4d67dab1,b1e29c72,e7ccf360,e8863c3,48aae396,2fc989b9,15debc6a,514da0ae,67ff38af), -S(2e4b50b3,b072a9ad,ab9b2438,bf554f0f,bdc06d62,f601bb05,7640b7c5,36949cd9,16c7ebe9,3dbf67b0,fc716d82,3f6a8fc6,4283d7be,513df237,e3afb062,eae6a10a), -S(3b893c39,58a4a0ad,49e3d2eb,b53bd3a2,fb9144f9,d46392c0,93a9affb,3d21bd2f,c965097,99ec1519,5877cad7,4ac6ac0,8c55e9d2,df34b4a6,b1758dff,c5faefc5), -S(195c553b,6de4ff4a,6b9ab252,f28f202b,504ddf2d,af69dda6,1c3d065b,592944d5,9faa60fd,79b63de4,cd3946dd,cd3baf8b,c5795e3d,e4018d7,c1733e27,82ca397d), -S(e8e5178a,c5b76d6,68cdad1c,be01cdb6,e9859609,84c05666,dc8021b2,12cc15bc,ba4eb10a,342d8742,504a468d,f784af91,b8cd1def,112dc8c3,4bae99ed,d855b0b5), -S(a5f99556,4e8d722c,a61dfc74,2cbc5ece,6f654cee,7c716335,5cd4f5e0,1decc0b3,bdce6c99,c4479cf,1547f394,8e9bfd07,ae066d7c,6baf7cf4,95ea2037,191e1594), -S(98065d45,270d94d3,e43b8c46,fc85570a,c72043e1,285d673c,ca1c668e,6373e4bc,a45d5f7d,3e6a51da,8e95333c,2333e7cc,aa938335,7bf7933f,b8004682,599db967), -S(bad7e989,8b6a97bb,98e66b9b,a2e533d4,7d33f0c4,d71c280d,efff5570,660282d7,3d3379d0,b9ad6d70,51002395,bd01c3d7,165e1f2,d61a5ce6,12dfb89b,8e4bfa45), -S(c914752d,4c1bc92f,f9fef612,77bd1633,840f9f74,2bf88bd0,d2fa2698,bfbb6377,ff8a4aa4,b0a3156c,7224f499,bc6147cd,d147aa5a,69c1c225,ce19c663,da7864ee), -S(d58c1fb2,7235da86,8284ab85,1a6ca2e6,dfcb26c6,1c544060,a0bf9083,1471aa50,8e4c5ae8,28e2ed6d,1fa1bd69,9d3a01d0,377e4fb4,bc692ab9,f2e3ede9,13bebbf4), -S(25e409e4,8a8f05e2,e0cf11d0,5a389206,18377447,cd0294f0,4a92eb02,1cbcb500,e7702eef,d40c5cac,4bc2f99e,93f0bfda,509f2409,24307664,c99fda52,a18286da), -S(22d1fef6,4140e996,9451dfbc,32f0891,7f600102,3f9cc11f,88ece53d,49321ad1,5a6c11c7,401c99a5,bed96396,9af7ca1c,bb612d1a,e1067cc9,ca4a1785,408bd79e), -S(ce176236,a9f48b50,7515532,ef8e172a,f017c5ad,87ca2f01,1c8b4ea0,64d44b89,a0266107,fd7d38da,53536d75,6e7b63dd,372566ce,643a4b1d,881e31e3,8a699508), -S(3080fc65,9c01951c,f643e315,f7d48339,e8134e09,5c5c0e21,f7b9ea35,1d859dfb,6355c53d,d8147cd9,b31be789,7bf2f65c,e3be9535,324f41c2,850b9cc5,ba607472), -S(e4798722,a4b284bd,ee6696c4,3c67aa50,11cb3616,7dd7b21a,ebe50ed2,e7d1a253,3d524d92,5dda9fcc,4422ff7,981136c4,4f373ea3,a41cfb7e,e1f068a2,466f6ffb), -S(c82b6536,1e8d8282,9350fd86,e17e63bf,75495dd7,51a967f9,51f4b7f3,eaae03a7,91b896e5,d673cea1,e6fa536,22737c68,c701e2a2,db8a4817,3c316006,b0b84a9e), -S(e911dd65,724fafff,55943a21,df3517dc,cbb3c236,e19aee86,c3f3a5f1,66e3cde4,a51bf72a,cd26179f,839e721c,1de0ab93,cf221a3a,72202b53,d8e552f0,2fbbdf97), -S(ae759e42,cf0c0935,155eb36a,5f07c251,bd4923e1,31b0477c,fb7ea478,9ca797f2,3c12355f,e7dcb9df,73362daf,d0ac689c,a6a24965,ce65fbf4,e5f9c6fb,271a8a85), -S(5a443113,c04b35ae,bbc16401,f2abf9f0,b9644cef,6e8222b0,b67fa109,a19aa3ca,6c7bb7a5,7dc10e2f,140601ad,6c1a7f3b,fe122e80,3531848,2a2495df,a7cc5221), -S(62fbf303,ce5055e4,761d6ba5,4e965e0f,cfc46a4b,e0dd885e,f3803875,e0152b31,14dfdf1f,33941493,d9bb0956,8f8214b3,cfdd18eb,6d6a79f4,c33abeb3,f6aaa86c), -S(47bad781,2ad847ef,471e3483,480fdb67,b08b5679,74f7619d,9f6b4de3,f3dae3b2,79a7976e,568e5220,8bfdf6a1,95a7d16b,8a4dca64,e53ee7c6,c8123d6c,839829a9), -S(fa4381f6,e09f9a19,72d7dc12,76fe579e,f8a9ea0e,c5ff06de,390d150a,fd3cd49d,ff76e0b4,b3f8408d,5c4d79ad,8ca85789,30692275,1d5d5d96,9aebf6e5,2971c307), -S(b891d634,64c7cf77,2b1c19f0,835869a1,50668494,e8889e85,6081ba35,7dfb0d6f,8d716524,65dd0f47,b39bd6b3,7f6efc14,c0108992,4741ccdd,71fa9a98,19e5f05), -S(eae22d01,98d6f036,5d3ac227,856633a9,d0ff6dc1,b6d5d1e5,a1b2e4dd,c7f11466,723a69f0,b551fa41,221e3a31,8fd2b60a,4baa0741,c6127e67,b542be14,9d255074), -S(765b7989,56393611,1b182aca,fa7a2a60,ad89f6da,fffaed17,ead51975,242008a1,e630c87a,91235862,444891c,42dff3bd,320a3272,2d43757d,5ee46eb,af5412f0), -S(ff77d59e,b5ef78d8,49496995,b20b98cc,c847ab95,253b3a6b,9d6119ef,5382ac12,b7791936,e1bcfad,8bd5fb0a,1b547261,ee0bee24,5c1e58b7,3fca8015,195d2b1e), -S(fcd78964,e8e5fc94,f575fea4,7d61abf2,c89ab915,2683e855,d48c6828,b95eaa6a,9f32180c,683b465f,203d4d9,2f2eacf8,396966e3,2bece1e1,413f2111,f000b000), -S(38e9c6b1,b2495801,455e5ea0,ddf4bda2,432b84c7,4f9303d4,c9d6e30c,8e87f564,ccd32af0,603f27c7,7cffff6d,9203167,3cdbe4bf,8662e224,498168c0,5e7eff1e), -S(9de95ac7,9e8ccb95,7b62bdcf,f9942194,4a691b3f,5646d800,68e2e7a0,976d944d,9d99c259,d5fdc8bd,7c29e2ea,651b4abd,354f8ac0,758077df,f46b0896,a25f99c5), -S(e4d34872,1f8f7fe,d81d810d,8fe26811,87d0eb93,5f8eb6c9,2735a55a,720354d1,1b95fd74,ebbed926,55004026,e2110fa9,5bbebf7,efb6b0b6,d7e883b8,34677cd8), -S(ff0222bd,d37a7b6e,45b182a6,cc744545,d60fb6ac,8171f625,a29d215f,1af3ed80,102d4fc0,c3434443,6b8ed145,a5a19426,247b5969,3755d3e4,dee475c5,1211c755), -S(27922e13,f03b2f70,bef94a31,589c1e7,9017c16a,9e57ede4,4af93c38,174dc1c,3f268d7c,3d9aa22a,6277ccea,c36b9377,52b94658,c44d110a,e276e560,d4bc18bf), -S(9f995f1f,76ae01ba,38b02cdd,a7f99b53,883e035,afb35b20,324fe6a6,bb65db6e,ccfa6f06,daf16088,7f2f8af4,18a5b107,cf1a83a8,12f117e1,7e938e4c,73ce924a), -S(c1b2bd23,8fa1db5,814a07a1,d6db2ac3,4f960dfc,c88970a2,9dd21c34,3fea87d0,e912dcbe,ff0391ec,7987f901,c6329c2,a070d64b,53131c5,7e99e6a0,27465f96), -S(789e932e,5665aa8c,24e2f0cc,1039cd89,da928d0a,1b4b03b6,b93fb79b,f40e04dc,25315b3b,bfe535e2,92519e89,b63da55e,f4c16a1b,d8af3394,b280ea62,3d0953a7), -S(19c54824,5815e2b7,b31d35d6,740e660b,84613096,60ee9bd9,6df823ab,1e7bf39c,9c0516aa,79e00ca6,8330d267,5b104e80,3660fcf9,4d785216,90a319a2,44885987), -S(2e73f0d4,de4f920c,5a5175bf,32e6b98f,5a49d1c0,a7af2b98,a6c6dd60,52477bf9,12dd835b,fc93af9e,680aa191,bfde6cc6,f307dfc6,aca349f7,c2affe27,40f87795), -S(5b711fa6,4463434d,d7c824ac,2a56d02e,46949ed1,d8e530b8,71e70a82,38ae224d,14329e12,940d179d,922b97e8,d2a2b7ff,6da66497,6879a790,1edd6035,f47593fe), -S(a34546f7,aded19cf,4d83329f,41cbd292,bc59f37,f290eb7c,ba28aaf0,a32a423b,9a2631a6,cb6b2989,fd2ba260,5aea7f73,c08f05f7,e025493f,459461b6,5ab24dd2), -S(850cc29,8dcb42ab,613b2974,57c80ec2,d98ef5d8,562af745,d4ffcfac,7e9c0853,b07a0e85,5cd335c2,728338d2,8a1c32c6,e3a0fb76,58b8bca3,f6bc02f3,de68a2ed), -S(8de69064,cf3f8d04,bc20a995,7677427,7b712ed1,f77fb7f7,9c361dda,2c7e8b30,34f6938d,750874d,573bd5b0,c11d9c93,b6260a9c,6ae833a4,350dd779,c515f16), -S(69d1e613,852194a2,b618483c,29517029,b3fdc8da,d679c07d,3204261,80f89170,a70f4654,8b7542b6,5da14788,56de6c5c,e06490f6,176794e1,a4dcf25e,4337d570), -S(f238036b,d55e7b7b,6d0835b5,2c3d5c2d,cdc7e6ae,6295e19c,2a0d6a63,669656c3,b401cdf1,15e8c93d,f5e230c7,a3ab387c,687fa690,d86da5e7,d038319c,468bfbfb), -S(ccc74591,1178eedc,76c98013,a52911bc,1da8f9ae,10f40277,ae51fbeb,2b6d53c0,d4cc4eab,60cbb4f2,9070717c,d6151c24,2914069a,c3a68d20,7982d758,3ecf0445), -S(ab2080d1,f6d6ed76,cc713c8b,46474648,c7d1bd31,fa6ca6a4,39d0eb8e,ec4edd4c,8da5323d,e205f2e6,4ddd80be,679dce01,3d1f2813,13fb16f8,e749902c,16362b0a), -S(96ed8ce7,36e0d3d,607e7b1c,fcf6316d,1bc60122,c1e2cfc5,5b20d379,621c564b,841b64b,af84d76a,45afd86c,28d32f79,115675b2,9a15c9a2,50c328e6,2a79695a), -S(b41e63b9,e3fff8e2,d89f2a69,b80f1d38,60a8fabc,20290d41,657467eb,9eef61bf,674d416c,82e50cbf,f001a44f,3ea4108a,c7cf8747,3b7cf851,ce9a9d1e,f5b90dd8), -S(7300ddd,4d22e101,a5ac174c,96f1ede2,e5a8af97,e4d7a5a1,e1f07be1,ec9b72ca,edb4eae6,e9d20683,6abe214,aa95cc75,a4246e14,86b05f23,ccb8c4dd,3bb18888), -S(5d152ede,6e8055ae,14c8c67c,3eac3dbc,1f080dfc,59d0f1d6,16bab4b0,460d21de,e615d095,b3ecba8c,dcede3b2,bfad0814,781b3afa,2b631928,74020df7,b62e1425), -S(bb8f9d6b,1f81a373,32a25eda,b4feaaac,9d82086,8297eb80,c1bf6c4,5f5c7cb3,772be893,a029961b,35f7174e,72dd5c44,e8c745a3,423cba1,2071ee89,92c604d9), -S(643730b4,dd3bf408,2ae96f7a,f3409b8e,690cb09d,f379e3a4,9e8d09b0,de30488d,55a68bcc,54be84a,3d79af27,e2d88740,e9e1eba9,e2149aa6,1cf4d7b1,de6f1e57), -S(82dec11a,c2c7a667,336c5d38,2224a5b4,12c7db82,5fb9adad,30552bc9,db2dbbce,7f7044e1,49f03a78,ea93c129,6bc63541,8b03e06c,5cf24bcf,7df70669,54e8ca26), -S(349382d3,95677d5c,f259f280,83c88ec9,47da1351,d26710bb,4a21d54c,cf770331,7e81f343,a9413313,91b9e4bf,e680a41f,bcd13598,bfa2fcf0,a17439f1,e8215e31), -S(4bf9f078,cacdc26b,5862aeca,d3cbf4a8,3c4321c3,62a562a9,eee4a8bb,5dc66125,6d38018b,4441d376,dd9f4bae,6e22782f,efb1c3b0,2642021c,31495b5c,8ab3fabe), -S(cf319312,ce28b168,ba4b41b7,8f06e0d7,849e672b,21aff86b,5865d32,4e0aa0f1,d1caf763,6d277e8c,edb4e03b,b676718c,7318e29c,e756a868,6932ea74,cd10a84c), -S(de892197,d6db602e,13a9f3e8,d36509a,8e79fd15,f25c9cfa,4e610ff3,eafde1d2,e2454f06,569b9b7e,121534cb,31becd31,31856640,16d5d266,a98fedee,f4026ec)}, -{S(6efd8760,aed4f239,bd97a00,63794c4,ef14acc9,f5b94862,4c7f8b51,3ff35278,74acac29,694c5307,aa221b37,f2ea068a,a269fcd3,c6d85aaf,a8c8eac1,17d7f997), -S(7b466cab,a5820335,bd6c9e51,7f31e735,d3e9276,18c36e6f,861d032c,f2c0efb7,12e04a7a,953d1ecc,c0cb9cab,6e06255,f909bc3,e0b9f2a8,e667150e,1eb879b6), -S(7d73eede,ef4f9ea,34fe9a3b,9555307c,5a8a0fcc,12bae70a,34e90b07,fd3c36eb,e4f4b5c4,8c1ecd05,e7110725,c7a39a61,9f66203,3b6a6373,fa966017,2f5c611), -S(a8d37fa1,c07cdf9b,dc6b77b7,cb6c3e5,99930870,6a2307f5,c7cc2e3b,333a6d1e,665e43c,58bec5db,c87595,8acb5fea,89a0a742,641f4df8,f1c8b238,1eee0774), -S(1f4a4126,eae02858,86df6ce9,3d6bf107,be37564e,66048131,43ff65d1,48ce4ef4,b64de137,1bc84933,95058a4,70a7135c,6202e5d1,c7406759,5269cb98,2e1159c1), -S(5f963c6d,355346e,9feb82f,90921c68,7df67c3e,6d0db15f,ee46d58b,60bee0fe,12f8f5ef,326e9b9,68ab60cc,1331fee7,11c9369b,e887067c,4dba63b4,707cf1c4), -S(93cb2373,e9272b3,378d7e29,59d7d935,e6395529,5b2b6482,15afb9b3,9bc5f573,45bdc11,d37edbd,51e816e1,5d27715e,2f50fb19,ed9a0190,573adc61,2f38db2f), -S(4f231e1f,caf63030,f596cddb,7afe9fbe,2ba93d0,e8b18213,79b349b6,7f8a3ab8,7fbc097a,f61f0c69,9b8b2660,51d332c0,ca8134c3,1c4ac6a8,d1a820f6,a389e9a5), -S(b3ebee1b,ccd21d5a,e45bad73,85779014,216cd61b,7cac39d7,5af121b6,b7438a5,a0c1a664,379cfa7,2b3a1ba8,6c6ec9a3,a62712be,1df870ee,df945b9e,62727b08), -S(9713f024,1e06a7c3,7953fafc,1fe7df85,4bef044b,28358dca,bcd82609,1a9adb0c,439c3a8,9f48152c,2a1951bb,4b70da95,3f3875c7,82650643,92717640,73f1a34c), -S(42ab6939,246a9574,185a1c12,89824dc4,87bfdf4f,bf960517,87a441b,5977d3cd,e5e24a17,416cc7e3,a4fca1f3,7666d42c,a8b19e05,28940a07,2630f668,3babe748), -S(8080c977,bc2ba584,bc40b6b7,50bec750,cf80e367,a45f64a,6639d15b,5fc696b9,e5e8290e,917024e0,5ecf369c,4e2fa4b0,76b19aac,d41f6424,7353a2b0,846db72b), -S(300d9c06,89570a8d,5066039,2a8fb68c,b84b6f7d,4629ace8,51e6aefc,5f88632a,ce1009c9,4fdd9778,50f2c2a8,f30732a3,253053ca,635b34b1,801844ea,90137c41), -S(42ab6bd7,b4a48239,3c17c778,ec1423d0,ed684ad9,41b0eb9b,ecf5090e,51a2aef5,bcd4f24a,9911df81,500c2a76,98d434e2,a5f6ca84,ab4d75c0,7b7f3460,82624b48), -S(34c3d12e,1dba4daf,aacbd46b,7a2b5506,874c150e,1c5b7f3c,3ecc3db4,b4234c60,647d9374,c25ad658,d5081ea7,ff6eda03,61cd55c5,3c8cc862,85a83bd4,17927108), -S(ed822bf1,85d879e9,94b40a42,b000b93d,8f3439a8,e1800479,fbc1c3fd,61a045b1,5e25f76b,5f44666,d94eeffd,72278034,e5414f7d,c12b3858,424aeb73,3b84e4a8), -S(66b6681d,683c7d09,963992b3,b7965df8,e152d1a0,f296a0e5,16160fa5,357c6230,306c1d1,a4e6fd30,2a9d6581,e9b1632a,56eb67b7,af92a8d1,4cbe33f1,c34f1098), -S(b80b913d,359a179a,1ded7997,f833894e,6a9f6e6e,e2d05bd4,aee84b17,13ec6369,dd03d2fc,83aec2ab,9cb999cd,82a015e,3720cdf5,a9016b35,178ece2c,a51e4ccb), -S(54d6ad3,34f5eb7d,cab082bb,e188eb7,185f6054,e3335e6e,200f8263,75b930d7,9c1f066f,bd6f050,3099adf7,e9fc7960,86353a6f,4ee8c25e,fda4bd34,81db0e67), -S(c782fad7,aabecff7,d49e45b4,495fa462,168fbd90,fc14bca2,a216bbf8,daf7f344,e94dcaa8,ac3a9363,cca59110,d42375c,988016a5,b41e64e,770b36f9,87eb23e7), -S(f8cea4a4,b451df9f,89a4e9a3,8f586d04,5fbb1640,3baa242c,4b12f7a9,97aa7b59,da610c68,9fd0ecb8,4b0fdaba,3c34a25d,70d0883d,3b686a2c,c3c257b9,68800ddb), -S(79a15047,b34dad08,500e67a0,8ba08225,31bea87a,3fea2b1e,223c2aa0,4d083e92,4e36831f,183cfe2b,5a6145cb,716ebacb,5c29c71e,2c76e51a,154db94b,8877a463), -S(c8d6d0dc,dd1dfbcf,e4d90d9d,8320f5cc,c9a141ce,7758df3c,a3252045,ea8f4789,f0275762,5102db48,dee39985,e7a91b50,4ca08125,b42de955,f3f6421d,62e29548), -S(a619ef08,787410d3,aefbea3,c6d53427,20e8359,f483a8d3,2f588d99,ece6b51d,f96dc23,1bfca372,10fc1834,8734e4e,28cfa3e2,fa5bcf82,2576714d,363d46b2), -S(1ef02ccb,45ef1e3a,bfcbe970,2f839ac2,845f7c4e,d1b2ec5b,46400db,df4665db,8aaf2a3,8dd2e57a,df53071e,4db215e6,a9885803,29c418f1,701dca95,e37f9ea7), -S(ebf69ecc,320d1188,80c6518,a05f824d,2f8be63c,77401447,fd57e381,76f52f6c,996e43a1,647c018,507a49cd,3867e73c,e0f82630,d36c9ea2,6c38bc57,41aa59a6), -S(1ec42d6f,eca86040,877404e,370d21f7,9497ad3a,2e527bc7,b6ebcd97,a5407c0a,f8180e23,290c3285,b8eda149,d26780fc,8f3a47a3,284ed732,e57e7c6f,a1629f9e), -S(f8ac97e9,a3c152f0,c71098d1,816011e4,644bbfa0,3578412b,6f03f5ad,5495cd0c,df74b06,a4ee84e1,a55836dd,6ab1a681,7bf951b9,cf163dc,70ac6cec,e286b13b), -S(557b9739,5cf5aba5,676ea063,1d404c9,b8abb95b,8672889e,d385bec5,6bbf5165,c7df864b,be165b82,5bc10790,20306b9b,8f3cd384,67edc2fd,bed045b8,fdcd09f2), -S(b44a67c3,4d85856b,62db523d,b15e1efd,b882855d,c63a7c6c,17decc01,1cbbdd4,d224fac9,dfe6f504,296703de,a7d67da8,6c530641,46823fe1,81d2c994,753d838d), -S(c9df9666,ea8eaf4a,14c8847,90e0e456,35db94d3,4d5f0680,b1727c8c,a863e398,10917719,32d9592c,fb272952,2c1a1cba,25020f33,95a6ada6,f85c92c1,996906be), -S(e56736f5,2c77db45,66bb0c10,46c8554f,444b829e,72be61bb,cb376b64,83e28683,2f32beaf,ba8a5aa4,5fc33816,ec2432c,9fe6c76b,172afc7f,8eceb879,f29651c0), -S(bebffbcd,bf56c1cc,8e42824b,ba8f0b4c,35cd732,d1eb160e,96a8ec55,13082be7,5d84e045,a5d285c6,be65e663,b51da6fa,acd3787,7748c439,73eefa88,88263df9), -S(c30e6d10,a518ff5b,2537c8a,89d2e447,c0d7518c,529c4dd5,b9575536,2d9f49f9,92da3c0e,f9ac9946,eada43f6,2d811aa8,26da78e9,849b847a,9fd0b0e,5e71d727), -S(65bf5bd3,ca8f5dfc,9a1799d0,357f24e0,2bcc4b5a,7706a454,3d08a,34512abf,7234a79c,a6c4598b,c2480b8c,5a5a8ca8,f343c41c,514054f7,42611d68,80277041), -S(680c6de7,ce4b261,3698ef55,185b7678,3d6ae7b,9587bbf,89995034,ce361a03,a22146e,3e025e43,565b5243,89bb57e7,6af1b740,7769be7e,6cd29b1a,1d472765), -S(83ffcd78,14a1455b,501381f2,523a675e,92a3a688,aef481ed,aeb0fd0a,14c37671,d780b968,b263153e,e1f5657,de678f55,6e43b840,e17e6eba,694ac093,dc9e8e7f), -S(b8c2376,6ef2d21f,5505b265,a1b27cfa,f0f5a59b,54b31407,1fa9ef5b,2457762b,28249c7c,25068a13,ce473b0e,896ece13,65a23f57,2626fb7,e5ac1e33,7976aedf), -S(99327a6c,b7606c32,92d98fb8,799f5f64,cfa4b0c5,4fba99ff,aa309287,d034bb1d,aa09fe57,4883ab5f,6b07830c,d5c12121,de3bcf52,68f8dfbb,37ccb8cd,61cfe55d), -S(3a9f4dba,2fd6493f,bbb21e8b,d36644c3,d4da0699,faf8029d,4ac7654f,380a18d,3c8c87a0,6bf2315,32a5bd1e,e44ad483,b44ada12,63d4750,6a55c567,7121fbe1), -S(65aff743,11534071,2676c7cb,2e5762ca,297acce8,535534bc,e495e27e,2b6f4353,5b11d44,8b7e2593,b8964f7,317f78b,5eb4d169,d968aa17,91259135,15087ba0), -S(457e7433,e8a8b719,e6e6b506,cdc1654f,574e5020,4ca22877,f36770ab,bf855eb0,949d5089,389f939,5e762659,53aec631,e369e8b1,38e6168d,b6528405,bf144ffb), -S(83253254,4261c8bf,b4a32676,3389afcb,9ee3d56f,44c70c08,e9e70bef,fbb092b1,3ebfdef,f0bd720e,611f0c8d,85028d87,8ffbb5d,7c19c3c1,e7a0832a,2ccbc0df), -S(98ec0257,7a1e4b16,369ffc2c,f17b0ff1,82af8b5e,25ae498b,e7acdfb1,b069e572,e2c72d87,67d16e14,44315c3d,9dd3250f,ee7c5ed,73337d03,ccb8a4d5,743537b), -S(d4b815e7,1e29d5d9,7e96c122,7ba6fece,60779b1f,574adc23,b53bc206,99c3ccd8,df98ad83,9c4a9133,d78b0d12,a8ce8765,61a3530a,29707357,65ea402f,72db0cfd), -S(88753aeb,3045bf8f,335a59a,9bd4287e,555a9005,5940a0d5,895b19a4,be237ffa,9740f21f,4abb4d3d,ae4b5f7e,9b5ab141,810ef2f3,9cf2d98d,570dcd1c,4d330ae4), -S(eae3895d,f081044f,6ea4a9db,73dd1300,b4a53f5,2a5429bc,fd60cb6d,733efd9c,4a9a829a,14149e0d,a629498,a3e03cbd,723d807c,a47a16cc,de5b9c1,a443995e), -S(752b1e2b,761e8633,7c4ec063,2fe7f626,e7038632,d93ce2d2,ea789825,97ea0d44,edeb1b08,a076b69,9fdbe919,e20dbee1,223c33d5,ffc6fdeb,36a5d1fa,4399b8e7), -S(9854c41d,104d82d,840fbfaa,d4da5b51,40c1aba7,80bafb5d,24646e10,a23f8a4,c170757f,23eb38de,5412e2ea,3a040c8e,cb10305e,69290c20,32e2719f,e26bd499), -S(81d720df,c9396536,5d977db1,410d4a5c,fd5078e2,21e368e0,5a8faf83,44097d1c,a29c17b5,518001fd,775afd10,693865e,d84cf3f0,f7bb44db,c5b3bf27,b192be60), -S(555dbc1b,7809b8d9,9db97d6b,c9c75ecf,4592fbae,3784e2a7,2150bda0,e9c8cbe8,963fb2f2,9277580f,9ae5668b,f31249c2,7429cbe2,5bbbd296,81574ae9,35e8d443), -S(31dd018d,28c81808,fce67b11,f621358,71be0366,b04d5f69,73b3f11d,df2b37a6,43837cb7,c56c10ad,1fcb57d,91bb293,aa91740,a8c5427,3f10bedb,560ac06c), -S(8c3e7d99,cd849afe,4c3e8ab8,af410bd4,3ee951ca,10307e05,4f569854,e8752d48,fd4d3081,69dfb22e,ddc706d2,36bb1918,7ab455dc,eb44e362,eea2863a,3f0341ac), -S(6fe0f368,f918ea70,b130864a,60e6541d,23daac99,49a28e44,597315f6,d85ad4f5,e30fdae,7c6731a5,ddfefba9,ae685a43,21619203,87b66a2c,799d84b2,f2d42c98), -S(f181faf7,623f82da,aa7730d9,56dfabc1,b4a662ce,c94282fc,dd3852e,8a43b91f,2e148d3d,9c470d9b,ca5be26a,5e191154,441d86f7,d6234085,203e944f,529e7256), -S(8cf18f22,23085bce,a35c8406,d9322ade,97eae156,4f741e36,2d3f57e9,e86867cb,e5123dc3,c5be133a,f25f90bd,de7101c0,6b2ebe44,cc83b7ee,a267a3a0,6a2c2b4f), -S(72cf023a,8d20a4fc,3ad5937f,cad6f47b,1030e02d,9ab0cede,58794a3e,f5c9c6dd,a2d02506,35402d63,85d0fc40,af954464,15fa929d,3dd95c,d4159edc,300fee82), -S(6c87417c,7e9ce90,b67c0ca1,469d91f0,98a9e67e,850ec140,fd489ab6,b4477ec0,7aaec9f9,a443bad9,89dd08f4,8d397d3c,35d970b,6cc9eba,df64513e,57227106), -S(54ffefda,eeb2a69e,8de97265,e8d7ef5a,576a4f1e,df7ceba1,7f94cb3a,a83a96ca,7d76707e,cf533f08,2c3e63cc,eed8cd18,9bded8ce,835a37cc,549b550b,5e82a3a5), -S(9dba00a6,d186dc34,a21207af,9aa597e4,432b8fb1,b1fbbd30,6caacbfc,4db25e35,259faa28,e791002f,138468c6,34e0c20,c5555b48,a1b8a35,6d68accb,41d8f7b8), -S(2728df39,afbc765b,38f47b21,6aca8cad,33b5b2b6,363cbdc3,3ed434ba,5c9201bf,de91b280,6bddbef0,562c02bd,7d7bd16e,7551095d,534a2566,9618539,5e22a4e3), -S(77a45f41,2353ddf2,d8cf7ac4,afeb1a3f,df6d20df,702e8207,f29286a5,c3558ba4,f1f5003f,510959e,93be5f5d,7d4f9498,70eea705,51b2383c,22215a84,8ff83fbb), -S(a0da4abe,d0890614,ba574a88,ffba223e,71163293,b4ed6df3,8b5b6e6f,997cab0b,3f542151,36570288,344391b,d3144b50,55545b2a,90e78b9d,20f894e4,2f43bff6), -S(202b20a3,c8979884,9a275f6f,7fcf6e11,4a21309f,2f340387,f663eea3,e1121028,35001416,97ae4ada,4e7e0b01,e9712385,ad971605,6e6c0cb6,c1cb6bdc,b12c3363), -S(7288cb0a,fb450439,2ce2867d,3ff3d2af,71344402,a7ec2198,152aaa40,9d85aa32,e39ceae9,6d3fb740,91531079,9770ffda,fe11434b,b5ce8213,deab8b43,c9426006), -S(de1e33bf,bf324b9f,dd8b305c,1d77e868,61dc6402,b083778e,b488275,1609417,bbcdd28a,13e3db76,e76f836e,93a4e54a,8550a389,5d02a03e,a99e80ff,cae1e3f0), -S(c88f921c,c2dc7aa,1b48d681,319a259b,33313e5c,c31ed767,737824dd,b99fb563,66ac4897,206652df,fb7224a6,771f32ae,bd75e318,21164444,62419320,d45f5e1b), -S(adc40ac3,97458429,6277e8c1,3f3b0e15,d8ab082a,e024f8ae,901cec70,36083690,f0497ce0,2c79352c,19bf649,4fdcb631,60c993b6,6d4c81a3,679a8006,b6e31779), -S(f72b6a10,5599d35e,4f5b107d,a2f9e8de,f1ce7211,7c03c8a2,5695af9d,d4a42926,41306d43,7d83913b,fdd51a1b,3c9cdbca,5d4082b1,756e1f5e,2c2851fd,b50ceed7), -S(f8bf4a89,b8577191,98efcac4,a695f9d5,d9d7f017,c9c0ad26,ce8301bc,575d8771,ea762173,96b1873,843f07f,826d6d69,e985d38a,119d7923,99b20484,cb20d8d3), -S(83523352,714c758e,3e7d1627,44e1fbe9,991b0c15,efa1345,fd9cd41e,ae84fcaa,d209aaf9,e7032525,e8f496e7,7b22011d,e20e2c0d,901e835f,2e64fd4f,d6b44e6), -S(12f7f577,31b61df1,a2f699b0,ae85b95e,92ae1fa9,7caca4a8,7b7cb6ac,4fc19145,2c52d855,505de067,213e3054,8d7416fa,ba042f93,27c21cd5,b47086c4,d01696e), -S(48254fe5,aae306d,54a14098,c87a0bae,4cbd0540,c8d36ed6,9c19abd8,ba0738fb,6f37a602,ce702d45,549ff185,338b150b,17bc868d,649ba4be,b99ff744,5ea70f3a), -S(5212fbaf,dc8a9270,fee8ca9b,ce872a3c,b875c3b3,202f92ef,b5327a4b,e466401,73fd045,69ed0d82,4169c191,8ee937c8,87824719,120996ec,11a9fdc0,ce4437a6), -S(855b8d00,c3f84266,6af52981,284b5845,36a06019,3b722fd1,483b8dd8,2880e0b2,5b494189,5d3c558c,548ee414,47327cc,13ca4e7a,5b8eb7ec,7d5da63c,7f89006), -S(49faaf81,850bfce2,7752768f,4808c91e,be1a8999,f4673650,52099584,37ce9747,6eb4c92c,a2235629,c90339f6,d7c5f136,a2329eaf,f26d6353,da9d4679,f07f8db0), -S(57afce1e,5164670a,7b3a8a8c,cbcd7261,a8775833,1f74fee,7b541174,9844bb5c,452fcaa0,1237bfb9,f3d97bed,4eda5fa9,ed72b580,c2b95953,8eb227d5,60252fdf), -S(9537b024,4e19fbbb,c17e42ec,9ac4c5ce,51fdba4f,51e7bb28,ea53ba77,661a8728,43153797,f2b3c74c,ed3cfee9,c9609683,36f2876f,2332e95a,cbfb6d5e,84dc9f3b), -S(bc816077,c64469e3,a663409d,5e175b45,ee14adb1,703e2bd3,7692b38a,31d49c6,7f5430fa,11e07543,f781482a,f95b30d,d58cc8e7,e8107b6b,54f314c0,c8e77e64), -S(dd03731,e07f5b55,3178ae07,7df0930e,de774e47,3e52e028,b7f39a5b,583f1d1b,7cdc1846,fe08633b,f9fa470b,7710d02b,8ee07902,e38290f5,788094a3,61174168), -S(132ba7c,e36518c9,195ec6e0,cf3aa576,1f0d3b76,d2124fc3,b43fbdf9,bd196170,7b59d248,388297dc,9f72b75,b8aa607d,327cd873,8be5c1ff,e8e035ba,611d599b), -S(798b3663,8f3758c3,93f93504,9584d055,e52f9cb9,abcab568,477f3265,68f5dd80,f270bd3c,5b236c6f,92bf2937,5ae4761e,1e5418a2,716326a,c62707b8,617c2f1f), -S(1db26d05,f64a6f1f,4b6911b8,3cdcfac1,bfe57344,7319baa3,8a539fa8,dbae42e0,8185bb2c,8d009b27,c7edb12f,d1760a13,e2e97747,52c3b961,48e7cd0f,2c0ca28a), -S(53600f43,411155f9,676fd005,ece88e90,ce3f68eb,bf9f418c,b1ccd460,94fb9013,e87314ca,ff3457a1,ef3a12ab,3e8f7a54,b80b7e81,91cf3378,cbeb9a1e,bb02caea), -S(31445cb8,39f9aa76,4fd46b4e,b39f0fde,18178467,81a4b1df,e9523dd9,9c37a732,58ef4007,d56b3ecc,cf08f220,d5b28cba,d9e6ef50,cf878166,9af25bd1,16239ac9), -S(3968d2b0,80d50365,b4df89e3,a50ed48c,fb41f5f4,630a1fc8,67a072cf,36775c4e,15da358c,9a674846,3fb6d243,8e8569fe,4d9ea766,713ad5c7,15461485,c876f215), -S(a040c7fa,1ddc8d42,efb964af,ca365776,99f200e8,d23cf93a,653cbfce,ea24507c,7bb2fb2a,57f4749c,83f696a1,4c974781,8af4ee58,c42c0718,1fdeb867,f54121c3), -S(2edd58db,873d3d57,42bc774d,97ea6197,152a57ff,b0f747ab,1d26f577,b8cdef89,82ec3302,ed5ea5bf,79e696e1,d67d762f,9573f895,ecf3a891,755dbd61,c11a7702), -S(b519f379,8949ae1e,1138e3c9,9a9486c2,77f44ee,1f9aa34e,b54a34c2,6f394313,5786b86a,7913b9c8,e38b6bf,2edc278f,2d4807ce,834c30da,ac3f5222,7af4a458), -S(d3be1b71,d03703e6,194d5ab8,ceaabdff,4a970fab,60caeebc,13ffadc5,3f973757,176caa0b,f46c299e,33e5ff06,294bf813,530cf048,fdd0d98c,dfd3e9a0,a42c33c7), -S(85a03707,c13f7b49,878abf34,cb77fba0,62d3d1e4,2b00f7eb,6e159c66,48290fbf,487c50b0,c811356c,499ee9fb,5fb78a84,98d70194,62a15417,c0e883f5,6baf6f45), -S(fddca890,694d87de,a2e0f92d,1e9b9e9c,7420b4da,bb5d2a89,3d282dd0,53d45a15,8a896375,7558132e,d1137feb,fc9c9c0d,4e6a6de6,1e75a8a8,ea79664d,893dcfbc), -S(d7cb9e4d,13e2b747,6f91a951,2aa93ce,c954a542,c6acd5cf,ad65bdb4,63071664,2880964a,13083d03,8755c9eb,9c2c8f57,b68660d4,a5227ab5,261d6ae7,c9ba708d), -S(98f619e3,76e7bd91,f5387e58,b57ccc84,90a6fd68,1a569cc2,caa253df,86b6959b,59d49098,67b3c6b9,8ded8edf,a67f5c4d,4ec7e,8dec78e2,68314f8b,f941867a), -S(35f36793,f5dc6d0c,c8adff91,2db459c5,dd405272,ce45031d,bb118383,d108519a,568f7399,aec63e71,9c63b0d1,480a9afc,662c8920,4bd7ba30,71b0eeee,ddf3ac2d), -S(c7e043b,b02f15ef,689666b3,8ed29704,a5059027,ae23c3ba,f75a2a90,642934c2,cb5e67d,551e180a,42274149,127c75ff,2be6113,bfe56f46,47008ff2,d6b72578), -S(cf95cb09,19655249,f16bb911,9488af73,c74ff5e5,e508e322,2a044f2e,1fb87796,d476c517,3df5b269,889ac45f,5b095db4,97c63334,ce233da9,4daebef9,aa2b88b5), -S(b38ad8a1,640c2aa5,b77db077,8a7ef7b5,b9795e36,20612fc5,e48c3ac,6fcdeae4,5e97b2cb,8dc7839a,d1f80df3,a9a7e203,140898be,6a6301ee,c3aca617,366edf66), -S(d39404f4,c9e59b56,41fbe43,c0abf3ed,4ce9065f,6d4d0224,b1cb1b33,aa97d3b9,573e8e27,44903ffa,8e1efbdf,56d3975d,23bac9ac,de0f758c,1d018e7d,d049e49b), -S(9adce43a,9f603359,5424daaf,c0ae565,c468df8,6beb9b49,ff533af4,496fcf32,e2cc9853,af216c00,4d71949b,c55a2c44,38655847,75cb2d00,ed96c5a,6f143f01), -S(66d1438c,8c9202a7,aef7d11c,682fed36,b88d5978,d7611a06,5d2ec2a1,b5aa8bd2,d1cef3de,eaa43df,617a7fa8,3a22fbcb,f8aae418,5de59e00,1e11b37c,d34cfd05), -S(442be1e4,c65e3e33,db17ed63,d852e62b,f8ff33d3,589a99c6,8d2fc4b4,dc8bfaec,63ed32e5,6bd86b07,6fc357,cd556c62,22402d35,5272f42b,a982a496,1f7889b1), -S(9c80efcb,da724a78,f6dc4de1,618b0d39,cf383c6f,d104bdd,2476147e,b6fade3e,102a9767,4ecb12be,71aa53b6,b0f353e5,6a06f1a7,b14cfd31,d48993e,4e766b86), -S(a2d10bfd,bd01700f,1c105396,bd78c7de,7baf91de,ecabc8,94938ec5,b4d99951,4a7db817,c4ce92c7,eacfc287,91992398,3042412b,ab017689,9c4113ba,6ef4bc3e), -S(847921be,b36c0615,ae10e9c1,b9791adf,667d1896,3af938e5,365eedd6,f888ee92,c4ee9b79,91ec9eac,9c08ceea,f610ec27,b3a0be64,6684b3b7,8ad1c17d,380d99ba), -S(60d7dcd6,879f9c5,6a44cc9e,26f5a5cc,6a6500ba,99fbb676,e5992457,e611b840,c4128d09,7ca3a257,113aa74c,29f063ff,52e39bd8,c8a4bd68,4c822cd3,386a652f), -S(e3a4e2b0,5d227414,38ad53a1,5366c13d,7d377dca,fed5be5e,61387448,1e3cd263,fab9bc4f,12cc2130,5b0afc2c,275cf3c2,c12682e4,1c772776,568f6219,63fe9c5), -S(af13018c,89c75180,af73b61b,5ccc891e,b42592d0,f2345c39,926a0ea2,402d6e87,eb122961,6a01567a,1d69034f,e8ca133,136694b7,761f4500,25754951,c9e38b42), -S(a3a7b943,c5304cbe,d736b95,fdfc2283,f54164c3,bc3d186e,7b017d1,dfbf9464,7b779d12,909078fd,9cccc9c6,73afaf1d,bd206420,44f941c0,4a676aeb,e2eefaf8), -S(ee99d382,c6f590c8,a9e266d9,9500e9ef,cd685630,71052e95,28be0aff,330e5476,541966c1,1cf15028,a6448de5,5837bd73,6aa11b70,bdaebc1a,1e8223ba,7a69d146), -S(142ba015,699ffb3,e6e02bd6,aaf084e4,3d100421,c5aad92c,f636691d,dcaae138,94fc5a5c,cdb79bb2,1cb733b2,50a0d4b5,cf37cfb4,75ae290b,4c53cac6,43ca7aeb), -S(75f254ae,9f98f3ea,17d9e574,5820a2df,16ef6027,d85ef056,75790b92,b345a144,63a94cfa,2b289f55,300729ce,77f9a5d3,681b944b,90719028,cd8de938,2290137b), -S(f6db52b0,1ac4f26e,80ac7f49,fc81cf48,9ebe7df9,d2085d2d,e08cfa7d,3883627,ed4006,f6c6d8c5,2bfc2fb1,8014f69b,7fce7868,7c0217cd,3d813faf,8518152a), -S(5418d34c,61fa1981,be925614,c56ac5a9,651b90b0,367cc6f0,23f4ad3b,3455798f,ec800abd,42af6eae,3584abc,cfccc4b7,14e98700,539ba36a,925da30c,ef57ebb1), -S(7ac961ec,59031427,8bbb04e4,4e79634d,a88f7cd5,d26d6ac2,a6605273,7adc5c1f,5ae54a73,cbfecefd,5574b29a,4ec5aa13,1912ef14,491ea386,85ca63c5,ade7e914), -S(eba2daa1,67aa43b,9d8d1ffc,b0784ad0,8bc563f6,243401c9,79d13396,bd9351f6,ece65820,bbe5bf06,6300f1c2,e16af4a,4d05263f,f4da582e,9e3892d9,9063a1b4), -S(bc674e6d,62757b5c,f079229,8b624c93,d1765e8a,44ce9abb,84047873,c62cc601,8056031,468638d,251fc37c,751580e8,29dfb130,f34c7f79,31618d3e,8c3b0ac7), -S(d76792aa,b3dd3405,45cd8374,958ee104,86b08dd8,1e1b99f4,c02b387d,b9cc3c9,63e21256,6b92c21a,378ce4de,cbc28dd5,2b563106,cb5afcb6,95f2aa02,fad96eed), -S(b0f0830d,80cb007,8c8f84b0,d753b059,6dc0f1a2,456cbaf1,bff5716c,158eee33,7d229908,b8acd65f,62a4c9c2,aaeee8b3,a1355e40,492552ce,1283fc52,d512fa4c), -S(86ed6a70,2cfbaf34,542ce456,b589a492,c9e19b4d,b18f4a73,3f257e1,2902bb3b,ecb26bfe,700e06c6,598bdca7,d0eb97c9,5992e438,c6d490b4,b2907af5,3850ac79), -S(fc88d9be,fe183b9f,3d952f51,79d0e2a7,2c56b79d,2a3c4408,948f4887,bf5b6113,c8e6d8a,91329b9c,c197c41d,8f2858c0,eae74ee4,5fe259ed,fd93bba9,fe3cb7e3), -S(c4e1983d,e86d3856,5381dcdc,e11910d9,2c96700d,a67bf713,3a6bf601,7461d444,39af034a,a1f8caa0,b01e4a32,2a8ae84,8e93e9a6,9c97fc9e,f8e8df08,2b211e3e), -S(6dd8075b,4456919c,bc97417f,7a94f6a1,bb9c07fb,8ed54986,8deb955d,bdc65eaf,bccb1ebf,57a86b87,2119eea5,17346eaa,bdcb5fdb,b3a71930,7bbcaf27,59781a9e), -S(a4ef5a0d,1e9a65dc,f4310820,4a2ec8f1,72aa8a8f,71604c8,39b026d8,a3a3983e,a7d682d,c7dfc382,a67678ee,12eae6ab,b6cfdb1d,7646f4ab,6c1d9269,1fbe338b), -S(9a250997,84509b90,f17c29ad,2bb39ccd,42e3147c,ab53c2a0,a739a65b,de4814cc,fd746694,ae6abc3,6898bf52,e0e6b3b8,a63766e9,d2dbc867,3f9b17c8,9135e4ff), -S(9e7b2662,58b0b90f,707211db,a9d4610d,4f49d08,c553dd00,f58c242e,2082c095,ac8fd168,bee47d4b,c8b2ffa3,72fa3ae2,657c435d,4d9f4da3,67c8c232,6d4b9820), -S(65646ccc,5f53bce3,edf35c57,137b7f5d,a49e385b,f101c5c9,b6182035,c45e0e0,6ae3b77e,cd3f9837,99287240,6a70ef79,c3dfb8b6,c3704f3d,9ba248ff,e6344092), -S(15ce9fd4,a87cdf9b,71e435d,b2148927,7ebf17f9,218d0d57,af3c632e,e227e2b1,47857e6a,2f5a9710,2c082dbd,d0edac51,65d949bb,cb9a325c,4f164958,a2413534), -S(ff44a162,2a259be3,512f234b,dee87a16,bb9d7739,cb84e527,29d60fb4,4d073fae,5ada42a4,9190f1cc,e16cea1f,392b01ba,89969695,8926f16e,f7aac2f9,a9cce2cf), -S(a5f68def,8670933d,907d508,185c3ce1,a67c62c5,33c3d65c,3c199d08,33536f99,d859eb34,2bd36baf,7e9f36de,f1dcb7c1,db6f0e19,12e7c9fc,2799afad,d210fac1), -S(4666bb71,c1e24ae6,d6c0f9d3,5a100fa4,309f30de,cc4c4935,9c937f51,243571b5,aba13ddf,96be4e04,97e758b9,d0532160,cbe62077,78297e4a,30a2ccd3,459c9e36), -S(131fc338,b0acc38c,b817a182,fd4919af,8bbaa00b,e0d80ce9,b46c50dc,8d7e972d,2761b62a,bada1136,4bc7bc3b,4fe7c0a3,b6d8be3b,d05bb3ed,dba2a071,188812b4), -S(5232eae0,3b377985,7e57c34b,4f9ee30d,a97714c0,bf33b63b,d520ec60,9bb18557,c243b06,ae8404cb,a01ab038,da6b8708,ec6698ee,f6d0f555,85f5e0,6d8b2330), -S(e95e4da8,afbb1484,ea1bf378,642ebd59,de13f70c,53f2b470,252eaf5a,c01823bd,dc77ce77,688e13d1,4083c7d1,d91fefc6,bfabde0b,bde46657,d3080d15,51cde44e), -S(9f3a7cc6,759db98b,f6b45257,8aa1a8ef,a2601d64,64028025,ddeec5a,c6fa8b6e,e5db2c3e,d23f72c,47d9d5bf,8bdfbe98,b9a1e97b,57d8a9f9,60f10fe9,8056a4c7), -S(96981f2,a1e0c0b2,1eab0a4f,fa56283a,5555bfe0,75ef938c,66dafa26,8f41d946,ae191f21,841ad677,420a77d6,ec440baa,c1426dc,dc2449a3,eeff6f7d,94e4f012), -S(d805bbe3,a8771fb3,3a22c51d,d73ad400,f7656107,3767fedb,3babebd0,226a1244,5bad82f9,ed6a1a7d,ca0532b8,87c7d7fb,1280c05a,f461321e,9065e11b,5c7aec51), -S(ae3b990d,32ad44a9,874da8f1,79e4f7e9,fca965c7,d7281f07,1df80c63,2b9dc432,3810d68a,b5cf8ee6,af08c822,d922621,8197cc39,194ba913,492064a8,5405a346), -S(69fdac,1c5be33e,fce9fb73,49f936d9,ad0d9afd,e1df6d00,df6599bc,4870b6bd,2fbb05fd,3e82f2ca,8c0340e2,d43f0d99,98f12f1f,c433046a,52aba97b,9d30ff3b), -S(1b0c0ecf,b0e9e6b2,238ee645,e33b44ef,5f102985,77df53e9,26fc2f82,d1aee964,9400ea2e,ba2d25f5,2607b213,8b30475a,67e5dbab,bf8e5ca3,38f84bd3,947adade), -S(7e2e1b2e,8f69a883,9d9e3993,312c9bdd,78a2390,251d4a1c,209b0caa,47eb0171,674c4c18,e61fd02b,660ec735,67fe7340,591c2db2,924c9430,bfab3948,d3a84eef), -S(d42acdb,d02a6a9f,da7f9d83,9d8c240c,7ae50331,3aae1d56,a0e1798d,8e668ba5,2c54cff7,bda5ac87,3d044272,b7bd52a7,dda6a14c,c9bf9e07,3b0375d6,6489e70c), -S(6a746102,1f9780c7,5eee2394,823354ae,cfdef6d2,46892b1d,c7150863,1e6f4c93,f7957ef3,1cb47e0b,9e3563e8,1fbe69fa,1e687e2f,3e3efe50,d21cc4b7,26053d29), -S(ad164b38,d21a5211,84b6d47c,be01953a,5f5b8a97,7f0d5888,b9fd9495,691f2749,5709a9db,404b1a06,5f965af1,7ca7a2d7,f036f39c,556af11e,9a0a7340,52c2b5d), -S(867099cb,84481d32,d9a4f46e,2e3338cc,9d5f14cc,f65d97d8,441fc8be,38e36296,8688faf9,7a3eeadf,8a42e884,3e0ac108,90f7f417,8620c0b0,49d13e44,9190ed8c), -S(d52d12cf,3cca7ad6,ea0ed7a3,92c4da04,8d31e279,63b1a9e9,ee5e9d07,b3ceb2c6,fce207b7,1aa22562,2f589efb,750f984b,b52208a1,6c07990c,768020e9,9711a80), -S(da5ccb53,c4c46a06,1ffbb2e,4814520d,ea373d68,1d426071,c9ca49c4,db5efcc7,28b00c21,4cf71f17,601cd24b,4516dd20,4f12fea6,c7fac2a5,43a2176f,1f150aed), -S(3e8a38b,505d7916,8e518d17,39198d6e,65139b44,edb38001,72a92b0e,410c4174,f7b82a9,62980288,47e06c3,e51e1a6d,f2ae9cf2,e2468e01,8ef79534,a8d6e0b1), -S(42a6d29e,4952ebd3,7169a99f,fa59742b,58bc24a6,c861dbff,ce79346d,78b7bce6,e6da3768,2124c365,878d577d,d1358dd2,b39a4bbf,e25f8bb3,dc97a533,c40ffa7a), -S(728aac39,15d078d7,4b687a75,6b166e05,d9636a71,bfb1103d,aa78fd2e,b8f22519,db2159e2,a71d66e0,e68e504d,40d60bfb,34f8be08,838c1435,f9018ea6,bd88c876), -S(ab5218a8,a7c5ef3d,f7538035,a1812787,f6cc2019,798935ce,92d9fa34,be65f3d1,fcbb8182,d8cc462,7ad1082,795c7b87,3932e97c,6bbaa7f4,2af231ff,67dc7b8), -S(e655414,ceff2752,990448ab,9159c7ae,50490932,a356bf80,d1669a6e,ad808506,cc0bf966,9915d938,219c197d,37762c8e,491d7cc9,48f1c993,c4406dc,384018a8), -S(9ee3eddd,519e44e4,c53bd4a5,f7101964,ac47a421,c72fe25a,96f79516,96c078c8,31f39cb9,f5441d,613eb470,5e9ea328,ff1f0b74,3835e7a0,f9b6ab5b,bb9de8a9), -S(dd7893db,e0028143,fe5739a,832e4aa1,ffecb200,d13f7b1d,a4877234,4330c15e,a38052e6,e03f06ea,d3c3f712,964457a7,52c7eef0,ca315f56,4060022a,66f6ee3e), -S(e7ab0025,d07507c6,6cd34270,8c0a89fd,53195b4e,ff3ede18,69488886,9eb91cc4,caede34a,6f8cda34,77bacb2a,935113f5,93b69979,18102777,bbc26128,9b0cb112), -S(47f608df,6d649b02,e55fdab2,a2bb4743,2986b9f8,61460cc7,c4961f51,89b57e91,179f29c6,6dd174de,bfa95876,22434b35,2e48f45d,658bf7af,d26a19a3,50333560), -S(3015cb0,87376de7,a18e7349,556b2351,72f27f37,e3a217ea,c7a43762,bd3e57c,a2e673e2,6b0f1888,14cffe51,2ff43eb0,c241e239,1f130630,dfab55a0,e12c844e), -S(aa7f171d,463433c3,93139c76,71d1a0cb,8b7745c4,3f3b1f1b,1669e3a9,75120ded,b8c9d145,9f9e9651,bee3a7f3,fdb71bb0,6deaafdd,1912896f,4b6a0e74,6869144e), -S(1847e63b,ca44c694,9ec3ac84,773af743,337d2dd7,46b6c5a3,ea9520ab,5af25469,ac19fac4,e3dd014,349c44d1,3436cb8e,465a754d,eb3f3c2,ae71eade,6c5a067a), -S(c11064d2,f638bedf,f762b481,719c85ca,7797e913,79cc3d12,3137ae2a,7a273179,7f74f429,8b47a566,bd3b6eae,80b47dcd,38e8780e,2ceb8833,dbd74462,c8f3db3f), -S(de6928c,f298091d,d1a42817,22d8923d,de25c954,ebfb273,80e17943,c641cbee,b02cffb5,47247542,be586c6,e88536dc,f6882d91,e76aa7fc,8769c2b6,5c585cd6), -S(2b8b1dc9,f379f2fc,a30d1f28,7877b47b,42f04b20,214c0beb,13aa2d28,83c52d12,1f660659,b7ea56c7,edd02c57,d6daa12c,d13671f,b657dd02,e75905b0,64d51d81), -S(90b39618,3eea7012,c537b000,f5f1ad28,e0416fe,6b1b874,effbfbfb,b963be57,bf37d7fc,ef9ca5eb,6b9886a3,b6b87f3e,976535eb,31cbc0b,464e69af,fefdf9d), -S(4fdfd77c,a033de11,59fc95c,ae07cd03,c570380e,ad2a376a,957bb26e,89bd4a8f,a1b30601,245aef10,ee891ce9,83cdbc66,390baaf7,b9c833bb,ecc34148,79f6a866), -S(7e2c3510,9c0a3eba,7b8b9d4a,c3c8d1e5,31304e45,25404814,fd66c3f3,3f12a1a0,39a8b59f,ed4d9d3d,29d8d1c3,130c1fd1,dbe7f2ea,cbc0770e,fa18e76f,3322a107), -S(4b80ce19,a7101706,b4bcc308,a4cd92b6,f8177a97,e2b2b6e6,1ebc2ca5,32c4b48,b72eb80f,55486930,94c8bbb7,bc6985c6,29c85d10,aff7d243,e5ead021,2b44587b), -S(8b07cf,264b3d2a,21705a59,dd82bc7b,573508f0,597831e0,336db2c5,c3702e3b,1b992b9b,8fe1a29d,d9781827,edb8ec89,49f6d412,12fe7e24,212f805a,4c4ff0ed), -S(3b65c4e1,d3171be6,67b01021,55644627,d64f9375,bc36fd3d,2c2a4fab,47a59e68,573fc9a9,1a09f5ba,78ed796b,496e1d68,a3f529d6,d0a77095,5ad16baf,e7b1e047), -S(baa6b559,e674ace6,a0378536,8643b0ff,42d8ead5,1c8d937a,7b1de152,62956003,eac99c3f,696ee584,7080f488,3b112c7,f6c69b2e,61a6e20c,135f5933,86289a3f), -S(e6453682,6cb25506,4107be9b,b0c2c225,5038c11b,96226fd6,5f8db8ce,70e32fe1,f74e605c,71912ac9,5e2399df,4f3ad24b,1c3a23a4,4b5ebca3,5ab8f31c,737d9aa4), -S(1aee4f20,a2db8e58,f33a8eaf,4a8218a4,b93212a2,60aea21f,64acfb56,3c8c5e83,3fc248a0,956a3136,daba7450,49e6330f,845ffac0,c2ed2f93,36ad1862,eb8b331), -S(8810ec79,33613ee3,49e0dba5,4a8ae34e,67a01322,46830eb6,41dea38d,c47f5941,c9c15ef8,c6a57a44,e9ea1832,c1c62dd2,c8aaba21,48d2153a,6e5a9001,281a273a), -S(cecb3ed3,a3380083,c8217e07,4cc0473a,3cd2c9f8,1ca8bc29,4494b01a,fa1bdcee,8ea11818,8b25ffcc,7d83039e,af605c9c,4132c83d,e97cb207,ca83f43f,26a557cc), -S(ea24fc58,d19415dd,aa780932,f7fded2b,e88987f9,9387d43b,24773ba2,1b810bc5,5176a2d7,a5d955a7,6452bb2c,49048329,b83ebcf1,2f3433ec,79573c14,4446e149), -S(facd3728,c43fb0e1,7f03a1ae,a7997e47,615706dc,3427039f,b994e14a,9a06d7be,ebe7826a,fec22f08,3108c710,9b944cb4,c4427b62,11f1f85c,474da8b8,25965d11), -S(439fdac4,66739dd,82c29854,fa9d599b,6fae190b,18192065,8a6cfd7a,1cbc9a5,f8bba187,677d0d3c,d50ee132,3cda2daf,d75aa6a6,1fca861c,2836d096,d1e3ff39), -S(167491d1,34593c79,6cb90f5f,868cea3f,56ef9b1d,e36a010f,a9d90eb2,9818d9cd,38303727,58f84ddb,ad5733a9,ef131555,14c314fc,4749efa3,4562c441,201d506a), -S(31ae24ac,8a76f509,2b721ef5,102623d7,eda96598,84563c1e,8177e3ec,6abf6ae,c3dfe7bb,c8017a0,e2f501a3,c5f11e04,d5a64dd7,ba2d0ed3,2082b7cc,fbeb2e1a), -S(b51857f5,526b8179,3e7bc5ec,7b74062c,57dbb146,1fe68d3,48dc3d55,d1c2d66d,f4313526,d268b372,5d1368bb,d40ac55b,d5f43377,de17bd6d,efd8f536,7c346f3e), -S(ce9c7eed,356d5ae3,b3334031,550f375d,35cd6e0d,eaa760b4,aac1141c,bda83df8,560b3067,c53c8f79,5916c5bb,34d99c02,efe4e5f1,f4cb47c6,f0662aee,2f07807), -S(1a9dc184,362a2f5c,58c53c53,160fde7d,f7b4c64a,e9753b7d,2d98be7,8c91cb33,bf4f3c80,8798aa25,bbca244e,1a070a57,c2ea26a1,59ae4ffa,84a4125f,c3b1823b), -S(3b3050a0,724a3c3,746e5bcd,832799cb,875758b9,2302eae4,82bc3c22,f17cd341,be5afdd,5fed6544,23bb069d,6dd96cfb,1b82cd9e,14dcb35,e0d7333f,54f924a5), -S(a4493930,c44f988c,fb634d59,5a0defbc,b6e9b809,133c0925,5c8ccc06,b93dca40,da27ecbe,97603604,2a559942,7176dbd4,fcc95ada,beedaa43,e40d5ec3,de5c4770), -S(47667272,59f47404,5fefe2ec,7f266c25,f9583c16,ca8fd4da,3149e8d1,bbf7dcef,526f565f,caa55541,d31524b,e942ab80,a895d270,a8cfdcf3,99dca02,75cc0f0c), -S(82715959,aa92d89f,91a7f53,af2d7e2a,2a3e8b85,2e30003e,caaea68b,774bb918,85188269,f1c8e6b3,328f1e04,1e4b79f1,8345dba6,49541f76,30dfd9fd,c1957b9a), -S(caff710b,8a246b27,1b7b8cb7,aa0eea69,3a1ab37,e58612b4,efbeb2b9,f1d4c1b3,7d20c6b4,5cc53865,7485ad82,43e7757,131528d3,ec134a13,b009032d,bae1ae23), -S(6270f6ce,665d2b6f,7d6ebcab,f556a681,78da916e,86b543c5,97771fc3,bee9efa,700f4b6c,b1487e66,af0ef5e7,9e98585e,b22c8e05,66cdd93f,db0e6ac2,809c4271), -S(f5d502e0,33d809c2,32f5eeec,bb4fa68a,97d5d231,6e06442b,2a3e5bc6,fcbdd6af,e802e5e8,ef9d6c91,ee5b858c,f6d62ccc,302eb555,2529cf5a,808dce72,14e3644c), -S(3a0482ce,c7c453f9,6a4d6f35,d8e3e51c,5f94b58f,a68e607,fa09cd44,ce09ccb5,fdd0d694,5601b9d5,437e587b,ca0df637,e17e7ea8,cedf9a6a,9f6f164e,f979e523), -S(54f22100,7ffff6d9,d5886947,8f164fcc,a67cfe3e,65986be4,bf9bf65f,8af89959,3b9af1d6,9036d3d4,6a6d121a,9653452f,61c3454b,2c786fbc,c497f0f2,e0ff792d), -S(7049ffd7,46bff6ed,c29f2e5a,d3dd5397,e96cc7cb,a1c30eb6,e71994ff,2036fd97,6e127611,95338ac8,ee94c953,5aa13afa,4f79d1d7,63994baa,e932b468,729501db), -S(f79cc302,7b4eb747,a7d67fb7,b1bda0ae,e47dae79,b410a6e,dcfda1c6,8c69b1f8,81d75d83,a5bc0e36,25d6aecc,6319120c,1c8df3ee,eeaebdbf,50ab9629,47715a9f), -S(fa0fba16,15c8c22b,3895ad47,8a8e2ea7,3438092d,150c86c2,8527b38c,2077a9f5,5f351702,7e1a8231,1eedd70,4cb519ad,f550dc64,dd1321f,705fa6c2,54a18947), -S(49b2fedb,7acc5ed9,7ab5efa9,e5b35377,b8dfe602,a0fa8a2c,5294abd8,9768aff9,f6b7325c,29f5f6b4,f3b18c9,366a85d4,60df8b78,ace02604,8af1cb1d,972e4042), -S(3623f1ae,9e3bc23b,7e9d758c,4444489,c3d9477e,eaf61b08,37f6ed,b9e0978a,f2176087,f401aeb1,f245a2a6,962afec9,fa7425c9,25cdff19,d137bbd9,f756885d), -S(67ada72e,262c36b3,cafec765,ec0209ad,c926b367,e5b8730c,b5d4db5e,37741312,7b1d7d71,511d4b61,450f847c,242ff70f,9729b2aa,c2e2d97a,4083e7a9,c07ca08d), -S(aa61ad71,44db1e8a,7d8a2f4e,80b471ec,bb891cec,7d16a8de,99ae20d7,9a11d00c,b344fdaa,bbaad87e,56d9093c,2fdd0bd,59316f31,2dce7a6,344ffdff,84ea71fb), -S(5dcce9b5,ba254153,bf270d61,494776bd,84f7be8b,f6a6ec2,9c2e3189,98e243d7,cd3b40e4,6bb08d2,5797da0a,6afd9066,63211e04,fba739aa,6e4f7f1e,d3068746), -S(8fbd32e3,c91dc619,ae0863ca,47b95a2f,3d8ffd91,1e41ce5c,b9bdf529,2504b1a3,b89f6d35,691e8155,703441de,b0d2d726,83247df2,ea46357b,ef5676a9,e582f29a), -S(dd31d01a,7af2d173,ba0c5c1c,ab7e59ec,cf8882cd,47904372,45d8a786,d1bd3480,91b2ec5c,59193d1b,1117763f,8c913d87,af40f6fb,abe53ef3,3e7548d1,eb211155), -S(1a9b64a2,52ecc6b4,4c17f134,cf32dead,66e4344e,44c200da,8c261d76,838a775a,1a2b618e,e96fc285,6be86b09,fa6caf61,4f7ee3ce,3bc34ce3,72c522e1,4a95905e), -S(ff9613fc,de744879,ce9a7c85,11508428,771d9421,b760d75,39adc805,61db7678,9a736730,5df91c31,9711c882,ede59e77,c09e2c6,f8b05232,2c0f79d2,77a4ebf), -S(3f29e50a,f584e0be,71247373,be4e9e33,8fca36e2,28f8498,ab57bf37,31deaed,b41490f6,72bcecd2,7c45a524,ccec1502,8186fd1a,759e4ec3,ce2e4a4a,abcca36e), -S(66457fff,d8836522,26260eed,4d00726d,ab8a56ae,26c68feb,f6ed99a3,ce782963,511b11cf,9237b49c,ab1bffdf,681f59ca,957a8182,ca2827b3,6cc962ca,d2becb29), -S(cd369d78,9ab5764a,a42dbd61,7fa711b4,757b17ba,fbf012c2,17a30cd8,dd42fd6c,42299f3b,674dee41,655ccb47,7783b8b,e54e0ca1,ffde384e,dd4cebd3,283196e1), -S(ad9bb10f,622b22d3,7c25ed15,323f1675,c6d12016,3f059469,6a8f508c,318c045,73f1883b,ef27a26e,a2dd4ae4,c399be8,2101c1ef,a6e67dc1,77dc343c,c56d66db), -S(2bf2ef32,e0277bcd,5ecafa49,910eaf8b,f107d591,fd0fe0d7,77b1ceea,c600c42f,6b8dfca5,f91f53fd,5fa8ae2e,53e72c95,9823c44,d2c4e7f9,7badc1b8,56e6fa80), -S(e7498183,bd8f01e0,c272e36f,1581c1da,907d7b06,8e3d6cd0,3d80c051,30dfdcd9,409fe739,b7f28ef2,4b94cc71,8856c99a,e67aaa3f,bf3bc8de,d71cc22c,9d4e4911), -S(b3921311,72c00c5d,fde1ed00,6aa50d01,9353bd2a,9e27afd8,60a71e02,123e7887,486cb8,d742f42d,9e00b8,e82083ef,bd1b8334,9babb4c5,a3a85c2f,9441fce1), -S(6cdd0e5b,edda536b,9c747302,4c3a8645,ee929f54,ed7f23b9,7a1cfd1c,77489e24,b190166d,b0ad70d9,f0b422f8,e5f0a0ec,91bd9cb5,f8bcdfbf,2c7594b,71c19e1e), -S(51bb4ad5,379c8dac,c5e6e19,6735c84e,9dde67b8,bdf4457d,35bf937a,3d726a8d,49bcb2c7,a0d6af45,8544b9da,674449e4,c099a56f,d0dba507,6b02a9df,5ce294d4), -S(c57bbff0,297f3040,3b81de70,fe524300,5b7456f7,997f4037,f6206e0c,277c74f0,316c5ab3,95b66038,ec5772e2,7aa2f7b5,b54e5511,6ff35e0a,5c4aa11c,efa8d05c), -S(ae2607b,d956ff85,12b5554c,b188978e,e0408c13,82739be,4e68b9d0,7bdc45eb,294424cf,51378200,ad3eae19,26f89a73,ec3398ec,8af9026,5ea556bf,83833a27), -S(95671646,1c47678d,5012d1e6,5b918e89,c96f699b,a7ecf63f,d6eb275b,1fe508dc,abbdc408,a59b2e85,95a7a2d6,fd133767,849888b2,f17070f2,9e827fa8,17bc66cb), -S(e98b0e03,d1011075,928809f0,aa62f238,40e8319f,b0108be0,2925a291,967c7702,ba34d7bd,138fabe2,11ac56a2,2d385316,4cdcb1db,ee647cbd,73493391,a87027ba), -S(c0f9812e,b7f529aa,fe875709,1928b262,1277a751,73011d63,b0c92efe,a02291a6,ed5f2cd8,5e85ce14,9f59f50,f3a6db29,67095adf,91b08dc2,fdacc0d1,d3d56391), -S(fd4dd84f,75fe56b7,543a60c1,7a3ca1b4,6f7b9b3,6d6d5c4b,eaa18a6e,6c4ec6f7,cbe12b0f,c1bc2973,ab395480,50d768b0,8c9ff86a,97f2ab4e,942cf095,a10603cd), -S(f00052f0,700d99e6,4d94e1a8,a888abce,3b15b52d,1d08f20,3234e5e8,9ee6cdaa,709b247f,f1daf175,ad7c29c3,bb5ec78,1521c5a3,3e4674bd,d97d9891,7efb07d5), -S(44d51252,7024b64b,f6d30ed2,9e176fe1,fbf22cd7,5fbbcb13,4aedeecd,5ed2c023,eca73cf2,b90a0f38,2745a43e,64048010,259c0c74,1deea6fd,bdcaf497,9b1e2f2f), -S(15651366,b6cba09d,9409023f,964e48fb,422f3211,832000ab,6e84e1ec,faaa1472,bd79070b,a7100d6d,63795ff7,43a26834,85996819,e9bd81c8,b08dc473,5e6bab6e), -S(f8ea84ac,35b6e596,5b6ea25,8411855f,71de79ba,ccca4ef9,b79eec8c,c9e098a4,58da08b5,26d6d3b,22ee2b0f,7e04d2b,ad902b8f,9f4f1f5,454cc0ec,fef6a2a7), -S(f4be9c47,94b6e479,8ba892ee,3aee0fbe,b0cd7ace,1c9d2f4d,ac03d92f,3efa405,e6828465,7a6e2175,361a914d,4d09eb7,2468da10,d72dd3b8,47b71e5b,6c8593e2), -S(65cbda31,ff7780f5,2b31a743,ac03eabc,4f2e3155,8083f198,46a03ca0,d582e348,b8433ae9,848e425a,603c4591,8f64288,fb58c184,454c6c1e,e9d8748b,c3a546ee), -S(e1bee56e,3f500a9f,4b5e0557,157bcdfe,9223c357,2d70ccef,8b8542e7,f24bf9f8,c5b84a5d,395d9c19,8f1cab7b,3a9cfbf4,dd129a03,e9fb6019,b99c48e2,a0d574fa), -S(7de38584,d12ff024,a179f361,5c44d704,c4dfcac0,4939a8e4,a46d1574,7b6eaff9,2797f251,ce328323,e181c130,59ff6d2a,261a12f7,ebcc0dd0,55771a4f,edf812bd), -S(5767e926,fd4ad964,f4bfb7b1,c6326e55,97f9cce3,ada51a20,6b4808f9,e8abbbbc,64a80f76,8a89806b,98f0bb01,b370c200,149c5484,a9cb5f3c,af8e47a4,27813693), -S(828bdd32,18e6f809,6c1fb305,1e797ca8,3914f9d3,ad051eda,d2964cb2,dee88c6e,5a7f7cbe,166f2cc7,b747a1a9,3e3de1f0,3a0da8c4,82eaf9e7,d5ee7e7f,e4936882), -S(617fc9fe,3af26495,bc6277a,86387377,55398b94,1665b70c,32d5a2ae,3d8d2909,278aa70e,58c0ba89,f44dcefc,bcaa7212,e52d8eb2,f3735772,11e864f,2d522ecf), -S(1f823558,2c08ac8f,f58648db,194bd6bd,1f3659b5,5fccd0f8,67c9f11,86e20634,bf356f2c,fa221b73,bb118567,518147b8,f0c8f19f,b82ab45,41e12b1e,c9fbebca), -S(f6229866,82530e4b,301cc0cd,576e9fbd,a65bd52a,d85a3ace,6477bd57,af52c718,9d2cb0b6,ff327470,e8beeda1,1e2d390e,28917515,a8bbd587,ec303d77,f57ed72f), -S(423a8b60,fe61752c,95353258,acddc1d5,5ac7f226,695d1e73,984ab059,8810f220,feb12e01,7501fe26,72059bf0,dffd41a,f952a4e9,84491463,29a4d294,895eb654), -S(f55b2c40,6ff6f463,1a2715e9,d1471c98,9f3df537,75e5980a,2a48032d,9936ff12,67888b7,e6116a5f,94380503,d1fe63ea,a3ea7f71,64e79500,a0db1201,31acc6cc), -S(cdff1ae7,ce2ba4ba,8c8aa999,aea60f06,f6dff050,2e802f6,8f27a352,edf9e3d4,81cd9da7,9fb9adf2,31243148,623906ff,3e80d730,a4977dc4,16539452,58d8f2e4), -S(ba7cfaa5,96502414,984b4105,739c5fdc,a77c6eae,f8b96cdf,8b8e9fe6,f7f62819,bdcd7dfc,ab11f75f,e5eb04c5,5e7d8f4e,b622ddd,8134e668,cc9f27cb,bdda688c), -S(4a7b5b47,865e94ef,65ee1053,ffb75ca9,8a7a01e7,78d8c9f3,9a8d5c9,ff2daeaf,c64ad5b9,2a5b9995,77eb3a4b,5347ebee,99e5bc19,15b1f43d,5af38361,9050e5a6), -S(26a13407,1f6b82b,239bfdc8,ca2a7f94,110a63a8,b20ed990,71d63e5b,938ed91a,14fab6a3,819f4bdd,348ede08,397d7f81,d514e99,cd777fb9,f42917b8,4cc80b7d), -S(154f8ad5,405cee5b,42ea1910,427ccab0,1861c0e7,29a1ddc8,7e8307a7,5102bc4b,37c6a2b1,f7532681,7621f58,75db7b09,18118be9,6259ce12,ecb15459,3231209d), -S(184496b6,b31e534d,ea2a9712,f22b83b5,a82bd14c,2cb90b8f,b20cb735,3d4b9e39,bdb92f21,7807d1a8,82912dfc,50b3af67,ad9e936a,6409e263,961a82f1,31fc4c0f), -S(2d781eb,a2253f32,75feaa51,fcef2a34,413effb9,2f6523b,371fbe54,3f33789f,5c0f0c47,b11b4b38,5e8d2d75,eaab2d02,39c2e63f,125f21d0,17d34fd9,d1f6a91d), -S(cd6fb1d9,790c93a8,3813fcd,8036c0c8,af3c431,f21d334d,8816001a,41eb83ae,15f0f885,511a12b2,804c90e8,cab5d209,76db1e9a,9fe18326,9d1c7570,5bc24f65), -S(97f9ed25,9852a72,3b4bd360,681d52da,fc7d17b4,5e7656de,1448e499,ceba2aa8,3c609c78,25553260,a85ccd6a,3fea7b00,aa87e76b,3e0e08c8,2f7c3fe9,ce760cef), -S(72765585,fe283950,cb316f48,d847132,8782681e,54dad1f1,c0a0a50c,c4086767,147e2389,3ad0d7d6,a3472bff,2c6560b5,93b554b0,e6247618,3439c576,205b4fd6), -S(fcb0ecd5,93a00061,2439cb19,f7e5f71a,4612ec9d,1b9b825b,8ca322fb,daddcf3,5e9f5967,f7131ebc,1959da85,94069704,bab1d58,4a06cc8f,78cd4140,9f532eff), -S(ad12b476,ef630659,2fb0fdbf,522314cb,9f185f2a,e420b057,880068e9,7fba5539,38ee0f47,57ce8f0a,bb6cbb47,ecce2e86,5ab84597,f6aa91bc,4c4c6b52,68755886), -S(372e498f,7ac9618e,3850fbdd,c9c01995,d96747be,2183e472,8dac7ac5,a1c7cf65,4d5de2e,940b12c5,fdc8dfac,69c7da20,4b92e570,b59a8bb,2cd930e7,42b76cb2), -S(dd613209,fe9e2699,9371509b,5162b3e6,e3557515,c73eeac4,800f6e28,28b56fb,fb1c28bd,c0b4c0c2,bcb53557,5b3b4377,c9f29786,31ae6c65,490ef38e,7fcbe1c), -S(8da18bf,6f680ffa,bc4104a2,4b397a87,25240704,287d7532,72df2321,dd94402d,46ccd8a9,401c4fb1,9c81a737,43330fd8,d3a60361,b94e47f1,68342280,373e7264), -S(1800dce0,a2f3a3bc,29d40690,ccddba47,fe8a71df,e646fae1,15d4a784,391a13e3,b333eed5,deb1b43b,c6646a2c,909012d0,21c0796d,c14c90f7,d49c6b68,52e1920d), -S(b6041277,4cd089d9,9c3f4434,2d328b6a,bfbde44,11a60f38,ffdab086,74b834a9,3157019a,32bc8cde,344e60b0,970b26db,4be7077f,956e98bd,39cc7915,64a13f2f), -S(8be5e638,5fe5f9bd,813449e3,bd76b6da,b4ed7fec,ba853ee3,a302270b,556281ec,e114a14,136a7341,5e8af8bd,23dd589c,cb10441,aa173eaa,21c06ff3,c03ff1fb), -S(1ddbdfad,990c5764,ab076a62,27497400,410f5d84,3b9f403b,d4f51e5b,f0736518,b2688561,7ff17294,9c8f89ca,2827f0e0,a1483e8,b856a659,a009dc68,c5683f0), -S(15458735,4f122df2,18c33929,8fcd0bd9,d032411a,cb76df93,31345ba9,668413c9,1b3d7e33,cda314fa,fb90abdb,b1ee2105,27b35732,f0b77f39,69c942a2,fbc54195), -S(925114ed,22625dd6,d4d947df,87a2b63a,a97f3a6e,d47afec6,9e11a1b3,3b798630,55e48dbf,a47c887e,e3ba5758,4f697f6,7f6a1d73,fedae7f6,f63e4592,cfb33e03), -S(9111ec73,d2e56190,7db6c07b,e7324fbe,ab51d18f,8423d484,cb6a0d,a0a7ad27,f7317b13,4befd605,a28b6549,1b2752f3,26c86370,f5042832,1dc22b0b,9240c8d7), -S(f2d1a752,ab206393,7f780a3b,9f39d87e,9d257c22,beb1d286,9434256d,ba9dc3ea,39d4603d,e66337cb,f0b9d39c,cc40c16f,4835ea6c,aed5d7b6,2cf67ccb,35d5e752), -S(2588d10d,a854b844,afb998bc,23aa3742,76938d27,b08ddf70,48605df9,ad55fd52,826c2422,4d95ae53,daa562cc,88e44e52,5d3ff878,ae350e30,c1c633f,219824b5)}, -{S(2def7e67,7906cf3f,3677e7b6,1b0a8f8,985fbd9b,23265ea7,18a5c16e,139f0a8,650a89bb,df8c8326,d364fae7,558de827,a529780c,9b7bf8f1,c6925632,7c59c74c), -S(6e6cbdef,4d5cbace,b79293f,ecf1a4a4,5de81e3e,97e4c30a,ccd6cf79,5668a013,729e4c49,2f454b35,4b127cc3,788bb93d,fd83061b,7f7f6ccf,c24d3fae,d96a7f6d), -S(29d56adc,c1fe441b,123a94e3,fb8df47f,d8bb8565,40c1d3a2,d8e7ed35,c4eae6f5,6a3aed22,6ebdde19,d2bafb8c,68656edc,9e3da959,f2af9872,3ad29a04,8a549a33), -S(c243cf24,3cc28801,e120fdc7,ab6f8ad7,531a5053,1094cc2c,3a9476fa,e0491344,3decbb31,22c91c6f,502eb3c1,7ac22bd1,509643af,3bbcafa2,ae2b6eed,18decff4), -S(2d2bddef,e75d43d4,a8b4ab19,b2259a6f,24bfda1c,11fedbf5,a12fc353,f0039157,215173e1,1a9ac83e,b339dfa6,ed66efa9,da876aae,5d1a690,4c8ea43e,63b683b6), -S(d2796d04,f82115d2,c4849c4c,be608005,1a2dca90,9773a524,56b2fc44,8bd6d7e7,be176139,829c1b69,352e502f,23b724d8,1181ce81,c447e253,a2bc132d,e3bee967), -S(48cda6ae,152ca92f,287a9cf7,ae9be740,29cb8e3f,afc859f5,31f920da,883eb4b9,55fc18ef,af858cdf,a098c4fd,8e3f41a0,92292093,a3c66866,1361edb1,c07956be), -S(702bff16,c5121a82,cdb8d6ed,fab0e741,f76c08a1,70bdddb3,8ff191bb,3a96ec64,5525ce00,3cbab9fa,58b60b7b,5b5e85a1,e208517f,91b0caf4,9adc0c5d,ac0e6e23), -S(98d066f4,30911d2,238cdc81,5133563b,338f9a28,2da63518,6635af43,fcdc27d5,6f10df8b,7bbc5ed6,a64f1884,1087d5f5,6cdf8df0,f9dd493d,23f6996f,ff39e065), -S(44e69b1d,5b7c3816,af2aa890,dec5e389,cbdfe5d6,44d6c0e2,f36527a2,6127b24d,1ad0e960,7be9fbb,efde8dc3,6030d3a6,41e325b9,48129ac2,b26cc1bf,11b331c0), -S(adde6eeb,fcd63063,ce995ba5,3641b01e,f0797d41,d9e18f78,43972f89,9d7a518d,7002020d,f2576876,2d82a067,139387c,7956680b,65fd70ae,3d75bfd6,fd0f77a2), -S(f0f09803,b43d4c1a,f187d94e,3dd9be54,703cae52,5f15fa37,ddcfbf24,98c9c24f,96f4a35a,40523728,10ebd243,ac6d1419,672fe0d0,c013f1d3,460089a9,2457f7dc), -S(dad39c7b,d3edaea6,3ff16c4f,a9a30a9,36d7e447,939327d0,d4a7fa4b,33d7126,6a927d43,3237ff27,f3f87631,c85e4294,1b188fc,d5ec4780,a58409a,cc95d02), -S(b44484cb,b4dc709b,4c21cbbb,2d7d94a2,c5435cb5,1fda7dd4,c3b787f,55df5d1,70e35874,be7a22c3,1e43f2ef,8b4eb222,5c1dc3a8,cde5fc0d,56ab9970,bf4db709), -S(84dd9c05,3cecdabb,b3ecf8f7,c8737e22,634fea44,80c03148,38d6bd35,6a15634c,7cc6a067,81eefe79,d565946a,96114b52,8a482eda,a9028c5c,b925f037,a75335b1), -S(e45d6bb0,50e66a94,d22b770c,9500d960,6f529222,441bf9fe,7856899d,edf3537c,5ec38fe5,7508aac0,eeea33ac,3aa44dc3,e600d184,a4ddb9fd,64acd359,be96336b), -S(25f043ae,b509364f,43ee5ba0,291c95bd,d442fdac,3f00e338,6397fd4b,295416ac,42456a08,64245a0e,5dc9d06e,1f4aee74,b4ca1c80,1281bdf0,59e319af,f79c7ecb), -S(77c7a59b,64cf6153,275c083c,ebecc3f3,59e66002,3bd2344b,a465cc5f,d44b6938,6415da93,e98298ce,60d96880,2dec1899,84badce3,642ee36,70558d0f,bfddce01), -S(1930909f,61cda446,a270581a,2bfb8ef8,14af75ab,aff6db5e,c9235020,af199c3f,4b7d06a9,5a7f72b4,ad189ff2,348a63c6,522e8b15,38309e97,cbbcb121,50f53498), -S(14125e3c,7fae63,cf0103fb,8bb86de4,b97572ce,eb872dd,5d850825,c1c5b43b,dd1327ad,8570188c,1817ee7e,37a164b0,9f37fa90,88784d96,f91704bc,e3e50b71), -S(c8e7c8ae,b060e8e3,1e768fe7,779ea91c,3e62cfdb,80893516,825d13cf,6636face,e08a5ea1,9b5a859e,6f8f6a1,43dbf751,854fd9b4,2ba6c1fb,80acdd9d,9db87987), -S(3258309e,4b1682ef,5622aa75,ee7a109c,ad650ed2,93edd279,55fdb064,c35abd92,4a192aa,838bc722,8c0d7fd0,200d55b5,241cc762,d252d138,dcfabe8c,e2ffbcd5), -S(42a5f570,4745968b,a836648,373af34d,d09c8f86,536004a8,6e043c9a,4c11a57a,2bff198b,5e8bd837,3011ccb0,1fa54719,7030f47b,eaf44ce8,6faaa86b,166ca642), -S(f0d3e1ec,fd41bc71,d2950d5,d6db5614,e1b560ea,f8119175,f7286a8b,d9c6b563,f4c2e948,a30208b3,a7943bb5,564747e0,50e079f7,703a0d5e,f8039d8f,50acc8d0), -S(7f918a96,3c4b42f9,17c61ed3,f4be8d22,c9055005,a5a3f02a,6def60e7,305ab89e,c5e60518,189e093c,62d6f7bd,de1d723d,878683f1,22b9ad69,2a300a42,c5ce9b5), -S(c8663293,f25331c4,a42b1e16,bced09c4,bf7407ae,595e1331,24d0f7ed,99cf422a,df5f065f,d7ee1232,8a3428d5,c8485a28,d882f31d,e66856a6,ee4aa396,79d978f7), -S(778cb411,8c5128b4,8641ca54,2cbed0fb,e9240380,ad3736c0,cff889d7,1a6cc639,8a1d3417,6f2fd7b0,20b46be0,7905b963,cc1a3970,c2bc1995,daea532f,9ce8ecf8), -S(11e3d37,e28172c7,de168ff1,2fcab6f3,3441c007,1e562bc7,d0f13392,df64d0dd,a811db15,8e49072a,7a238be1,128618f7,d7ed2e15,bd437aa3,69cd2a8e,3d28d95a), -S(d65b7bb2,143c9f85,c5c43c46,57cbb87,3d9df9eb,876fa72e,a1f1a221,37a370a7,f2823561,e19c6208,64a1e8ec,ead2101d,175b7255,2ccb63dd,937a5049,3033b986), -S(d02ecfd4,74b5d84e,96111bbb,c88bca3d,95498de1,4d133893,2c4c6068,9f19efe8,87c93642,866c847a,d592a36b,bfbbfc8a,68b3da63,a7d7f380,ce472b0b,9e0f1325), -S(978310ef,548ad9fc,1872bb08,dd0f9ad,98889ea7,719c5cea,fdcf1bb6,9853e2f,d067d57a,4e7ebeb1,f05127c7,9c4ba3e2,fbc3c2ba,9cd9f2b,66182d69,2c699e21), -S(66d8712f,a2221e85,3f4301c1,cb8b1413,ad9288cb,bc64a778,4881de9b,bc1ace0e,67f8a70a,475e9208,c1fe988a,e9ef79b3,67295abe,9ae283a1,5801260c,f916f8f1), -S(da8b079f,280a64db,a73ed601,2d183e75,175534e6,cc295a63,477f6905,15b3daf0,c55f2528,8812131a,99a89f92,cd6204a6,26a7681b,e4460ddf,9a1940c5,8764f43b), -S(1a2bb7c8,96722b4d,54828c68,8708bae7,31937165,daf08d98,eb02fe0a,a59cd00a,f0cada44,48f88668,e46425d0,f64452f8,42be2fc9,bf33002e,fee5cd76,39e5d581), -S(2a55bbff,5aecb50b,97b974be,f0cd3203,34752370,957a9e60,37f2930c,e11a75af,69f9db00,b89a2063,1b4097a0,f90ef087,a9f7cd81,ba15c60a,faff63a6,a4add6a), -S(2fa92f18,83e0ab3d,d6976573,83734908,a4873e8,bacb0577,c44bf104,5500b6c3,bc24564b,d4f60723,14aa2864,216c6984,22caf8dd,afe0e4c3,a86e12b1,5faed4f4), -S(5548afc4,b095db29,28511e52,bdd99a63,18e5e15e,17e99da5,b9e0ef0,375b0999,784726b1,d2152b34,4b0c1a2f,b90893ec,80ffca3a,85fe3f65,7be4a850,175982e9), -S(d4a524cf,6659a1a5,e24a40c2,8e4c9cf7,da607f9f,c209f88c,63c35dd,4af282b5,a73bd4b2,599d92c8,395be7eb,cb70d741,154291db,151e988d,9a7a4f84,b277b886), -S(e0fb0973,32dfe006,54ea1a3b,858d8d6b,30c26fcb,c4339ef3,165b861,ead90352,43ade413,92521afb,1e87f477,45ca8b61,23775ed4,9a1c789f,49a2290e,1d032def), -S(ec03ed52,bcf2ed6c,c7fc2a19,c95a53cc,3b66e344,4d35ae06,e5d17e2a,b6311f0c,a83cf9ac,89accdc4,667686c1,4dd83d8,d3633ad2,6420da7b,321b3123,4d8150ce), -S(dad8eb7a,a7a8686d,d78c18ca,7f0d4d29,edb8ddc0,4e5dc2ed,4e0f0694,1551aec1,10e00983,af99a823,a32d82f4,2d7845df,d3828133,963ba48a,19497860,d975c600), -S(c883f469,e74f4434,9b4e1459,5fccb517,7e2c2f8b,445feece,901dbe96,a2556ee6,2bf2b62b,5b1c3415,29a822e2,16ede0cd,b75419b7,d212774d,7cf3721c,4b9d496b), -S(8c71d17f,cd711b3c,4e2c1214,64d9dc47,c36db06b,c877a0c5,8a31cc25,2ba585a6,9b248bce,7f4899db,4c8e250,c642d24b,20419ab3,a65cd4cb,624433c6,37aedae6), -S(4be86c17,32474f86,f8331f50,b316e0ce,d6591d47,49875e5,33e1b825,7b5cba39,c4ea74d5,62489423,45aa7cf7,82bab029,8fe58092,4943d3a4,d2fc6f0d,7d0fb590), -S(f5eaf803,98fa27f8,27771d6d,50dba53f,32beb3f3,40d6c045,cf8b4253,644bbf5a,32809769,fce5eb19,f0877c19,317e6200,11303b0b,7ade7e37,abbec95e,fc83740a), -S(585c8726,bdfb440f,8cee9bc2,4461e3f1,8cc7431c,e8f1ead9,af2525ad,8b32abce,3ffa336b,a5bde184,676f33dc,e46c4114,4dc412a1,8db059a2,d7c6b021,7728c62e), -S(9175ea6f,746ee2d1,bc893b3b,6faf835e,ef72ba7e,588128a6,56cab59f,737871d8,83cd907d,b0d601f4,88cca1eb,283cc2d6,99913dd8,391eaf27,cb18ab21,6c13cd8a), -S(c5898c32,306bebf7,7a89cafc,29b49af3,d1ab7fa6,95072cd8,6a8c2bd6,aa8f5d14,2313c593,c67e797,49e44600,7181b257,dbc876a7,e3e04747,c3db35c7,d8df24e9), -S(d101d707,76661eda,ea604ac2,2e449d83,57b638b1,aae03a6f,2683ebd,f6e2c413,7186ba53,b8b1d9bd,b4dd2fd3,7b48c3c4,144bd996,f4254291,3c4316c5,2a98ef87), -S(72213fe9,8e8c62cd,bbf8264e,6ac01240,f3dcde5b,b5f71b46,4d8d5617,6fa65efd,80b256e6,21a5041,63b31c96,7753adfc,9c27b4d8,cea73e91,dda2d5a2,7bc50fd6), -S(274c0fa9,f1dde789,1f88b202,4c4e78ca,ed19ec00,7c6c7a05,6028fae2,d8ca3f2a,d5557bdb,96e52182,83cfa76d,f9f0f83f,2619f951,a7bffb66,8cf3732e,7beb88a7), -S(7d3a1d16,66c2b5e0,4f7ed96e,3762d04,118aa293,69fcd8a9,1cd8bdd4,6e862e2e,a004e644,7b49421c,af6c82e2,1bde2b4e,84d663d1,a39ac9e8,5ba43b4d,73e7010c), -S(77069337,2c31713f,1108bca1,730e3d0f,927d0c8e,4ce7dbed,c2c02a60,b3e54d0e,a935c735,18c40ad9,5cbc8b51,9c859f7d,b48be573,cf45e6f8,cd47b8d0,1546372c), -S(ee44b4ff,e008f122,b4ce1a11,d98cc674,e340c874,f0c5c0be,8008624f,b13a937e,90e4a82a,8f002b78,7fc34998,cf015340,dd4854f0,78d87641,bfcbca47,df06a728), -S(61c0e32c,e6615b09,304ee233,90435b99,912b6de4,766e0c14,5345956f,af9e89c1,7531bfb8,414347fb,650127c6,b1f78ff7,97a092c3,2c37d358,8e612cda,9faeb851), -S(bd7026fb,b47a72ea,d28eb317,35ff8ab8,ff244b96,51fe4205,adff8247,2b9d0aaa,6dd60501,40359152,83b7a16a,3d0481e,e8c7b99e,29843068,28c41727,28f21b9f), -S(8fe350c5,b5882f87,ee976108,2ef77b55,8355e02c,9ac40ed9,76d45187,9e0fa902,21b32a84,f2f31dca,9072b843,6c21ee47,9c02c710,48642a62,2c485449,b907f6), -S(93226eea,b65a86e7,c0fedc1a,f6b038d8,7f587823,a9a2ab13,a9975ad3,ffc8bb3a,d294880e,867877d9,b5d87b20,3e7d7860,71167666,fac09b3e,9fd82033,84c4d904), -S(1fee0dd0,4dea34c7,fc6473ab,e89c2e43,215c5dda,6918e089,50d7005e,df1e21c7,dd7b1dec,b1a85eb0,69cfb830,be847f89,8012321,549e2611,92e719fc,2ace36e4), -S(e6304e92,38fedcd3,580cbe51,564589bb,18ad3cf1,3846dfe1,ba40786a,bea415ff,219302d2,53133378,ab25b331,bbfa4ec0,e88178dd,c2a39378,dee7ce64,4c8dc6af), -S(91f97b4a,11051415,7564c8ea,2a60303e,f6f5941,7cc5a556,ff244e18,444ea39a,80fc4cc,3d57cf97,6c9e7794,d89e1b33,d5849b02,72d3e544,5f73fb5,655d54a), -S(7ff60990,34769cb7,5a697d0,418ec2e2,9c5a9716,9ad6d127,ab106518,9fb7b2de,d7fcdbaa,8aa89058,e1f0cbf8,409b9879,6672b305,b6b24a61,42562de3,2b1dc49e), -S(a418647e,61276567,84939f3c,2375d1cb,82871b1,b8004a12,1cda8826,1eb5595,62797683,2528565c,78a7f4b9,d55fa782,bc97a3cc,598c7579,d48b136c,eeffc022), -S(26d408c6,39f97be2,511b4816,5e862d13,f6aa816e,1e936474,63eb47d6,eacfbd67,2e3448d7,fac889c,c9499396,c2de66b7,cddc064,186b6df6,3a6a831a,6672c34b), -S(56f12bda,d8b630c7,5ee497a4,93d48907,63eb1bd7,93d03fee,a19ff997,f42f5464,4d1a3990,7c650896,4fa7ed4,e815379,8e2adf10,80ba7246,3b4e3536,1e34c3fd), -S(e350608b,35cc41f,9fda92f9,34d16e58,c53244df,1446b03c,2e782a53,2926c9c4,b20d72bf,506c2bc0,b35e022c,c6e2bbfc,f34c71bc,a4b44a2f,317741e8,bffc1dc9), -S(5a7bd940,cc23b3e6,614c92db,a08bbc7b,63dffd6f,11117b2f,80c2fe2f,849de903,502e5557,8fcc9495,411c7d18,9979f7fe,8f4f587e,53991dfa,4ade527a,43cfcecb), -S(99ef5580,b219aa84,4cd407f7,d949c07,f7452587,bab97ac1,faf0b143,7351be63,512adebd,49f4f2aa,a26dfb8f,e5c483ba,6ed5b4ea,5d4ecb88,bb165a3e,2494faf7), -S(99c0c468,a95e76f0,37988aa4,b2ca903a,64a95b17,19f119f8,e12aadb6,5438b9ca,fdcaec6d,c390c33f,31b4074d,7e5a81fd,f2b9f8cd,b5f14957,533bd406,fc68ce33), -S(a9f80643,5f1442bb,8a14f402,6ff6ad43,4d84e34f,cd499aa,adecb2d5,125f1829,533e1697,3a3b7b4e,1e82a4e4,115f8be9,b811e787,61fb10dd,6908e0a7,aee4a7e0), -S(8ed6f9a6,2ea10768,4f90825a,e81d486e,92a9a890,78d144ed,53f54cb7,3568baaa,d99f33c3,b7311023,c4266c5d,adae7ce5,a6409fba,d3767f3d,669aacd8,230d8568), -S(84dff52e,25665e13,102e23c8,698e8990,e5d63e86,330703bb,54242843,8fc9a46f,b1bc70eb,f8ff0905,e2ba529f,1af149ea,536fceec,2a5621ab,bcf89756,ab0f69cb), -S(1bc3844d,78f82cb6,ada3b0d8,86b4f89d,1a4344ba,431070a3,3f3dbc77,2c523410,94580bbe,a198dc00,2b226e48,7a745090,ec603b3f,aa6e5847,8a8832b8,3b0fb096), -S(436e0b9e,aa94e6e,b20f58c4,678ba5fb,5e1d79ca,a7bf4179,3b91c962,325979e5,1615e98e,ce7056c0,428e55ad,f4353400,4ee4e158,347ac5f0,715b0f7f,86c17047), -S(45f8a062,4d3ba9dc,d577dee2,f5387f25,3eb3b53c,31fc6e97,836bffc6,f85b9357,b7a628b9,b9068247,d8415fcb,c5f6e6c0,e72dd75f,cb1abb62,c947cd06,5ef22ed), -S(b86ae36a,bb489583,84e95ee6,8c46c0bd,8f0110e9,98e34595,1f6e6b59,fef4e2d6,2e3ef338,ebe96f24,ac112d8c,a6803f9c,338179e8,c54420c2,981d0159,27d983ec), -S(247b2b62,79dc1d09,6085fa0a,390bc09f,2caf6d90,24f953a7,54aaa29e,a418574a,4d3fc5ab,9b3912ae,f67ff98c,2e641ba9,bc23aa8c,f60ae6d9,cd41ec93,7c4a834a), -S(737bc72c,964ee56c,822f1e31,9ad6f9f6,57785748,55689eff,492c7587,a98deae9,2aa7dfa,d4f105b8,690a507,8fe81eba,2736c301,6ea4fe62,71e47d50,18e4e01e), -S(d2ecf284,fe7663a3,810ed1da,c8533d5b,a647004a,3e22683f,78dcf0f2,1db4c5c8,2fc3895d,beca5b8e,17a2e3dc,3346b957,3eaf4457,ab0a140a,6d119304,9349df04), -S(3cac275f,98f2ef42,b0f78a1a,52218150,a18fe23d,b1361151,a3dc7477,fec811ea,a426ed39,41b7ef3e,48b0e267,fc1cbe50,4b1e5671,f4dec906,a2659792,2ccb6259), -S(f74a08a4,6fdbfa99,843c24a2,f9e5fec5,b941c29,43a25cf,131deb7f,1c3303ff,6fb92df,aafdc8ee,cd7c3416,fc89fb5a,458c2c97,84f71698,c512981d,a8edfb2a), -S(91d44932,56fd4608,48f04de7,25b3fc8c,656a38d6,f8e319f7,1ecf513,146eefcc,cf058db7,69aabd80,12ea780e,10aed66f,4bd5e356,1b0d359d,167ebb3,2830edd8), -S(d194e53c,1a2a2c80,f7bb24be,b372d751,118da62e,9901d94b,66cfd289,19387bc6,aeeb2818,d00b7307,79fc14d5,31a3d803,5e5642d3,b7335543,13c8fda4,c940b387), -S(ec18acf5,a9624f91,1273482a,b03ec7a3,345ccc2e,282a6fc1,cbf89a2a,45e798b7,ca9f64ec,caa12673,a2901fe3,684ac70f,501b4d63,601fccfb,4cb08e53,86671cfe), -S(488bc882,77874baa,6fc9edab,ee101b5e,1d082a4e,d49da47a,af5e6650,90e0566c,9487231c,3e6681ff,bbf953da,54ba603c,89a00340,c4e50c51,545a5c6d,d51b98b8), -S(25d4374a,7f1eb525,825253ef,a3ff3747,e4555f36,9fec50af,21716ae6,8a11d34,cf475aea,53df9a1,13670563,e0ade1b0,d4d90da2,11b87318,315f368c,d53c5e18), -S(5db16271,c0d7e9cb,dab1baa1,4dba4fdd,1716a7b2,8c2e07c8,186899ab,18a6418c,344f8bf6,b722e92b,ed436fcf,41be9a08,327002fc,7b3b57a9,2044800c,a0d1b2a6), -S(402bb93e,8162ae4d,f23f5d72,611eebc9,8d4c00a1,e4d8967a,da1bf524,9ad1547f,f0c0b1f5,aa183000,7a964ed9,12bacd81,9a36b55d,7d2c7c1f,12da6066,a28c1d68), -S(87b76fd2,91fd3508,52544b80,85b07b94,20fc325f,a0ecf42d,9354df82,467d836e,f0a2c79f,4613218a,3b35cbf4,24b5fea1,7d2ee9c7,ab912be7,62270195,8b70c133), -S(e2d73ca3,ffca1eb4,191eb705,c22cfeeb,a7f573f8,463a0cc1,c73bcaf1,3cf6c791,61b861e2,5aa3711a,b92aa74c,814b4df8,37172f43,ea0da2ac,d81ae961,1735fa85), -S(1e59b370,be38e5d6,4f8b6fdf,7c2351af,75ff9d32,1f583d58,bcd0e8be,ee0855fb,d166688f,24b4b33e,b171343a,87bf8828,5cd5d073,a5023bfa,dc542660,70d3cf13), -S(52ef3e6f,5aecda7e,e2a6451a,ec2badeb,235829de,b7cf6e1c,5a6970ae,662e2078,533ca8b5,8d9e2e7c,2a992a22,3f385846,748a1686,34e1fb2a,48d3f133,8512bb08), -S(a4b1cd10,20a321cb,53717818,ad0d39fb,5e9524db,4456e0c8,eab045e5,b2a97be7,979d9ed3,4601d962,3f084e04,9ce4683d,783b912e,6a92c07a,38ae744e,fa7d046f), -S(bb01149c,2352baba,8f3fcca6,a8fdf9da,854d7,7efebf92,6a0d49e,abcfd871,b186fcef,1d368ceb,351d5e35,35d19052,7373a9,36a625c4,c0b3cd21,d4188720), -S(978e8fe7,c4088cb1,27f9e8d7,5dc43453,ed16470f,4f940413,eb800ec1,b315f269,6f7f521b,1493b81e,6f099fb7,22ae2a65,f706a351,2b74338d,b708bfa6,4a34f6e5), -S(7e61704c,77e4a6f6,925a1c48,8965a72f,7bc8e76d,cf316371,13f682,b5fbc0ca,da66aaa2,c39dd05f,7f5803bd,e5bfa0a4,21eb628a,12df0869,6c6614f0,176b15bb), -S(87c537a9,b97dc885,3b7957b8,2cd9ec81,b8b65d58,47a23106,e6df3d5a,cac3fccf,4939698a,6123ae1c,42cc6ff1,fd006fa3,2cb0a5da,a3889721,f04a4a59,e0fd7dde), -S(590b5b95,37a08784,f804111d,6ccd7df1,7bd317ef,aebd7bdc,96f3df4c,aa8ad437,7aaf5053,1c187684,ed8238af,c621e151,dd6e7c6a,2c18bdc8,9914a1f6,cfde5e29), -S(913a2ff7,a9416e56,afde1c6c,6273d7df,150deb4b,f2db3f3a,7ff7fa8c,173ccc09,e865c6d1,33da3db7,2dda798,9a5b860d,671c9de9,d6132784,30b5a552,85a9854f), -S(b01fa220,1ba66785,aaff5f59,347586e,162ccb08,ca58179d,5dccaeb7,636b4db3,d5589b8f,2ba1ef60,23936d96,f2772d4d,cfad1f26,cf124265,6765dc2b,7d9f543a), -S(511fc077,bed929a0,249c65d1,3f59c607,b8bd0279,c3ffa23e,8c6c4ab1,800b6363,74b03bef,b913cf04,f44fe5ed,40ff2ff5,9e85db23,34ba902d,84dad90b,68a72912), -S(d8597fba,dd03e235,defd0d4f,72c054ba,880390aa,c1c356c9,1eee50f7,8ba567b5,86bfd1e7,f1df87e4,be26c892,d2c1a634,1904c414,bf84dc81,d65f701,efe90bc1), -S(34b46527,86464956,6dfcf2e3,5717955e,4529f88d,786ed832,f879bb9b,5f24ad6,916bacd4,52fb69a,e8f20094,8846e706,e3cf466c,a34a7c6,b9a24df1,1d48edac), -S(f68965c5,55a826be,187306c3,8695dbcf,370c5fd9,1a018912,ca143d8f,b9e96c07,2342eb5a,bea7b80c,837a18c7,ed606930,248ba6d4,f5ea3650,9a3aa10b,c0326dbc), -S(80bab356,e346b2b0,511775f4,be1a7bb3,fba9c65f,5cd035e,b9300162,547e75c0,e96dd58a,53a9e313,2c3b494f,2c53bb56,da17f573,8bc90a10,58063906,52c33363), -S(55a3ac1d,88f00e04,ec95215b,68f37594,9e10abb,ebb1928c,6cea668e,62897e7b,31b5984c,4280d3ed,125d2223,57718f54,b8e406d0,bf4feccf,2deba94d,45cfd5bf), -S(7e0e03c3,f82556f5,a85322ad,61cc60b5,d096c684,19c76b77,f328f51c,bc5daa41,36b4f520,f84f8e1,7fc79bec,bc2d4340,e77c5b0e,4fa944b,c0cb2f07,4c5bb1ce), -S(fbe1fd76,8dab92ec,b56819c8,901cb8e8,cabbd809,f61c0f83,70fc5697,7a90b28f,6fdb62b,d011208e,aca8f8bd,68ef539d,a6a5552b,8187327c,19c6f4a5,40b1e750), -S(ef2a9571,ba9090ec,1c50d5e5,d8955609,2f7e7610,625860d3,c0e1f22d,e66e7a0f,5ae0a396,d6cfe9eb,7e3e6923,e7d1d925,851fa4b1,38217320,92191366,a3aa1c27), -S(81652fcb,7a968f46,a38a6b9a,f3f6d831,577fd45,dbe0cd75,ca4ae8d3,c34812dc,bb130db,74334258,e5dff98c,cf8e72b9,95b986f3,7177c98b,ae6f7747,3d869e17), -S(e0daf5e0,a32eb5ea,606b2760,62c8a60c,a4b476ab,b5f2b172,9a15c529,11509e75,8eecb80f,c47d33de,c036c661,e940aa9d,26bc8541,369315b9,b7552487,d32e0f4c), -S(cf0a6b13,f6ea26b3,8927139f,1c5fe769,6f297e00,46e4f529,1c4d5c60,57dc917d,b8c731e7,5d0dda67,63c1cec9,b70cc4a7,e39a7ca3,c1dfe8c8,4a895d03,b3b185ab), -S(a5b5cf9b,35914a4b,6af16c2a,ffb6bc8b,5228ac11,ea91da48,fca654dc,b6b8bcae,e6fa217a,42e72a81,b8f564fd,a5438d3c,5d0ce8f3,71b1d6d7,c577d70e,f0daaae3), -S(d4c1d178,b462e260,c6b7eb43,b71dfa56,899fe5d9,a421da4a,edded57d,4a0010bf,339fe1d4,83f047e2,cf2cc9d3,bcdb8f0a,df9b491c,ac87a512,e901586a,50f35276), -S(3d343aa3,c6bfd408,1b64d616,2523b272,ae207a5e,bec0e530,4e0792ea,3743b150,5dae9987,49073817,cc513c16,382edfe5,749a8dcc,62f4dba1,3e0c88eb,c978abfc), -S(34242394,db9874c7,14664ff2,90cb1be9,c48c1746,d53aeba1,536fae00,7ed83a4d,59203b4,b8b3e0d,9c34790f,f9cd0716,8606cade,9af8ca2f,b77a6fae,d6e10ae), -S(aa8c1b42,7588ce4a,2a0fb437,25a27bd6,6f598323,fd525e88,a3a586e0,d2d64a08,2f1dcc5c,269065c7,a966036e,c281d05,39d4cc40,fe42fc37,667a49e8,850fcc00), -S(699d3ea,9658f9e9,7fc0b69,4927f4a0,bd95dec3,cf104144,8167e4b,50482c74,416ac99,d59c046f,a754a7ba,d37b474b,ae7d2192,f90719e1,39b6af6a,e2b2fc84), -S(1cd6ac9b,93f5b488,5c06c9d7,a44ea260,11c9537f,d75f5abf,e9d7ced6,c14a994e,818a63b3,d367f655,4afc7651,7fc85fdf,3c69b881,242eadb5,8649ce89,f1905e00), -S(297c80bf,24a78c2a,245008bf,40a828a8,575e6362,5c555653,980f8313,6ccfd660,5ccb3479,60c1c639,60da5605,4bfd8d5b,61ee83aa,d815164a,b387dc37,a44b412d), -S(915638c5,f9d1b491,99f6ea3e,c1843d4,33b832cb,fad78dc6,ad55fd10,9eaf31d3,bd097f22,440a0c35,e5648ff7,724fe5,2163edd4,3c1b2fd2,7c49d61c,7194f225), -S(f8274560,da2fd048,5b974537,16844970,d1c0c1e0,ab450703,739aebe1,28a7788,58c71185,2a63aac9,5a080ac1,3d786a6d,75488625,622afdcc,f5344ab2,adea04fd), -S(94b4e84c,61fa07a8,6c35d554,816f2131,3727f614,d641f3e9,8ff74509,fcfd444a,9a30a0fa,30f3a772,747e3a0e,b0d17ad1,c029558b,a5e0478c,160c109,fd43df77), -S(de72f827,3ecfa2ce,67d55302,9f242afb,c3ac130c,4e711a41,545edb3c,dcb90d64,3b64bab4,4141392b,76e492e1,49c166db,272e23b8,dbf3fb13,b17396bf,1c3834b3), -S(6e7b3c5f,4bf9bd45,1c5b25d9,23fb5768,7aa2b1be,dbfa3317,db823b8b,968263fd,5f7c0be4,ba960cad,e120bde3,c8ab685f,e80f96d1,5a012993,d1890b89,563cd7d8), -S(3e4c6252,307c116c,33f5e2db,5690dc4c,57210b58,3b2250e6,ace138a5,24a1b376,e82d521f,4b50a3e7,482ebd30,93f7ed8d,70c6dd1e,6339af4,7ef453cd,ba3a91a), -S(99a27d9c,802a5519,3f9b767c,3d9c04b3,7c6445b8,e49887b2,55bf325c,118bd175,2cba1615,5809eb23,8e8a35f8,7d80c011,2b0b1587,1e56c567,26dbe6c6,d9a477a1), -S(24b5cc41,130a9fc0,d694c99c,a00edba7,2c8d2a94,7db35421,6ac18ee9,6a88e99b,d409cef3,7e0fda7f,27478fa0,651ac750,bab44341,98d60fb0,50db541d,f416c488), -S(903e8ceb,229db84f,803346f6,9db1b473,4d375dad,b29ee771,c194c1c9,4f068066,405c25cb,2ce89007,bac620bd,1e7bb959,c61fb5f5,cb60bec2,15a978c2,91c63aad), -S(77702bf1,2ddf612,5d3803c7,19be7b60,c4dfc0a,54bfb54b,c58d2595,230e92f,dfd2bbd0,8cb1b67,f26bc57d,2b9bfaa4,7a03872,2011c58b,619794b4,c0bf5eb9), -S(27aee8e5,3f4ba917,29f463a0,888834ec,e83a022,bc9862fa,fc5ecfe1,d082fb41,1be8786f,2ef69516,e18131be,28cfb9b2,ec0ff57,6dc75c84,5f2a7080,94b40bfa), -S(ef967d14,d819d4e5,5324496e,868c3167,b94393ab,e3382466,44fd2b59,efccaabd,98858ad2,fe5db334,740a3bf5,fec4bad1,96d39e5a,f09209e8,95e086f5,8a252975), -S(a2228f83,18c5fc47,1536bbb8,9baf820c,8b2b48bb,8ffbd4d5,56ae162d,bb80a78e,79e06c54,ae0030f3,a6275aa9,8897e7e2,637ed005,c6aadb63,33575232,b54b2bff), -S(5ef437b0,d9a17584,6bb1e711,7b7fa86b,504385fd,307bcaa7,ab558ab3,d2bc5707,5aeb2e4f,83a73719,e1268a48,6a578d84,3104f0c6,86749b59,7c4b3fee,8ae5b586), -S(35be1b54,47f8a2a,512deda4,31958c11,9b187997,66eed6d9,d30040e4,363274dd,6539313a,1d5328c7,bb389c47,98c08c05,f9412c1b,31c08509,3af720cf,6c604288), -S(4e548261,89c3c699,eeee1560,b9876e4e,5e0c8677,f849a9f,e2355d2d,aff7aff0,49bbccfa,2a7078db,d032fd27,98a701c1,c8947c0c,fecfc1a1,38dfa387,4ab436c8), -S(37d9ca55,6ce9a853,b79fc831,69b6778a,43737dff,f5eda67e,eba8f267,867018c,9a9ca2dc,2512c397,a16780f2,25686b51,7c40d90d,d97a8077,91be382e,86378d10), -S(ad37553e,383b985,a4054cc8,a909af65,5daa7957,c380be16,aed94ab6,407ad12e,98e09fca,76eca761,9e3905c8,ef688726,feb7891b,3695d06b,5af5aa3f,f92dac3a), -S(55b0a9fd,7dee7ff9,84cadfd2,fafa3f5e,30cc6fd3,72597902,c8cb9163,55e2a0d5,97da1eeb,96599624,39eec4f0,7fe182a2,cfef4a9e,55a21b1d,64a43a8a,8edbfbed), -S(c79778d6,64e3f159,5c9ab43e,3930b722,f734079c,eb131b50,badaa53,337669e0,1dc01b47,e9908908,d318e947,8cec0a8c,37f7427c,bef205f7,9000617c,ea33c723), -S(ce6964a0,b5fa0b4a,67385884,12d6ed28,75da7d26,dccaac81,7f3aad1d,4a9500c4,faad869b,e4e0262f,fd67cc01,a0523f98,d15d9cbb,7bf7e8f3,fce7e20,26b7f765), -S(70f8af3c,f7fea8de,e62a3ec4,770828f0,52f819ca,e031c9c9,a0706d0d,b4d5751a,b4c4a600,6e4f831e,c4bd750d,62a52d0d,57399b71,ccb71f6d,c00287b1,67a1dfd2), -S(11f0d683,9f28915e,24d941e3,7cca8754,bab9a8f4,96807679,89300b02,8e79a041,1adad681,9d726c2e,2bec5f69,75ad8a4f,c7209872,35ea7486,2ff38333,2335a647), -S(36a0d630,625c455,5c8b711f,a28e2d0a,4ea34f6b,c81ac8a2,6861d58f,ac3bc9c0,89c1e59a,fab4fd9e,3245ba79,876404f,b4cdc7a6,2a9a90a,f307a8b3,17453467), -S(791e10ba,970b964e,db48c4c,fe698317,fcb64bf3,db8418e4,86c45e6a,fb0e1819,e9ee5073,73d105c6,b7012ee0,ba60b9f5,89d98773,f0bcea03,14d6f707,7746669f), -S(cfb370,cb6de70c,58c40464,c20c1cdb,9850be9f,ad9a4af4,2bbeb6b9,f173725,3f5bef6c,814390a6,c99037da,eb7fa919,7e9c806,50efc919,6650a42f,ae425619), -S(1d5b7762,bfc3fe49,bcbc3176,158f186c,f909c04a,31480b17,2451acd2,8024321d,ad60b8cf,215cdfb6,62a29985,c9f185c2,19936929,b9cc5911,4cf5329c,44ba080b), -S(304bcf43,342c9d7f,fa8e05c,66cd140a,57c4f58,d223a1e2,6b93a374,7c73882d,e250d896,acc87906,b79d9ca9,63246ce1,9ddd44fc,4e834643,f2d592ae,219f9767), -S(60bc17e6,9cebe27b,b504d28a,b657064,3bafd4b4,2d82e3a5,77dc8c5f,4a05c4ce,e45ae47f,6088f05e,f6709166,9f608598,ecca924d,ae7ad37c,1852009f,e23912a1), -S(cfa64de9,ee4a849a,de71b1b4,340b8d18,1341d00f,e86bca01,3d62d800,3e20454d,2e72bcaa,1967c37f,a8f8ec78,b82b5f6d,3c7d0136,28bca50f,c884825a,6c967e92), -S(400e67b0,bbefc4f0,7aeaee57,1c495584,de4e7832,377bf171,ee3e38a2,69e53d73,762d4b13,f91d4e40,ba0a3fbe,3c085922,3386add9,b8b1c432,88052b9e,cdb8fa3b), -S(fd3ebc1,e1c751dc,7f897ec1,f0ae0817,22136109,11010904,6c105497,47602cde,43699e3,74af29c9,692fed1b,acfe00c4,f2d91908,eb7cc181,7c270c76,453343ae), -S(60a18f0,740f1caa,ea056b17,9808ddc4,aedac1f8,482bfeb6,a97516e5,d84c0a30,6efbcdd8,114ddc58,cfc193c7,f11ce4f0,931b3f56,4290253e,a5289d25,7e7d1350), -S(c08a77f2,b9bfe746,ef89631e,1bbe07b8,5007d1eb,bb18547,6d7f8f49,4283e1c5,6a94da87,4c350d0b,cc23ac89,9d342752,97421c77,d7b7293d,669cace8,78121770), -S(247f8ba7,b8cbaf03,2358985d,955b4ae5,673622fb,ce1b68c,877db077,d91fa63,a180777e,3b8b7d6f,733d0565,b038b345,d598a9eb,1d592949,8463940e,99f7d74b), -S(18b7101d,a65cface,68d7ecea,5b926eaf,79722f9d,5962a86d,e1eed6be,ca08e4fc,60b7377d,eb39da03,f5bad331,f41586bc,6e3bfff9,f7c9eb7f,aae6f7df,8869f7da), -S(4f6bc39b,33d45e5,325116d6,f8eeb341,d15a3f40,57b64775,932f9b11,a92e1959,1cab1c18,422dc38a,e1a8d4d4,ecc84748,4c47d862,42ee4dfd,28624a72,bf693433), -S(45ce69b1,cdd90a2c,a14a2f87,b12d1f8a,7425935e,2f2ecd5e,6f25b087,acc4ff2b,3f850036,ead34b81,3eeffba6,c3b9dc77,8675152d,f569bc28,d4e74539,896f4b34), -S(8ef39f34,27339934,a1b969f5,b203d187,2d3c467b,1a25ca0b,d59b385f,d78d0cde,926604a6,8f82a4e7,a7e5507c,e1f1730d,c43f9a10,bb15bc15,9d8b940a,7403a5b5), -S(cd83545b,fd621045,245390b0,938c12ed,d530949f,6ebf0e5e,90ca8617,637d2cdb,ec79aec2,77d9b2a6,1721b499,ecde68f1,44faf32a,7984550f,54fe9208,517a0dc9), -S(95482d05,3fd19bfd,20a218d,82442cca,89d2f1fd,883300fe,9898e7af,3e1e7c3f,233aad3d,c798660,1aaa61ce,ecfdc48e,9b3e09d0,76a14945,eaec9d67,60713743), -S(f96fbc5f,eef4ffcc,d5c8ce74,a390858c,24cdb060,529974f6,fb7a7afc,759d7684,d41bbd7f,54c6ba72,aa64996,dc8237a1,27d767f8,ae4ada04,26879426,6343d663), -S(c31f5733,a92bc02f,28aa1abe,6dbc932,96ef1980,a8b876b4,941aa05f,3e4415ca,cbb9afbc,166505de,b160f3a3,fbc99c6,8b9aa548,ba80b83b,e70700ab,611d6bed), -S(e710e709,b2d1abaa,ea81e54d,4c913029,61d058d3,4aaa329d,bf673da7,6cc50f87,e6078cc9,c093a8c4,804ade7e,a2bd8f74,78b93dfe,47cadcdb,18be11b,dd450acc), -S(3209825e,8e6a7a03,cbb96e9a,cec60e29,fb3d2113,310a5f27,69c789d6,fd2d0ea4,4a1b86bd,fa71c5ee,fb640c0d,2fdf6941,42790350,a48b7189,41cded36,e6627117), -S(d26aa999,c82be0b4,25268242,c969c812,7160c34,8d61060d,2cd95fda,4ad91572,193c9343,5ad89189,37df995,5b8ea66a,5f81fd49,aa463d63,bea7e793,d7867078), -S(f505f201,a5f0a8b5,420db5be,304e3824,5552efc,d7736f27,a70d63e0,846f7a05,affbf297,4fd36a6d,45cd403d,e620fd5c,24ee5094,82f03dbd,4ae8d1e2,8047e07), -S(e81d7da0,665574cc,11b5c7b7,c7d49ea0,e12e5a31,d8d4059d,e589c87f,8ca189de,cd36628e,f84c929f,bd057c9e,9c429e0a,28562415,7a1f718c,5f6d9c6b,2402a25f), -S(d183676d,573926af,6b409350,fcec841a,9d7450fb,2c122dee,dc7f061,8ee870f,4401a6cc,1b298b4b,b7069ca0,70452571,1406bdfb,8d991e0c,a252461c,155a37dc), -S(7d8eb701,a4555db0,e28755cd,b99ec00b,188a5fd5,aba9fd63,b0fe59a2,e5f69621,26dfe0ea,387948f4,320a99b1,79cbab72,e0e7b4d,dd91023e,3ada4706,b1e14de1), -S(62b18c1e,6b41494d,242c807f,aea4cb90,6c369829,bd480aa1,51d42ad6,f2ab6e16,806a683c,ca4ba62c,d0d7210a,2a642a97,11a2c336,2cbbdd40,a14c49dd,7445157c), -S(3beffdc1,3d43053,e4975be1,2212ef06,756e420b,28c1da19,7f719140,40754d83,19f74783,30213117,c1cdb3fb,c500423,14c36c4,bb0b6073,504e29d3,2a7a81e2), -S(883c1fc,6c1e9ab1,f8728eb6,7e3c820b,bce57c8e,78920acd,88c56b69,8e21b57b,a6ee80db,2f153833,f397e1e9,f7d0bd3,b68e3a9f,a83fc262,88a3460,241f30ff), -S(cb54c3f1,d3007e9c,a6f4c7de,7cd6e728,22ed6627,3d64251d,23df0352,ca7f3f56,aee4eed6,3bde44e9,132e8405,c088e412,c8dd4856,9be5a980,adf9969,261282c), -S(40b26863,67d38ed4,ec41c0f0,b8393698,969c98e,e3233fbb,b2c9fee6,14fc52b2,9f3c3a8,44703528,e8a3d025,d536832f,f17e0988,4e90a75b,82705e61,c5b4f811), -S(90431e86,74d9685e,4c91e51a,a897fd1,b5aee499,7a8c7405,508d77a7,d0d742ca,b35bc817,b63059ca,8c21e0b6,f3c198b5,ad7f19d3,7711d02f,4695712b,e8706df5), -S(5ad701b,3bc26c4f,cdcd7882,71d259d8,1d134c0c,53063b21,c740d7d9,9c235474,615f2956,b5056865,3103ab4f,d53a1e00,49bce03,db115d5e,8dd36c11,1615f997), -S(75a3782c,51dbe62a,f9da5199,17e3a59e,b04511d9,f11b7312,7dd35b8e,6da95cd2,38061610,c0052d14,bfc4ef8,62d92a5,d59bca62,9fb7a240,299ab954,8ae21484), -S(28e60b08,2edec9a6,1fdabde1,b65c2e0a,333b5b2f,2c8cb97a,fc20ccf9,13792765,c96cac7f,4efb4633,8d63ddd5,33968f6,d09f074f,28e3c57e,dc868e7b,df4105b6), -S(7dc515d7,f7f20959,7e52b182,97b5933b,2ef9ef30,38e18236,39f6ac5d,214762e8,37738e78,9222d0d,5d7e7979,19b0ce29,81b7be24,abd4e0f0,8b989500,a348218c), -S(a8ad8d74,cf467d29,a97690b0,a1c539c9,604e5bb,77d4f719,fe1b7507,d51215d9,4180c361,21659aa3,fa84ca98,8676b3c9,23639184,ee991576,3ab9878b,558fba54), -S(6a71e2e7,99f1c56c,e38052c5,767ecb1f,85c2abb0,55832994,18417a12,9bae566e,481b3cce,208f33c6,6d4181e5,7648061a,86246ccd,31f92eaa,6200591c,1662b7cd), -S(78d0ae79,7a94ae5c,b338574c,1bb635bb,3207b491,fa42e6fb,7c861eba,ddc195dd,1d9e9cff,32ebca9f,d707544f,ead5363f,15a9af8c,e11d8036,49c6fd8f,cca067d), -S(1feb4e2c,357837d3,8ed62d33,4cba95c3,54ab6bf7,2d9f1007,b7419ecd,6bffb072,8e096dfe,15e187e3,92c4a26,2b94d5cb,63fc4cdf,f14e1b76,33d40946,ab074a45), -S(e9a3ce53,cb11bdd0,6c0be1e0,848b94e7,ef68d881,88069893,2facab4b,d19b2344,878838a3,d85a38a5,60a45847,20d8ea0a,34cfe7c1,6b65f35a,60b766f,d77d5fae), -S(2043c86c,4c96437f,f96ce0fe,ab5f428f,76966c30,4dbe6637,397d6b35,730e73d6,82eae267,3e2fc564,c128723a,b74feabf,905218a6,6567ea0a,4cfa74ec,5ee7d22d), -S(d02b8896,63ada221,3e6b458,7bbaec0a,2b1cd8b3,40a815e,fd9f3e36,c782727,c5c4cd5a,4bbcf08b,e1b8620e,24930490,c9f0d61f,66ef0c2a,937e2077,b178f8c4), -S(345b51da,c452419b,6cc320ae,8222c72b,12073fc5,a77ea07f,fffc10d8,61482094,5a0406fd,42916840,8fe4c276,bae94cb,710f6cbb,994da133,932c9d7,cc73242d), -S(275d0e66,da342f04,c9cbd00,18219dee,1a42f9fa,418d0a55,3f98b88d,ef845ce3,3fc25f10,74ad90e0,4ff09d42,204eda1e,a63fa50c,152cea14,d322ae5c,2c4f6dd0), -S(64709e5b,8c4eeeef,9b92177a,b4a04de5,f0150612,c84657ab,855d0145,ecb3aaf,c3b0e1c,56a5a00d,868f2a1e,35a40b0a,9d6b55d8,2df87d15,95b1890b,8b9a3a94), -S(64bb29f9,5e7f48fc,d436891,8d527785,2ba8a6bc,f2e1df43,f7dc4123,ae2b3be1,1f4a8fec,eba87217,3cf8bba3,bd19598a,ea1c8998,945f5b32,f1f52d00,8ed1355b), -S(6f401b0,2e10c301,27dcfc91,2e3a3396,93e8d2,f392507c,338dc113,d019e520,d9a59488,ea1e613a,99bfe1d9,dbd36a1c,3b65ff90,fe8983ce,9665ccbe,1108073), -S(3af33a8b,63b062d5,30b7ed95,c9d279c3,7be8e95e,6e173411,9d354814,b361abcc,4a5f16b0,b6ac8371,b2674adb,933a7f62,d22c6133,1ccab67,e6abbff8,66124fae), -S(a3feef6a,34754c7c,d888e898,bfe5080d,e3669502,d5ec3fbd,ecfb2dfb,8853fe54,a3e7e218,6d88e82,f600be21,5ea5bb93,44a6e10c,464e5f7f,e1ea24a0,3eafdcfe), -S(2e6f36d8,910a303f,c4c93cf,660c31a7,ae7b2ef6,c2ab5cb,940f9623,e2de83ec,3ca98ac7,a03b0b11,1104bc99,d693d068,7350c4bf,f911c183,1848bdd5,bf35e66e), -S(5d7cbc21,3016b19b,2dde662b,a677902f,cfdcb91e,25dd62ea,583b6375,1cdb5aee,871c5aa0,d44c404f,b42badbe,a9b99a43,29db7694,47b93d92,bf5dfdb2,648f4677), -S(383c7ab9,6e772e7e,47b01559,ee3bd4ce,9b86b38,a6f57968,64e45eb7,112fa1fd,254fea35,3ab6bfa5,2018668d,9f3cf2ba,bdb4aa59,28bd6a07,852c4b4a,b9bbda6c), -S(96aafbb4,1d6c96d8,72a6a577,13b25b75,814966c,ec1f0162,31b74dd1,46322ce3,bdf9a817,4c367d1c,51d4be31,70cdee51,a937445e,f19c1c10,52da1f67,e9e9561e), -S(4700205b,e431bf70,6728bf7d,16172589,7d104107,5153a9d8,7796bc96,49d479a8,4117c528,9d404239,97f67970,65d3a9dc,6b3f8c13,1008489e,6b23a631,6f86551c), -S(f81281d6,7377a69b,5ee7c680,744ea61a,668eb128,dc404955,f541b0c,e414b37d,e54bd7b6,783b6888,4bc72551,1e97c5eb,ccef5049,a28fa13a,a15232da,eed7e23e), -S(d898d15c,276b3b92,77f39c23,93f60540,6a7e201,443cce6f,d873d8a1,44eb5a,5785dd47,80f67f3a,7efab06c,bbb1044f,98d4425b,b0f1cc99,3b6b4b2a,a5504d4f), -S(56297c68,51dff96c,6122ae9a,1cdd2ce4,b1aef6ed,884e5998,28c77de5,eeef72d6,4f2494f6,5ebbf2ea,acf70249,f543c97b,add6f6ba,3b152b22,2b371a83,2f8664e3), -S(1adf1f2c,a5f3c153,ce8a6dfc,c1a5a21b,d98b99e2,135b6e8b,494c6ba3,2703822f,13fc7044,cf6c75be,ed84aa6,bb1fe11a,9f36c562,5a152c6d,81b373c0,42bb99a3), -S(f42c77d3,b6b36250,bf4f535f,27c00c8d,61b5ed76,d4928138,cc0e672a,7c72851c,3700f507,c90c93c,6fa6648b,40df90e9,b3292356,4a9bd471,4cc310f,e48da924), -S(17aee799,938d30d3,7edb6b8c,19d4d0ad,86ecdc34,c4b7d504,9d2b3b9,3e10cbf9,2527fb75,a787f794,a5f06a55,c3b33f7b,c575948a,c5454bdc,c14c598f,34459647), -S(55acc75,4a188608,46ffc6d,a6e3e2e1,18cad61d,e508d333,784fc716,555c98e2,982a4306,65448652,14f42c31,18e3214e,3981529c,422a0c76,d30d45d4,777aa87c), -S(d06c7e99,dbaf0943,6a6790be,e7487614,95ace755,448580d2,7614a30f,9bb7b5f,a6958136,41f3025d,de7ffc89,689b385b,b3c6ab83,6b1f21a,28e492f,de7a6fa5), -S(905423fa,3f9bd590,1a502d2c,7d4ac0d,2f728dac,3199db44,b35362eb,c964c8b6,1c33ef01,ffd75d94,bdd523f0,a41d629d,bb5ccf7c,9305d309,b3ab0842,16cc81ed), -S(8e799bdc,f32e5256,218dfaf8,5d08b6e4,d083975e,5ff2059f,c5b57966,3dc8cbad,60d46f36,c0e04600,bee76037,3af3196b,78b0957d,7cda51db,f1ff0c8e,fe6454ad), -S(653174f,8da924ee,322a18cc,8dc1e89,2ebfd90,dd1ddb95,6cf0646b,1e87ffb5,ace4b278,27361b77,59031384,57d0df70,9756272e,2f9af74f,55651c40,db5c4cf5), -S(77569132,e25d0051,b81f7692,d46faa9a,640e7d67,30cbb6b8,60078810,5267336c,15b2a80f,d78fd28c,d65d1e4e,4e81ef8c,37c8ae46,e66ea794,b60a0e87,f8203d53), -S(ec162da5,7ea2e308,183ce06e,d2fbff2b,3ec6e70f,e9d8ee2e,a4861160,205e506e,597cd367,d22409f5,b5737cd2,f1878b7d,c5d73603,3470839f,daf2d0a2,1b1a6424), -S(dd4a71b1,70f06062,b476aa37,aa025299,3d6d5020,a30f56df,6f31bf64,5633c6cd,ee4544c7,866617b1,584ce6bb,78627918,7222b0be,77d7ec4b,21e842e9,32c8ed30), -S(39ea945b,1d56a29,bab310a1,194f2e20,e13af9ba,5e37cd5e,d24c7203,9f4805fb,b29aebd6,9849c35,9dad83fb,56774bd8,3628f423,b724efea,80f778a8,370240bc), -S(bc774075,cd344d6d,a2f00112,3201bad3,bc52199c,b099441e,1d2beffd,16c13ae6,9e2d4f9f,2e019b0c,d3a8f248,31780f74,16569a42,58ac8f07,9945e179,c087959e), -S(de53be6a,6ee4fda9,ff2f399b,ae8b36b,b8331c83,c76756d2,3ef734da,57c60246,335c66f3,7472e014,3831d92c,bbbbc826,9046105d,64bde79e,108e09d6,b3f6f23c), -S(6cea6faa,a27557d9,d4561e57,ea755ee3,3d9f6905,36f91ed6,da93267a,fe758b88,e187e21f,4b67e4ff,7a285d97,1d42080,12638b5,ff88d4f2,ffd5cafb,6860a928), -S(fb5f6a80,5875c22,f2b4dac3,9c0a6f05,849fe524,586860c0,c3f9ca19,8091045c,6bbc77a1,f95ffef4,2105ed15,1ba96fa9,688e9e,cbdeaef6,81394b61,a4cf8f1b), -S(79a6afb,7ab3b569,e913cf30,72ec03ba,82c4aa4f,6f90be32,354286cf,52350b8a,32bbd09c,7e512933,eae14a47,fb940fd4,c60c3cc,c27b26b4,4588b278,6eaed993), -S(bacd7215,27863177,9a1878bd,800dfc59,95041824,3bbd492f,98ece53c,454f8613,f6ccba02,47279a13,371077d9,9d8e5e19,6e0c8f28,ee4ff9c5,21f2e928,c8a8dc1e), -S(15820a62,6c489416,14856974,18ebfae6,a7148dfa,895caa28,691bc056,c0e6bd52,14de4c03,8ebb058c,51b82407,1c58cac6,1bf4d105,e2f1bd77,419aa4dd,168d57bf), -S(9bf21f25,14f78ce3,5bf4ee31,334882ea,74106a98,bc5f1a56,d7de831d,8fc007ad,66962819,7a38b3d7,9af6dea6,e4d0f9a5,c03cc43,20742d2,83cb6573,7972622a), -S(b4c70aee,a8a836bd,cb3ff409,d0ef44a1,ee4bbc17,e93d233d,f4fbb081,3883c0db,48f35a4f,c9a9deb9,a454cef0,c0a2fe75,fa23ddb1,d1a2ec6e,2f16aa92,59bad8b4), -S(56d682aa,9381f1ae,4f356230,1f2f6bd7,e39f3e1a,1ec7eaf8,4894bdd9,78489b47,6c95eb11,4fc24964,b9bbe344,bdc32627,ccf1e6b2,b7ce8ba,e466c728,d348efbf), -S(7c7a9846,11fbd84a,9962cdea,1aea4ef,3572d15a,99b1f3dd,7676974e,f797b377,c1372815,d6ace43d,139a57b1,d37937a6,2f0b56f8,bb24b48e,a42aeed0,1715c7fc), -S(a89c7e,16838239,fdb87872,6c107176,7befb82f,ecb9e14,5768bab4,b823e2fa,957df64f,eba5b191,b6ef724c,18a1c874,75728177,682311ec,d709cf65,5ed37dc3), -S(7fac1495,4974d3d7,ac54034a,b497ff66,3f6cb327,506cb906,b0fd3028,f85d3dbc,a5c140ad,9a1bfaf1,ea578aa1,b14ca9fd,49473ad6,32300652,1f7e434a,dc45c4d1), -S(1e3032ae,8406cbda,e7bde21f,44a6ed5e,feb5787c,18c1ed16,1892c24,45294cf,a73be032,b2e98fa2,5fe054b5,d6d30081,b6b331b1,80124e8d,d85e2fa4,c69666ea), -S(abe408a9,5079597,bb9ab65c,852a985d,65391aa,7de247cd,76b44a02,67691d7d,1df3e191,219619ac,79bd7808,b5166a62,29babd11,e287989,65e15651,8472e8ba), -S(45ace807,55779736,65e5235,1133622,9bb6d606,6b5f09f0,76f5f984,51322f4,da7668a8,b0906440,ab68c7dc,41602d25,4bc05a78,f5a4320b,1775331c,537f3d87), -S(2ddf9c36,4dd4a1cc,c3582ed1,e44c0b21,1644c44,525f9641,c726afb5,af481780,cc3f4d02,36cdea64,cb350d0b,9c44d223,ebed2cb3,a66f44df,5e296ab6,41b61679), -S(41818580,a97d4a79,f6952aa7,db37d288,a40bf8e2,5328201c,284130f1,216868dc,4d6212b,47944485,c4e2c4ef,b556b856,2de81a46,89f0401b,2d7ac123,fc83913a), -S(905ac526,b7aa8986,1b2cd233,16455338,fb0310b1,adabeea3,a8e66fb0,5d2b7c50,f166e203,33ce73bc,df2ae289,9aab8004,568f3af6,381f0914,1d980155,7674d7aa), -S(89b95280,7022c368,d05f2fd3,10a13a24,1436909a,6695c999,f448b2ea,2be1c642,8d450758,5f2ff980,3a74f447,8a403ac,60c4c28d,54a77556,89748c58,f1efd1fd), -S(d4ab0d06,df52b5d8,9cbf1c74,9d25ac32,9abdc525,1d260933,490a45a8,bd5b0eb9,f5991ea3,6906dbda,efd4c6ad,6cd36380,9b978396,765c5ffd,f538091b,b25bf652), -S(aa3327dc,8c9232f0,48c14e27,fd235a6,58db506e,7de5e2bf,33edde07,38109ed,9dbaebe5,644b9728,23539091,56551b3c,540d9c85,3fda5bde,725fb89,d6bba192), -S(2d4b4ef0,3699faa3,a519a0a,72ea3ba1,d2f43f0a,c22a13e9,3fef213f,48b1773d,e6720da0,40eb745e,f99124f6,dce35709,2048462c,5623ccd9,f58fb739,e2314fcd), -S(fdb1cc8f,966c7bc6,8d264c56,8066a106,b102c741,11e40514,a2521dc5,5ecd5035,541b7302,a6e38776,30b178b4,b692ae76,3d59b5c5,cf5e5bfe,6427de67,c271dc27), -S(9a711c07,1b47a858,230c5111,5622f83,44808f0c,ed08c7ba,95170a83,1139b5ac,3fc4720d,1e63f39f,f4170950,78a268d,b7f9d911,3cd8bbec,6e65696f,e7e3e44f), -S(aabbe7fc,608871d5,48530bcc,44006a66,319d002a,4d0b49a2,d9c6ca4b,ab9d39a0,2ab2892b,bee509ed,8f221a9a,4f9be9fc,d9d3a2d3,3d7b54ad,383064aa,b2eb9465), -S(238bf052,fa44eb80,3ad4b6e,264942b6,da3ef420,a6c2f113,b2ce2020,9341d0e2,db6d37a1,47552f6b,8f6ec7ba,7554d4b1,49ff8372,2ed461ac,6d5d5a33,90afb0fc), -S(b276da77,f35f5a18,30ac7277,230b70de,1359c3da,c8e68155,6862a37a,6bea9fcf,8b2f05ca,cda2bc01,898d45a2,b9b20bc9,380d3beb,c5f0b346,96d4f4fd,8958a1dc), -S(5a7141a0,afda71c6,a3e8eda1,83409a64,e48fafdd,1965c00f,f711f7bb,ba1625c0,34d782c5,18ffbf0d,c6f9b0e0,b8403cf3,14cb817d,3e84a7f8,63589aca,cb44dbb4), -S(d186323c,b93ab6a4,b435154c,8c5d094d,51a8aa5d,586db604,d1fddce0,f35fe864,65c383fc,ac4a0450,1d483bba,62a1ee4f,247aaffc,7f7c790,eb4fce7b,782ebd32), -S(908bc35,6d29a3f5,1684bc27,72bfcc5c,552ef35c,a2fe9ece,f08111ec,8c368e7c,93fd8d48,6ad5cdde,c7ea498c,ba825468,caed6c4e,ac1c46bc,43411f3d,de9091b7), -S(21e05a2c,6ae8e1da,d9e4d553,3841c89,2d24f91a,aa201b95,f5f3a25d,d07231f9,d8cda13a,c6f7c54b,abcf3096,997e59a9,617b806a,1d805a5b,9d5d8621,d37a2505), -S(224de404,5c6b241b,4b705523,777dc0e0,dfde304f,c6be8077,cd831d0e,c738e33,bf8c695d,5ef0b37,52c84199,d7ebcfa8,d4988d32,f64a79d1,f0863ada,b6f84804), -S(3fbed77f,3851705f,55eac28c,f3921f23,c67a44a6,3d2dfd01,89d78835,d6106a6e,2139e1c6,4d48a58e,24306471,6bdd7098,c7644018,966a2b02,236b64a8,e628b532), -S(5adb241c,b09f712a,b5520909,53114781,388a6f2b,66218069,d6f5c758,1e4edb2a,9932237d,1be0cb9,2d18dfcc,6ccced53,e6cfee60,d897b6c9,b40c3ee,2b5cc9ec), -S(a4396528,ec7f9a,cd8550a7,7245eca6,117c4e8c,c50a51b3,28063d68,a744d7f0,efb8924d,7f921890,71b1366e,e8d0b620,af274d45,56f2d992,ac709d71,9f5252d3), -S(e36dc303,56a9e037,c9ececb0,764aa755,e1493e23,5ddea3ac,44ed4caa,4fea7bc7,338d5c5b,f5a84dad,5e865696,2ed14c15,70d4eb8b,89fa60a9,973921aa,dfd44353), -S(a6c6c231,238ab32f,361743f4,5d337eab,4a529a42,dc45f1c0,670fcbd8,a0dc22ae,4a3433e5,b415460e,4816b9c6,c1db0657,58aa6279,ad4f47c2,a5f07219,c50d00d6), -S(df09e277,b56e0f7c,2e93d8e4,d47778a8,3aa32c99,b0ac74c9,d64ffe8f,5e44b900,b77cd700,b6027f96,9c80a4e5,a2435750,35ed890e,30fdd9af,b41abe4d,81de4e94), -S(803abc31,138b3d57,9a18a580,bf0520e5,d9328812,14f5587,e49371e3,fe03b02f,a270bed5,2ef7cd2d,4d5cdec5,9d92c980,6e700c33,a487b4e3,f507332,99b54aaf), -S(ad15ba0b,c5cdcb53,6b55cb2f,171d1db0,712ff30d,b10d05f8,bce4d70d,22bc0bc1,fe7faa5e,1699e6d0,1e31be29,b5770756,fa6485f2,f3077f82,33789582,bb5949e), -S(85cdfde5,65959eaa,d025b6a0,1616b7ee,8f710833,187243dd,1103a0ee,65031993,facaf5d7,31fb65cb,f10dbf78,70ca3fc6,68a0581a,4eb73326,15d03f4b,87b53204)}, -{S(9705d56f,f75c7d2c,bacc47a4,a6cf8b10,300c688c,fdbd1b1,528f41b9,652d49fa,c53f7f11,896f2edb,fc957dd7,2cc90856,c5df9d86,43e42489,70182843,84201b98), -S(69db829,eba841e5,c2a1d54a,7f8857d4,4e898caa,fc8d990,eba45c75,9986958b,6b5589ec,635f24b1,4892d895,c56cadae,635de22d,de7b5b09,43e1c4a0,d83f0120), -S(4a8da056,c550978c,725da71f,6cf59df0,e13e3d86,b2255f10,827060bb,9af50961,abc04394,216df6bb,1052db88,e23237a8,13985857,a8048c7a,51787b4,ee7913e0), -S(775d4538,834d66c0,d41a5627,f2fbec9d,a5ec1e12,dea8572,7a32413a,5cbc3612,2c423943,5281901c,6e6665e9,d98655a4,91477e73,fbb3874e,7793a3b5,4b2ccaae), -S(b9eb2bff,b24696e9,36393471,a13ea71e,7ad68377,e78b9eb6,cb40d9f2,7da4632d,c54bb96a,383df77e,a0d77c53,ae2fcbaf,ccf53c73,99e4ee2,faeb338e,8cb40e8f), -S(a8aeb77d,ddeac4b2,71efb2a9,4f44dc31,9f32a0b9,7a1d0e67,8b4bde2c,a3a59233,8fde1a77,e2c76aa1,b5ba70da,dd37af0d,d98115b7,f17d26ff,ed936a7b,5803374a), -S(16f1cb1f,1e8bb14f,b475b130,ff1d0ad3,167b9249,efb9fe20,b31ab365,cb92fc60,9cfb2bed,8c1eb7db,6bc1b7b5,baa88916,b8f68fbb,d23be873,3c54c038,3ad0ac4b), -S(64563829,eaaaa500,c57bee41,f356b8c2,fe7c89a6,93ac0fc7,35044ded,5ae6292a,7298e685,c9bf4faf,bbd527f2,7620ae5c,2c3a342a,4c8d919a,72afcbbc,8b53a50c), -S(614092fe,2588e655,484871f8,3479d350,319b21dd,511e93bf,db81f898,7b2f3137,d10cb0e5,1201122e,fbcb3788,133fc545,7b0a4569,b44ac629,31421019,909adfbf), -S(e0b693d6,60f49c41,d3dbe7fc,51fba3a7,744a062a,46b57b8b,36504e9a,1585f5ea,21cb0611,a5014796,a744a507,2a4ebb2e,41dac48,87bd660f,e1f14a39,819e8c5a), -S(f3ee19e6,d27afdfe,a932fac,72f25828,a6f52c1d,671dd85d,3db0426d,74b8439a,d7c32438,6b62fe7b,fe894468,aff8262c,38bd0eed,4374c9f4,618d16bd,e2925874), -S(fcdb259,b019b7c0,ad0b2e93,f07a89d9,e26f121a,7974944f,85dabfbe,ebac9359,883cb06f,fbe5a647,60711b8f,d99783e0,4f59cee9,31d5a3f2,2cf1d692,894fe4b1), -S(bcad7844,a44ec239,dd113ada,7acf73e8,6271c920,72afb585,60b0f002,a09a539d,428f8d0d,529add2,73ff3728,83f92160,940e71f9,c0a06da2,3084363b,a2586edf), -S(8d54b2e0,f4083478,d6a2ea0a,1416ea8c,fe176621,30e2bb28,fb733656,9ae4ca98,c6d6ba83,fd780d91,ecc8016f,841fbb62,1726fda6,5840f183,7ad17bc6,33106a3f), -S(c9513674,d582a1e4,d91f6ef0,55920a50,1fc230f5,e5bfcf42,8c1b15df,d7f3a8e9,d01c55eb,4d685119,8026badd,3425d4a8,f56e7ba2,6c306b32,5686e279,81aa5cb9), -S(51268b15,a1d43b33,b95e92e3,cfdc7740,679cbae8,ff6a36e6,1da3a34,c8eba7ca,19699ee6,98d95b66,95e21f40,64421d25,a95aa7b9,9eb7ff0a,69331e34,c24952ba), -S(7b46c85d,6364fed5,87230ce0,9e932aca,ca356858,1ecdfa8e,f9b236e,1ee7b671,edda0f22,6808b01f,2bb5df80,2c9b613d,469eda9,e90be70e,4657342e,67519cde), -S(bff9cc3,b68413cb,9f9eae8d,f84adfc4,563069e6,28ff023d,6ee3cfda,8f97a935,651a2d85,cc10831f,f1571320,500415b7,24f232e3,30f47261,8d482924,40259e9e), -S(b5370f4e,f8b3af3f,3e936c34,e7c8cd89,21d4ecc3,7e5a5c0,a205fd37,9abc0aa8,6e889dff,6350f4ec,c3a413ed,694c1ae3,367d463f,be212a76,bc2a5a4a,b59bb09f), -S(72623c52,8e665a8,80c31e78,88b5777e,6b53f02a,6ede4aae,f2ed3bc1,ed351d42,4e2c6c63,c762652b,43383c13,806162dd,1992bbdf,88a3c714,a5f29522,a0db689b), -S(446e4144,8f66c9b,8eb06f5b,e8fec592,9abeacb7,befae28a,cae5091b,798d4f0f,62da012a,fc3d4eb3,4207db5a,8579c581,6a8b1543,b201e1f2,90b413bc,a57f7306), -S(428248b6,49cd424e,12b81504,46443a3a,b6e921cd,79e9344e,4613c653,7d0fc039,864dfa6a,fb191af,91286054,ba7f09fd,75e3d661,c91f939,ef834325,aa26703f), -S(c252c5c4,13e2a430,18ffeb55,355644a0,15e04cec,31424a41,9533af9a,eac0b688,c37efc23,26a2d965,9563b7cb,cf0953f8,cb3ec5ee,3c7ef263,3a6389ad,eb00fbac), -S(b5feaf98,f617055e,b976f63d,55901b93,7e63662c,5b6453a5,79a0c905,c951c037,5372b044,fca66887,566df1d0,6fe0aa12,d8405f84,529db971,a6422820,e6ce7f08), -S(c628a5d,72550157,365031d4,fe16f6f7,94636130,94447c07,e767ec63,8d62986b,539fb7a2,9bd686c8,9e98a1fa,ba95a493,2650b98e,f92198c4,534e58aa,39de796d), -S(f1d0b5f0,d6e30201,2bb50ede,eaf78813,f0a72315,6ef086a4,415e2d97,44acfa73,cd8accc8,fc951f05,5409599a,6da7e5e7,beee325f,2a7466f9,9be63efd,f6d9416d), -S(1d46b065,ac7fd9ea,5771363,dd2ca1a4,cadaf6e7,8e93a037,87aec58,af30f179,f3518f13,c9aa688e,7770d0a,d4dd505e,a22b4430,402ec3a,664fdf89,e9b6e752), -S(2bc0409a,b43950c3,16588fb6,51db2509,a66b074e,6df5d35e,a2ad0fa2,1dc32dbe,2a6df1c9,97bdd5bb,c831d308,d292a30e,68e1dc03,c16ef2a3,183ea616,b16a2891), -S(388a72ca,cfb9856d,174f0937,dc6d721f,63f915a4,6c2fb4f1,1b0cb296,8390109d,2f70bdaf,ebff44d5,b7f6ec79,48184e57,63831421,5dc35d40,48e5400b,dbc84d5b), -S(5404f49a,61865863,859fd7d4,2f008480,e93d8c50,3654525c,38c09ed3,66f95640,71626266,fd861532,a73eba6b,69c6fc4e,2c727ba4,b10e6274,821f3b71,fbd3ab2d), -S(eda6db04,9e8ec72e,c224ebf8,417f2123,8a50b2c5,b149d4f6,2a9bd2d6,78a0f67b,b016fd67,fb3f3fbd,7e53c210,94795570,7ff177e6,38f5a8db,74847496,5618858a), -S(3b71b31e,eef08efc,571669dd,c4deee31,e72f898f,5c83766b,8e58db66,e0c6b4a0,8dc3e307,4780ee6,b8122e3b,d6137998,1c80b72f,66f9f3fc,46bcd11b,a78b821e), -S(1ab86db3,750a687c,39c7a672,c115c29b,1f8f4ba8,586b9957,6b6b1894,7858d52,f60a122,80e05d3c,cd0cfd97,e1029cb5,728ff2d2,df077af,13645402,51412618), -S(eaa96c50,98e79e7f,27b3887b,39a6f74c,983eb44a,9b9fb7f8,e36f4582,596061a,4da962ab,c183ec56,5e37b1ee,3f75c531,3be12425,df54b4be,e4510b45,a84969db), -S(b3b4b315,6609efaa,7964743b,c6789f67,8e40b123,c336f64a,51bb322b,79a6e569,30d6e2e8,4b2cf3cf,e44b86a3,6f3655a,4e1b8e5,442084c0,454f5fde,c5cfa180), -S(1dbf8ef4,174e8259,ccb03ff2,bbacced,d04b30e2,301a4627,77669f9d,4e02f006,6292dfd9,f5df7ab7,31103e38,da6b59cf,4ea57664,887e8804,b61492ea,add33edd), -S(74a9e0ca,b7f1168d,d1ddd81d,fd00e731,7acb92e7,a81ad625,6f655fbc,561dcb05,aea7175a,f97dbff,a0ffcef7,1c89a8cf,d101b3c0,6f424d9e,bced721f,19578d7c), -S(17d35d3,507f39c8,b7429cd0,9c04fa49,efb0d47c,a0c1a0e7,6a303c85,ac5d35f0,88a8998b,603095ff,1771d3e6,d7d69ce8,268c8f6f,20df114d,88cf83c4,e148c4a3), -S(890a566,fb2b0ac7,1a269b9f,90a20877,3611a6c4,ded7874,ecb8482a,f758b0ec,6cd1086d,8ad35581,bf49b063,b1818b20,8e2cb340,17a9c0c8,1a197450,e8d7fd8c), -S(13d1b6bc,13d5b669,6a6a423a,906476dd,d3a671cc,ebd5e119,a8cbf6db,622ecbb7,1099ec23,c79d6dcf,3d2380b,eba653f4,a3fb4bd5,bfe22e4e,abd2e57f,3953fc85), -S(775298a0,c8968fc4,6c7c7e7f,571a784,13ad7766,a9409a6b,6ce02a2b,3e033934,2c3640fa,17aba57d,e2dfa700,ec4ae691,28579db9,91ba8670,a5d8f0ec,b9009c86), -S(ccdbc86b,a89a8496,35c20279,223ff5ec,8a545acb,58b04b53,eb2aea74,ef56ccad,9d229bdc,2b1731a5,730c8f75,5edca111,c52cece1,a65949f0,f51525c6,2f4e6abc), -S(704800e9,c4e03a4d,9aa9e41d,8619508c,9d17766b,217a3d3f,cc5efca0,67594157,7da8e92c,22174290,d08c222c,db33b345,c45388bc,da9434d0,99514d59,2660c24b), -S(3b958586,e7bac33,711be679,30158ea2,38bd6801,f087ae0f,e694e482,a4654c06,93e08192,d074e631,6f7681bb,49b9398a,cda6fbed,c42d372b,2bf3bff4,66ec70dc), -S(1ef945be,6fab11ec,4b48a57d,d2c3ec3a,5eefe46d,afc58284,a005e02f,6d5a8dc,1ffb979c,66ab8493,8a12fc83,52eaf5ed,431c3d14,d6e472cd,503bb1d4,1180c069), -S(72ba6f,627d78a6,c265ffcb,2c8a1e3e,c716f52f,4dcda188,4ab23325,b3bdb1eb,7cf1eef7,aca4f18d,1b1324d1,ae6bcf24,3c870fe7,5a977c6a,c6872ef,c1602afb), -S(2fc567f4,3df8fed0,1eed527f,8b4338d6,92143c20,13b963fd,343aaa4a,ae3e971,c3375e3d,e52b9c17,647e36f0,b4a60031,5837b2e9,c61d039b,1e934ef4,b9cb8864), -S(6c80f08c,30b3b243,1c3a4b1d,b2cdcae,505c671a,11dab05a,4ecfd68a,e5cbdec3,46dc33f8,8b54e177,88358d5f,bfc4c834,4e376338,8cbe10aa,22ae5062,5d3ed7da), -S(587724ef,65997e21,e38bfc75,80707319,c3065fd3,9dfb9cf6,fcb3de84,d28a0f3a,4993a8cd,7f22b55a,88818c49,8eb18807,a93d1246,f0f1efa5,6ce0efe5,68366dd9), -S(f82fa826,8a43213b,5d871f8c,fdb6a6d1,e706ad8f,2b8930a2,c495bb90,39d1d5a1,78749a3d,b47e256b,9ab3ed40,9b9ba1f,741ddaa5,431f4f22,896ebdee,8ddb5d98), -S(18177602,341d74bf,9ae572c7,d60febee,fe37fe20,80c89722,434b9ad4,3c935dd1,aed1c747,a87e00eb,2fd8ca9a,b860ebff,f6ff6b6a,9a2dd505,534b28cf,1f37f7e6), -S(842785a0,11028ad7,4704fd7d,15e9284a,cee1272d,936c1300,d8598623,de359971,d507ec1d,cfe03f65,61a7b192,6c14e4cc,dec54fb8,4587a9a0,cafafa5e,81b35f77), -S(c22076f3,441370ae,c874a32d,297b54c6,f284efb3,95741124,21428332,140763ce,109248e7,857ca454,cd9fc292,731d800e,8a29d13,e557224,bdc47992,717306c4), -S(14c75d2,c7f48020,7f6c7b1a,ef4be041,d2c13f4e,48a9d9a7,b4809f2f,a20ebc67,267d7fa5,be716683,2f48fe5,f782b719,c707edb4,4e2eb6e9,3217e6d9,adb78647), -S(ebbf722c,67339545,ab15b2c5,f6c517e2,e32b319,a5c526d8,656ab4eb,4a72486b,2c56f524,3d33c2d7,7c989453,3108ae44,f8b5d86c,9082fee3,c99236c0,258e42ff), -S(9313e212,4ad5658c,9a50fd28,70af7f26,9661fefa,41b0b5bb,25b8cc05,9b8a2892,92d4a8ea,73210fbd,a730c8ad,50a19e7b,11f65025,a2fb2915,7af992e7,b9d449ed), -S(5549d2ac,f2a7b23a,908d1529,696530a1,41ffc39f,323cae7,374666c4,12d9fc5a,87a51da1,f8766aae,f1161369,67259d,6137b607,b579a215,59e9e3f3,3a4368b7), -S(dcc897ed,9f994741,1e15bef6,8eae2771,27ee8d5f,b2ef8ecb,f47e057f,801c7b1f,5bc17162,f6470848,a4b222cd,357a4e63,c3a15ce0,5fecfb1b,19290b7d,6af6bdfa), -S(a9ead801,344ca82f,738dc5af,85534bad,d320aa7e,2af4420d,b4479cb7,d9d747e0,1e3f6e3b,d065bdc0,99630291,9f2e408,361c0f,76ad5c7f,4ce3f220,a69fb30), -S(4e7e2308,67db8bae,df576eab,ea65f2ee,23efb749,e0047ec5,370b0db3,2897997,6f59c99a,15fc73e8,e393805c,d04a1254,5b8292e6,e8cc8cdd,cc426b16,90b9643d), -S(6d52baca,67e37e9d,cd68597e,f2ec6b83,27abd9cd,c5088043,f420168,726d7c8a,8e721f7c,7d77b0ee,17f2bcf9,b5b1b9b,da9545fb,1f4d4c7c,d544f070,2af986ef), -S(2b4bab06,bebed117,b09c6304,18185408,23b27f24,72223ab1,9dfa9d41,25271d00,c8e41ed1,6e4812e8,c32b8c9,4ec4c4a4,f3f00c7e,2a5bfe2d,27b6ea9e,82329cc), -S(21b85eb6,104564aa,c8b070ca,52b993af,4260e911,4cec2a4b,92041c05,f420285e,712a8ae5,e03bfcac,f6d39f31,ae20c22f,c702b364,35fbcdb8,6a14b1be,7622ebcf), -S(b95236b8,fe6becfb,98249114,a26e910b,62bd5286,e10a0dff,dd145b5f,ee2dd84e,3f0b83ca,e4549f4d,4512b410,57757c4b,7a3b115c,32819af7,6c31d204,c029fc21), -S(7b2b3f20,5debfddf,17bd4922,188c6bb9,a1dfdae5,910803c7,24a6cb4,d5f827e4,4e60c6c4,c1932812,457f7bce,98b8b77c,66512966,9149860d,726b3f08,4beaa2a4), -S(b2333534,312b443e,3d5a5559,67da3b7c,caca2947,2aab9281,d389e10e,2071cc71,5bb0be9b,d27c0b27,b2a2a68,d0767f2e,7ef79a4b,4dffd183,2163d7fa,9cf98ba9), -S(20067cc5,1be142a2,b6f5f30b,18fb52db,a675bf8b,669b1fcb,d297f73e,93920522,a80c956a,f0206a2c,74b11133,82fcf2ef,883114a7,a72012b8,d7dacd7b,ef696999), -S(d092a75,8080d695,2464009f,672a00ba,f49d884d,744a749b,fd884228,8670f2bd,da092b71,78d8a373,fe5dbb6b,2822c9e3,901b356b,714044a8,6b70bc5b,e5018f9b), -S(91f482c9,2e9c481e,79b596ac,e716270a,ee9e9cd0,3d502c9a,96a6e8ee,114d6887,af9bf0d1,ccb2bc3,3d8d3c4c,20346223,19104e3,53ccaa29,4de71967,634e0b08), -S(51bff42d,76705ed2,334de997,dc6d916d,86274f42,494a86f1,e57ec18e,538d195,2ac758d,cfb59a56,e483d361,d7a5e3ec,de0a640b,f94ac8,cb9c4a19,9fe423c9), -S(285483a7,8b621501,b294bd80,3469a136,2ffce135,a526574a,38d29d66,c69733e6,c5f3d286,f82fd0fe,f799902c,76421359,921280d7,72a91c42,33379711,e55a1e15), -S(848dde1c,490b4a3f,2aeaa7e3,97cd2840,23539cdb,a3a79752,601e5868,a29d7110,182c5fa8,574c673f,91302647,2f9fda27,dee3f57d,19c10e04,e84ea4,f532902a), -S(bed1c6d6,82d48d91,3b6ece9c,c71cc51b,418d6f5f,f2f5fc78,f4d27bfe,8eea513e,7f278fee,8696dbb3,fc762602,dcbe1a5b,653b8738,e93ecafd,8c23a90c,d82aa45c), -S(46d3d211,67a906f2,64f7ea9d,231cf44d,f523afce,8b99c3c0,b5f88ce0,f19fad02,7da52bc,905f1f2b,78c798f4,4ff85e90,c4b7ca2,4d2ab28b,cfee6cc8,373676e9), -S(7fcc6146,3554506e,931212e3,fb68719,914943c4,a067c3c9,a0952225,c5f39fc4,ac90244,c5d5446,20b17f6a,75cf6dba,6a05895,e1f3a097,85fd6ba6,a440ec68), -S(a3cd5ea0,b43c25e1,c45aeae7,1d05fab,e9009262,8b544d6c,364abd1b,a4c0b9a3,312ab3bb,fbd8cdab,1c7d01b1,53baab40,517eae29,b8ccb28f,27278a3f,7bdf0b85), -S(c446daba,1825a802,1d62796b,1ef604eb,d905db5f,9874eecf,7be2ef0b,1cd2e9fa,1562aed0,d869425d,3adfb280,a959fbcc,195f632f,f6d8695f,f8eb3381,f7f274b1), -S(77c9a086,1095246e,b59ec6b9,5af0c435,a64ac0f0,a238fa70,6c5aaaf1,3d9e32d0,8a89b6d,442a911f,66d1c966,997331a3,db74fdc4,a1305ec9,e13f2c1c,4f1524e7), -S(19e2aaa4,fef00f4f,64ec5b45,d8cf58f0,37ffecbe,f305ad18,eca01edf,33e62cd0,2d636e48,ab56e09,12b922a,d567164e,93f6185f,4b3b5b54,73dd3b62,5a1bf359), -S(5e6a3b49,60264ebd,1b98d889,5722f263,471343d0,a18f540,141b6d17,f5d0ac3c,8f91deaf,390e1d5e,dc5c329b,b8a067a0,e5f497c2,39fbb4ac,3de3c3d6,ac61f35a), -S(6d90b780,b75219c0,5e5f30cb,61f5c9a0,44c446e6,8bfa56f3,f80d54dd,6c06aa91,6e02731a,dcd7f45a,d52a3550,f6b37f32,4a913c2f,6e48f264,480e3248,a06eeea6), -S(e4358de0,e3e65fa2,25d164dd,cadd7ef,cda7a801,86d11fd6,92222d90,24131cdc,8621625f,69c4cb56,67f92d53,74bf8746,aac1d17e,a9401978,89aa4db9,677c2320), -S(6088bfbc,79b7fe62,df884d2b,ff605794,9659ed63,3d9b7543,ffa88cf6,db81063a,ff27059d,811db138,a061d6fd,e4c289d1,54d7c28d,1a13bac0,10004c83,9146cd44), -S(89aad23e,2b364a3f,6f4e218b,2a519c35,51b58eff,fc0b264c,549e2d41,f1552464,1f1e9915,1a56f61c,e48f3a75,4fe02fb,2cc591e5,8e7289fe,39c88345,3c868b10), -S(c354a06b,468e1503,803d69d5,919a68ee,9e60509b,7d85b543,dc06a004,215525ef,e6656a2,bd6c2569,aed8d779,e061842d,3a65f9ca,a46cf5cb,11a870c5,3411e09f), -S(960513c9,bf25992e,265e09c8,4749b4fc,d3dd1b9d,8de5ba17,88099526,2e2fce90,f2cee526,e2f19b4f,b089e3e5,aa4f3d4,dcd5be51,67afb83b,4471a220,f961fe26), -S(915bfb4b,e41aef95,f4b84b87,5f4b0f11,89397160,c8b0abc3,5c976a08,29c7b534,e1238986,b3b6ea5e,528fc6fc,ce95be98,a0490c37,e2964739,6294a245,5580607f), -S(54a414f1,cb9bec65,f1e8f09a,f12d91de,8615f47c,370a3a18,78beeee6,8297e07a,9d9accac,fbf02cf3,a99c5d58,9e9cbc3e,45e9080f,1d345fdb,93ba4306,c6972ae2), -S(4495cbdf,4f71fc3d,bbaccefb,1eec5f13,acdffd13,9a0e9a5,cb798086,a8a46b2e,1100fcf5,8f571f89,4b625179,31a33fa9,eb2683b8,9d6f9ae8,748d6615,7e40f6fd), -S(737740a4,35247754,b4264e73,7f7c4572,94bb0b0d,102d535d,86995ea1,68b7aac7,601553b9,eb20b8d6,8a0b9562,139d75e3,d3003a4,12837753,29c3696c,42f02f63), -S(e0dfd6fd,1e6def44,55afe74e,dfa69eb1,310ea3b2,6d55a13,73cc0118,7ca720c4,e6d63ccb,96084257,8b764a05,15ab78a2,a5afc188,a8f7a4e1,52adfd3a,e56c6bd7), -S(b4ccf2f2,4a114f61,cb24bbcb,f300a643,3190effd,4930afac,fb2bd4e2,1cffbcc0,3d9fda60,7a752c7e,4316f355,fd0fba2f,1f38bf3d,e9a78bf5,5ebe58ee,e7d13a0c), -S(9efadc19,dc6bea69,e0b4a59,e0bb9e35,a1d4906c,4d612da6,f32f7f33,c96345be,19e891e7,b714e7ac,32f801a,bdc2904e,df8882c5,dbe25ad0,f414fc95,da4915bc), -S(3a4058b1,cfc8bd88,499ddc79,796f07ef,a59bcd4b,bcd37137,2d76f95e,bc177c95,d3024cba,358ffffa,aa3a95f6,cac1dfa7,1d5d4f59,91598a33,f02f3141,81acbee5), -S(30ac9730,53bfc762,7f7bb8e4,a97ce1f4,3918418,e3ad8f1b,edca9bd8,dd7f6ab6,495b6849,a4d4d9e7,8ffc49c8,976b5f9f,a631e1d1,95fce967,416659cf,f91c6147), -S(248a974b,35f025e6,1a462050,38a0a856,d136b68a,2ef09691,69332629,a35cf2e9,b25a8e72,efb765f2,66794992,9b3ae32d,f148021e,63aae20a,d4450e3c,6b5fb5b5), -S(107899a5,11fa2b90,fbe5889c,fef115f,f0c9cac7,62f82cf,12487318,63169a2,ea1c4278,811fbe5a,6f011375,35b584d1,a85d3236,c66d52a5,845a6ffb,3706f8cd), -S(91905b3,e5602f5e,6a780acb,4a33f7d5,4d87b239,dc9f19e4,99560d22,b062e897,caadc62b,71d3fcc8,d9d5e410,7a11fb75,832693af,46ae99e4,d8f7d140,900b82a2), -S(e103d0f1,1e7bfd74,821dd503,53b08f2b,3c56338,f4750fdc,76b4bbac,f7ab2404,eb65ee56,1dbd1e1f,d5437b7,b86b1502,3bf423ee,f75e7620,aa6558c8,a039f741), -S(f35e2c54,f2e8f2e3,fdd18dbb,e0244de4,5b9fe772,7c00727a,5f12d7b1,def1c45c,a01aaabe,85682057,b649ed03,e9786133,e5d22cee,4e5c56a8,31bb310d,fc03cf78), -S(5cda0c4b,ae3e3ab,8aeaf59b,ce9b57bc,da0d8cc1,b638cb8c,aab26347,e8188bb,d992c965,4e8a3d6a,4838c9db,64fa1114,e88986ad,da948ddf,52ca17f6,f600c219), -S(cecf5b7,1a36fd7e,2990dd73,9fd150e9,e6183368,436b9702,f9dfa05d,a88220a1,34bec823,e6cf7184,f837e738,3c4b5edb,3ab3f027,d3034639,b038efee,5dafc8d0), -S(5761d842,db207d20,42e3df0f,d95f13b,8f09210b,c7c8521f,4c33ce69,5473c28c,31c68feb,48e1eb87,afa40cd0,a4e55c9d,862c914b,714a290,4dbefb01,d59e4dcc), -S(d4b5e716,5ed18b35,61994dc0,e2af0ca6,3d34d053,d89d211f,4157434c,dae8b10b,137db71,89d25a86,cdcbc931,ad30c5f3,27c368e0,6beb1335,746cf6d7,bbecb07b), -S(6e9a9ebb,9cdd9729,f3bd261a,ee9ccc5,3d55a9a3,fb79d370,489ebac5,9951df97,32db39cc,a1a862db,172670eb,132f79cf,dfeb7022,ebe19b87,3d9781f1,1691f4a9), -S(ab4f56f1,941e7a55,7f7090f0,ba8b10d0,13db8e61,f702ec07,c4b99b2a,a54e12d0,c1a1fc11,51f23ef9,521ab291,cff740fa,42e00fd7,1ed3012c,86e72709,9374c637), -S(6f9165f7,e1f44fc1,1f7bfe76,7e8f7f77,3d25caec,17cc7357,d0b99ff2,1258134c,350f1c38,50c74078,3dc7a5bf,3b590cc6,45063e44,f46dfae5,b1c961d5,822b5840), -S(ba866c2f,67d4b6f0,8317a5ee,32519cd0,93c17fc6,6421a156,a4056eca,dceacec3,93fa72ce,612e210a,42f81d5a,f3c16d26,36895eb5,4e2d8d98,e6d3589f,d6ec72da), -S(35834355,a9445a8,40cd6b00,72e6a3be,54d80301,7da65bbe,cd1bef4,6788ed6e,92097690,e15e333b,55aaf635,62676402,cff85231,885060a2,2a29f263,667e6b5e), -S(50864d50,6835ed6f,86b25b45,11db0367,d88de358,62046623,573e35fc,6524b4f4,e970bd97,a9692202,376f485f,5548a980,188650dc,91ea1351,8cded8ed,7724508a), -S(ccaeb079,8fc41009,fce22bc3,3f191412,4be3fc03,cf9031ea,84f1a017,b9d5b3e3,b0ca53ef,45ed8340,f448edae,2ff784c5,c0b3bf3e,ff93cba0,8c2ebfa,eaf64df3), -S(46f30e66,cb54b89f,17063c32,dd1543e7,e73d4a08,758560a6,e62e7329,63076c0d,b84bafbe,69b45a62,498dd9ed,d202506b,9be830d1,6d6fecd5,69fb8f96,6a6a3042), -S(265cd9de,e006d582,45a04fc8,82f0ba5,b7fc91c3,6535e748,514ec587,c7f80327,7199f872,7a6d937b,6347d351,2b0050ac,a8e37652,3d922cf,f60c4b4a,846a0f57), -S(31cf7fd4,4e30a151,5e8a06e7,347416ce,104338af,3cc8deb2,ebde204e,de6fad28,5e1a97a0,bb0d965c,ece3be90,b971fcb2,a5d52ddc,5f19cd1c,9db15671,e5101d4a), -S(61110e5e,f84ac25f,85154139,d8d6c850,9ec024e5,5f796b69,f69e7bf6,3c41ce05,b67f5359,bcdfc138,963568c0,b386996d,82b77005,563cf104,2736856d,e548abf3), -S(539655be,97322448,a93f3760,9e67a02,ae39b00c,ce1bd156,cf9e78fd,65788661,105f9f23,4f075bd2,dbc1b74e,3e81dead,125792de,6025efe5,7463588e,eb5a7015), -S(e899c784,7f0b1e06,d4dcdcd8,1d978af0,aa00395b,af7e82f,a25c1534,1281b81f,f37e6134,1687ee5,942992f3,138238eb,1b2f13d0,7353f69,905c0b02,f629f436), -S(ae2d2d8a,be3313d3,33ff5efd,3d31b73d,799b1684,47478e38,7821ebff,8d722ab8,680721ee,9acdb2a,bf38c78a,910cf9a9,3beb66ff,d086c982,639ef987,3c234ac9), -S(b9e7abb3,9eeb4754,5d79bc29,97187c99,c41eb1ec,7fd6eda4,33eabdb,d60a5470,638a8f7a,b02eba6d,84d23582,46180a2d,864be6e5,a6abd36e,b2609ca0,3d0e0ee4), -S(2b20a9bd,a7a6730e,95454586,a6778672,6bc18e60,9a765fc8,c54cfe75,ea0a5a06,2e442fab,623d335a,e9c2a2d7,f89349cb,cd2af4e0,218841c6,d5e0bb9,22d0e382), -S(72fc3a7e,46d9a6be,f381e977,7253e8e5,f9db3afd,46648e8f,33b65080,ddd2d199,85cdc38e,d45cf08d,c23ea251,cf8a8c49,6ee654da,ed173c93,ee380d30,2a0f29bc), -S(db069c4d,3b0faba,af16a827,74452e57,72aa87f4,ff3b97ba,cf17c75b,349e4d86,b794f792,85fa96f8,a7037f7d,ca851a52,7a83afca,26965e73,6408ecc4,1247c3e6), -S(7cf3ebd5,aa1b2065,7d7d0ff6,a34a72e5,60436327,afd1f548,ef45eb4c,46b01b82,51de8d27,2ac224a5,2e5c2645,1a9863a1,8c9f8c03,43663023,d7621a9,21f1d855), -S(73b0a3f3,233b1fa0,30fc1062,69453fa2,2120b0f,e6f91d1d,c637e0d8,6573ac63,e04e33b0,b118fd12,30a816ba,a5ad9265,90ff186d,7187a7a8,cb740e29,8de71787), -S(32769d34,ca2c15e0,6e520b40,6a8cafb2,1f541f25,130dee67,7f4bc606,d3480db5,59ee4d85,31b67173,a8c1aafb,83ba9ac7,2f72dc7a,238e1630,5a3ad39e,d508334e), -S(bce22865,2f6cb032,82f50e4f,c834216b,59a6e9c3,e787cc81,fe8391fc,3f2b7101,d5ec8a38,93820cfa,85daf98c,281c1059,51986ac5,5f4ec530,925db0e8,c98661d5), -S(6911f551,e3522b85,93a1160b,356a5254,968a45aa,cb9fb870,37e3cb28,7674ea84,d26573f4,f3a58064,83d6d814,553f8dfe,e1d3b413,66062b42,ecb1f4be,56c39839), -S(171de86c,6dbcd466,2cc5a0a6,967dea53,46411198,a8fad3c6,a21761a0,5f3303df,4c6652c3,ed4e1b35,119473d5,96ce0350,19ac08,acfcc66b,8664c86,21288b0f), -S(8afa0269,be8300fe,592b612b,19758692,bed5d98,6374838c,126981a0,60a8af40,6f93d092,f4d82898,7d3aaa28,d8764c8f,937902c6,a2fa6380,91d4e6c4,d07d8eb8), -S(9c6f623b,1feb0699,59b129d9,aea3349a,13b92c41,ff7cae56,3f39adc3,474a3721,c6033ad1,f7045dc2,76f1937d,31d01a83,cee9a2c2,e6e8e0cc,c130c852,76a76b78), -S(5c88e5,bc110d8,ab0e77b1,e1592dcd,d576774e,4efc3499,5d05dd43,fdc8a22a,33edaf3a,e34fc2ae,b2d1743,c5be7c31,7ca09368,8226b5b6,c98be55a,18c162f1), -S(244116d6,b514bc40,7e5f5ead,624efe69,dcd1997d,881a6490,d2db3517,5cd57fd6,e9194bf2,e27251ea,60f4761a,5114d205,c4d2c13a,c9fe5887,61098e90,beb5b353), -S(db49b35a,9dd72d8c,8d0f0424,20c769f5,955658ee,7eff4ced,9dd7d31b,c0252dda,222806de,3c908a10,c71528f4,132e59b5,d14480e2,391a8aeb,8a6f7de6,1c3bc66e), -S(e208bc35,609acd41,72adc7f7,94ba78a7,9103d213,78c1ef29,7dddabbd,d782598d,f8b4fe8,6f6f1fb2,3c4dc711,8991a334,7314a3d0,1428fabb,6167bd64,dbb31e6a), -S(2da52754,60fb82c2,d39a242b,fcbf3433,be971662,acf9c5be,923859e6,443f3d61,6270758b,6974d5c7,3e5139f0,35d1e218,aed29c9c,bf17b6e6,b8ac6708,b09c69d7), -S(3df8292c,e26a8c51,3e5af6f0,4bf7323d,de655d97,dc00ae71,eb8e1488,bddc3132,98b07c95,c45573a7,97481882,b2f91bcb,6aee1d75,21377640,b6a52721,9d420750), -S(a2a22d6c,e949e74f,813c68fa,587c00ed,3c044c2,42456a6a,70b83f30,d8bf954a,6f4c0800,efe49001,9770f0cd,ddced4bc,d9a3994f,a1721cc7,df0576cb,e289b9a4), -S(8a240ca0,aa79c339,b274df12,b5d739f9,97a84246,b330c28c,fb148c8f,dbe40559,e8aabf1,7ab14974,899689c1,113e002d,2a410d3,b06cc5c1,d0fe5eb4,1bc480a5), -S(fd61d479,d57d73b,1085b312,2c5026a6,588e64f9,f642148b,589de7bd,418a3b45,e0e660e0,642739ac,f2127785,dd23475d,e83dbe72,2915b732,cd19dde8,38b240f), -S(b9cf694,82581706,6565e261,e9c231e,4e95ee01,4a8eb744,12472b86,d5b2861d,969b8e83,a3c2b9d,a4f496bc,b4f7cd78,a7e418b4,c793676c,7e1a8c,fa6bd33d), -S(91ee433b,c5c7e9e9,becb58f2,bd659171,2131260d,8a26d65e,b3fe33b8,442fc3aa,86215e62,1cd6542f,32c9ac7c,930282f1,de0cf7bb,6f6f46d7,a29ffa28,22127b70), -S(1cda7a25,3e8caf86,bc67a7ce,7fe66799,e4ece2c5,64622557,f3b402e,e4b6a6a7,28e11403,94b46fac,df5950f2,9f44a66c,e0c0fdd6,942f1856,db17019a,40cc7623), -S(52471c90,2508a47a,718f3abe,285b8be0,e9e1e243,35e27673,35a25746,2c864fcb,94d8cf1f,5c08836e,7dbd2373,860d78d0,c17960d1,5babf5e9,fe85838c,1923673d), -S(dffa4f8e,137745c5,d11b8330,59ba9fd3,3d09c9b3,bab12c64,dda46a2a,63ba3b33,982d5daa,f0bf5143,e59e5c2b,54051c11,f8e42e30,adac79fb,6cd19446,e56ef372), -S(7d5d28b8,88d15a4,3721de73,d1e3be0d,677b6153,58a3664e,63bcfd04,c85bd47e,9f987506,34bf602d,fc02ae9,9332b494,9f4d1f21,84a96f70,b7c51051,5546556e), -S(8e65236a,47ce5e43,671364a,2e99c5ac,4375f3a2,9110560c,fcb4895e,637be7b4,d4800683,8beea2a4,9b220e38,345e0719,b91f2315,caa6bf8,1ce59b58,c0ec0b79), -S(e8f250d3,f4365f7,696a9b58,b09aba7b,e884be51,86c5f1a6,d513b9c7,bb3c6718,7548cb27,8710e668,27aa9940,6caaf865,e7b723bd,e21b6ebb,855b8150,cba0bddb), -S(87cef4ca,dd9dc07e,a82c0f5e,943e5ea,42b2a9c2,8ed24e46,5604a85c,a98e08a5,736974c8,9718b1b7,95fab8c0,9cb4a3fc,1dc9c73f,cbf0eac,848a4421,7cdbe789), -S(48485885,4cd24d10,aa546441,e132dcba,b433b740,b9eaca38,cb80eaaf,bef064a9,91a91c0f,87523cdd,c6fdfae8,d16145ab,a2c67a44,e7e9655f,417531a8,9e44f693), -S(6f7180a9,be73fe3b,3c88817a,154ecf8f,3102fc3e,a1dddf97,4eefa00,224d7149,e1ecb8a0,bcd0f4f4,8e039dfb,8974b552,4456c764,f4e668e3,9640c3da,4cf24931), -S(d2f859c8,29ff75b5,cd951da5,2fcf0794,251293a0,7e8f0bbd,925216c2,4441fe05,c5edfca0,805026dc,32644722,70f22291,f65b60f2,5f93648b,f4163ad6,d12b704a), -S(38454e28,6e44de11,7f44b4e6,27ad0b15,d555c6f4,f8450624,d5b717f4,88c5f47,916bf1c4,eb9c5159,3e52e3a0,e1414e97,652997c1,fb9fdb03,f34e96d,4c8cfe1e), -S(b039e580,64f64b6c,dfcca8a5,1c93b169,8aa14b60,a2bb6ac7,d098987d,6b72b5dd,17cc6940,313d054e,34ababa7,99fbb1f,a518df36,b2896039,adfdee62,dd5f65ed), -S(5633c240,8a81d35c,61d6d5fe,3f678,220109a7,97716250,aea118a0,52939b04,3997de40,6495a96,ee3e655,3a69b04c,b11730a,709f1077,a5ac9916,85c0ded6), -S(a4f3f220,a7e2c9f4,bbf541d9,8ea71661,e142bb2b,76b4b7d7,af989652,2d2cc79f,40064f02,5dd4bbd7,9bf80bd0,f697dd6b,26ca8ea4,d04252df,ce5888b6,5622e669), -S(94568051,acf08d5f,e36691a3,14b44373,f46065d5,af48e08f,f34adc34,d3d7c15b,59672baa,3698714d,2983e23,1e7d985e,acc15cec,1dff4ef2,dbede100,972d2e16), -S(a4ddf835,3421309e,a41570f3,cbb0002f,5fe81975,35dab4ae,179a7f0b,dd24472c,ce127d08,cac2622,56f116a4,c993f504,b6df5833,731d04a8,1c0f0154,c4126078), -S(259799cb,4a4a4238,5bc3806e,17f19a56,844ba9de,8e303d2c,1cc0ee3a,a7831da3,aeffe3bf,b15297b3,4919cf90,cc808308,ec41c63d,f4af573e,b1d46675,20aff2b2), -S(d65f0bc,b0065fa6,4b13abe0,b621b2d7,b08cca48,2eed0267,8b131fc0,e1967dcd,eacecf44,defa0ba3,3bb5e8f3,9ed0bd15,5ab9aa57,81a22307,ea0633aa,64f98f23), -S(94ae2db9,1ea43b15,fcb2acac,93cfafe7,36874373,efa30c31,98f10b3,b94a1b93,8df119e3,d4872a0f,3b40d3dc,fbb894a7,59f5719f,b81f875f,71ab5b7e,f8cf7db0), -S(126fff6e,9e1c65cd,d7e8aff0,6a20c00e,cdad4440,64ffa43,675a0df1,f7c0ab35,b4eb051b,e05cc632,ac1e23bb,23814d1c,91caab71,6b214dfd,41f6f44c,bfe2dd72), -S(3c8081a4,4183a093,45397a2f,c895877,79139c29,ec6dcf0e,d24016a8,e9d3b210,45a3dfb0,9ff805eb,f7533bcc,1022e0b,8c69b658,88a0393b,66ad3151,b0c3bd57), -S(210f6bb1,25fee215,9a04d068,c87093d8,303ea3f9,1f8f20a4,69dcffac,39295f72,d96e5591,4b2f9eb3,20b9e17c,f3e9a9db,9f284be0,3575b192,3e8d561a,bb5e4d5f), -S(54e9e6d5,df0555b,3a29f1a4,33623e38,5edf8a41,d19fc0b7,c82f151,f14a73fe,ba04d63d,36b3d5c0,3ac704fe,7d15d939,918b8311,1f83bc55,4cd56c33,ea709936), -S(1e65329b,765365a8,6a111355,eb0308f7,c1702263,f8ad9e35,46bb285a,2fe6bfd6,e265bf55,5e975aa9,f2d8b9c5,420c33eb,1a05eb58,ff40da46,2760971a,d044b654), -S(4380d3fa,48cc932b,4f5453a6,24dd7dc3,b4071e7b,eb1a1295,ad8e64a,aa7b40b3,6da29a3a,30cb7bfa,26bbd0ea,cd84c98,c4091683,be9e9742,8dca4fff,5c2a6393), -S(c3990744,d6f84a2f,490a9e8d,feac8534,4b1d4524,1a573d53,9718b6f1,c1bac2fd,2387052b,2161f56e,fb3efa32,13bbe3ec,97e2c78,24c648d6,913bd9b6,c8feb342), -S(d7e1c842,25966972,5de9fb3c,25ec9fb6,4ad1ed23,566e2930,292507b3,e099dc34,5e1cc09,97290936,184c22f9,747e043c,dfb86fde,142dc129,77502a2c,4ad3fbef), -S(f14fa91c,140d3de,5936b6b1,5e4a1bab,8aa22013,ceb72503,27f608e9,2e048f8d,8f429f64,7396fc1c,fb5c33cf,e982cb9e,a762735e,7e595335,19b2e302,a976f0cb), -S(c7837842,5ff42ae5,fbaf9186,81440523,3286f91,5e170133,d81ef705,e80c4f4c,84ade3df,47e23a3d,9f16de8,f61c7d1b,b0428619,8ca74b68,78947cb7,4a5faf43), -S(f39bfca0,beac1ee1,2e98624f,32830908,609e7c64,37175322,1650e813,3874b0c9,19e4fcce,fbc53b63,a3a6baa1,252b7331,fe5365f4,86300711,f6c438cd,4da8aab6), -S(703da707,37e1c78d,1a6dea54,6e896d59,984b1ac8,188fb720,ad837273,86a2c188,e8b3547a,23877467,75c9bcb6,1ed4b4d8,9ee22da2,1052bfc3,aaefceab,698f3322), -S(ba5f3f79,b3d5be05,a3d85b78,16738253,7fbb206d,841f8871,b9f578d2,2c17126d,40acdb1f,c139be,8a1350e8,3d52ae1c,449b3874,71794282,d5ba72a7,5aee5a78), -S(af43cb78,d080053b,7fa4cb34,4d70be1d,57f2acb5,e6718bce,abcff626,c8a44d4,ecb553f,1aa18a31,e8ba2306,22898b2d,fee8d6e5,2dfe6ca1,2ecb5f73,71a5987c), -S(3a3cbce,2b4e40e7,f2c32398,9dd6d35b,74f666e8,48d73e8f,b5810439,f0e1749,f29b185,7c7c98e0,696795dc,f243b662,835c6d00,9a7e55d8,612f6841,d3b891de), -S(81c28d3f,6cb88bfc,dab4f911,98e1184c,d0455bbd,998e8ef6,e98cef0c,fbfe101b,5fb09335,f0527b23,555db9,e5079979,13b75422,d75b5059,198341c8,542c53c9), -S(e9e5ce5b,3c613100,5c4e57de,6133cab4,d65d953d,a4536926,fbcbfdce,1ca56fcf,f9016f,bf8ed329,4a1a5fd0,cd66bbac,e0cd87bc,e51adc95,628b1a8a,25ac1f4), -S(bb45dc5f,e2265ec7,60353992,45f51c8b,72b642ec,219396b5,5ab0edbb,f890c4c,b375975c,c8107cbd,1f5068ab,c3f2f62,f1e9b76f,befef470,be29d5d5,a615408a), -S(38356fe5,4d91f656,79bf2558,36290b9b,b0840b9a,fccbc6a9,163c164a,3e4c7f30,17101271,b3881a72,24373054,39bbda94,6ff03805,abcc35e7,d960a46b,54122ae6), -S(fe6f885a,2996a35d,2886e6ff,e1d0945f,515f5853,c0b9e922,ea82c4e8,db2b2385,2310d0b3,6846cb50,bc3159eb,37cc6b8,47645b07,207ec23a,c75b26e4,fcc0f96c), -S(f84f2cc6,f645b44f,b4cfa5bf,2840caac,c6f512d4,4b0aca89,987bcf07,af8089e1,dd3ed3fa,5ea7f359,8c2b2030,92ede474,b2f594a9,61d7fd6f,8348813d,bdb97f9f), -S(8f2921e1,dae78a3a,4557d895,50de9bff,7641749b,c963764f,e12bb329,2ac092a,9c7f813,20fbf8a4,b4f08b57,58b02cf9,1472612f,113f1be7,fdcccdc5,2336058d), -S(28dd6677,d6085587,46523eef,46aa90fa,496f04c,94e8aa00,2636212a,913eabe3,3f6da403,cfcac4ae,f2bac7ee,9788590e,5cf58a6b,8de534bc,a2dfe892,44309e34), -S(307b5b7b,d959def4,9d3518b1,a53cffa6,f1d87c73,157a0713,b3276821,30face1,b32135db,5ef40508,184b19f8,d3f150b9,8eaa6c4c,edefbfba,ff300b2,86177d70), -S(caa54ba5,ec29788,c53ae86,c58b8436,dd9a62a,cd41797d,1cfba1ce,2c70f251,71ba3e8d,9025e404,aca75114,3b74e0eb,4ef2fe4c,179c1146,e774b432,1e51d7b5), -S(2c2d5637,4a4d6333,83f5051,c6beef25,884f41c8,c5474107,e8f19532,580c8e63,897e1870,4a3767aa,3ce72f7d,dd4bbc7,b8a77594,469cfba9,f3a366a,807ba256), -S(7aa31729,dd90cc03,e40e41b3,5682ed5f,1ac4addb,3287c2df,b4061369,18065e02,e5662d23,55a0c036,73b120a4,fa430d93,fa1a6b34,c371e464,3e40432b,44aecf85), -S(2f882827,4abc0c90,27b6b76b,f60523cc,fade023e,42148f2e,5e237c20,e5da840b,d402a02,3dedbaae,ce4d003e,95daf219,cf47b98f,ad547a92,fe77090b,b9772ae3), -S(a4243ce6,15596c36,ea766263,4142a9ea,817676d8,a9f6c7c2,2e6ab9b9,a74a2fa0,6a2f60,20ec81bf,3d32c353,49f29fa0,db06e8fc,d4058dbd,5214aa0b,8ddbc595), -S(8b7b7e38,a9b704f1,3dc12d15,1f46a3d4,950abd52,cbdc79cd,693e00ad,b7556934,2cc742ce,60e35db4,fb432d93,299e5fcb,f7647856,d8ae4e8e,2bbfa6fd,a60a6a84), -S(da61f7c,31e2ae17,39b188cb,59c9132e,e7120f34,b49a846,66538a2b,f338911e,c8d93b53,d102dd0e,20da925c,e6f63c04,4239fa5a,2d04df8a,9fe68f23,6d03b6d4), -S(38925464,b72e70e0,361c0420,ac92348e,3d208b63,37e55b31,6ce554de,afc2fe09,c96c91f3,c452504c,fa868726,7985c532,181fd1ef,82344a45,4392a4fa,8e534c82), -S(ddc0043,46b27c54,d6a927a9,a053195,335c476,bc602490,96b1c62e,e06b6cef,be6ced65,445cda54,2cef4ff9,2f85289f,bc6c5007,362a4cad,5df4ec03,b450e7bd), -S(5c82a52d,84832270,3cc7506f,fc457b46,8aa8d5e7,1c55a4e0,2dc1971a,a298ee6e,49839199,fe6d88d7,3a75b59,d06a2fb8,a0dae45d,29c35cac,161866c2,caff5021), -S(b9793612,74eca1cb,e5a41462,aec446a1,d70cfe40,61925ce2,558980f,c1d9d435,c59da470,8771c732,d7c94291,8dd76768,ceabdc74,4fb49700,6305b591,2cac9d50), -S(be9ef1b,591477fa,7e3b3f2d,a0c9cb1f,37dbc3ea,f4529f69,2f455f57,fe3a026e,9617409a,97621fa9,b8f8d926,ffc895bc,eb60d2b7,37708bca,99258077,e9d5999c), -S(397f89f4,ea848a85,860efd86,5ef395e6,26e9657a,2cf04097,7af1e8c0,f75e6953,baa93eee,2bfc5d47,e096d20e,c31a2a07,ea369c85,66dd8402,80dccafc,86e991e1), -S(ee263d15,e4437d90,9f1960f6,504663d6,410a12e6,3f70bb86,de33e148,2ba907d3,2512cbc,bc9cbd9e,f0037e87,d51e6fa7,9d96c748,69b702e1,aef8614,859604bd), -S(3c93ad7a,85d2c4f9,1e03bae8,1d9ab6f1,d706779a,41387c9f,4b24ae1e,c8b7497b,ad1aaa38,5db82667,984d53f,88cb0564,6140f339,3b936f3,6d39099e,fca9aa36), -S(fcf7a309,e1362a1c,6659c2a8,e504ca6,8815e320,9ee6a8e7,96c4f173,f1769216,970368e2,15005e71,7cb31c4a,b0963246,796656c6,be28022b,e458fc9d,424bea47), -S(7237b824,1ea29c9,5f7d216d,e15a1c67,9f4f546f,6f79e306,14e2b2dc,226b9402,597f98f4,8ac7e00f,db3ffd2f,88e3e16,57417a6a,25c18b20,c2bef0c7,fb49e6c0), -S(1198ec44,7691883f,5045634,c4475b75,95c2ef24,29e7124c,2ac93bf0,2c0de7cb,ff51c40e,d65465fc,4688436f,7f5d873f,d8be9b50,87dadf04,54b64ff6,e9f8f789), -S(bc5d666a,7d29ca8,21112968,8395a4aa,2fcf4f94,a8437d22,6ccf2501,5ff713a5,6e7ad8e7,b74c48f3,45e71e1c,605bf4cb,808862d1,aa292686,4723b14f,c8169c22), -S(1e05f444,c110aafd,e3c828b,97db2721,d9ae0270,456aafbe,3a2c5579,ea3a2154,3e432d3c,baeb8056,105b67c0,c0e1551b,eeb617f7,c8ea4ac6,4cd29f27,c77b534f), -S(2d7ece5d,4ee96a96,91a5812d,7bf888c8,6f0992a2,51ecd061,b583965a,895c94f7,9a9d0b4b,da5d4500,49ac087b,a30bc507,aba5baf8,f98ede76,debf59f9,be1390e2), -S(3b717ec2,ffb0f062,55cc8241,f972709c,6c3507ea,8e11beee,d5e267e3,2fb576ba,5176f106,23d062e,ec697f2f,c7090352,4fd6700,95baf419,d0251030,101cc915), -S(304652cc,3fffd5c,c86daa47,ba797d5,14d7f3bc,11f5fb04,83b7c217,794a7156,c0767215,17b5f18,f92e6995,f35fc65a,434aba1d,f48a2977,62d1a04a,a587d479), -S(2c9f0acf,c4f3b56f,4a0c6262,1fac78f5,1a486173,dd6bf323,d66bfc48,13ea753f,b12aea95,b7543ce0,40291db2,1ba73dd1,2f0be788,38a81d9e,8e00e0dd,7400ab05), -S(bd236103,9f096e04,770bcd3c,3a10d5fd,66ef7fa4,a6c869b,52146314,90ae5dec,d28b95e4,6774745b,23ad0dfb,dd4766d9,8a2f770e,446a5c16,3277499b,e21b6511), -S(e97ff1d7,4ac00778,97caa1d0,a640ffdf,3bac580c,beda2fbd,23f25f3a,e9a26f5c,f093150d,95ea1a72,3a54e382,8c919940,3c296d5e,fd2ab41b,25cbfdb0,9aff5ee6), -S(f8ae0f13,a6beb793,46450b3f,53f36ce2,8c81fa18,56bbedf8,87e9723,9e15026,3988af1a,f632948,8e7bcc78,5cdc1ae4,a572141a,6cd15429,e6b1b40f,5b44e529), -S(6a944e92,c051b864,d4d26bb7,594f4ace,43951291,44b6d255,5667cc08,86dc515,13a75d28,c910c56a,a5dd2e75,9893d4a7,d86f0efb,dcf715b0,28c45277,50745660), -S(fdcc9b7c,4cc46a5c,8b114e05,c1f44bda,ad11957f,f05a0544,7fd49ce2,7c6ebb5b,72b243f0,1c142e35,f19653ad,a3d8012a,67f0501,a155a644,67629b26,58943381), -S(841e3eb7,17767093,19efc620,4b1dbf4a,d339564d,7ae6ff8c,647a9c27,93e9a5c6,1e5d0b55,7e50e0d5,9abecec5,de33570,d2a57d8b,a2c2d4a2,e90c0ac4,d4edca19), -S(fecf1c0a,32317cf8,469f181c,5bd52ae8,50913793,53569b28,c0c90c0c,dfc7b248,c61056df,56ac8e15,1077dc68,bd0a4819,c19ccecc,552dd14a,bfd6a457,516ce448), -S(82efa605,ac4e5e4d,1b68bb8c,b3f8d24e,47af1820,a7600345,757a36dc,2b241c52,171f1693,a2a0c1df,531d3d2b,5da06241,651482b2,3eaba4fe,c5d0500e,868db6a), -S(5ca04a7,afee22b4,c250d0b2,98691a5e,6b6805a6,b44da5b3,6b8a100,4fcdced3,7bf3a990,465166b4,e8d19ede,f41d7ec0,c7ad86a8,2ac57853,fdc731bf,15a3df09), -S(db455b79,de85315b,ed8ee65e,d8b5d659,5df2d2ed,9eb6e9cf,ab939fe7,93105df1,d821dce7,395db88a,98624ed6,44705a39,e2e53e6a,ff3b7405,3e8b9e18,4e1efa5f), -S(f0033201,aa7e6293,de70665,38eb3133,d2a6b56,5e73ace7,81fc98ed,ee458fb1,612fe4,d18f43a1,12988418,42d875b3,2c9525fa,154b859b,8258f904,d69c5d08), -S(77172496,3722d684,2039d1b9,92eea093,4c0fab8e,4be3389d,7d5eef1c,c31fd291,af3b1ad6,499c3224,aa47c6da,26064bd1,a2357acd,db722182,19350cbe,b84ed1d7), -S(7f27ed8a,c56722a0,730ca755,f23bbe11,ac868be5,e5571f70,5b11df40,28771532,adc25cec,11fe3569,7c8618ea,85005c05,b0fc73c2,db51d6a6,fb55c4d7,6ab9094a), -S(919105a,5d0f13b9,d0c6618e,21257efc,587858b5,6b6b4477,849f43dc,ed12bc0,54c7da67,731e00d1,316a0461,3debdef1,623feefd,784702e,eb42b995,4da27472), -S(e04d08e8,ab086e2e,155ac0b8,408c0163,e2db4afd,57703ec6,8a14c43b,3ddeee1b,742a114b,87e041df,93d15822,80a41360,86b9294b,20efeaf2,4d6b44b6,68a891ff), -S(82c95d88,5715b88b,5c583b9a,467a5c83,4b066ad9,3dde97be,866eb8f7,fa23452b,dd594973,f5cc5595,55d31870,fd9dd65d,c2b79733,c9db8c44,987314a4,d6ca0bed), -S(634fbc51,4efde752,b8726840,82372231,6166a17,ed706b00,1ca80ada,e4c43d8c,61cc9b14,11cc8e1,3f6a5243,64b04221,ece416c8,f5f381aa,8c3ff977,2c20042), -S(d85436a0,1c84e01a,c71ec9d6,93fae5b6,21764db2,1a8604cd,c7b37b21,452348eb,d4f9e6d8,5e65d57c,8bef1acf,a844d20f,1055c756,9690a10d,a230f5f0,8e0f9f8c), -S(200772b5,67197246,2ca9c5c0,e042d0b7,6990a34a,506494f4,f66265fa,4458459f,15e7e0b4,23c66afb,92411156,5e40b8e1,47c97bb0,28bbbabe,8e1a83cc,49b96e23), -S(8d8e235a,8c425a9f,d3556276,2b3c5404,ee0d8e2d,2e41c785,a05f34e6,1ce50acf,74032ab2,8e67f7c1,71bad531,fb1fefd5,d4aad08a,f44543ec,3e731dde,6d2877b1), -S(a5936747,fd423569,cb233184,77b992eb,d2d996bd,b47908a9,59d1a556,bbd51804,4cd3cbc8,ee2e795f,fcf5fb64,4deecb2b,45d6aca0,d70bb33,83f7d16a,d52ad109), -S(486156c4,8f785096,ddffbfc1,fb1d358e,2fa7600e,4decc327,e8b31014,21b75001,dbbef974,6482e537,225f5459,f3f7f62c,b0229307,72c1f251,75ae3a20,f6410527), -S(be858e3b,217489fb,1401b203,fb268592,ca1ff022,4d6fa329,78de85d3,b8a49324,f0bff99,e982b3e3,be3a45ed,f96f19,38d98b51,5b899d16,3abe2e53,bb67e331), -S(641e9c7c,cf17bc7a,45bd5298,af2829ac,b0d78a28,7c03f056,982e14ba,807ad7a7,c4bfc1b2,e338f2bf,7c9afc27,63ad340f,b5b27787,fba888a4,b8c4cd86,cf745fb1), -S(e8566e5a,1e855981,c6e275aa,3199dca3,3ddbb528,482ef60b,2e87c9cf,544cdcf6,94adf4a6,1643a235,9ac421ce,c5aa5ccb,779d4a9c,62bc01f8,93643405,4329b8bb), -S(f826dbe,15974b59,f4c45c11,584ce96f,56494195,4ae5972c,876a5358,82c5ca5a,79babdd,ab8c5a53,4f527ef1,459ae3bf,990f9bbb,a0d1dee9,d6ce6c53,330b9a96), -S(ed712f5b,a2d886d1,5e7bfb43,9c57bc1d,c2f9adb3,9bcdb62a,29c05d2b,1b483a07,36830fc8,b64cded9,719e6552,2ac7c6fb,3d6dee60,dfe6ad8e,30c5588,e4a3d876), -S(bd372233,901475d5,a6a2e1b,e11240a7,bf866bf4,cdecea09,541c718e,202991f8,4a24709c,cc93a928,9706125a,8922c828,fc309dd1,533e702b,fbe0fe7b,218f5c65), -S(f196cfc9,50001e76,1e6453eb,3afb64dc,46c793c6,58304f0f,ca3fa342,66da40e,274b3da1,eb8ac4d9,aac325c5,187b1507,ea4e24b6,1a74c2f7,84e9218d,d4c6f68), -S(d0b4c5ad,98eaed0e,6011c072,a2de350a,5c24da34,5a60980c,fd1c73d8,3d1ea674,9cadcf76,7371d792,6b818ee1,b4be2c53,5cc1d760,bfb7c47d,dbd846c0,c2568449), -S(41051a05,8771b3e7,a8fd33af,1838b679,b13c480d,ecc065a2,a3386d9b,25c822cc,ccbf9cf1,df8ebe76,159ded17,2268f71e,c3f44e4b,2d5a2efd,5d4ff9b1,7f41f8be), -S(1d8f44db,4d7f28b7,8b911ca4,9f622337,414fb0b8,81b75ea1,e93a757e,36cfa0df,e486e0d4,83987655,8d4671d,537b47ca,f734157f,6843118,ec5a3293,839fb77a), -S(71fbe897,6c6e30db,b71530be,42cc3fd1,80d60acd,fb3533c2,c0f2720e,e1a9bd43,84560b27,383d8db1,5558a2a4,a8107878,4c62325f,60ba0669,69573488,262efa7f), -S(7f42e7a9,cc3960d4,98e05160,95477ca9,a23cfb84,675f1b0e,c38e01e6,86daa99,ab0c4acc,6ae1fad3,82eeab7a,e7d1450,6db254e9,6abc9a9,d8c55c9f,7e09621d), -S(8a9c65d6,5c400f53,db6a3f86,ece6e185,1295df9c,19a55e34,348d5de1,c6242448,87d177f8,12769257,ca0f6e42,e1db9067,2387b8fb,f0462051,59a55d8c,79377af1), -S(d7b721e5,332820f1,c8f16624,4e3ea5f0,b63117ca,983ae4ee,9017d44b,ab18b5ff,b2b5b7c5,9b0fe6fb,386e185e,44cb43db,76e005f2,a5cc57f5,4690841b,7de26d19), -S(fc81762,38dbbc4b,3969fa08,31c22a19,bd163b3,4327452e,467b91ab,940622a3,b5f38676,ba86221,b0a02c03,6819df58,f2dec21c,51f456eb,7213289,6f7a54bf), -S(54e5db5d,2f87f24b,6e62ba97,6d941198,8584b337,ed801172,82080190,821d2418,ffa698d6,3e953ebf,b755c0c5,15976246,b5ecfa0e,397051ad,136f88fe,81987e14), -S(b18d7cc2,4023df48,776ad32,b64b234,1ae42cf,74b19038,6f3de4f2,bb029bf6,a12abedd,ead9d502,eb28a8ea,d65b2a19,29ddd548,1a7fb93d,e8d43b94,bfdc8547), -S(22df5ec9,d2acaa17,473e0ea7,2ca2eb49,9622677b,6abc063d,1bbb3648,7bd3294b,4d98a1e7,8dbfa279,227a6090,b61a5831,a6eeec3,519710c7,85679d5,61b48a6b), -S(6ca320d1,fd3750b6,5606108f,43585ab5,fa3663d9,65428a40,28c17eb1,95790eb5,b346253d,d2912350,86ffaf0b,bf7af93e,3b4f44a9,fb820a53,286067d4,98019e87), -S(9df9049a,7cf65986,5c88b93b,3688e9f0,53eacd78,561d97bf,58358952,f1318a9b,984b2aad,3891f7f8,df36b785,b56f4967,1f572f11,2d87023e,6003b3f5,fb80f3db), -S(6e96057d,9827d88a,5ae84c28,c1aa2158,af62d298,2cc26c05,30d48d2e,d879aa0b,92cf1366,8b9784d4,25c16b50,afdaadf7,e7c114b7,783050c8,7715d6f5,1d273a36), -S(5719e0f4,60efeb2b,78eab426,ce8a0623,3f092d2c,97d9edf9,3d22d403,a07fb86e,5c27677b,63486c8d,3f2454eb,30d5d511,bee44e6a,5bebca46,8e1e7b38,61c69a12), -S(87e1fdf2,c83a698a,9fa294a5,252894c5,4f84b148,178a28f0,42870a24,e7ce1175,654db1d7,c34e78a6,e9120a54,6b9df354,b7d385fe,13a3522c,72adbd4e,660f2cf5), -S(9c915f39,cee954f2,3d534662,f2d381de,834a1fb5,13739902,6c1b6b97,53050fad,8b068e52,e6821405,8974c43d,8902a00b,d2aa49cc,f0c4adfa,fe631e09,ce658112), -S(d77ce2dc,6b94603d,c2093771,ee39e720,93150705,56ee100b,a4a2738d,b6d22ada,81bc70f5,96f31096,a2054807,aad9e9e,63260eb6,9d524289,71675300,8d71bfbd), -S(ef509ae6,9fa82146,ac152c96,d76313de,c1857882,a71e8955,270497e7,33a3af9d,a614aaee,6fa558ea,fe7d8d3d,4090192b,c8a7b70c,d4dbd766,a965d684,544e5bbe)}, -{S(5b27aec1,c644f0a9,ba7f6486,9a960ea6,28343ab,da3feab2,4a2d6add,754866a2,3d1f365c,2aee6c1e,ab2f1879,429b6275,5d1bac85,2998ef25,8a914bfc,ca280b43), -S(51509477,fb7660cb,b15636f7,a53b1e42,6066823,690af014,b227d14e,e428efc9,f43b885b,4db6e28d,d93b9feb,f035014e,8600b6f6,ad6fbf13,6eafd789,2fdae717), -S(484b85f0,516bcba3,ee08f829,97496e55,b3856c94,25682c80,837a8d65,16096083,8649305e,2f245dc5,d4a9082f,a29f9421,fb20ad34,2754d8a7,8ed0e3c3,ae933ac), -S(8fd997a6,792e739f,83666c5e,25bbbb47,ada14d89,d3386cae,2084dcc9,f546ad7c,f85d46e1,1eb472b7,3c4c3731,bdc3620e,c2991b29,599871e5,e215af28,9ef08cdb), -S(5fbed326,3a7332e3,104dab58,c47932c8,a3f262fb,14fa35bb,a5021344,e965871d,225d98be,876cb5df,db578da0,c25be784,5ca1f5aa,7ec273a1,7b9b3ad4,5998202d), -S(d3ac3c1f,84be4b7,1e47da62,ca159e02,5cbf45c3,a40b34b,c3f3b28b,b0bbf1d,b2b94603,f6769cda,f9a766a6,31d7f48,e194f51f,2250347a,34719c55,beb30e17), -S(6233110,a8f6b13b,fa99dc25,b912344d,1cac4cab,f25318e8,c7d1884c,9985a468,dd458304,e3782dee,71ac4c33,c4e45e3d,79dbff13,437f9b99,ffa991bd,778e0707), -S(3cdd0f3a,b2b52a8,65ad9d4d,d65e089c,e2a66772,a20d5dad,9768fd5,6ca5efe7,ee940af9,90ead7a1,a7916eb0,44470103,b73c39da,23288072,1ff245fb,93b021b2), -S(9aa9bf7c,d8b58d8,411fde00,84e05511,6f11dabf,a699a1c5,614eeb3e,4af41bae,71d72932,7f05269,a99de5d,cee09c4e,dcdd3b76,a4465d21,ceac33e4,3741ef6a), -S(aec139f4,4598b687,c14d01ab,250160ca,abf5d9e0,1cd69959,2ed2e988,22345aa6,d8307e0f,9018ded8,d883339d,7ebe1fa,8ad39889,d0853c89,4743e704,d5afa618), -S(7f99f6ff,4d46e361,8e55f46a,ed55b95f,3203ee16,848893de,c33c5756,1184611,bdb6721f,987283ec,873e80ed,450d8c5d,9e7e2a02,ae56fc45,9e69d3c2,d2016c69), -S(8d850e4a,e682f751,22cadc1d,ea01a22b,377ed983,c833a4b6,e5945fca,4d227b2f,94c22c5c,3864879d,e4b861d5,e9e33523,e5f848b4,fbbb8d3,4aa21a,85066e3c), -S(194b8c89,7231a783,ea9a835e,ca4b6744,f0d0fdc7,232ddd43,237fb622,14c869f,db961536,179e4275,5b9bb682,95d1c75e,b2b7a19d,d5084960,7d9622d9,cdf46937), -S(760ad01d,c8e83c2f,ee63caad,9a86f648,f6b72424,4aa158d9,66b05647,eb6cebb9,9d08a9fa,1d21e580,d34c9fc9,10b8c294,522379fd,c61fb056,895261bc,cc827a3d), -S(c2186e23,813e84c6,222138b0,1ab17c55,d47af51d,8e4239bc,1600fd66,d971cbc2,200a33c8,7f9e6d4,1d5d602e,6002089c,6246345,107e8b5d,5abcd35e,7203ac68), -S(4ef2336e,857336cc,dcf3c9a9,48685847,1f639021,bad06218,8a66e4a5,dbadd35f,67f8d186,e79780d2,b063e723,eef5531a,d95a653b,4289e98b,d4df52be,1b40e8e5), -S(16d03f6b,c21a2a55,bb0467e0,fb8668da,de88ccc8,cbdf562e,39c992e0,4cb66545,82a7c24f,b5dbbbd6,4ce566e1,94834d22,7127ab7d,ebce6fcf,60ce1482,4ffadacd), -S(edb76db2,a1d454cf,e8b9761d,951fbefe,49054fd7,fbc7e800,5051ae27,5b41e8e2,343aba4,56c46bef,17a254e4,df28e783,cb6b09cb,f40b062d,22a04aca,701b66d0), -S(b505feef,7c6f5219,7cd9b159,5db0e30e,f1f3be2,7e65001e,df1a9f4d,ed86af06,fbd1a957,d0a4e43a,652c2555,312ace49,92e2647d,5167c18d,86410bca,87705e18), -S(50e755f5,f14333c4,13be7594,34be8d74,3691156c,12a46ef2,c730839d,3871f097,a2925d1f,263c9c2b,32c4fe8f,4cb2b7bb,8cb6cff8,3f0ff900,213afd01,e5d7f01c), -S(6fb573f1,529a88c7,9f278108,82d9c8df,2a02ee28,84168ea,7ac41219,23d7a96b,e34f7cb1,e4c93ccc,8e7ec63d,4cd5c198,efba1a26,fbd24ca,2f09d378,30bf2589), -S(3cd35cf0,c96e32f7,2023447a,f9ada5f3,8082543e,12bbbebc,947fc3ee,215ec98c,24ae2376,10990d87,f4d9257d,45857e86,de05f6ea,b06c889d,c44d948c,dd5c4b84), -S(6b853761,e19278c8,11a01f0,499779fb,a2daec9d,a5ece88d,b25ee726,21f42eff,fceae86a,242bcc35,885a83fe,ca3807e4,13f46408,8d46f68b,860ae389,c3f6aae6), -S(d32d3024,34b1cddb,ab02db35,4144d96d,845028b7,c8b5b45,adeb3ad,84eba58e,762cc6a2,78b94842,7a7fac39,de201c91,c92f25b6,b472456e,67407ad4,9b977b45), -S(64275dbd,a2ecc977,3026dde9,f1a098d0,63986d88,8e958430,23ebae9c,82218f6a,e27c46c8,41829e88,2276ab9,e146635c,953db6e4,f1295efa,3111b0c9,40695056), -S(1becd08a,a4aa040b,51fe7380,396a18d4,1fac0c66,91093cd5,d74a31a3,2b2e3a9e,abc07812,ee13caa5,b040cf7f,ff4637ab,a9e69db6,7834efa3,2f864858,ab138989), -S(f9976dde,8c971e73,fbcd5ef7,50947027,711d5a7c,bb273871,cc293cc7,f4a1f732,408ca6e7,ceb96781,f0b2f4a0,af58f2e8,52ad5438,3399ddc6,e9a65144,282aebe9), -S(fa71702c,91ef2cca,d80796,ef0c6246,9ef32e16,8f5c9ddc,9fc7241d,f3ebd2d9,94491856,fd63fe93,7ae6e95b,b35bc6c7,85732cd7,7305a83c,65ff9ed4,42f5e11b), -S(b5ee5d7f,60398c08,f66d568d,1ce39d82,5c64c7d7,c65c030f,3e35e86e,c87b0036,d2c62b4a,71f9c662,9914ac79,7f34203c,eea50a58,ca8ed06d,582755b,380ec185), -S(7aa05776,3de6393f,a4b36ecf,5aca8f74,6e5e68ef,152065c,820a2207,80452ca4,58d54e32,840a40d0,b2a8a175,4138a62c,f054aad8,85e97731,9fb3fd6f,d9729bfe), -S(74b062cc,f09ac530,e607089a,8efb5a06,656dec8c,e1d1dc01,370e43eb,39594b1a,6d93d5e8,eb3244d8,8457e0ff,66cacb14,d38e286e,f42aa6c,3236b2ea,883e9f64), -S(dd56f2ee,f4dbedf8,ba5efcdb,c569ed21,4aeb7f0c,e3aed757,e72c91ea,9dae7642,c8a30e73,efb151de,d38785f3,2f5a9030,4e62becb,b0c470b7,1f049dff,7b75c9a), -S(a05bc315,ed5ccf78,34d888a5,788263e8,573a4321,7b0480fb,960e0a3b,e7575d0,9b8568a3,1b1b8f6,ad507db8,b6016280,28f43990,1c9e9f94,14ded563,6d06a78d), -S(c19022f0,5c316bd8,e5c50a4c,1a0a6808,b7a1a696,8ccec214,da81e039,53baafd2,110b1cbf,5a01e8f7,95d0b996,a3e6c2aa,3645ffeb,59a77473,e51c4810,665a415a), -S(feca2015,14edddc9,8aba216b,cc37722f,f6c60202,d16c6925,422582f,dfb241f5,61c06c06,d0e50e98,2d9ea3d9,44079084,e37b5c9f,9aaffbaf,c89d73d0,20dfdcc9), -S(d3d271c9,2b843b36,a24f1928,efd4f197,c90f176a,70539f,e290b150,24a4bd89,9179320d,bd5577e2,d7e58d67,131e47c9,118e78bb,18690f7a,74e9b38c,99cdf6e8), -S(2d12ae62,3f4b552d,4b7cdcd6,8f16c9e2,58d83cdc,b5fe567b,a5216cd0,6e94a2fe,469fca9f,8d15b969,8687e33f,4a6cb20d,aa8aee7a,a2911802,f6f26f1d,fb22d63), -S(55c31675,9974d7ea,57b0c133,b6e1f1b4,9ecf0c15,feaf74f6,b63d6d8,ff525a92,de38ca29,5f85b65c,4b56dbf8,22edea40,19f61207,f16b6364,6943d43b,4a959f14), -S(739facb8,74194ac1,e60a2206,10a82629,4f1bea44,ccb08f67,33fb30dd,79706bca,dd77cfb3,641a3786,109dcd08,700edada,8701732b,819f41f,14a55104,9ef8f38d), -S(9768a20,2ecc0ba5,8524d10a,c6d2c18e,611a1215,401a8ca6,571828cb,ae5759bf,5d35c2bd,2e7019e1,6e6bed11,15a16d72,dd4c5ce2,fd848434,4d8bd392,c4a680ff), -S(2161e7b9,858db630,a1bdb50a,6b13a6b9,829c302a,a836f0e0,d89f5a35,70065067,c565cffb,915ff76,7bab8f73,aba21a7a,9168274,d52681b5,301f76ae,a9b6daf4), -S(2a9fced1,fe2b258c,6de7b534,212419e0,c6c1cd6a,50257dc8,79f954d4,c351d7a7,887f8024,d75a1f72,e61807f0,d8c310a3,5df7829f,714433e2,214f9180,ae552e9d), -S(769d9e4e,8a1967a9,1df6e8b7,cf282ab8,7f9e773c,5dcb94ae,8af7b125,6254b879,53537a42,ffa46e16,63821069,f5bbc62c,d7a0206a,7407aa8,154c82f,dc390650), -S(6fe3bbae,441f902e,7ea02e32,44e3ecfc,6c45ca71,9bdd5e4f,23f7fb3f,540d45ed,d0cb3379,c858c9e4,6115517a,c65d3452,16dc744c,60a6f1c5,7cbaa8cc,f4462123), -S(6226690b,d8d94bb7,168670ce,8b4d18e7,a35f0fef,ab50c816,195f0b4,37fa16e1,cc8f53f,9d16582a,fd2be5b1,8db42faf,e8d83ce5,481a88a0,9c54ed2b,7023c3ba), -S(1e5d9adc,dfb56218,1d10999b,336412b7,d8fcb37e,dc5d20ab,8f8cc789,55e8a72e,221d5b4c,58ee5fc4,8cd34b1a,cc9fe795,2d890d35,4047746e,405d83cf,392184dc), -S(9e978fa2,ce0875b4,ff79d6bb,4f56a9c6,10d646db,c81cdb06,5430f9e8,4198b707,9608823,828dc9e1,2835e261,1026ea34,c9b4583,46ed41b6,4bbf8441,fd621e35), -S(ef6ed3e0,587229f5,aca0534b,f632fb13,f4067712,9d41350f,2e92bc1b,cc1d6f8a,c9852e66,260fa65b,13ba714a,2629177c,80030b2d,867f4e98,83e60ceb,402e5ad1), -S(3c104b7b,79c14740,46a032e4,8ac22ed0,1a8b8812,3fd1b457,977ecf3b,b82e2720,809d1774,22521dfa,f05dd418,e5783577,d542d683,8904cfe3,35d8215f,1ee63b6b), -S(5fcf6b6f,de14e372,11d15178,fe37c914,bb9802f0,e67cd3f6,3fe72688,e9fd2dfe,4e468677,2032e358,25c89a7d,28fa840f,ef33bfee,7622421a,f2393182,ffd8123f), -S(d3f81471,d6d530de,7b8fb0c6,125c1b0,596e4430,dd89a22d,94a516e3,3c1cdaca,31da0106,ebbd0289,c68bf092,381054ff,718a8bb2,aa65a9d,47a0ef45,acdb8e7d), -S(c1d365d1,98ff150,ba208d1d,486de98f,1cb9e23b,4e83c58e,40d15f77,9b12688,7c11b3b7,5b8dfb0c,ddf97f80,e3ee4655,1242897e,2152048a,cf4910f3,2b819a3e), -S(c935f87c,752efe3f,d1208536,2c49321e,ad521ffd,b11fea5c,24e1ed72,cea77a28,1cd31bc4,46b90688,266b9f3c,74426c89,ae4c442c,4184c3d6,206deb3c,a92d1fe5), -S(2a88eb26,49349f3e,7fd6a43,78a8fdeb,86df60b4,dea3416,1c811a59,44a98040,e7fed2fc,a145255f,a06e13bf,9bbfb1be,6e15e330,9fd624ad,9b352c8f,1caff852), -S(313ff59d,1dceac83,4c70fc63,f1f32df6,ceb4253f,8327ee35,ce4ac575,9ec2821e,d0ca06e1,30d083eb,8a7501a1,dc80398,e67a133c,973121cb,377e31d8,fc4bfa14), -S(ebb8d7d3,81dffa3c,8ad10bba,aada6598,98ba7694,7662bfaa,e5acbfb4,36e6931,f01e6b28,fe03ffb9,42ebd387,a29c2896,32bfb526,58a7abb,34c10bb5,24cacf8), -S(208055ea,a3c94762,5e9cdbe6,91584b6a,a060d127,63f9a305,ca360baa,9d601a7a,ff382321,b7f3b513,1551c441,f6a8365,13d16c74,f3b74345,a5100ed4,de88e00), -S(1579f653,1ae0ef0f,b9da909d,959b82a7,1e158400,b5d34f5c,8d66667f,cc6e5c92,50f898cb,60c9630b,507bf817,fbfb7d3a,29d3772c,74e7a7d6,19bf4198,7a09136f), -S(4b40b410,56a43404,559ec18a,1bb18544,ad8896a0,c8182f51,b9bd0b7a,ca178f51,a9f22e06,79e43402,d6397eed,285db77b,15ff1073,6a367a95,3a439961,8cca3fac), -S(67673db1,2edf2be8,c0d330f,b26a04bc,bd0e6714,5c7b0984,11a59719,e845be8e,c34f45ec,ae724308,2245e950,f62b0c2,2b6e1b1a,eaf5d8d1,b503d9fd,e09e8cca), -S(8c1ec49b,81d8e41c,3bffb5f3,7765bad8,474f647c,833318f7,b6227608,a1f8a9ef,fbdcb1a4,a418b7b,5398835f,8f68de59,c7430754,87f52c50,a968c40c,35f3149e), -S(d823fe57,c0934eb,a2f15d1e,b445418e,e5092ffd,b3241d94,3748dd70,9e4d0733,b20ce02c,69b038e4,a5e37858,8dd0dcc2,f2433141,a2fbe473,e56d860b,379fe4), -S(d16cd142,a198d5b3,e2e855c3,b1b900ba,12d0e241,c914377c,1c880cbe,c3e9a10e,e0fc81d8,9d32e421,70161026,97e51be3,91a984be,739b23fc,6e3d6649,109ca782), -S(34353521,1fba36f,58fb6f55,aa0ccd4f,4052ccd5,8edccb05,164e82bf,111b0af9,4a9ce50d,2d0bbb0c,66a74a00,c91d5f7c,92b416b3,f0bca8b1,38e5f456,fc48f6fa), -S(254b9165,d4afe2c5,eb4360ef,2240fcf8,f8f4ce78,8237bc4e,c8edd63d,92a8b4fe,3c7267a9,5df9d1d5,96208351,1739729b,25d07ec0,53f30233,acbf1f88,b9cd1f7b), -S(a993528f,cb239c1d,eb824cfc,41ea09ef,72cbec61,ebcaf0c,4ea7890e,3aae0f3f,78b41a68,6f832e10,576820f3,552b181a,ef3b133a,fd5dca99,c7fd7b7b,247336c6), -S(dc431b9b,2d0002c5,d46079ce,463fb29d,6fca380c,4edf8188,34c354cf,7f123f13,32ff1932,2de938f9,9be1fbd3,3c553510,8c1dc5d7,caff8dd8,c4db6218,54b9bba9), -S(bcbc08dc,4ce90c27,54b9a79,ffec9320,3c78b60e,adb3f750,2cecfe12,d475773e,fb691bf6,8394b040,d2049147,6ee7ec8c,6d69baf7,a2ebdb5a,3b455088,3285e468), -S(20ab53a0,d5a26bab,ff0700c8,945e2487,fef10dc1,1c523b2a,14dfa8e9,fa6d68bf,c6ec861d,dfe29d4d,1a23d3d0,99802f20,ade886d1,257f669c,3315ab5d,effef915), -S(c58dcb0a,8700faf3,55a26e39,58c61617,3c2d5c07,824041da,71dc5d0b,6bc351b2,78ba4b31,5d716184,9bf53d1e,94a6ec8a,2268538a,58ce2f17,fa1ab6eb,beb9810d), -S(3d665b4c,831577a8,c536598a,3cfdb3b,85e1f45d,566a0b9c,a6852ae4,171be6b9,e6a349a1,36827310,e362adc7,cde91f6d,e6330122,592d1dcf,a7917d1f,8948fece), -S(6f8d4774,efe7b37b,d26f5849,22b78273,cc5ad16d,80f0f4da,8c54e167,33c5c7ec,b63ff2af,2fed919f,256de972,bda71f9e,e4a5256a,22782a0b,c06a7a48,57876d44), -S(97daf45c,8666f208,ee72dcad,c4658613,b8466605,be2e83db,69104973,5516b1df,e33deab,5ee28d64,b818e2fb,6acbe9c1,cf060142,210235b0,dbd9514a,ddb57402), -S(c712fcea,95039f2e,a87762fb,5e5fcba3,dbf7ff6e,658bb64,71a4f890,88e6106e,174f28a4,9b38ff36,1c28941c,b89c1d62,4606c269,6619d157,f05be89a,ca550fd7), -S(f42d3ea6,d791c681,ef6c16ce,9ab763dc,df7e1f54,42512b3e,f9ef8904,f6f30927,abb04412,3f2f1329,17cb8a01,26d21fee,59606715,6a3735cd,4cf2969f,a506eee0), -S(a77b7262,61365881,c1aeb570,12555deb,6fe98240,cfebf712,386fca2e,efe460e3,3200fd50,9500ff2c,df4bc618,f43e705c,b5000762,dc3bfd57,4ac66722,edc06daf), -S(82af11e3,34b229e,16877594,b9f7f157,8cf51255,c7521ebe,ebab9a81,a2b1bf76,3182824d,7afc4ee4,2e5b3965,65f07bdd,b47d0f3e,39685096,e96bf5de,4c00f47e), -S(b015e32e,802b997b,4c8db911,4cd0a3f7,8fe91699,a9d3c344,f03c77ad,508bb842,28aae64f,70b35de9,992216dc,ca1cd63c,d41179e9,b7ebee7b,964031c5,3cc56a00), -S(580ae367,e9118f01,858d82d8,20ed6c9e,923f3d,be934b3c,d0860fcd,1fdaa714,94a96e04,8b7d8b49,fd12bc04,d6a0f7b4,a0bd671a,dde14d92,9d8eda25,ef3ce73d), -S(b24a5ed9,65ed6463,b30b0be4,ee048957,2c62524a,50937daf,e863dc0e,4ea3484d,ed8897b2,3354ddae,149620fd,a3f7e17e,c8a5b46c,fd0d955e,7326ab1,2c7542c3), -S(5f9b9a03,2b21c8e1,31e13c2c,8019db2e,524a85f6,3ae03014,d27bca62,971b938a,3f954d07,f7ef5c7e,e4b288d8,3722e458,d38d5950,b38ee4b8,35ddb017,68a1680e), -S(61d23399,c8750a26,ff4220ff,c3a7564f,f6df92a2,fc133ee6,c9228ac7,56a77b8e,a3ea3176,80b9fe5c,25c74f3a,5cd0f4e1,73f9a47b,f13c6757,3ad9584f,81c0d0fc), -S(39129baa,19373bf1,db83360e,c1cf46f6,cf6041f,7aecbdbd,c0cd8155,4047f4b,e524c633,cad2a058,3826b241,a0f9f90f,1c29aaa8,7fe9043f,61f243b7,35966525), -S(9f4eb067,ba8943b2,7d9c90de,e3e3f570,9d470e03,4400b49c,8863852b,e42d2d82,7decbcb,df928f29,2359c31,5c4e9d1f,7c81daeb,4153b6e9,835fb10d,cff87699), -S(c3c41675,59499453,4ebfe29,32fc3a8c,fb0bd4b8,f58fcdc6,111e68a1,2931d68,9a6e07d6,271039b8,e3198823,589508c4,353888e5,46e8a759,873fca67,a687aadf), -S(389932dd,1bdb022b,aff12e7d,96ad188e,f2a38d,e07db076,d4ff0292,878a581e,591e7dea,d8378307,82c9df98,3eee4623,d736bf1c,7cada52f,9e9775c0,9b2c0e7f), -S(6a24296b,4ed7585b,b6e1a7cf,a6bae760,bd87c580,c5136641,ae890ba6,c6aca188,d389a8dd,df70e094,32a77278,89142e7d,7a1ed1dd,63e56961,14d4b9a4,fdf7d48e), -S(a3adc560,82a6a35b,76013450,a511c437,29000a3f,4df1cd21,d5a37aff,25236ffb,9e298b2d,73533849,d981556e,c4ccd2df,2cf8a84d,49fb32da,414725d2,e8bc8172), -S(b1761d8,b63ede1d,92aa5d47,9de387c5,10085632,dcec781d,44b1cad6,ff59a49a,16e10005,9f5b54eb,fde33551,d68eb053,a91a17a8,65703a4b,a0e4fcd0,ee35927a), -S(da2439b6,9512ddbb,8a3bdf44,c3dba4ee,1047594d,f274a33f,db442c6f,3313cb9,23a2b190,cd307fd,354474c4,95e6b0c2,df104478,e337e7d4,9acf1204,666f16bb), -S(5247030d,514afa45,41d07a69,e5670aff,71d42ca8,d6258e5,298efd35,2ea5912e,76a36497,2edb4c57,e29d6de,9990e7d5,f542c84c,764831fa,86ef5ab1,938e27af), -S(8d2dd8c8,80fd50f,94fa6552,3270fe1a,61c92810,3aa1fc44,d2db7955,765e9f6a,1a99666d,2f76e63a,ed386a7c,25a6e66d,cf3552f8,5979cbfb,355a91cc,ddee161e), -S(f964ec9b,b42fff6a,87d268fb,b6f58bce,c53bbe95,5780f6d2,765c682e,3b29ee6a,f1b5d480,1aea1445,177b7e30,7ec2ebdd,4615fefc,59b22312,1ef80277,45790fb5), -S(388ac82f,677422aa,c6576748,59fe634a,c9768335,b9f6402,dc089b40,186b8898,5a93f486,77033639,b9c0861a,c82e6326,e7a20e73,9fb651f7,ca99c3b6,b56e0e9), -S(e67c3d3b,760b9bd2,10cd6ed8,d261c0a9,3a24395b,5bff814f,18d1b1ef,efc5e322,370323bf,db8d6a31,8066dcf,439c9447,72c8a049,9df2486f,426a1a4f,297b3c47), -S(e3cf3c48,39595c97,a6efef6,98e75220,4d6ae09c,d4e7c231,24e16902,a175b95,91e50db9,f3a1a3c5,634fc2,6dcf9010,6fc27d4b,aa24e659,fd247c5f,93c83593), -S(b16d475c,c60b5286,2bd250b6,f4ca284c,69e30698,96eb3633,18ef6b7d,3928cddc,ef3fe367,312a3e06,b992f862,8e5b0c75,5b6f6ff8,fd62cf8d,a0353a52,1e6558), -S(758a7aa2,9433f0e8,ddcb6e85,70ffddee,2c487f7a,7800e6ee,7eaea634,c8c3b7a5,cbc5ebe,9bb4f480,2d50f99d,746065fa,7c484a84,30643962,50508ed0,a75ddc49), -S(3c2b2b05,10564b7b,7f53dcc,406d4329,e0faae16,6259edf9,ef26d1ca,308f0352,19f44e13,cd4e6107,2983cd91,81f942a0,f4cf0f4,8a10426b,c3f30dcb,8693af36), -S(ff644ef5,ec4f91c1,33ea443f,d783573e,debc003,7f74cac5,af866a37,302cae5a,50eaed81,332176c4,20e63c38,9ad9faf0,75e45a26,8119342c,b635231,1778e3ca), -S(2ccf4da9,9aa616c1,900f566,89d356a5,1396526,d488b635,f10c368,ae066c2d,46da8b3f,ef5c7994,9f94721a,2656b55c,6946d493,49a03aa5,fdf90c0f,4a152ed5), -S(5cf33ec4,cf6f3af0,18e94ca3,2d31845c,f1c4764b,2ccf3992,48467c4,b3f11924,a5cf6368,c5b617bf,6c69c7f9,fb0c769f,285720e1,432fe54b,def57fcf,8fa25b1f), -S(5ba03c13,93b9a100,928e6e3d,a0cdeb2c,8be4d653,93a233a9,b7811e4c,d242da22,15f9029,4890222,960a70e6,8046c2c5,de15de6b,8ada4243,64357c39,b11cedad), -S(ff9cb0f2,62e3a7b1,d5ebe749,112c8b02,4c766789,c2973446,ca2b8884,e5eb1035,f5194ead,3d090604,86d7f0cb,f72fb540,273eebd2,7c94a199,6f9f35a0,3834886), -S(b747105a,da190d97,48094f54,ef60d1d0,30e3f57b,f32d5477,5c6929c2,975a3978,18f9265f,b2cf77ca,f5aa62a1,8e82933a,2cdad96b,2866b5ed,c18196e6,97e9565c), -S(48c6d033,45abe61d,aca1dd55,8d782685,d05bf49f,2897fd37,ac112e98,1feb0ca9,853a71eb,1a1dc7f5,78adf995,a254e545,a1effac6,7afafa22,cd2c6be5,d9915b42), -S(27d839e0,b29aac17,b84a7654,b2e60cc4,6b8d02ed,8079a525,cd0463a7,f21cfd2b,9974f97b,504bcbeb,d8d3f3d1,1db05229,69a72357,2de8ed56,ef877402,8a435c55), -S(8fc52f0,3dc76184,195d95ef,baca3ced,9aa1b3e2,5f36c75d,65e67d4a,28337ad3,6e024d2a,ef78ac8a,d59450cc,de13c8a5,2d23eeeb,13d11cd9,7b4a9fdd,be716a69), -S(afcfe9a7,44837fea,d3140ce3,4e281510,5fa23b8d,1f497440,8d6ac3c7,70b46c6a,253c825c,8bc94bbf,3dd2a33f,f6eebd7e,203a34,69858d9a,6b48638,5ca557d), -S(e4a30e5e,16db32a1,83532b32,d466e985,d664be39,bae1dd8e,2e34ea05,d8575028,58bb5c1d,95922c2b,62aafb36,6bf22c8b,35d8947f,a082c4e,ce9d8ea9,cf24eda5), -S(76ee906e,b69e9ea9,667d4582,99c6c47d,c0868bda,ad8622d9,b8a85a9c,be6faca,88f10eae,25307ed8,e519abac,a00f721c,8d08e1da,344bdd62,5f6077d3,4295f4ae), -S(bd58f596,ba832cb4,2e3d7445,428f79c1,59da797b,317cc471,88188f3c,715d3cd4,8bbd7cd1,a511e88c,d7a904f1,6db60414,d4555337,1f72435d,cde9b5d8,715d169b), -S(8d450276,b722186d,2e93ed73,3e45fd3c,660225a7,eea0d90d,bb6b7370,1b2dd80c,271816bf,4c5676a,86efe5c3,5ddcc606,804f4cf8,15d19937,16733964,e00d552e), -S(7dad1a19,4b46b8de,f3d16ee2,6fb3d1b2,a9d9c026,c5923bb3,f4f88bfb,736c2b7a,ebd7b4fb,6afc3648,746823c4,d179687d,6d1b41a7,fbb597af,f028844f,b6377681), -S(de25311c,898c652a,40fa3c4c,6022d195,e4f5d336,5f8781e2,2b0bd1db,5c733c73,194b36a1,1d99a3c5,4e7c5e7e,31846b12,4229ea92,74737a57,22056cc2,56f3723a), -S(cb204893,6466f088,32470071,1afa626a,a8289325,913f28d2,f1e17ef2,8fabe7ff,c60b4373,bc81fd85,b871c930,827b6833,cfeb6708,c40c1942,676cd766,ddd7b390), -S(6ab3128f,9735753e,341ac4df,9e4daadd,aa5034e4,831b9681,15634e41,da047af5,ddccce3,47c9c588,88169f04,78859080,27c821e0,1400212d,4e40ebb0,999c9464), -S(c4b853bb,81d90026,c6463268,6440bc6c,42cb7afc,513a748c,dbf09039,82e98774,6ab31853,982a0b98,48173818,215f13bb,940248db,26eaa964,8300dda4,1482850f), -S(4a489c6e,cd52b4dd,33956733,977fa0d6,25e4f721,d5389076,91a4a251,e1c65902,7f7d73aa,23f31098,c5522a38,1172fa16,a10b4e26,9457c09d,15c14954,bcc794f), -S(d58a8e44,50f0ad1c,298d3add,5ae874a9,5734c031,3d2f27c5,5966c468,d8b0bd3c,7bcd6ddf,d7759f7b,3523852a,704862bf,4994f6ed,4a85c430,e9696d8d,365fda41), -S(fcb440d8,6d7441f7,52b1aa2f,28d4d5ea,ec2fab70,a7739b7d,af6678d5,837425e3,ac13b9d6,a0022a93,67d81f8d,f7824b73,11a98184,30c5bf50,89f21a61,4b1d3686), -S(3cb6a8f9,b1f8058a,dd2f9076,19a3fa97,8f13089f,fd0e41bc,8ca94760,9dfa9762,4968d4a1,8674164,74d98e8d,7110df5c,8c1ce11,903bb98e,4fac0a4d,1082edd4), -S(2e719fb6,2c09e74c,46fbd39,abdc8e06,69e38992,4424a985,60aa405e,99ef47b4,bfccaa88,e1105982,de52f422,15c5cfe3,a82b7c4a,b5e0edee,46ae657a,46bc6d30), -S(809d777f,f7e7d3a,d02f4c83,fab4e618,15a1c29e,caeb6d4d,8573889e,33035a5b,4d04a535,67a1a24f,f04f4e8e,259ebef9,cac4e89b,31cd8135,2f7037aa,da84c69b), -S(6538984a,31b67a2,2bd11be0,2daa7449,2abe195a,86c08fe9,d1465e99,e08a407e,10610211,327949c1,f8e4b459,831e8fcb,2b7b4db7,c53dba33,acfcd510,aa22e935), -S(e67dac32,6ff78b27,eb24b489,85d1ab53,60441d3b,62258756,74741a67,c0b37d33,48065a5e,21dd1e4b,b5c3a085,16f00aaf,a57e98aa,9c714663,63d168bd,90b72337), -S(6fee80f8,cd36865e,f4548366,70f9e40f,3ebb2754,aed3f5cf,1d73faa5,e7e7c72c,d3d52778,2d4675b0,16addc86,445378c8,5fe38f75,3e3bbdb2,d8a73e12,461a5d1a), -S(9940330,2dbfb6cd,45a98327,e00fc86d,171b39bb,811a0af7,bf0916c8,b04fd369,2a5bb90d,126b586c,6cebfa67,7518d008,b2348e11,362a5636,8e0b1d0f,8046aee9), -S(43224e6f,292a71e0,3e1b3168,4a30fa0c,a681fe1,283dabaa,f5629633,5dfa242f,b6caef5f,77e5598b,b8a477e8,66cffba2,30927e28,d8e55b3f,fe71fab6,90c6f567), -S(804e1a5b,8e16bb85,f041f46b,a0fa8ca6,a65fa2b3,48432e66,ec10eafc,1737ce1c,2b77d1c,b1acd0d,878013d5,465779e3,a55713bf,2be71990,7471962d,e07857f4), -S(f52a94fd,6bb9d519,3692059d,868901a6,33743257,3ec200f9,61b6d964,d090f849,33512a99,94327132,501a0fbb,166ea870,f7bf1ed1,657d3080,f4d7ee1d,acc85128), -S(6febda44,3ab8d9a8,756333af,86ce177f,32d782a6,114a7464,4b1fd081,9a436087,65fb2b1c,8df03ea4,2e72c6bc,82e2a39c,57f7912f,8f513fc7,bf97a45c,4f9e1fa4), -S(da0532a6,176166de,9350ae75,7ee99a5e,9502f292,f842e94d,74d35230,518876a4,b3ff19c7,f141a7b4,f24dde01,a82f988d,8178555c,38e0816f,e1da20fc,d724f510), -S(1db46fae,ef1d0a54,9217028c,1fcf73f5,6bd573fd,6c4b1730,f3cb99bf,2e163ba5,496640fb,ab04b388,3a35ef75,5d2a0ae2,17522488,a567d7f1,7bd951b5,98ee7456), -S(e14ae4c,2f1483e5,a580d3c3,6ff82525,a6df21eb,ac91aa5d,39391e5b,650b5436,d54ba5f3,2db765ab,b8f6e464,5320cba,c029c13c,2edec227,d57d3cb2,b8b6faec), -S(a382424e,a89563df,e7157fd7,b438c992,604a49bf,1462f590,b84591f,88ef7e01,b8a510c1,4bb0f355,6d432ddf,859d87f7,9f4c4448,522bdd86,a4e99328,2ad6f960), -S(266c1844,3daaa40f,821c1ae7,7da98daf,aab29b79,36ada9dd,238c5fd2,73b45614,e3f38773,27910ef8,d5cec282,9b7d8b29,83a184da,870ab8bf,4f43e6dd,4f0cabc6), -S(e7b29b98,b1cea663,3e686d67,19778d3f,f6af2d87,e93bd576,10c95232,e8ed5d29,ecf316db,b2a445fa,2ec84705,b453314d,48e16de7,6310b78d,a19f8a45,36f27bd1), -S(d36a3000,869795e0,9eaf616b,6e131204,d341db61,7a18ef66,e133a59a,acc47bb2,24b6bc32,487bed32,9d9bc27d,b08ab6e8,114bb6ea,e813d80a,c3dc7add,9ded3979), -S(c9783ed7,85dca51d,55e55a39,4c4e9b91,9c4d4c3f,ea461afc,51eef4bd,3a351cdd,e8e62138,4b4aa109,6d269fc2,a364a3be,e4584bd5,c551435,3dcdedb0,9037bbb8), -S(764eda83,aa90cd1d,9cb96785,e4df2614,aba504bc,33403866,b6f13b38,521bbf79,9d1fc736,72bd368a,cf6f9d32,489a81ee,782ef74,964c44b5,6dc4bd2a,ad4363e6), -S(f757e8d5,aae09922,278d2301,77f1c80b,5466f76a,f9f8d106,f0814d0d,b152484f,83ef8bdb,17c78a8e,1a4c54d5,d356170c,79ad312,6d62ef94,94c1b683,1798adfd), -S(a180a3ef,400e4918,9cd8b3,e12b3907,5b268be8,4c83956e,9e08c6e8,230b7fdd,ebd5b8c,75f1ecb9,cf2c8ff6,e863447f,7c821219,8944686f,b1b758bd,ef9e84f3), -S(5ed707bb,96ac41d8,8d85db26,fef84af6,d5f7d8d1,a680a0c4,8f23a1fa,89e37dd0,bf45cf6b,d0bb550e,590dca49,fe2b158d,e91c2835,3c75f49,98c1c446,8ad03e8c), -S(f8dc28cb,f149265f,6b6499fc,baa6ecaf,78300a37,2dcae813,59cd0d8a,e00cc52,179468ee,d7fa52ac,372cbf1c,c5974532,de4198ec,10e75f95,43461ce,fff87415), -S(8ad564f9,5abb28a4,5c807ce3,1b487918,f6f963c5,ac0cf977,c5fb7957,2954d080,acf894e0,35653758,fbbcb5a5,63d5c196,60d29b3f,315a784a,29168df2,98c8053c), -S(14503a2e,83fe0cfb,bdca0382,e872da3,bd7b6d6e,96e02415,258a8989,55a18e5,8955e448,67226b0c,c529f16a,35a5297e,dee0fae5,228ad6c1,257a0204,93334896), -S(86a30681,82b8006c,282bed7e,9b4654b3,ebf5c4ea,90c92311,a56a876b,3d78d183,1213bad,e418b68b,46ee5494,a7dfb32f,d74218ca,594686d6,f5b8b6a,26a4c3b7), -S(8b226ca2,c060c2aa,13e581fc,9ca8e471,bf8d1c4e,228f9de0,2015465,43b7c70d,4c264984,52085c7b,e549c4ad,fee6e710,9cc7b9ad,b94e0ad7,f7798930,917d1509), -S(ebd1c317,db586e4a,3792ecf4,4b2e45f0,ac727360,2848667d,19efedf6,c4c942b8,7c252d24,d2639fd2,2c0a7ce2,fb277157,f421e3b3,4d1e0f6f,ffe31410,213d06c3), -S(1420c547,78d72aa2,1f54a5c5,83f82c02,b5f3f64e,cdd16250,3741f4d2,c01d0b67,ab4ad7be,d53adc3b,158b7cd6,7cdffade,beaf126,f17b8c32,62d62ffd,764bc686), -S(e9728ee2,3744dc09,1e798ed0,786d7ec5,a31cd5f0,d2e019ae,3f52b8c2,42973d9c,9f0edbe8,edd17b87,3403b94b,b9e8fb8,62cc4463,52944322,8531a365,107c8861), -S(c2c41287,cdef251c,518c1820,ae86f38c,ac816984,b14f3fa0,4060a425,699cb291,ba991c3a,2d04b449,5dc04fb,6bf6b820,a4c62a01,f76dd8d1,4897ebbb,cb40825b), -S(6a63edda,8380737b,365e58fb,3a0fe1c5,816a8c05,f24b33f0,ba0c4473,45a0ba51,54ff065a,cd9c9ce2,876b5066,4f56599c,f22fd280,ae8fbc2c,92c38eac,c0c0fc1e), -S(63ad7964,e9af4b60,78319699,f8846900,e41a159f,c5d1b924,bbef3fb3,cdb2d098,bcc3e4d,2c17926a,d70f43cb,31c4a2a9,1a89a8d,3b79a8b0,1ec9d9c1,49b606c3), -S(c9e80434,cac460e9,bc245b8b,6cf501ff,3d64bb7a,a4ea5dca,c8932dbd,609e8354,87b2ee6e,a42e02a,9fac38bb,c013391,b9af1965,dbce484,c5a3bc02,86fa6172), -S(c547f029,6388b9de,f6502985,2ebee9fb,f9e4b8b7,f7a320e6,c7576d9e,e30ba1e9,a014b375,7c859ac2,29527273,78886397,56324353,25906a28,ca6e737e,acce884f), -S(a21349a2,a171bced,4034c1bc,f79150ff,84830ee9,95bac1b2,b1bedc13,c95f0d31,ea32dcce,6af2b400,4cb4213a,a67f3448,2b09672b,546e578b,28adc6b0,ce022db3), -S(4457ae67,185fce79,deff71cc,f73de43d,23a9f4b6,f374f637,c8a99b6d,2d582d7a,1278a7cc,6f1a5a6d,58824021,af2657e0,87ece4ab,fc5dab51,f85312aa,f6468fb4), -S(4c6743de,9af3d665,a0192f80,bd015fd0,d16fd42d,8d026175,df9cb80a,84e0fcb2,86cfa514,7d0a88b3,6a0b976b,eb5530dc,fea2cd7d,b6fb0409,bf1bad24,33bd6aa7), -S(6d591172,8f3f1fa1,3fdf09cd,7045404,d150e597,64704152,1ba15b64,a8782af1,fd22b976,4e7007d9,ddcd3b89,9f060e45,c59e4a9,470f4d87,153581b0,11b7d2b2), -S(1aae2b60,88895bf9,d199f120,506faa23,85c63220,81047e48,1dd7d0ae,6a6f128e,c3e73fe9,db489a15,87ed17c9,88d29145,848bac85,134857a5,7f2233fe,b558f030), -S(8a42240a,ffad26ea,8125ba65,2ba897c0,69eb1e7f,e821451,4521519,817c3fb7,927c6b3c,9b35482c,55199381,b4997821,70be3f27,3a1ea14b,97dcb193,901787ee), -S(a4b366e7,8dfcd7b2,3f997552,663afb38,3de01400,2798e0d6,b20ce8fd,43a78cf3,b6c6dc21,b22334bb,69f6db03,4860840e,da5c23ab,d3206be4,cfa3ad3b,b1a41c4b), -S(44b8576e,7a2cf334,d5e9db51,86605975,36504ee2,3c138e9c,86fa9589,91a8a08b,79e1e4c8,2a61e956,1bd8076f,5fa8d029,d5150348,ced9a145,95b9a1f1,82a05d54), -S(88efb8a7,eb91f4ea,6b97a97a,30bf21f3,94326140,ec60eeca,23adafc1,fb11ae22,c540c164,542181ed,38036b5c,417a6b22,819c4818,73da6882,c394d87d,21011fe), -S(3d939a17,76686fce,f2e544c1,2406e89a,aa7256d4,8415e59e,f00e3599,1b630682,cb784214,6c633d16,4f3e47e5,d7fca1fd,bb46e76d,d94b7588,d21d6ab1,f6e1ae97), -S(6cc31f3e,3e5e3dc1,ff2008d0,27ae58a9,a73857e0,26d1d304,3aee9f90,664aa53,15923b66,8ba62960,f2938e29,9c230e02,fee1f3b9,936c4658,36f685ed,e0863073), -S(c8c42052,4a7837e1,57e5b15f,85c4768e,883148b9,bc490f12,27a2ffaa,9e5219ca,99f0b3e0,6c2c6bdf,6a105e14,5745e7fa,328bd209,720157eb,c665321e,c99c708), -S(fe57812f,c8650a76,6c34f0dc,468f008c,71db839,331038ae,accbca1a,30d1ab9d,27f732e8,23ca34a4,dec45aad,7c2a4cd3,43ba0cba,f2bfb75c,6ed6deac,2e524249), -S(451482a6,1cd89411,e533ffb,d5e3326,d1d6d7e6,caa31fe5,7531f892,5333a253,c03602bf,83bdd5e0,edea9cb7,328d8315,d568f3f2,be8ef1c1,7172c940,768ba474), -S(e3aed935,8a98ade3,1206182a,66254c6e,4215efda,e5f75f0c,d72923d7,2d6caa73,f357e418,4cb28038,cf3d4abd,c9cae8e5,90a6da68,a984c169,242d2725,cf5b7829), -S(26f048ff,87b2f0be,2559e62e,9e66aeac,222901b9,59bf20f1,df872ac5,b3172107,49fc51e,712b390d,9fd38df5,2023112c,85f2f29,5521bc,4ba8334d,7a133a0e), -S(f77e22bd,5403193c,4532800f,2db0a283,d0c000f2,18a09b89,d8d10175,184089ea,7a8f9b5f,6e94cea8,dc8c4276,a7aebc47,8c2d296,4c37e3a5,5db10ec1,10c2d385), -S(2aa4ea08,d6580fe,2c0fd0b9,cb266837,7b6bf2e5,853adc74,bc58804f,b8735e4c,81c26240,7984cf2a,8ffedaa0,dcd359ae,9772773c,534b9075,9ef97d49,755bbddf), -S(93de5e98,8e136037,37cf4d1a,284125cf,2b2cded5,261b7b2b,9759f7a6,62aa5f53,5d2f3168,2a9c0f64,caa483f2,1a84d28f,3004dcd9,5d3344c3,e67b28b5,61e74d59), -S(90f86beb,d1c5534b,105b7618,606bae2a,b0fbdb6,d4fa3f4d,f78f12e1,fbb81ae4,c887f5ca,fe5a0803,9e9d16cf,e5f61c12,678586cd,fbc7f65b,ab01b60c,be5dc191), -S(e0a415c0,68e137c3,b5d3228e,d9d22d8b,b343fcd3,916f2e06,f2499528,1cdd5948,140cdfac,a0276f79,adfb826f,4c9b4a6c,f619034c,a7a3d0bc,9d948abd,32320e80), -S(e9f6cc7f,e29f218f,be6aee63,32f731e0,5ab28caf,254939dd,46e3fbe2,5fb6948d,7c91feac,7fb402d7,8f71be8d,98dee704,c1a0a4cb,43c319a9,9b78e555,62349a39), -S(136657f8,f5006a7e,89bdb5e6,e9a7e477,f78a29f5,ea5ab67d,c948a9af,680afdcd,b8570d97,c025fa85,6e1c95c7,a70db126,f2588430,cc01da2c,81fa49a,1e388b4c), -S(2a11afe3,c4e73600,5a0be836,60f7c99e,6cb0acd2,b6a0745e,69d4c1ee,605cbaa6,a28072d2,50bec98,ded00976,d905fab5,91aee0f1,997386f2,c798b102,46bde95e), -S(d7ceade,fc762de0,36ae242b,588ddd80,ad002019,aa885514,b98545e4,30ebe453,20e318b9,67c2f786,c53f63db,8686acee,84bbb7c8,3435b9bc,e6c664c9,8832fb37), -S(505fb394,d184e5c8,d9a826d5,55ba9525,7ffc00df,3c0ede33,7153bc89,86e1a925,c30ce615,771a2219,40d3987e,52af5c30,8fe45b41,d5078eb3,821fcb8c,9ef722c6), -S(330418e8,93f9360a,40656da8,883d1fc4,89441e5d,5a533c1b,23480695,8e67ecb,2103e7a2,e02ef7a4,c245b479,f6778cf7,e6419d4,41bba641,6f6c18ea,8bbd2459), -S(1467a11c,31ff8b94,2270cd53,54297b4d,e22aaa6d,3aae02b9,51e7f998,e0345eab,9d3e32fd,bce7daff,10685a08,afbaa791,bc0ebc38,d7095045,1b227db0,74a18cf1), -S(d58c9888,fbb41521,ded03c08,fd61032f,c403eecb,1c810032,e5eed64,a93c878,cefe41e4,8431eb2b,6c6e9877,fb83ac78,dffc5147,3c1e5929,28539567,a08871a8), -S(16169695,7d2625ed,b6aa9bc3,9f7dc514,e6c5e60a,39114c34,b960874f,c8c66c82,fff007a0,918a75ed,5bbbe234,dffda70a,7e17006f,1e4afec6,140b9a3,b762969a), -S(7c58b323,1bdca93a,a19b84e0,4312a347,5addc621,91c66fa5,a4bf97a4,b8b5552d,b1aa2ae7,cbd6f1ce,12b33408,513930c5,6335758e,f28f2a8c,c239f727,55ff37f3), -S(7c40af3d,d3e774cb,7c56e809,23b9fa92,f0cafb2b,f1eecb22,9c204cfc,58ef311,4dc0ca37,90e023e2,83b8878,bbca65c4,28b7e89a,76bb0b63,e92e9d20,3dde7cae), -S(a862b5d4,978928c0,49a466de,94176192,f1a57ab7,a849e548,ac12fb9e,369c916e,ca9126cf,7c1176ef,e6fbceaf,26760dcf,b1c24a28,96a3e3e5,a0051d60,ddcb4ecb), -S(17b54d00,5d185207,b4d8966c,62d3c535,c94c6140,166374b2,958b27d3,ae202765,37399472,b28ecddc,7e54d0f8,d80448ba,a0ac56b5,df9b1cd1,6cf44139,4ed92816), -S(40d75436,113043be,31bdee82,2ecc3a69,bbd157d7,72ec9b73,a4a3c96c,da28a6f6,835aa9ea,ab4c1ddb,35fa50e0,e26891d8,2b7e01e2,a237f4c8,c66c413e,faa7e140), -S(32b82a0a,5c267263,3e021c81,ddc1341,7a69e8b9,7b814dab,d529e38,424bb064,ecb8c97b,aeed6bd5,c8b922f3,1b4634b6,fa5393af,aa5e4ee2,c84d4aa1,651b4935), -S(ea460efc,85f7644b,bc9729a6,ce55296a,4277f0cf,3032775c,ff7fb96,da4c56e0,e8637568,b09fae6b,40a89f55,6f0cd0dc,a710fce4,b37329c6,57cdb05b,71b5b513), -S(cb5fcb0c,942a860b,6cbdbcf0,1b8498d8,68c8b9ab,bb224b79,4b8fc38a,9fedf311,3248669e,9fbf75d0,f64d466d,e42fa01b,deffdce2,99b45c1d,c7d8154c,fba41a5c), -S(79432c0,23a213cd,44c29e2e,f7ec5bad,1b4888ec,6673a84a,40a398b2,33aba92a,67cc9316,c2347676,b64e88ed,18fe3ff8,5c9e35b3,cf78d5aa,79c757bc,74d445c2), -S(9dce010c,4ce908c7,d0d79509,27b8803a,d695e8b1,67671865,2f97e264,3a7b683d,49419fca,ede145fd,7cdc7f8b,65dc7b95,11a72fef,2264fb79,1c8d40d5,a39171bc), -S(43b8b5bb,9b56581c,ce92eacf,29fa66ed,f76037d4,3656e4a6,bc0b7f1a,cc42803c,c83017d3,30b17369,70fc16e3,cf5c85f3,199d2d8f,a7179a06,1940bcb2,65313dce), -S(b0c8eb7e,c0fb39fc,b6f3c18b,ef96cae6,b9a23f00,751a4d6a,3a2f5f40,75e544,d66399c,d48302d3,2dfb5d26,9219eb3f,d81412be,c523df58,77e5227b,d65463f0), -S(b981ee1e,4f26ee24,63e81f77,f16dc05b,646e1fdf,d2a075f6,aa422e77,b3577cad,8a582c30,4d062936,baed15a8,9c39ebd8,2d5645d1,c0fdbd6a,d48c587,7626c612), -S(d04c88d9,8ff5570f,6fa37dd9,432966e4,bb524a58,d3ad8cc9,21d0ca06,8fa80889,dfb4007e,4f3ca38,304373a2,931dc322,7469d8f,9683e7c1,dbe59c2a,a17713fe), -S(d00d8053,68667056,55eca05e,53fa60f0,cd778e40,647154a3,c106a3e,5b8a90f,74785ee9,87323562,b815f4d,f9316a91,e489186d,7b1ef978,7ee398ad,51d8f94), -S(87dac80f,34b74bdd,6b2047a1,ebc132bb,c83fded,82405d4b,691d25f8,3e4226c3,da7e507c,2b135b69,501319c4,77ed0b20,731b56be,3dbfb386,4e0f4867,f03b120a), -S(95249c91,bdb94571,7b03d8cd,86bfcd36,3d51c012,38593cdf,243407c1,9322f8f4,a139a970,bff6a5ec,3d9876e5,6dc11286,56c98b90,ed6fa58f,157d7476,deb6bc50), -S(eaa86b89,f5a4befa,1caf1828,bcda7c32,792b468e,9e7530e5,13f1518c,3014cd5c,329bf9c5,6e431d21,a4cee5d2,beb4584,e7aa01d0,5935d7a8,44ee79ff,85f582c2), -S(b2ede9a8,6f324bce,3f62448c,a401d636,9a6ef8ca,89a48a9e,f9fa3bd,9138cd74,d942f74e,89ea55f8,a2642deb,652bf827,79252c83,b91782ed,6b3244a,439139dd), -S(c03fbf90,797b672e,24d06d02,fd70ce22,778309b8,96053128,70f48b97,aff20585,c5d44056,b4fca7af,4b7b16b5,fee76438,f2a271c4,655df4c0,8de3f634,4cac13f), -S(6da64321,c0642b04,ea7eadc2,a7739b20,7af8f1d2,fa99d26e,8e924241,4eba2a25,a08c3484,bf46e429,d7ced694,41412b1e,e2258109,b8c17dba,3370cd37,b8a77546), -S(9269c7c1,4ce5d777,dab467fe,3376662e,6f266272,5e2695f1,fa375b9b,1a1c2c4d,4dccb6b2,ecaf9f7a,fa3fe17b,e2a4054d,bcaa6e33,25b32070,24d5e324,ba1ba6b0), -S(a0933917,a532ed22,7a575482,c1090486,71a6cf38,1c6d825f,98f1938b,d3837992,c079790a,56f5e530,52760bff,8c76df6e,ceba6071,3e90dbc3,88b3527d,64aeaf9), -S(bf2cda66,ceb98433,d3e54e48,cfc15b2b,92c94031,ca9810d9,cbf2562d,c61d7017,2d31e7f0,ebe2068b,c16e81dc,bf1caa0c,6ddf3b52,13849e91,a2bc1bc7,4fecc72c), -S(d1bbcb50,4b9d78ca,ef980ea0,d2b6e8fd,7abc0d8b,3c9227c6,eeee3cb,956d6be,a1292ee9,ae1c3057,c45ea7ce,68cdf9d3,c19a6889,e58b321e,e9858dff,f4d324d8), -S(3cc406f,a049f410,2a752ba9,30f83d98,81110a45,db5fc387,c2d43a44,de33bfde,1bc1a076,f06dc2b5,ec1bc062,c9c480c2,39eb5418,4006e94e,623d2bc6,cb00ac91), -S(5fb9744c,a35cf11c,e11392c3,92bf0a98,5082ac15,5b265fd3,4cd61ad8,55532230,8bd17d0d,c7cbe859,4ff79a3a,15ded6a2,81bb065b,a78726a3,d3819ff8,58dbe34e), -S(27509ed6,ff7bfb6d,31ff0333,a994f531,abed34fc,de8ecf75,642351f6,b259cf3,bf2f0e5e,913d926d,cdca7918,57afbae2,309a4206,b408bc9f,d75b3abb,174d14bb), -S(a619b048,626b9e12,86535c8c,b5fdd8e4,1a64e834,1a8d27e5,d4179569,5fbf70dd,9f79dd50,8e50dec7,fafb80fe,99889701,54f382e2,c2b24d74,6d6d82e9,97049dad), -S(1f8ea1f8,4bd83b5e,56a8e6db,67b5416e,1052a6ba,cdd161b,420d7b46,7070ce02,69b2865e,bd3cb91b,548a4aaa,81d74310,88bb6c18,2d914697,39322037,12760963), -S(fd33ff10,574f02d2,e9c52bf,9a70b430,50917f88,a8eeaa9c,938c5f40,dcd1868a,25fd0d1d,80a21136,c8ac4a8c,4f369b57,d6221a67,3aefd4ce,be30d19c,9334c47e), -S(75799364,7cc47d16,55dda6b2,a269f061,f575ec91,e05af43a,f7e219f4,4b5d2380,d58645ed,d803ca11,f12fb489,9ffbf03d,daf82c98,2b6529f7,28e476d2,22fecea6), -S(fa0717af,d0f83028,3e8e22c1,c240d540,b81b761c,a1daba1,b45ba00,9246985a,ed48a3d0,cab1c4d1,59ef8f0d,e64a2442,c02acdea,43b5b16f,42a75a7c,68b787f3), -S(164fa71c,51623816,52949c27,33c668e5,2a5e3812,a3532452,a6ef44ce,28f49da2,11ecd95c,3dbd9463,4867af2c,290cc555,ef22832f,d7040873,35fba559,e4f010a7), -S(a213fae7,5dd15057,4b6205dc,fe03a2e8,cecbc7ea,1aab088a,fe20e8a3,b46a9a5,c135078d,f26d341,a767acf1,c7b449a9,4ccbd00,23459452,4f5b8f50,9b841042), -S(515d702,8406f03,6e5acef2,1445abbb,daf7ecff,5a31a664,a24396d2,f5d12b0a,db966859,4449028b,f3e6f53f,5bc250f1,51ef3df1,59e26c0f,9f4a346e,d60f3876), -S(3c41f639,e7705929,425ba8c4,2b2f77b6,6a461c81,3bb4e8e3,341eca66,a1344175,f57f10d2,46735f9,f6b741cb,4fc57242,7e5504c2,f6259b13,5745c5f3,a1b8bde9), -S(b8bb579a,f9826958,8e288e37,3be73f8e,7b573e1b,b7f5c1ae,3ad27474,1e9f19bb,5c51d169,607ae4a2,5e9fa70a,f67e6df1,89f1d7d4,705c2854,9e4d731c,f5f97278), -S(fe3701d7,1ecc1c21,3bed8ea2,94447981,75577963,2f8dfa1a,3cee1c47,858da678,8b69946e,8b7226c4,ccb1c5cd,8b416504,98fb7a06,ff8d27f0,da3de97b,74dc06c3), -S(9e7880b8,5a2dc9f0,143407b7,304b60ee,8dbc2b44,4f751fbc,f1b4d25a,da219985,595e4ea1,2e495f97,f61d9220,4f8d06f4,1a78a3,5b6014f6,e82ed051,2697ce7c), -S(b0d1246e,50c2dccf,7cc9746a,afa49227,62487f19,aa6835f1,1379a6e,f3c0f6a3,1dd6e8ef,973d8dc1,fa440594,a70b989a,80728e32,17fa0250,b7c1de39,b1174b45), -S(355aaa35,f5699e0d,e8fa3d4b,d361123d,5b8bf5f0,c74a149d,7cc024e8,2998f7fb,f905e0d5,b3abd09b,5f9b8c36,25f2597c,3430da0f,3439b16a,ada46421,4b678d55), -S(6eef7ac0,ee4da5d4,c8bb3e45,ebc67395,592f313,1d1ba424,1f909ede,818d6364,b0e832d3,92ea4728,7a35d4ec,861a43cf,6733ccb1,bdda8c9e,dd5ee835,92671a5e), -S(7fbbf8ce,f3e99b11,8def70c4,aff57b17,79e4e341,750f7b76,e44245de,8d90ed7d,3032f38b,6570cdd,e39cd075,e4acf1e5,815a065e,f2a84a7a,8f23fb20,6a0c99e2), -S(a9d4c727,a682f85c,b992544e,4e910ac2,beae12af,4fd74ca9,583ff9c8,c06644b1,794e13d1,fa08b167,433be416,c73d7f5c,c21413d9,a3d1393b,84e7e470,a6918686), -S(332dd1b8,ab8e5b66,5c614e8c,807a9015,56612396,adab5c4e,e8ad5856,9c44b1da,d4b39084,5fc9c364,21dd644,c323b5f5,f5d45b39,2885065,dc6667c1,2cbf6b12), -S(ba843971,6fd06d83,e4ad8774,4a82ca41,32954db8,b2bfbdcd,4935f6da,3df7ace,78facd39,b9739785,dab82b40,7dda50e2,db5d4b78,b9e57fcf,8c240b20,5aedb9c1), -S(ac7129c3,3aecb4ed,e60d0ce6,2e2cb73c,798cbbc9,58ef50a5,5bdcd2fd,d167b648,7376ed23,196f4c1d,cf8b5104,5e2c808f,a7bcf43e,2fb9f85a,ac2b3929,4d704edd), -S(17408c0a,8946aa45,387f043c,874deced,6a15eb37,7bcdbcfa,b7ec087a,80516034,cc942afd,78203ab9,77583109,a499b71e,18566987,48c2ee70,ee8a1c8e,60af5c31), -S(4f0df589,d69887f1,ae4e72af,61c083ec,8ab634b1,7b82d533,2d587a22,6f8eca30,e734fe8,926d6662,50cebfcb,50d48e42,593350b3,f2456e77,b6ff5dcc,9e3f3b6d), -S(b0d20898,74f0e672,92856890,51749d54,dc4ad1de,f6d12d3,243830ca,f8da2848,2e790c5a,79ebb86e,fd5a068f,864a7266,fe6d12e9,ec664f02,162ea3ae,e004a808), -S(39d07f28,30d2f3e8,29ab5672,db6888c0,fd224c68,57f3d0c1,aba89da,3f7ca96b,590a0812,e58609d2,e28ae3e2,9305da12,f46b8b0,70c07b2d,a644a956,12f6eba5), -S(20762b89,7ef06eec,ffce19ee,918ba264,4e93a2e3,9f46163a,99a0b218,a94171ac,e1e15917,3e3d5e4d,89cebf5d,6269b14e,784a0d72,e617fb1d,cf7bda13,33bbf989), -S(d2f0ccfe,813772cd,f3b75442,bc16e554,4edde28d,b6c64729,16764483,7b104626,c6efce8c,c63919f4,65a6778f,4b397573,4c4a93b9,43a40ea3,f44d4cef,78ce5199), -S(19520039,cb11eaba,ec1ef6e,676202bf,d5bc4bf8,4e40ed2b,2daa2a4a,2e07095c,fea234e7,3b01e2f6,d03768f4,a534c93e,c6e3cd50,457f27cd,7b6998df,b6e4cd7b), -S(3787750c,f3d73be9,52209ea2,38558541,8b6e79b0,fe1a303b,ef82fd6d,b2c9bf94,b91b2fbc,a09d6fe,b19dae3d,49416fc4,a7c1134e,22982bf1,4aa0678e,c5cdc030), -S(13abbdc1,a65ebbc2,2988a796,bb369866,4211dfce,d3a04d6a,6730d5db,6087b34f,9e4c4a2,b691acc0,b034b690,5488bff6,5397a267,13ed67f2,1374db17,fa8e8b21), -S(602a458e,1cd32ffc,d35ce5cc,c5d7b597,7e20c0cf,66a936df,4eeab00a,b7b31918,167ce780,91340b37,dbb5ab8c,e6fd602f,534149f8,4d67b16d,29724802,a8aeec61), -S(71082819,584ef5,2a690803,d24fde15,148e193f,35534d48,f7a1932b,d3f69928,9b2cb12f,668f96aa,824e3f94,79ee706b,c09723a5,4a588cca,22ed898c,c9aa219f), -S(6349c108,312beebe,145d750c,1ef2721,d536c507,4f0123db,9777e920,c72fc1f5,131f675e,95b5c1fd,856cff13,57a494cb,46e19a26,b9218b67,c6cd2823,c9e877b3), -S(892b764f,e954b331,7c5f8564,b67e7255,1287a06b,32bb476b,f616fcc6,ba329331,b0a0a00f,91d0d637,258aacec,9bd0ac32,e10ff4a2,dbdab74a,a15bcac3,d3fe55ba), -S(c2f38edd,371ef544,a1443296,afeb6a93,6705e89e,fb23a13c,3dc6b619,ea7516cc,6ba10142,71ab78f3,1603a39,dee7ae62,7ee034be,ab1fa0bf,61e18e7e,df40fa9f), -S(bea4f01a,7c61d100,da78c48b,e6277e38,6ec6c265,89a2274a,fd2e1792,b5f74618,d27126b9,9b074a95,690cff35,cbf949b1,8cf0c449,d76f2511,59f1a217,293ceb44), -S(7bdabeea,d320217b,d5e2e84b,eb28b664,e9632606,28a0f281,ec4f2edb,3f3b4bb,49c45d86,f06c42b,4e6e2664,3c4613e9,411103bb,b7abd818,1ab8a0ca,b9ea116), -S(a913e0ec,5e360f89,9c611be6,144a16b7,ff3d03cf,28851ecf,67ab457,53ec31f,9bc12b6a,8595914,333fa4ef,3096cd6,71ee444b,7bd6da65,67d91ff2,d1f278b9), -S(ec6ab00b,e272be1c,f0d359f1,a7fa0f13,55a151a6,d03a05a3,6fee5019,6275846,42d200db,e0edcf3,634055e4,d66cd689,b197f872,d91bf660,e797518f,f4c2ad), -S(a6142783,bdafb512,62b2359b,11286fe1,f15d7464,47f4f507,318800dc,c55ef428,cefd1ba0,4c19a732,aa498eac,9734197c,889cc973,6fd0800d,a051cac2,b0e4bdd2), -S(5f8fea38,cb38f90f,342d7daa,95912083,7340591,c4b98ac7,c9c8cccd,1f2ce457,54c0d093,45974a7b,268f152b,d96541ad,80561ec5,264af970,9ddcf7c,80bd5a55), -S(7b222e07,2d7cc37f,a3d73009,31ae8a3d,cc264153,6c538457,c153ebb6,d84ef26d,9dbae136,e560e343,af858aa4,20e077d9,f4e19cc1,c4f709d7,7875b44,780b90bd)}, -{S(53512a21,4a659914,82cc157f,da02880f,7c4ff9e6,47a93136,c1e55725,9ce7132f,3ccac75b,13cc40fa,5ab2e017,80f55f2e,b8e6a7e7,22b2e6b1,13a28316,b3c99d3), -S(da8a162,a47944c9,9880ddd,c2bf133e,4ec5d836,54609c06,68dbd68d,63784b58,a94bfb99,53fb0921,7b659c08,fecf83a,92b7ed8d,8138c8b1,45f9198a,f7df758d), -S(6eb60bb9,26ae0a8a,3f23d58c,e7dc6b23,f5c17366,2467ed14,61be451a,7513f97b,14225da1,8bb8ae78,8478014,6dc68934,8e4d60e8,41a46ce2,71fedc19,c512d6a0), -S(b03b0869,1b3495c1,5d06c55f,54f1d324,b353d848,31d5c43c,4d524d3a,52b485dd,d7a61b34,9f42ad82,7145f010,e00fbfb4,2e20140c,a0d420ee,11069b25,12147e1c), -S(8eb61e15,83ab8058,a3603895,7709ff11,85eb6bdc,14043909,1b1754f0,506c9bc4,c7ddb27,4c723f0,620fe2ff,2eb11365,1e19c551,32925a05,1b2a297c,9dde4a91), -S(e09474b1,3a1975c6,147f69ac,abe0941a,333ad7e,59495b9d,20747e3c,92f65d8e,98b01b17,b57f285e,b0b9b0c,52f8f390,cf2afd9c,7e90a024,c8758ff5,11008725), -S(20679abb,aa71c3b1,e4ae9454,dbb55cc9,fba632f2,548cc28a,e7f65ef3,c52335f7,158b4f49,53ef5e70,b1c1b847,1f7530c5,39a9e251,98ecab8b,d178b7fd,6b51d391), -S(51e2c9dd,b8da0e35,ac6b6325,4daeeff9,cfb2cfb4,94ea2ca2,46e9ba28,4b86ff33,309b9033,a723ed89,9ffecc25,2fc3c44a,d4bfa991,9c968ab6,664f53d0,4c9d3757), -S(b8760392,98ced8b4,2f1e9a81,2980e5b6,2e2ac1e4,2d6e8525,4bb7046f,68077fdb,310711c9,2b821f61,66854bde,4988708a,67e6c0f0,dd392b77,2435a50b,47d9277a), -S(ae072fd0,c88a0514,a1db9641,50022cf6,c186d645,57be5748,7f8a1029,7cf32f6d,862e7709,f135acb2,2d3f2239,f1d33af8,288f7434,191f84f,f6a0bef6,c5544cb1), -S(3390c74a,fe49647a,8c55fbe6,6b7eef3d,11462c16,8f4a4fe1,447fa5ad,3899ab0,ad8390b9,b98fb90f,b8885691,380229bc,24295d8,995c7810,5a7929b2,d0979027), -S(dd7625a7,10121e02,527bcff1,80f5ea43,efe1c39b,50c20176,6d172c4a,1dc58501,4f6b4942,ac8b6d5,849f2301,9f5112e1,c250b7c3,4f603e99,80ca8743,8d7c8f70), -S(ba116ac6,d0c9cfd9,16e059ee,d94ec9f0,b726e16e,851d771,340eb6fe,4bba54fb,aabc01d3,e65fe86a,4206570f,14571b10,5e226e3c,7d603b54,c1266f0e,258ca5de), -S(dc7ce33b,19c27352,a277797d,a5b70697,6e875638,e5315232,ccc814b9,a2ebd97a,5e4a0969,91396fa6,6d1d81ca,de2d54e4,f0e4e835,ef95f74d,3f21f234,d5f5cd62), -S(200a15dc,6f7b0885,bc49b66a,dcd41acf,b084059d,f55971d5,90173b46,e0755ba7,e68be603,f2c09661,af4e8ef8,b36ac49,270b97cd,f37260fe,9c27fba4,ebc3d828), -S(4969c231,3887e01d,c2837bce,68667593,beab92d3,6f7b0bab,c8368c6e,7ba31d5a,75a8e9b1,5ab4c54,a88a8678,12b93d0e,81887adb,3653518e,81d5124c,4503ffdb), -S(6f04a5cd,5913ac08,dfbe8f6c,57ce496b,dc05930e,56245464,6685ac62,85c3abd8,19fe0060,42a12c30,b7db3cf2,cf3e7a01,abd09063,6c84e285,2a045d4,301a8954), -S(41d07a8f,26009140,e5e338e,7b3e136c,b8b51e01,dd80d441,de584af5,74412fee,a77aeda5,4ea2b2cc,853e3b6d,c128c15a,6e758ff9,d22a8a38,3e28605c,8000113d), -S(dc52e1dc,e07a94e2,e1b7f59e,18e25e0e,eee2ea86,3f127649,a818e786,cc0f3269,c26c196b,a42c4a7c,331af677,e3ef1f63,8133dd2a,bcdc3c37,218b594,6547b3cd), -S(e5c26f1b,311566,152138e9,33ff4834,c17e6ce8,62c84c66,4068dd93,5fcf72da,2f293b72,9c67a27a,6cb096ee,53726ce9,fa88ffde,f8c657c6,af27d995,c4df36ac), -S(44b04185,5f6f4c6f,e6e6ca5,d71dbe95,2e1706fe,f9db95b0,9b073566,c235d50f,18f4285,cf142a82,bd26a508,2bb6b319,eecf0ead,a12f3d20,800de5d7,94d3858), -S(2c4644c2,4ca3b395,655beb0c,32d610e2,f9477a30,7757b0d3,dca3f87,4b7580b4,6c726213,c7864e17,3ff2ed6d,861ef4ce,6b83882c,1c319b9f,6ab76765,26f5f7c), -S(e3b2e18a,24306e18,c4cc6b9f,f42fda12,ea84329c,dacf0484,331bceb2,639f8ced,8a11b73e,4de49f5,6b00a3c8,2b366df6,afab3320,ed732254,c1deac3f,e2d4e601), -S(de42b164,ce28acaf,ac6440e0,274882f,158c1e31,2f080371,5f4ee6f7,6bf6f03c,385de0b5,c533196e,b3d3d0fd,fdd4d0f3,d173566b,7d5f1f6d,5c6c3735,7a98249), -S(3d018969,a03f0134,5b26adb6,31d7abcd,e6399f56,c532d486,bce5b501,98e4b68e,e8dc92f7,6a007d98,f6a548e5,3da24c30,d85b4008,2e7b923e,35a5f18e,93d772f9), -S(c77978c6,4caccd00,27b31a61,769a06ca,636f8603,49fec444,4821952d,9a2fa7d,869c3fc8,1f722012,750d9f96,349ee0bf,e08044c4,f8af04e0,80a03caa,84331df7), -S(f68d647c,e49e9660,efc740d7,1394b8e1,699764a2,9679660a,67566ffa,ead3d9a6,1d64d46e,1ffbb7ba,912b5659,656ce860,cb897a78,21958d3b,ef0185da,fee27c61), -S(dcf7708b,a5c5e05a,4d65200b,77b5ec5a,f08ba85a,46a76bca,dc1cb444,fef50aba,80c88800,d22637cc,6082bdf5,6774efe8,31095951,172909d3,4a400798,c34db159), -S(3dcc7aa8,90604a5d,bb22a5d6,91a42080,ff5844c,5c756fcf,86a2b0cb,becae,4b1721cb,e93246d2,9913fec7,16673f3b,8a02e3ac,dd258db1,d2a22bf0,4412bbce), -S(961f4700,f8c7db80,a5157a76,181c9420,9950735a,e1805e85,7b204f6b,e9b7d33a,85d980ef,b7a33331,4fe0c3e9,1ad61569,69ca8902,6951ce84,cf26c0b9,7d67ae21), -S(54d1da7b,87d57e72,1a6fb923,7b7be29e,db200b81,dd891b9b,9183e3f9,d61da16c,c7467f66,9010912f,e5dd6bd6,ea97451e,3a95d89d,2abcd2ca,ff0a3a9,b90ffa0b), -S(1072acc9,b5fb92fc,41b3fada,7d5a4434,13c73a1,734ffd33,94df394f,ffbff1ae,87594f8,f1f834e4,24756584,40664f8c,418ad3e,7a250e6e,863baa8f,a37e44ab), -S(ae4d4dbd,e751b25f,ea37ee64,bc8db97,ded52741,72f97b8d,64149db0,b8fafa33,d19761c0,b0370155,817e2022,8bf31e5e,3bd0f021,3f4b23e,881b6d5c,733fcd54), -S(328c26e,cb0f4648,4ab9dc2,c33d35a2,d0ead36e,8d1778bc,2771cf6b,55486c2d,63137d2f,a34981fe,f2e12dd5,5825b824,43f052f4,96211a46,995f0001,e6fe8322), -S(ae60aade,4c91ca13,d847353c,61ca90b3,205aafb1,c5c2f2b3,305c81a3,e4c7fd3f,913184ae,93837553,2916117e,34e04698,96b052c4,a93763a0,5f8d7153,2201f1e2), -S(a608ba7f,cac3c42a,20a61800,4d317248,e5fb7e69,b230cf53,567a4114,5d7cabe6,273eaec7,75b37b48,bb6f6ac5,695e8887,f8bde091,1884684b,e64b111c,f767ba1a), -S(ca5033f2,97194ff5,b850ce4f,77f303ac,6188e43a,848fa8cc,b1423289,da634671,34bde31,85e18a14,c0701ae3,4941de08,7e55cf6b,acbfd7bb,9a68fb53,62656790), -S(9fe36400,aa701955,6fb4bc0d,3740bc9f,363dcab7,2eccb27c,35a5d1f2,30f047de,2f841d40,bc786920,af86c55e,61c17d46,84b31096,72dea08e,3c04caa5,82ef33a3), -S(380fb487,1f841eb2,69c93474,4e737089,ddca3014,d9c8f760,40f39b7d,1e9271f9,c7c9944,cfa05673,85d49f7c,7051a04d,dd2d7bcc,36f0469c,8904dcd1,354dfd5f), -S(dfc4a0c,73ff4237,2716889d,e05c88bb,74462b15,2b02b692,6b41af3c,d52bfab1,31809a46,1eb7dcbc,8766031c,d8e02fdc,c882c7ee,a1e2f7e1,5342bb44,53b859bc), -S(561af1ed,8ddbf862,5f1553f0,31e1cdfa,34b8f095,6bbb8ed0,365ad1f0,5c3b589a,965b8e9,c6926a32,edbd7251,251a8a05,e83e40f7,7ae3163a,4a6044b6,20e39620), -S(d0a17522,1cdaf650,ed93f289,ff3d2199,e8fb3f81,7dfdfa95,f7685715,75a6e058,81f7478b,83dcff41,ec9c0cd6,c1515e02,d7eb550,282f37ed,168e6229,ce5c5d56), -S(3f42f09,cd5db26b,df31bc12,a82b6517,aeabeaf3,8c4a316d,27594a03,ecf3de3c,c0494e41,89ece4d9,d08a3c53,ea2bce3a,a65ac759,eaaf07aa,c1a809be,7482ef9e), -S(b7142a5b,239386c4,35fed19e,46fad0d6,2b4974c,f9a7c582,fc45af40,a34ca699,17db42dc,624a1d07,83b3bd69,fb6a8a05,e4175134,9a3d9561,1d4a74d4,28f42a12), -S(c3e483,cd0b21da,31845a93,b75b60b4,800b5e59,43a9708a,251d0135,91d54cae,8e67983e,1469d74d,c61be1f3,f606adcc,a02c5556,a1f06fe4,2f6dce0f,c4c5236d), -S(49d0ae34,23572f85,595efe03,963d6032,5bdd79e1,7a538a54,e43706b4,cf4453a0,fc1505b7,e4e126ba,2a0dfc66,d8bc8616,27918a9b,df985045,9df4bd6,2e0d2fba), -S(9f8373d2,f0053731,f0e1cb2b,1ab08fbe,8ea1a930,87908d7d,5dc06491,7afb4719,f22bf0cc,9b1b995,ce01a96b,1f73f6af,bf92ddf4,ca57e29f,80cbe5ac,a8604ef4), -S(f760b681,1374bc96,102e537b,8b187cc6,989602ec,118efca4,5391a344,eb82ba03,4592a7ac,655cc29,72e26d63,9a99eef5,ace2ecaf,ab414772,de2f8227,87c4d750), -S(4f465aea,bbb79ea8,60c87a8d,541f9c01,afa48dc6,765c24ec,b6a49901,307c80d2,adaa88cb,e882a86a,2d7c2ddb,d5eb2385,faffe9a,ff52481c,dfd6b1dd,f72eb3f7), -S(4f3dacce,862428f7,ab62b4fc,e20d1f12,19183207,64c2a51d,a80fcf1f,f86ed5de,97f8326c,21558e18,d4b7376c,1c14822f,d53c68d3,394dbfac,80a583e3,c668bad1), -S(f1905b3,d04cb49d,3db59404,4037ef71,e42f4311,d59b3160,b917e355,75ca9e3f,c8c005b5,5f49132d,fb2d316a,b0214872,dbf36f7b,f2c876e,6397ac87,ce6b1f3d), -S(8ee0a2bc,f853a469,27efaa1e,3356f1b4,61796e7d,7496cc87,8daa3f8d,11e46fb1,67b6599a,d8037160,f298c595,dd0a5a40,dddac020,d8c8c99e,c846cb81,13c13232), -S(a8f55dec,3872a5c8,c3d7272,6dc06f7e,5c7bff2b,9a8354ac,a184f0e7,8024a4e7,a27ffb57,47c61b33,fe555376,5e2148ca,76fba57e,fef4dcc0,3777dea0,3b2ffaf7), -S(e4cc6907,4387a6a,2e94ef7c,97daa582,9c2f84a3,9b71e76a,c0ef146c,a3209cc4,297b82a3,115c3eb1,eb75677a,bcca1e55,9d2caa0,31e1554e,abb697b3,90218e2b), -S(e3c2e255,57edab4b,64295050,94470b06,e380e503,cd55b106,52cf9fc1,d56c45d1,6621db25,53c70d69,f96facce,bbfd4ea8,32262010,35983521,360bbbb9,43110b8f), -S(8a27f3d0,b4c0ba60,b2875b70,33d386a2,e93e2263,a7f8ccf7,85a0a2f3,6488092e,9525a706,c37af8f1,5ec496b9,ecac74a2,e96ef02e,9c30abf1,2279bb5d,100a2ce9), -S(94f34fb0,2d416fb,4819e24f,165617c5,8929c2b5,a0d00bd,e8c3e71,7ef188ef,c5cf6f02,c0bd9e80,15a436e5,eb837289,66bf2b68,64a5ab82,88564fc5,166ac90f), -S(2a1e9e10,2e0ec944,bbb7c570,2ec1d655,525bc965,85dddf63,e4b4fc6d,ba65943f,64099714,f1c157cd,90393aa2,893703c1,ecacd1c1,87c30518,dcb05be1,d7eac677), -S(cfadcd6e,b147c4d5,3502b628,ceaf389,73ff3aa6,b46a304e,ab7a4608,8a7fbcb1,21cb905,2c53efa7,ffc62ba5,7ea8b29c,4eae5801,2ac40525,6f095363,ae169da9), -S(5f7ab5d1,86b95bce,a294528c,91bee6d1,c4dd6b9b,7f393f7d,db09a3d9,5d268189,9ba6285a,5ece8f7e,5cb8f8aa,4aa83910,3a2ff288,2864aa10,cd6f96a,297392c8), -S(38f751fa,d2993ca6,c3712a16,6981cb52,168492c7,2676c7b2,94463647,5510d2a0,ee57807b,89b36b02,d1452079,6438428b,7fa4b2c4,d4f52070,2f00ea00,33b7c957), -S(7c5283d8,c775232b,b03608ca,3707a2e7,5fffbfbb,1aef19fc,5823d8ca,2c5ee31a,6f645f62,29c3b646,c2b6b5f3,c2755ae,75a5a0d0,a6b732c6,38e946bd,637f7ce2), -S(d78a18d9,ed411883,568b398d,56426fb2,41bb3e0a,4bea3503,18314611,b297d090,fec8298d,79aff51b,ccb9f9fc,ed37639e,aded3174,4d0d934a,b19c0945,8b538559), -S(291affe5,8fabbd34,f011da48,53e100d3,a6638761,fc66874f,4760f7ba,769c9e7e,79c609f8,7ff45288,943bf869,4ec6d4e8,66c77f36,92d9e328,a85b1db9,92bec6af), -S(8cddced6,c63b74c3,608fe52d,aaae8c2b,15be6e3,e2eaa564,ab77d22c,f6e2eb32,dc05e6e8,e917755d,3e54ea2c,21d74781,6e6ab14c,8ad778d9,b7809ab,aeb12d79), -S(67716149,58e24e55,e786ae7d,64174609,5edd9dc4,c70ee3bc,d6764bb9,10253c2c,274f078e,7852a04b,fc766272,1c8290ae,95a7b036,45b20ad,9376504b,92642b16), -S(54bca4a8,96c5abdb,c8170b62,bc7479c4,dd33f4f3,75f709db,eccde832,73d452a3,7b1f1e00,b7f117a0,92196f02,1e499e,5b0a5f12,e4361596,5fd253eb,4891110e), -S(68df83,b0c12c86,a7ddd748,cd687bce,13ca941a,83b2a172,676971d8,566dc3a8,81fbb9d4,49ff2bb,851ade7b,18a5449e,83b2a02a,4be387fe,77eabdf5,964935f), -S(245ac706,b6009bc7,34782325,c176f05d,d5cecda1,9a0183b1,d546cb4e,55f975a1,72718f65,fbffadf6,dc9ebab6,515e7866,af3bf119,739207e,415d4ef0,f1d902a2), -S(548bb01c,70b6cb4b,d5e21e8f,dcbbdc13,76601235,9b1ae88f,2d615bfb,73ace38f,67aba9c0,d0532fa5,c71134f9,e80fa73,f47ad308,e27b6a2,3a3620de,f7e109a8), -S(548d71c6,c5dec0cb,a98c55f,720493d8,f16c14c7,97245548,5249ae86,cfeafc81,9c811c7d,5f7b67d6,728cadf8,aa0c3f39,54130c9f,81a3af38,24e556e9,40212668), -S(aaf4621c,4679308c,93fb34b3,d882aee,f7bed71c,23e5bb36,644b69d9,23ba66d8,bd4c368d,e9bdf4f,9788125d,9db04c58,aed4de1f,ecbbc52,2ef49b39,e0d8f54a), -S(bd0a071b,396afe8a,51a790fa,f11c5db4,2fb2dba6,a38b4f90,f7df7d86,f3fd0bb0,3dee630,46d723a2,1299893a,9f5b0371,e9d30aa4,d24ca28,aa9b1fe2,2636e05f), -S(57ad7d5f,7f45090e,4ffdb906,17ddb128,df3210bf,e10509da,dd71b00b,aa135e5f,58ba58c,b22308a4,d7d7c1fd,5f3935dc,69a5996a,d5825bb4,2fa73034,ad1957f4), -S(308c94cf,c0234e10,5c147a0d,155818bb,d6f534f5,3c02ceb8,14fe03fb,1e0c2c2d,90860fef,f41da4d4,b457e267,3585b997,2fc2465d,de0749d0,dbc3b8d5,251629cd), -S(ed769107,95f5a585,9fa26429,7e51b183,ed30cd21,ce489c48,6268ff01,9d500407,395ae9ea,b309c345,a6aed39b,f2fa5b62,a85801b2,74242b41,433735a6,41a3375f), -S(e4ca72c4,2e3d099d,f48a2154,b7f7ecb8,53ec83e3,4a25c1dd,f7fe224e,50dd6a9d,5c67482e,fd84dc6e,96e3b258,758ef03,a9b72b1c,e210ee6b,b6125143,f2a14f8f), -S(e0cebeb7,32a3881,66a10ad9,e4099f23,3b1ab63f,f214916,a2b24c77,de8c5d2f,6b15c084,c58da2ca,c074f02a,7dcf05ee,8b836bd2,bd7811f2,53df8995,6de6b3b8), -S(da35f459,40db892c,9fe6d0df,98f18323,cac75843,d5362cdd,1706cf59,329faf4a,59ac2e36,d811cce,3f9596f8,c7376f89,5c13bd99,1e7377bf,b9742aa3,7ff78bbd), -S(e1b0a76d,b4bd9e71,ce6bb854,670d2d6b,a6e8f792,bc303d36,bf3a9b97,46ad7833,1561faf7,6a4f6e4f,506ffb62,dc55deb5,6cfadfcc,9e4b14d3,fc5f9dc3,a5c8b801), -S(7a51bcef,7b352661,a73ba2c0,27c2fd57,2d77c45,ea8fcfa7,c39cf9e4,e95d7e36,dfd9a155,29682f33,cbe45ecf,4c0438db,e11a6fa4,51017b94,a33a4f14,5db35a2a), -S(b51f1635,6a08d923,dc87b99d,94399f2,41cf62a9,62eed5e8,de8b9a65,53d139c2,e48542ba,633cf153,43b97d28,157f19f,374a8b1,c154abe0,1624d5b1,17387b41), -S(62be0f15,6e567bf2,452b941b,2ff646b8,97708993,8c054273,7ec99683,d07c22f1,63c8e8ba,3941e7a0,f90ca26c,2fbf9341,df5db636,c113566f,a8bd1193,411de1ad), -S(78012331,5815683b,59ac7d62,54055360,4d4a73e6,453b405,b7364664,5dc78282,a02a235d,68bc552f,6627e23d,d01c2dcf,3752b513,a5e3d925,f9e43a17,4c947ad8), -S(19d975dd,16aacc11,a25b6d36,580dcace,3cb19e55,f4a0c9f5,b221a847,c8d64d2a,621bcee6,c7662473,ac82570d,7f888020,18ce7b83,7b635b3f,d44ecae2,d0633f12), -S(ea6d786e,dd234888,561afd6,a57d9d38,2a07450b,8bf787ff,b5763d3c,f9f7e5cf,ec4d538c,de2077de,a8c68b96,69bcfd9,700e2e3b,ef671a3e,38bd9d50,c785ed7a), -S(edfdbc79,dda15c6b,b74fe3d0,711d933c,8d466dcf,b0a51334,48e9025e,85c0e669,e503a18e,e2ce2fa2,3512c4b9,c7e70dc,ff70cc6d,e6f78e1,74fc64e5,dfd4a2e4), -S(d79bbe99,7c2ed85f,1f687ce8,b761caef,9629d374,ff3a1c5c,2e62aa55,848ba917,c87c80fb,db44be0,466cc253,5fee352,b52b65cc,c9ce620c,eeb0e09b,30dc49a5), -S(9a3c43a0,230fb046,ece16ba3,29999f45,ffbfd674,a1034025,8ed4b71a,d76dbaca,84ebd352,b26289f3,d0f0827c,fbc95da4,79baa21d,6a98c85f,1a54e773,d06dfb9a), -S(bba0583a,9915f4a4,5a015244,29bb3362,6d36cec9,f6d6e966,3d0d0e93,ab296a5f,f2f880d5,8b29cc71,23b7212d,a0068bc7,17ed8651,b262d8a2,67f2b959,4726eb79), -S(bfc82f8d,50227d6f,bd7be2fb,fa481d35,9b2399ee,ad216a36,5ee7a0e6,25843e83,43c7cc25,f3c527e7,a42e15f0,d73dcded,987ead91,4dca8a71,f6e45269,e0132aff), -S(e5a790dc,5c6399ba,43519268,e22fa9ef,1d93073b,e4b5a07e,d8c7ff25,c8674a1c,2dbe7dd6,c60650b8,91baa13e,7580afb1,c68c213b,cdbcb32c,b7d2f7a8,88f76a47), -S(c48038af,f4b316cc,928b2b94,decd9975,dae28b6a,46dc0d9c,808a5f17,3b251f23,8f1af5ae,31eae121,b5c53e8b,59766137,7e064f33,107784e,751c0bba,43cadd4a), -S(a0663a89,a8770439,4322ae5a,f2d6132a,e6882f72,7a30c7d6,c774d34a,50947e8f,6b3e8a03,6f099441,1b598704,55a2ae52,894a4aac,b49717da,4ac053ac,4a152d9b), -S(776c11b,2c5b2766,ec2d3376,63672bf1,933e6bb1,70d96423,484cc0e,f75fa07d,7ad71572,7d6552ea,62188868,8ed43013,53846bd3,da2e772c,e5e7752d,ade5505f), -S(6cfbc277,48c72aad,d60b2a5f,b04160f3,45fe3f2b,ce005f66,4a25e444,87ef44e5,96d309b,11b41b41,e851fd16,c4c751b2,be08a35e,d912bc21,8673ee4d,44d535b), -S(6cde4b89,ae0d961d,3faf8024,b64fad52,9bef7e4f,9f7792f6,ae242f6,7f559915,d86bb9b0,de0a82ad,ede30426,98526356,5d7ba22d,6be061d1,f31e479b,3590e3d8), -S(c2eb111a,62da4ddf,72cea94b,a85d2777,1ed639c,6c511c65,cd15dce1,6d4ed6ee,ccb342f5,3248ed9,b4e9c8a3,edc75d,cd519754,ec0e82cc,970a0190,40100231), -S(199dbd18,e72e70eb,7c16d374,c32e4f21,6f6f1015,96b91690,a846edeb,83366c79,3daa0e0d,33059817,dec9591c,a3981891,7a10a344,1d5d5be9,2ce4d81e,1e24ca3f), -S(7b175876,b6cecc08,324f0564,244b7912,59a04060,d63d9bb7,b1f9952,39b7cfcc,426a29de,e407029e,80872b20,3309b9d3,e99e9099,3892162f,385f7576,d9aef02), -S(8c182626,ba2b47e8,8415413,4c131ec5,d0464001,9ddc60f,7136ac5a,cb7f7f70,3eb5783c,c185c51,12afd02,16ccb429,d35ae768,3ff5f3ec,7de3fca0,b24369cd), -S(c21bf9c0,31fc1e5a,a18bcabd,fd278fe,ac280c08,d1edf19b,9dab3ffd,de8a6d5,9832eb2a,26d38233,f057708f,4465772,baeab661,c0b958ec,95e0e02b,94bfc543), -S(28003d74,2da7249d,67abb09f,36ef29bd,3eec106,5c02926e,eef4198,a17ea4b,f7a23dc7,779c9bce,64ee2bd2,eca6fea3,78cbda92,40c6cc9f,cef560e4,9b4dfeed), -S(de29158f,43169b19,4de65951,1c905015,2b0990cc,d24e73dd,a9b0fbeb,660749a7,2a39a6ab,42b79a7,f243a8f6,112333a5,8451866a,280dfe7a,ccf156b6,8f1f6f2a), -S(5c8c9c5e,8066e79a,38e3450f,59f2e504,2a65db6f,44233598,4bf0e4dc,37550e62,d33b710f,8d84ee3a,b8481efe,7cc4099e,8a47d64e,bc0433d4,f966fb05,7e4d68c2), -S(33853003,86c14fe8,1ae5ea18,1cd3ac20,87ed14d,6014bf9e,cc8b386d,dcd10541,db06c040,7ffee11c,5dca0af2,1856426a,97f3831a,850d4107,12b314ee,42ca1129), -S(43506cf0,bcb58366,a3faaf0a,fc8ca79d,3022cd0c,7b17ba3e,a7ea2e24,8332670b,4869e72,44c0fe15,39a93b9e,c1c16e59,880394cb,3cdda9fd,d545d4d5,968d86bf), -S(d13850f0,fa4e1a3b,12397c37,8b2f6654,46247ff1,d270538e,fa4d77c8,ae27b2df,91588b2c,c27f879f,ddd8a8ca,22165952,38224cab,e3090655,cb02b045,e869ac34), -S(995b5075,c2e57ac5,3bf1d8c,8b9a4900,207c9dfe,b0dcf3c9,86662c2c,9ac162c4,c75e3e71,3c7887e,1a47a400,dcba8a5d,4fc7841c,7f76f0d,e150bd28,ec3b14d0), -S(6af47ea0,6e2e8217,62482960,10afad10,b48d75e5,ee95f04d,66dce112,592cd7a5,2d6b4963,ee90bd6,21ec5220,6416178b,5d7b0853,7fe8cba5,ed06a25b,1078752f), -S(fa6a5eb9,780c0714,6f5abc1e,52bf1113,bd512198,95233975,4d58673a,64db761e,e57e10c3,d00af8ed,f4d601aa,e236e17e,91ec638c,d01c0c5,aba1d243,b95c89e1), -S(6d4b83ac,e44638b0,1a729bda,479705ee,e4194525,182dc1cf,f3002fdc,1ca3aada,1f57193,38c38891,fc6a0b52,c49c6bfa,c5de856,72c9ac41,3b137834,ae7ce48b), -S(6ea5d9b4,d638bdc7,22e03664,fb63d6b2,368a9bc5,eb6f68c6,61f79579,d89d9de0,c0c306a5,6073a961,c7e85e0f,3221bf96,b09f8ade,da8ef6cb,8289c8e,54540af8), -S(1a2f35c0,349c0cd5,1e4c9fa8,b8ffe4fd,8c595994,2d172dda,bb8bd8d2,d22628d2,55357f7a,cd9a9694,f2fb8a31,46546a4d,ae705945,766f8565,d8dee125,a9735003), -S(34f6720,2a17f704,80565d92,d5d268f1,95cc0873,efbb0a45,62ee87b0,bada9e07,fb3bb7f7,f878b28a,2fdd81ce,71465d96,e3dc32a2,1dea4715,61f464fd,29b19cbd), -S(93cb896e,64d0c453,3d82977a,872ae1be,1f1bd6c1,d4404ea,f7688496,2a214a86,f3028814,8f07a191,4e908ef3,66d447e7,1100fbc9,4ad1e4d5,bdd01540,135ce7f9), -S(1d5bda0d,c6378439,d30df39,5516e605,7c8b5f6b,fdda8582,ccefec6e,3d68bafb,45e2182b,a2377a32,df9b590e,943920ba,482db2e1,443c4269,37a6fcd7,14555175), -S(4d0c346d,7c4c5730,4125f376,9ecbca25,33a737e0,d5c4a85c,357a8f4b,792c02e2,4dfdb5b4,b04c0188,e8b1593f,a9d82ff9,ea4c8314,50231cfd,f5d0edb5,6f7679e1), -S(808f8958,d263ad70,bdd91b0f,76f352b5,c5c280a0,90ad41ab,28d60bda,69b52052,cf8dc4f9,eaa81931,f29a4e04,a0929d3b,c710f43a,845d6b8f,c8c9af81,7fc66d77), -S(6dfb47f6,e33f8073,9251982f,7fde21be,1bfdb916,41a8fbd0,1a36a2a8,6b10a3b7,447bb5a5,e1895243,d33d3883,e8210f3d,b412df54,adc9e35f,313a8006,141efe99), -S(8894aa46,b158f826,12ad4455,35ec03bf,c2625d61,58de4278,2848a919,65fe5e,3d280519,aef54f53,81a73760,6c4ace08,e48e87a2,71beadb,cb17314a,5a0e4b85), -S(bef6abd2,a6a2d391,a045c2db,24456a53,3dbda4bd,4e39c3b5,afb1e845,9cc6efa3,b329a528,f05589f,375c188d,83a3b7f2,89a40276,7482dd2a,4c5b07d9,df7543d9), -S(2588cbc7,171a57b5,afbc6685,6546fcee,6f1bba26,7cf73a8e,1eee643a,290c8b7a,2b6872f7,a85118de,ebfbb42e,21bdbdef,73426417,f2cf9a66,e430892e,c189f192), -S(e1362758,cbced085,6d7ef7c,9fd4023a,6aaff6a8,46be23e5,fb7e143a,e50d2fa4,1d4b750a,e8fd53d5,bab60889,36db9fd6,1c05bed6,87abc705,5882a4d4,45754599), -S(f1bfab09,821e2d48,b8849002,5222762,b703615c,e89300b,3774a966,c5bb2dd7,5cc77e20,b0ccdb36,c48687e4,bfe5e264,50dbc5e8,df38b1c8,322777cd,1396d309), -S(f3c5dcc0,778156a4,ed1fb225,bf1617b,cd56a4d1,4d91ab0b,a135b900,ff5cbe74,297e4146,42d565da,17933bea,4bae64,188843cf,9ba103e2,c33e533,15ca5ff4), -S(b8c26559,6fe544a2,e34bedd1,88a82771,8e48f880,ef1a9e00,d4cb7ece,84f79c23,9fe1b2b9,f3e3f392,8ff8b8d4,a72670c,dd9979f2,883f44de,f74dc6b5,be093390), -S(780b8246,11dffdaa,2ba0f9b6,154305b0,6a536c10,923fb056,ee6939c3,c456f6ff,802f9ed4,f6e395c8,b783b21a,d5b7e58d,6d3e17d0,b73c3607,39d21ace,7f05004b), -S(ff5d8fb9,f80b0d2b,9135052d,97cd1bed,de7c0622,f0c7c9d4,7add4578,62570cb2,9cde8f57,d9f72bae,e90a6e0,89911674,bfb126ad,933439df,c9c1498c,eb38aa6e), -S(9b05a751,91f7b248,f3eeaa5,2fed8be1,b1da6e9b,12313382,3bf46a8b,220bebe3,17c9939a,92db1886,e178faac,633fc1af,4249149,3b8e1c02,51c78d78,5c5ed5f2), -S(ce661b0c,12d51507,d8a066d0,5f43680f,909407c6,9b0de379,875ba50c,c8aefad8,ec469d8b,c9095247,53f92cb6,415445ee,7fb4a67e,d28d3019,6e1e1d06,d585237a), -S(20916590,d0a22ae8,3bcf92fc,91b93643,188d2289,12eca21d,5cefdb6d,a46654b4,2d7bf778,66ef1253,92854ac3,7846a5c6,3feb6b14,ba1b36a1,3b77ac3c,8670e871), -S(ee7c4337,24aab6a0,fa304ac,50501cd1,a540309d,99a63c56,6b20165f,1283cfca,9e3f97ca,ea42cc45,51283884,b19c2d11,50c420e0,745ce88,8ae82918,4db7c50c), -S(a23a466,57083750,56b5712c,2891b543,150c474d,2d02b9a1,8d72603f,b695ca09,f5b2c285,b4f341b2,966e71ce,d1e5c64c,e05e8058,ff2b4a2b,616e6f5c,40f5516a), -S(21193f,20328f14,cb0d47e8,6bccbd5b,e1a2fca9,fb1294de,6cca05ac,f5697768,16147a71,cb2d0f18,38f1e80b,f395a13a,9c630167,caac326d,aa890139,ce162042), -S(89db6f1b,d405c8d,b29673c4,2dad2574,ebec14ee,9cd6ad0f,1ac55f42,eff5067b,20c82a6f,ad90c731,420cdbe4,47e57450,d544006e,16ed9088,e5a77089,4911b3ea), -S(1162e4a3,4f3a6d,6b360059,258a1a4b,2a316064,b2e0aa56,3acf1a5f,812a9682,2433cddb,650c9234,aa4d6d85,f8442d83,1a9fb48a,9e92e62b,aac0ba2b,c90d1807), -S(6c439ed1,e0dcaa04,a87d4bd8,6898fbfe,80fd130a,c4721fd2,8707ca68,d1a99104,b221ecd9,2da68080,ec98c4da,be4c615,e2091f90,4031f875,db1e27fe,4dc852f2), -S(ba5b6e84,f225ce20,7cccccc7,6646f78a,3da1942a,55792678,18e70aec,b651daf3,9c50d8e4,f3e0386,72bed48c,985787ed,62c4aed9,1f32b1e7,482801b2,be4e09bb), -S(deb90434,437d5b7d,32228c47,e3e384ba,4424010c,20689aec,99809623,22cc3527,54ae32de,29288f59,e78e0fe0,b690b148,d60487b6,971e6c01,7561f49e,3b5855b7), -S(19120ae8,baaa0394,8db3e91c,973ce918,e3b80039,15b8df5c,564f8b7,ee7d4485,c260a8e6,e3abca0e,8b84a937,a9f5e19a,160d7178,d40906cb,4b2221f0,d6b9b84c), -S(d3f5dabe,754636a0,741b81a4,5abfcd5b,90b8acd6,94e58419,df0dfe57,e2e45c8a,f58f03b9,5c18b14c,859786e9,24ae9ed3,8d6c800c,57793e64,fc4a711b,71829149), -S(84b37eff,d81d892a,df94d68b,2776ae21,47c56d3a,c9ce48b1,a5057830,eea659c2,b54b242f,7e438a9,ed18b0fe,cc8a4552,dd9351a8,f763a5eb,6a217669,444a96ea), -S(32127236,3f659d58,2e0871a3,5aeeb25a,ab7acb6e,90c1feb4,dff53f4,a3eaf0a,cf01c0f0,8bb8ca11,dc6b019d,dddbbfe,ed3d40d7,2d06116b,62618179,fa8d32ff), -S(1e07bece,17458a93,98c489a8,aa0acb83,21743558,f009aaf7,1be7034d,c6263023,b0b063f0,c11ecbf,f055cd8d,6e43d009,a7519613,44498adc,3f7c87a,441ec9be), -S(d77e610f,8a969baf,fdacde3e,44abcb7c,27207311,c037e516,5a96f17d,a656ac7,645ef0e5,2e4f0786,5a7cac65,54066137,fd8536a1,2a4aa0bd,8f535254,72e731cf), -S(fa630fde,2aeebd4,7ac7caf9,3c6b4523,cecc5f4f,5a26d0d9,a11d6b11,19816c14,acebe389,85a9dac6,f3d80e0a,a4271c8e,c81aa049,d9eeb36a,e89fc522,55ace7d3), -S(e3e53a9f,a0d0286a,f56f1418,20ba1c38,1697e298,49fe82ab,4ae5109b,2bb2ac32,f0eb1f22,e432dc55,98844676,1fcdddce,de875b5d,f7d8cef8,109e389b,8720819c), -S(1372173c,a0754968,db48bb68,87d1c81b,47686f89,c6859fd8,3d608fa,8a767367,31ab8ad8,be50a9bd,99a738f0,345ba781,a2d39e94,1ad9ef81,4d4ed33b,bad08cc0), -S(5a82c886,754bfec9,69fbf970,2d87183c,4c6ecec1,53e50d49,d4a3e1ff,341b9b3a,b8abb03b,63e4bdcc,a58b3717,7f349fa7,4c87afa4,79ecc3ef,7e15352b,6d59d61d), -S(aba39636,9a7a032d,8cda05eb,588a04e,e0b3e75b,dea52776,16af7bc,14423f4,63bc3d87,8f419a78,440099d0,e26f7e73,8597982e,4708604c,e8eaedc8,2c54a34c), -S(1db97bee,460e7aef,f3132d52,48ecf43b,911efec5,1051efda,9a231ca3,a366bb86,8a297bee,fa67a334,97cfd06,211c0e0e,b876e570,e255f415,c37bfec4,bdcc129), -S(d115ae92,b28c2144,a62c6272,50cf5b62,7641533a,e5c2aadc,cafaa9fb,7f180c0f,b7bda4eb,63064115,fe29dec9,4af5f9f3,12a354e8,24827fe5,d33e0737,ac3a8657), -S(15234a63,9b7e216f,7d035d46,7146b90,2812f449,cd7fc332,ac8d773d,b042eb65,8c0d946,a55f5703,1c9ee375,b7e146d3,b1325114,72527aff,d4a6d36b,e96bf6a), -S(25290f2a,b404b4a1,19bf8895,c0c31357,1b9cac69,7d25c6aa,303cfd38,f375b190,f7b23d34,2ac85b40,9729f41e,6977d70a,394c037e,8b43c148,e8d7ad5f,1cd35a0f), -S(6a75480,e949ab33,dec0849d,80e4e458,e8a3da3f,bc7f0c10,521d752f,5fcfac3d,8ed6efb0,3dab1dfd,fb3d7c1a,90419b59,b4ed6a09,b76a1234,ec8f1890,ada92a06), -S(37060ba6,e749f01b,99de96,ca96ee67,ba0c6765,6c1d10c4,8952aae8,80350ed2,7b5eaca1,b6ececc8,87dfc4c5,79cfa9bf,c9e72bf3,a6bcf79a,3877caa3,553a420c), -S(e3bab26c,6646c20,279cd320,76c75574,4177fe6f,77de9821,36ec5162,5d13f5f9,3377bfe2,55a7c6e2,24ca5ab2,e36d535,75bc4333,75bff71a,8ebc1257,5f7fb0e5), -S(ddad1dba,85a9b343,bc53d5e5,956b8b7e,11331b3e,8a572679,4b275930,b9f31e07,412686c2,1acfe9f5,3ddf0e5a,f5ff827f,c3c912d4,7a4a4d55,37a9a5fa,29bdc4ed), -S(6cb6f196,a0deb885,568b7595,c3cd5198,d8755e78,9f194a53,ffb863a6,4858968d,56918ec5,2263ef0a,e34da425,69277e1,be8b7c97,880081e9,1532216e,c3798e87), -S(f5dc85a2,d7c3da94,833d7254,aa8c4a7b,6b105193,eac25377,d20ff6ba,26a608cb,a311c934,58419e7,823207c1,8d1cec01,dab3a2a3,248d1be5,e36d5b1,b076054d), -S(d8d0a942,57fc6e64,975a62b0,4620f382,c8946d2b,3a14397c,6f7465a2,1021645b,7d0c9f12,291e0493,87202b90,cbeb3d52,328a002,3b79b3cf,6c22e1c2,bbf4474f), -S(a9bf9157,b48c2e92,537bc4a6,43d03a4c,a0276831,a00ae6c7,b31a6d44,ebdce70e,34444099,98aa2495,e7d0ce03,fb265ac4,76ed8c84,ae87812e,b52ed5de,d482c1af), -S(e88b3754,d452d447,67b7765e,9bcc318e,2426e82,6f038685,e696b9d1,e2fc509,609f6fce,4e37102b,dc9def2f,77551726,a43d2b7,8d81a672,7997a94b,a6824723), -S(3f5ce314,ec4060ce,9d6ffcbe,bc6fe525,c9f5b80f,7f64b92e,242a4768,5002f619,bbcc8269,297e4467,950bdbbc,e0eba72d,815822fd,6679f5aa,122b5b1c,f1ab4571), -S(fccd783c,c1b4a564,cf93810,adebcc17,c2417f3f,d9358d59,ac32c13d,98c30305,65388d09,5f8d7c6a,1c0a40f6,16748b7e,30708444,acc9f90e,b644727d,b1984852), -S(6e372625,ca297c57,192852da,61b97651,1b0a6306,9bc63bd3,bbc17fa3,2c03765b,3216c5cd,2edfbc3e,1e2da24a,64c3de41,1229bad2,e44b4548,86b4766d,db184885), -S(364b023a,893779f,d8dc892,189f7565,b6642766,439d3e4,f9a27111,e001e191,74ceda0f,32a56290,8d9649ea,56c3bdbe,9a4c0bd3,dab2b99c,f9067a62,d34a9b6c), -S(99374e3d,dea10db6,b493a0c2,3c2cceda,8ecb2b41,6364136e,2f8acbd,51d01791,f9d261f6,733d7826,af2502f7,8fadd97b,c3644559,a1d18162,388c8eb7,b372ae53), -S(f1e858b0,2f8bab0b,12711388,70310289,9f40b11d,ba24c309,89e237c2,e5ae6aa8,3538eca7,9ae4f5cc,da8085c7,b53ddf55,adbc1b51,8d4ce4bf,9f00e22e,b7afa426), -S(96424847,ba09f93,37b83bc4,f5b5a4d,a79bbd37,41258d1f,95dafe86,f3b8751a,af2e7579,e2c1cb46,5a8a5d53,473f7d37,398d33c2,6c51f5b5,954fc1eb,bafc5ffa), -S(2f57a7c1,de175570,8ea98914,787ed66e,246a24bc,2ee81fc8,81ebc6a8,838f8e50,dddb2d2e,6254b5e0,e090ac4c,f758879,1c51b32c,f70361d7,f898258a,a7853c48), -S(4762735f,ba8aea2b,9eebe42a,b1eadf24,1cbfb083,163f8f8b,104257cc,360d308,b03f799b,2b504ad1,e98ca6c9,fc27a851,63fbc620,9de110ba,cbcfe7c7,783a0860), -S(6390203c,6c219a18,e6390e45,e8cef444,ca6de696,4ae43a44,e0700dc6,a735a125,a9e6e44,5a3aced8,f072c0a0,1f5d1d54,8f6059b2,880edaa,fb42fe8b,cd4787b1), -S(2986e39c,d19ad213,b171b4ef,c24bac25,50a6fafd,7907f9bc,440af15a,35926a3c,ac5cab3,b35f667d,e4d2d7a3,48010cdf,bfe0e6ef,67287bc9,ec39daab,395a1e52), -S(67337f65,973e6144,e4f10db4,d8e29ec4,46a03304,b6a949bb,cbac7ffc,ffb4ac7e,66589e70,64003376,8043360c,977e35da,41e22f6c,3c3299a8,e0642b4a,55c1b99d), -S(3f9f9f1d,e2775ba8,96debdb,a7cbe0d6,5d2058c2,4a54eb7,c021c226,96aefaf4,776f68c3,292e0ef0,ec737629,d15c8410,7e40dc7c,fe846936,3f2cb18,b4e772e4), -S(c42e2e02,20f965e5,3b40eda,a3d7b450,24b943e4,2067b40c,4662f6d8,1cdcedd4,89ae9af5,95837e93,6f419b4,7e8e0e3c,a768bda9,a6a5aac,801b30d,b34e0bd0), -S(89f638a1,7ad9e13a,378cd116,38a7ca27,181b7d83,6d8423de,a2ac857,9a1cb5c8,83397996,e70f91d8,5a72747a,9c2dcdb,fe895967,1e2001e0,b8ec5acb,67f4d008), -S(677a6390,82642fb8,dbafefb,7cda5bda,294e6f45,73312359,f6cf6551,ba0f2013,c3d208f6,e7c0dbf,f35ea183,9cce662,df4c0c79,d9ca62da,942a7601,f90c5d5a), -S(e5f2952e,36002cff,3787b459,f2b566d9,aded6da,b00b31ca,88c05bb1,789c56c0,6e635a5c,a6bfe707,f8111c0a,8853caa3,52ae42d5,2835ad76,7e6b0b34,de24d626), -S(e9d7e208,e3550536,e827e2db,1b5e33dd,6e3f520f,eca9c121,38ce6c79,cf9bc2cf,b2c90c54,90ef649b,51508c18,f9e2a87d,c95e7446,7434d9fe,cf362304,6c75a548), -S(76a0047c,a21f1cdf,f1934c3,73ab3c14,801f3342,e96dc8b3,d9c9f9ed,8ed32b33,28c5e795,f0cc967d,36a06b75,51338d8c,1967a2ea,47468a93,a79927a8,b93f22fa), -S(6e25a2c7,1c4d0918,45156c41,a6158082,44141684,a148b2aa,a0a29116,4ce9f7a6,b47a5db,c22779dc,f8368917,ab2ad290,f0ca9387,738a2cf8,f6fd00f7,f7120c22), -S(5dccf366,b6a32767,f0e9f544,315d56,754780b8,ffe31bd0,4cbd4082,8df79dad,3ca94a06,188ffb75,81f6db19,4a40b3f7,c827828d,5339c9f2,1f0bd167,2de0f8eb), -S(4f082d78,87db1b89,744007cc,14743578,634c144f,c199dc5e,6b024570,595aa74a,c982c1c8,8a724114,e164361e,12cc6810,7639a530,97392b24,f11e89f9,e3c63525), -S(73dedc7c,8cd2b6d4,de56e4ac,9fd8e7ee,77f314f4,11d66953,2da150cb,896025c6,5805bc18,3267c258,8a7a5820,1e5c8f59,f05e8384,a380486,af07c89c,1b1a318a), -S(8ac4c219,fa1cb64f,625b7b6f,c1278cd1,2958c9c6,4cbc964d,127bdb2a,e472b43c,7dff6939,5f076e57,6882d7e2,d0fcb544,1e301834,cb5085e6,6000cb23,cb621cae), -S(72388fba,92feb394,fc6e6cf7,a849752c,41665040,54271441,c7a9cdae,facdba6a,cb846fcc,e7518e85,54d90f1c,286b889b,31bc2910,4915f30a,b36bd43b,e2234e8c), -S(4b11582,3f8b93a8,5907a139,5d4ef6f1,2a34576d,bb021c66,9ec26ed5,150e5fcf,ae353938,3897397f,15daf2c2,736c3929,93a1d05d,45268cea,3cd62ef0,a340f5c6), -S(b4b2effe,f45073e1,57b3beb9,59a177ee,89dc672f,c14cf312,fae3449,60064d00,bdfc076f,17d0523b,a83d21bf,e0f78623,ca0e777,eb78415d,965c4f6d,d1476472), -S(8143ce9f,a7b5b232,3d3d6337,8892531d,12e3152e,e14ff290,1790300e,99434113,9b6c8eed,b575ba3f,94029d9a,5e7eb6b5,1952b760,2550e10,babec290,b0fcf0a1), -S(83c04e84,9fd179d0,d6add7c2,6ee808e2,a75262eb,51301dfc,a15e6a16,4e698c51,a4c05e15,156790e,802f7670,2d10dc49,239f8d1e,fc9d612d,c7e8aa85,20b789a1), -S(7f5b9f0,57d3b50c,c39e81e,150a741a,488c0bd1,2ca18fe5,cf871b6f,22832554,8246a447,5609e61a,a474db4a,c9f526f1,197cdc40,86c7ecb0,edd7ecce,2539aae7), -S(e27a13f6,a1b82bba,ae5d0212,e0fa90a3,a6885ca4,684f91e6,dfc8343c,14841979,c9164ce9,a53ef56b,b5805464,7becc9bd,64a49103,70487438,87152f38,237ad8b8), -S(4ba91b4d,e63fb74e,9c06885,340dec13,8f6013c8,f58abb7,5ef0a748,bc323cff,6595582f,fdf487f4,feb2eed0,206bd640,7f1a24fc,3cdb0fd3,bcab0d30,739efdb5), -S(37a80af0,650f33e6,360fac3,19b28e3b,817bad51,bedf9193,c745a45e,93f378fe,5edff10,fd0229ac,3ee2794f,155c7f12,b50a08c6,7b5e6d43,8931af1a,a039f892), -S(65587572,6c9a2bfe,9c2faa59,474247c,6955cf20,1bcf6c3e,513e7b54,2b5dba5f,8cbfa42f,ee790c4b,ea965128,14063b46,25131ec3,72028680,3fe69ae,2e896389), -S(a289ebad,8d4a93eb,f7cad50f,1477246f,1345a3db,7699c9f3,9a7d94c5,1433f957,41ab3d30,9b10aed2,32fb4d6,ebd906ba,50e94f34,9e4e6ddb,a65ba374,d4bb6f82), -S(d70d75b4,93a9b2b0,9af912d9,50336091,3e8278da,e73f188e,9d7f5f5,b159aa8e,fd76cbca,4edacf41,f568b81d,8f854fec,439a0ddb,caa0ede2,5f7986b9,a6ce746e), -S(97c66bff,6c03339d,9b688460,58e4bf90,12273be2,32b1f5d2,89a426d3,72024ebc,3db99430,4cb5571d,7c5ff64e,76a90913,8ba307a5,ee8aafb6,6bc884a7,590d0e7c), -S(b88b642,5b8aee75,ce0643d4,3e2a168d,2b1178c8,a9d3e5a,ce2aa55,1130f8bf,cb954eca,4898b75d,db5f9c4f,68f8d9b8,6fb7352c,112e222d,4e5ea298,6a47df3b), -S(41fdc70a,bca5624a,cfe93282,1550ed70,d31133f1,83692b29,c8013601,afe6d0e3,608a7ed2,d675b20e,6a9cbb69,7df4a79a,f70a570f,a2676830,39b69c27,a984fdc0), -S(3f2304f1,b643cdfe,630e184b,854895aa,c2a03f61,59c70ed4,a9837fc0,c0869434,df5e1d6d,11333420,be9df6b6,5eced485,ff0e4d5d,3ed79ec3,788e15be,dba57b56), -S(7da74b0,687c9c5f,d063f1cf,44b2c644,d51b2e17,49a3f8b2,b98b0d4a,7ab43258,2537394c,a042c341,b5faa3b0,35f5f19c,fc2ec9a,f6f34c52,34980336,1d89fc99), -S(88487901,eaf30bb9,27ed414,1a9112be,dbc46be0,52f43a1f,e910f23b,52073fac,6bb951c2,b7f30e71,9ee77955,50189ee3,9972adb7,fdb7a8f9,f335c8ba,51aaf659), -S(ad5c1c1c,ec3033d3,9f3d1ced,41f2e369,de9883ba,3f78e7b2,5dd658bc,42aeecfd,90001dd,b99673e2,37405bbb,f4d4321a,496f4350,660bb9d8,d5613846,e4e6fe6f), -S(bd8dc061,3da485f3,43335bf3,88a57a50,429d436f,a74a83e9,8d9d93a4,868a38af,173d962a,fa7cf6ea,65c8755d,870e4eca,1ef9ba70,97d9bf6a,be26b575,1fccef16), -S(900c9c35,ac4e9132,4f60b380,c7e80b88,f33c9d7e,242a248f,6425f010,63d99af9,5a6e22ae,dade8294,169c4645,a4bd0e73,ee212154,47a4f06e,6a662a0a,a7b88cb4), -S(e9384af4,a6f649c2,720601aa,7c5e62ba,2c60537b,1fd2c416,b2985601,1d18165,61295342,ed716c76,c4d35706,95a69bd,65fd9a2b,832ac562,59686967,1833b0cc), -S(b053211e,e18fe64c,aba2f7fa,9d8b8d5,e79e11f5,8188a811,12b2f9bb,e61ca72d,440ce2cb,27a783b7,defa2d0c,a0334f84,7d623960,ec5007b8,56f8c7cd,932a89cc), -S(6e4ec6d2,3a333b66,56977023,2e7ca03a,5fe1475a,d82bb93d,a1aa6489,997a65a2,306fbe38,9ef70003,2d69ff0c,8d483ca2,c321fde0,5e7bb1eb,8414015b,c1ec8527), -S(546aaf63,1b68768a,cb4240cd,917afaab,60aab408,17e7d5e4,74525ebb,2638eecd,ab3e9be0,841c2b05,5b85516d,a7d89a82,9264d773,c3d6f92e,4a01a7dc,e157d02b), -S(312287b0,260355aa,7b5ca09c,aa8773b8,27c1d703,eaefe0e0,99097e6,4f6cabf2,eb73ca95,f36a0d11,45ea347f,dac667f6,c32e7ddb,aa2ea5ce,e5f5443b,9de2b90), -S(95453155,af512fa0,8c745c6,d125b76a,d0c76c3c,fa21e64,ee9109b9,bda25b04,958266b7,5200f00c,bbe904ba,80294860,bdf8ab4b,43ea7df1,72badd31,55fa414a), -S(c0846d82,c4e06acf,9208af16,3c854637,242a7751,bcbd2f7c,f0c48cf8,b690bddd,3701a7e6,7161f8a8,8a3c8af6,337a7c63,864c1b08,6cc96321,a1748cf3,f51026c4), -S(d2f24301,44d98d6c,a873294b,26a0f0b,e1fa3e20,96e98fd2,c2fc59fa,3744a432,c8bec973,52fd66be,ddc74ddd,83117873,3ebdbf65,1115fd23,58344938,4f56b194), -S(1fd84c4e,abd5a38,847dc661,158677ba,1c53ca44,4a45fde2,b9f333e9,c5345dfa,59402870,3c5aff7,a508eea7,a419cc32,d2c72742,4e3f71aa,b54ebb37,c4c18afa), -S(441c5505,ccac21ea,630d129d,538cb631,6a315281,d7b5165f,c8e837df,6de93828,9c035747,37779fca,92991de4,e4d771dd,a683c2d,97d15c3b,941fbcb3,7936670b), -S(f48aff13,ccb0f2b9,29e760bd,fee45815,bc1b5962,93bdd09d,ca16feb9,e83553fa,a543a386,5a9762ad,90c4c270,743db1af,6a5764a0,ab75415f,3c8be28c,8d90890d), -S(2758e9f4,7bc46ffa,19a0d74a,1a9faafe,effb2c71,5f271d52,6071c340,78228f69,1acdef34,44060612,367591d8,38256b45,1cb883a6,d749d80d,12edef00,ade9290a), -S(af1d3280,417af143,129fd94,cb216f9b,d73beac7,c09a9d31,e7db9023,f568c3e8,27fac1d7,6f33eb8d,7766cacf,ff91936f,2c540a0a,a0e60c9,a6942fa4,2329ea66), -S(299f64ab,28071d25,4614d985,380918d6,944174db,1c9d815b,bd334e80,b961aa0f,80ac4e19,47b1d355,ab9a85e3,e8c009bb,f6ee09a,9f99c599,4a81369,607ed3c8), -S(b45cbdcf,14222123,d45d9f19,bc92236c,6ed90909,91081804,e0bf57a5,e0c724eb,1330030a,d6b49e4,5106118,1c9ae21d,606591c0,e326c5e6,ce09ef4a,37f1d15e), -S(be8f11b1,c27d3ccc,40224467,c26ec9d9,f7c60038,deb6b296,2d3ee415,11292062,1db86cf8,130bdeea,debf75e1,8bdf0d7,83357050,b7c4079d,1eacecdb,19b7c34e), -S(9274a7c5,af18755a,ecf84a48,9a0c81f2,9debcc09,9e875e76,fa3572fe,9dafe482,539bd087,e98d5d23,49ba9422,a99f4f3d,4241441a,59347c9f,57526ba2,358bdc98), -S(8455cf49,a3e4806a,46747459,ea510a3c,5ddcd79e,1c062750,6478e38f,1577f3d,dd941fca,cb4c717e,3523a7d5,6206cbd4,3e4e2993,36f7698e,605b97b,4d927b5), -S(8a4ae542,f82437db,801fc18f,ee57f9c6,d355d55d,29cbfef3,a498845d,5acca7b2,fce5096b,712cf054,bea762b3,521ac601,946d193a,cb229791,9409145f,753b84f9), -S(1de9a879,fa9677,69fc9f3e,d0ac8bff,327d284,97278947,7672a972,bdb192f1,ae095175,6c8dd516,b1bf6734,ff4f6b11,4dc0b94,3d01659b,4525347c,3be62b30), -S(764826a8,88303d4a,45db3a44,7fe13a8a,555f0973,da32ab3f,79c0b504,81ca23fe,14b29537,dc0e8a79,d2a64d1f,d8eb96a3,9d624216,deb614e5,2102b7d3,45dd9f1), -S(19470720,24d9f677,652300a,da20e5ff,39814a7d,daa7a363,ad3100da,7ca8cd3e,c7d36a40,62edfcbd,243b7c02,f0313494,4db0d7d5,6097018,23e17244,3a49b4f2), -S(346e886,d5a228ae,5b894ba1,fd25465d,47baa88d,f2c48000,9db7562f,e75f5e26,f2b61353,c4b6aff7,52318707,99e0e262,8c7d1da0,6b510f7c,bb995ba6,e1048f), -S(4aab5528,f4423b9,9485dacc,66de7f6e,94c34b6d,623e9ed8,538b2d4b,97f74fcf,a9ffb993,3a816aef,69fcd7d5,78930e65,d05afb67,55370005,4913d30d,3f2f5759), -S(3265157a,52941c75,a280bfd8,780e1ac3,62f1f5d8,20e62ca7,ed7d8b86,1440642,1dcf93c,525ec12b,97d1a700,f09f37f7,2d57a4a2,adc359ea,b1a514ac,a8862e9e), -S(74970421,4aa5ba55,2d0ea93a,b57d7788,5bbfa9db,2c074169,345a6c08,5053029d,88ce8b1d,77f1ee5a,63967f86,a8b77cd5,c5785f18,73566125,7c99358c,9f78ba1f), -S(6060ee1c,bdd369bc,a0e75dcf,36bedb15,a6c168c6,a65e4d9f,f065bf7e,c4afa889,eedda38,3a9aab25,689ce477,75273558,f2757adc,4a4d78a9,b693a1a9,f57a6e90), -S(6c5ad52a,ccd3dd47,427ed711,538e5517,7aef476c,e9a3856e,c5ea6b23,60b5cb41,70e69676,421bcd4a,e23f252,a4d2201d,ab77846d,9fa00303,60f39880,6a252b8b), -S(59b3bdd4,e63f22e9,7bb57319,c5dcef38,573c40d0,4dda14f0,cf799479,abfd0d70,be998425,f4f56645,2eccbb83,e4ffa58b,1144d70e,f9a28249,5bdee74a,6904c15), -S(d2d11068,deff8644,b07d75e5,6eb440c8,1da830cd,427d4b2f,558150e,83fdf333,41f882d5,5b07cfd8,9212f717,77b3a846,ca57ea11,c40d480,16db8e11,f3faac3), -S(3a87cca1,e244a5d1,b237d776,a170f5b5,5efbf254,dc1a67cf,f9578af4,6f9d784,47b25110,42be177f,bdc07222,9bae8b89,8e6b2638,6fdf236f,93148d78,31f71fba), -S(82f63ea4,34aa60b6,fb16196a,c2979486,12a12e50,c5ecda17,8e0f6317,d858d026,22a4e99d,e5d95329,bd8662b7,82c32ae8,eb0b494d,6dc1d395,daa7fb23,97c5caa2), -S(bbdaac46,6d3bd845,fe67a5fa,3ee5ed3f,cd2e762b,e35220b,e9fda52a,51795bbc,eaeb68f0,4ffce7d9,257236f7,f266bd5a,a85833d9,f4a06eeb,766bd426,b403b515), -S(d3c4d162,862026ab,9263571f,4df35e1,c0789887,99bffad0,2b677a63,4d20a367,cc6b3c0c,c1cfaa4c,ebaba6b5,57b914a3,f23618aa,f7282448,2f3d6ff9,966bc6ef), -S(558d059c,52a0b251,462be6a3,d8e0020,f5c0d6e6,44407dfd,62828a29,8eac4f3b,bf82d395,2e5a6d58,6108ee1a,f7bfdbcd,b4450f4b,30c72aeb,6109ed01,7c338a7b), -S(880bf94f,48db9565,cca7e8d7,b646ab31,e9be0736,727c4266,ec68ae38,c0a04196,8cc3decc,aa0fbd8,36aa86b5,ca245e74,8e22e8f3,1b34fa8a,5a1de2e3,32d10218), -S(5bcf6861,946ca2f6,258abc7a,9db72de4,20170290,ca0c6765,9bf93286,5d806dd0,ffdf39b7,1a08f3a4,1be73acb,d9ee2924,af21c53,22b9ff48,94408928,3cf22d59), -S(53f70440,f6c09489,edaf304e,c064466b,2bd9ed5b,e9affe95,a8cb22db,d842abd6,a7e74cf4,55af4dff,3b3bef74,902daa5f,da664d20,be94863c,63cad3be,30b13ab3), -S(d6c95017,439fcd33,9d122e80,a36ce813,f8eb4312,2db80ae6,e4b09c5f,277237ea,b9ce6112,53a6a066,7fd411cc,a1584cf,b1f05348,240b9b5d,f73aa3f2,637073c), -S(7d78776a,46072c1a,15c23544,f013d058,a3485a49,83a1593e,aa8c2c25,351c0bf1,7caf8c7f,c802918d,602be0d8,48eea77c,58c9d65,15a7f9c4,8df5e3d7,ebc941ec), -S(30586c43,54218314,3881348b,e81076f1,e8d3b527,8bbfae38,229ab1a6,6b9a49c9,d3e968c0,f94cf4e8,85b22bac,45cff2d2,e2fab151,36b2a2b3,fc2949c,1f9698f8), -S(93b3fc28,34ea8639,8a15fa40,2ff48069,3bbd0710,c560915f,e66b798,2e402625,e9382fb8,5dc35590,27b78b8d,13730cff,c2b4dcda,64d27dfa,105fd5dd,b307436c), -S(27375095,c1ae101c,11f6fe18,cb926f38,175d90a6,9e394884,4fe5331d,e466ec87,6aa32240,9ad70cf6,1b8ce6ac,6c518959,accef648,37839a07,8d18aac5,51ada043), -S(b4ec8bdf,f517180b,5c87fd51,e5ecea5e,5ea6d107,525fab0b,6b80a0a8,d462345b,76950c00,5a2a7e57,888082fa,631ba270,af02a5c7,73e57869,f3295ff,74b18bf2), -S(efbb3723,c386d2d2,bf0806e6,c42bf0d2,4bf94b7,b10d0dbd,d4ebbe06,d0a22d21,af0d1096,4781bae7,c7438228,b2525fed,962bedb0,b741cacd,9a7027ab,6a3b29a7), -S(2b6ebf5b,24e78685,65aaf770,ba36142,51bbfb72,f49af29f,c55dff7d,a55674c2,396a0cd1,886fcda3,172fca09,807c929e,afe8b5b6,38d63b05,6baffaa0,743ed723), -S(8229420,323c9f9b,d88bdf0a,ac9035,fd33c3f4,b1411cf9,28a248e9,bd71f95b,e8566565,2dfa438e,289d021,4a1531a5,632b1369,24c01cca,6897842c,1dea3995)}, -{S(534e9d8,bea140bb,4970b516,c42f2677,dc413f42,9b7c56de,e261f60d,ec68f9d8,e55aff90,1098b0a9,ea377acd,b62dc479,da109514,2654107a,28c68e9f,73b1cba), -S(c3d305e3,8e23eef1,707ff287,74f82631,ffcf3814,ceac1e41,52d932a1,67c24c51,10234701,f8a8bc0e,66bd6d38,d3924b0e,b57bc295,2d2c190,e6ccb935,2baf8778), -S(1f3f8c12,8d216272,ccbe44e9,43e82acb,d91ad650,72bd8ecf,adcfb1c4,38c44272,e5c4b103,a42d6238,39886157,43bcf8ac,ae397188,1abd5299,d8152ee5,674bb58f), -S(84f33b31,be4a83e8,6ead05ce,df1c9eca,57c60eaa,fa917c7f,56f75572,902d360f,854aadec,13bb6307,70855f06,a77ded40,5be99eaa,93a06b08,dc0fd7f7,525613b3), -S(9b4e0dc6,aed24421,2160f3d2,a0ad4ea2,8c9193e1,e442f632,a956b03,7f9b4db5,4d3d4970,9c0a7244,5e0b9537,2510902e,6fcf18d3,be72cb9d,c3c8a252,cbb593b9), -S(5eeed41,8a5e9d4,fc0be136,b5799c78,bf819dc7,32280d6a,43f10f39,e17cf8da,7615a870,c5cfeb70,1ab28456,a912dd6c,c2b87fe9,8aedc101,bf3beff1,89edd2e8), -S(413932e7,c2e1fe6c,dc1e8330,3c60e361,dcaa1fbf,88e3f329,96a77df,f39b594b,6891ea57,c7572d9a,b134ec3b,bbb65547,3e6932db,1d34a142,26b806f0,afc2cacf), -S(f73a8ee3,b7345479,19a49698,af05acec,1771cfa4,91d3bdcb,81cd997c,b63ce64a,37047e7b,e5742560,9e1640c6,5e89b560,138a00c8,e11700af,3061c185,4bf8a2f1), -S(5edb35c6,c68b4956,2cb6a0cb,3e75990b,7106668a,fbb71f37,2b167e49,5f535b9c,deedc3a8,56a5ee53,60e34c44,e7169af5,7a86438,b982c966,48e37b64,683bfc0f), -S(71eb89c3,8f391043,3c7c1b8f,a3689201,ea234d5d,b82a78ad,2deaff4f,c2bcf53b,350f58f8,1a2a8a76,4c70b16b,6d6f5040,882ec073,1fc9e3e3,f09c2daa,f113d5d), -S(ba4b99b9,71d6e91b,32227a44,be3712f7,93908f54,9ea958db,c1a425be,ed53cb5e,4b985486,76b813f5,df3c84b4,ef8f3279,94c65e14,525357e2,5f82a782,f2e1a041), -S(1975444e,ccabe01b,dabf3542,f3bd4651,94515698,c2b03f16,fb56559a,8d5c66f9,88287b5e,140a9558,2e65ea24,613cd20a,e2811e72,3fb8b12c,dc7c5fda,c5e0f50b), -S(e1ef5109,f37af125,d6f01cde,7b90dd77,cda704d5,121e436d,8ee8bf15,e2e4d4c3,458d2e4d,c8cd77fc,10b26fa4,c19f202b,d66fa6c8,e2fd2e4d,56299e7b,5fc9063f), -S(983839a2,7b582450,5aba0977,80dcdc26,cab2250d,d895a876,b17a4a82,3faedf63,e236159b,9c330576,cfb674de,a1bec238,3018b697,b8e41cb6,1992c5d1,bf49c588), -S(3f4997c6,b1efec78,fc198097,af19e301,16efe029,3cf4ac86,dda22ff2,78394c8f,e92d795f,d14cd101,eb15c75a,41c854ba,267d0557,47c81536,e887f97d,b67e3be8), -S(1095049a,b90e7946,c24bc411,892f911c,6b72d0fc,12af1186,ec43dc7,bec41a6b,85cfc876,55842640,8f24e382,a4e91ee4,7411a3d3,f4a257a2,6419b495,68363dbe), -S(567729a7,12f183b,e7ea601,68aaaead,594a778a,e9b936d8,a397a78d,f53ff5a1,cee7716c,68bb61b4,586d03e4,95f7bf0e,7c215870,e9f1dc0b,1f08111f,d855ee4), -S(ccfcb55,f8da139e,ba60480,ca57d942,5fe16cc0,902ba610,fe8fd2cc,cbcdc016,4e4d8abf,8517b55b,8f6c0dad,3adc94e6,8d995917,de33d623,432cdfd8,188ba22a), -S(869ad71d,22fb7aa7,7b5b65e2,c7b85a45,34185b07,a70a7a5f,fdc963e9,6de4c2ed,3bf234ab,30c8244f,d7a6671f,cff79848,ac53e1ff,fe104aa3,387824c1,f6a3659b), -S(5288d151,6d72c379,e14361e9,41835760,73e67c92,6919ad4b,a69e29c6,43d416e0,2f010e43,ecffa3ae,3d8200b7,e6f35ea5,31cd3db5,c5079b33,1ec1611d,1881f8e1), -S(b771768e,9e7bdb3d,76ae8a00,c4258be1,db77c45f,92318dac,777e9ff1,7ad71320,b068224,7f3fbb45,8e7deef6,7b52710a,5c6c38c7,5a94c154,9e503d81,72da0fe8), -S(7444e64,88164e8e,575729e7,88dc3197,b32d04d7,403f9565,611ed212,a708b98d,ea2a9cd7,49c5a3f9,f2d509e9,5a69745,a5ff933e,1c87c141,ac5112c8,b70a4667), -S(6e995fdd,ba6e0954,cbf84ac1,1d0990c7,ec5fa3ea,6b6f070b,2a68844e,ecea4ca0,743017fc,340132db,cb1d73ef,d1bf5bb7,95b8a0ab,8b898af0,3b2f36c0,b5b7d921), -S(b60c9741,38e10b6,e879b4ac,8de83494,7e345e8,cb5a4320,9a5bf1cf,286f0f85,469d652a,c9cf7d15,268daacd,4630da47,d74ae560,6ecc49c6,9ce00afa,df51d990), -S(70f4f8a5,42de7bc8,48555b84,6c058d1,eed230b8,6864a079,fb91f662,ed27f6c6,21323c29,bd6321cd,e946dfdf,d705894a,5025e2aa,abe9a0db,5efd1223,db2b2457), -S(b23f838b,3aea4309,7b1fdfcd,bad0a3e6,225ad4fb,a01ad0c8,49985f90,8a7120f1,7569db8f,46491a9d,b6566f95,92e126e3,6fa681b7,d0653b53,c45e2cd4,57c3bc4b), -S(9e447e8c,5d040a11,4964ac92,d91eadd4,80597e42,5181be50,5027019,df6ab481,c58a3c86,7fa55ad9,46e0f3f2,729a389,b8da3706,81c895be,5697090b,310e8834), -S(6f98b221,30ae2b8b,4f5852e7,d7e6ef2,1241ff92,ffb63148,4c8265b7,6d863f2a,c4f8bec3,3f9b7f66,a9827e8c,216489c1,c93506d4,42938861,4658e7bf,239a6419), -S(ecfcb0e8,f66c9de8,4d4f93af,e890e083,1b785a19,7b7994f8,c6d5ff4,63532df3,4d1d6d29,429e7c92,4f91a6a3,43b8e805,748b420c,b5536186,9c709033,87696ced), -S(baf48656,8401761d,2994b7bd,44d886ca,9a1dcf85,14f1796c,5b39326d,8f9d5690,ad60d65b,28f193f1,5a120a7b,9bc692f0,100e6189,d26703ee,1a941cf8,bbfe0e2f), -S(574e43be,ee264130,8e0e8d5b,dbf3f28b,3027c865,e13184d2,d2e1256f,4c56a401,e664d4d4,ecbae2fc,45cb7963,e9722bb0,8e72ce14,82f97e69,3388090e,602bc9c5), -S(b289585c,25bf9b38,9d89b7f,5b98dc76,a8e7ca73,f753aa26,f5d6ee10,27e3c41d,7cd41d56,6a17bf53,444f8ff2,3ef7d117,4459b1d8,1bfb1534,cbe7828c,e717ec68), -S(61ad4ac1,7baf7294,a482354a,1aefeba5,882b1353,b898bbe3,815103ed,14eb0411,d09a31a0,2defec0c,fa80ec5a,d4412b4a,fee6ae94,559db5ad,1bd7a349,142b352), -S(adc1d894,31f83ab7,a6ee5ac9,49b0b3b,62a28c80,c5737387,47136161,494e967,bbc7affa,2fe3a76,96cf69b8,e0c95b38,5f836d89,638ea2e5,8347db7b,dc316d4d), -S(345384f4,491801d7,11dfaae9,f7fcc4c2,adcae518,a993d0b3,f43b0e47,5d440b5b,bdd2e3ca,a0826774,e5e40693,c531cd7b,49514b2b,fec5b39c,9d995106,dfbfb5b), -S(e2fff030,ca48a7cb,6d587044,fdd94a9,d81f5605,57750b77,7435ef6f,f4af95e5,847990ab,1fa110a9,ff895c51,20d9a300,c805b343,3b1fd578,a62815be,77cad922), -S(b0342b00,a1bb6391,7154ea18,f3ab0649,45051137,1004c15,2a6eed35,adea23b2,1cbc4c91,888f52d,efbb6551,bbac455,ade7d78f,9e507516,ce0fc70e,d67e2515), -S(948901c3,3f670c89,e4393400,14bf7e4c,e59955c1,959929b4,ee74b3e3,112ad9a3,2a39d44c,93906444,48294f82,bbea8bc,b431d2a3,48435b88,5eeab283,ce9c49ff), -S(a7f64583,3fd0a62,367d4675,b94a5a49,f9fdf94d,c6597ea8,164a00ca,7a3d5315,b4fd7015,75ab42e3,9d51622b,c5639f5,9b67fc4c,a4f2f62a,7b6bc3b8,fc037d3c), -S(50147d69,fa4c421,25b1b7d6,74cca767,11db050b,fd2efb0f,d2f05036,796f446b,5445ac4e,674244d3,532f046e,127692f0,71057a33,b7b40f73,b897e8fa,213e2ce), -S(ff1db721,3b669b14,1f92a729,de0952a,86da626,97fb91a4,908441bb,117cfd00,62e7eb6a,3060afae,2084883a,662f780,ba42efda,13c1509b,13123789,364aab01), -S(29ca39b0,ca50e1d9,c718e00c,7176c506,c2eae92a,157cb0c7,1fc50790,7278b727,61bb5ca6,85823de7,fba69cc,1cf9a21e,eadffbeb,15267ada,a8def3c9,a54de3a7), -S(62cd6a0e,a50250da,650615fb,de2e19a0,6d0b74d7,316d7445,79f2be9d,f4023545,bd75298b,c2a3ce99,7e7eaf8,fedd90e9,9dcff8fa,e345ec42,c85e5ecf,61ee1654), -S(4aa8cbe6,57418299,e63f85c2,38d077b3,a1162f88,7d9430c6,1ec2fea7,ada0a758,6e360a94,7b07c27,9fd97867,e2ddd59e,3e77308b,169383e1,a7174188,fe507bf2), -S(6640eff0,e4a7b619,1f66b3c0,ae5e0b7d,92e2955e,23ee7beb,8ebf2e39,65ae591f,b4634bcc,7ef0e6f8,5dfc3694,27a0fa2b,a0e9c0e9,caa03a4c,fd90b50f,72feacb2), -S(d899ae0f,b22f7740,73013f98,9386e5ba,da6077e9,dc49feb5,ecb195a,bc6969c7,2dcb982b,e71ec202,472b4c77,d725c59c,ef6a5725,606d8226,30482554,16eb8287), -S(c9691967,9032dc88,a4580ca,b338fa3d,812ddfd6,7067917b,a2a1289b,5330c6a6,47a8d9ad,608a3bb5,9eabd2f1,8ec9bf89,4c3cabb5,97ff03f0,93a89d8c,a6b4fc82), -S(a4d25f7,3af5311f,26435b3a,31455ec,ee7a3b6,d6c7e850,14875a23,a7ad35c9,bfb5b89,af0362f7,f7f20fd8,a442c285,6f4d330d,247dc6a0,f8434a6,6c5a6d79), -S(edec5d54,3804127b,a814f23,3aa3be2e,e5e46a6b,ec12d2b6,9ed7648f,c30ac1cb,d6009320,5fbdae39,38d1f797,a5184457,7b645345,c36f1d80,705e3c82,f97bfd78), -S(257170ba,c36336aa,2591c583,48455370,9192432,10eca66a,79001a4c,8f340577,13a0acff,184799ef,a7211d79,41340b6c,ad8732a3,d57745cb,383bdf42,ff8e39ed), -S(f5ae8c79,b6a65f05,dc014993,7f60b25a,6def44ac,30275e9a,d787ba73,fc5305e,5634e58f,b5603ba8,bdcabe67,7f757371,c377c1b1,3f67366f,c36027e0,d953d2c2), -S(86c0376,2172c6d9,f53a9370,ca9d1ce1,79a2bb2e,c48211ce,d06732ac,80c9402f,964b4829,a76d7654,91e6a165,504b2302,5efaab99,b4cfc14c,2e84a801,fd220d6), -S(3d481453,e00c8714,4c6048ae,e5e44267,1a601b5e,fa6430fb,54203ae4,c6fd070e,69bda5df,ce150a83,d861f309,349b3397,32620170,d2d9c259,5507c7dd,591f0dc5), -S(8a8ef7e1,733c3e75,c3b39fd,7cac0656,6af1bd74,a240fcb3,b52979c8,2a56e2d6,846956b2,da6760b1,852cc3e4,d0eb39a1,7fd79c78,73dc1c65,9afb53b7,b25db246), -S(ec2eb41,21923a7b,4449d61d,9e9a996a,75469c05,e86a4911,16c15206,97d741e5,488c3501,9fccb8c8,33b09546,9c27eae8,66a133ab,991a24bf,c00691b3,9e1d5be1), -S(a8c08ac3,b959476d,8e58e8da,72323b81,33f55721,318c664c,ff5eb491,7aa19562,83bf5e5f,d76c877a,f10cb1d0,8b92d9e0,3a8f7db0,2c571449,ce3f5ea7,adb3d9c8), -S(eef63253,739af912,b7cacbdb,3e190add,f2931c2d,e0997fbc,5ce02cbc,56a53e75,14c4d6d4,5143b60a,f0a75249,42582d70,fdc17027,e13a2460,84523417,9a5cddf8), -S(65dc0be9,e7028f3a,c15e5e2b,1d27d339,d12a3a40,eee78b5e,4942975c,f65a781f,d635b3a7,97b5ac7b,c072fe35,9a7ffdb8,b1aecb13,fe933b3d,cb627b47,abb2e652), -S(e0cd5d6f,81a70576,2c65193c,c0a2eda2,aa5ba2b9,c9fbca52,5148a4c8,2f2c746a,5ced8640,19c48e1b,8f1f97da,ea66cb96,fc71ef84,36b87a53,e2b5a841,1d474cd0), -S(66d2d27f,eca16c6c,f8a68712,85f4dc01,92fd503e,6fd39cbe,89007d76,20a966d4,56551c4,ba79a293,fbad2b84,4dd1f5a7,a6c8a688,656a79d6,764b9b0f,df4f45b), -S(36d496cb,2749b975,9f4474c6,a4dc0283,e19a2e29,1c488623,210ba1db,1154ebe,a46cd868,c01b05f3,3508961c,61f0a83c,3ea06996,829aef29,37a93c7e,8840514c), -S(4f53c3f2,5a858506,e11681f0,dbfffded,b6bfbc8c,63ed6d09,3028a55c,c19683a5,2a31675e,7e0f8382,625bec94,83bae5cd,76602e36,1dac153,45209b10,78fdcffe), -S(9c6719c4,2f375d6a,c2891fab,c71bfa16,a40ef26d,b0ce93e1,46634221,da12d8a1,38c92598,10c67724,14f83d45,db2a5506,a993e277,f20a8430,97ba286,b2be9afc), -S(115eae71,89f32e1c,28f86c62,abb7cc2c,5fcfb927,6b3d7655,8f7f1a47,8c9ce0b8,229377d0,9b80dd76,4fab10f9,7cb8c1ad,5f0c89b4,47ac663c,780fdf6a,71a0acf7), -S(4f06c1f,ca76fc9b,d58fdd6f,12d0c64c,df9ef87f,fa579b3c,fe7f8819,aa68595b,12292991,95f91eb,18105a0d,b576fd33,1eba5e9b,f6944557,e9a54d9c,c7ac9437), -S(1f18b838,ecfb11b9,34a37132,6d765ad8,b4a1f11a,6ad51d67,3e7d5bc6,8823e742,fe6d5003,e851cbbb,1d575d39,d48ba2d2,de8858c5,95e2e73b,26127e61,fea194cc), -S(905708d9,b066738a,252116d3,451b2330,5ad84a12,92199acf,1bc0eb86,b7209109,7b3cb65f,6f34a189,584ce179,4112007c,71b2d6f7,9667880d,684768e0,9d706d0f), -S(bccf7efa,808ee0b0,f19080f3,cb4c0fa1,2dc46c87,2a7ee71a,1c1a171e,b9f03962,66b9d38a,5582ad7e,8ed7b0c5,2d4e5aa4,a14fe624,a51d02cf,7553f7be,fd2f9ffa), -S(fb6505d7,2fa3e83c,26d7cc0e,e8e8e160,1c46ff4f,299b06ba,7b5250f2,a20a4ca3,75935eb7,e923dffc,c3b0bf80,4861a3e0,a721266a,1395f424,16f26d27,9a582ca5), -S(208d0bb2,1fee812c,e93934a6,c5571d1a,a8d8b6eb,3ad58357,90661718,86a4c103,7ab4af2a,e062e5c3,9f83467e,31d95f4a,c1e0d0aa,d77e2128,a8916233,97379bce), -S(8ff01550,87e8359c,f5081e09,71b5b80a,e482507a,217114a5,8115577d,ffbbd5a8,47c83838,5bee81ae,6738ccce,e1149821,e433b9e0,e11cc919,3bd180d1,97a07519), -S(dd938972,59966349,9edba2e0,1932c7c7,883c99b1,11f3dd2b,f6b079,770f7cd0,c485988b,373de68c,9a07d8d2,3d8380d9,ce28f9dc,9dcd3abb,99705aec,c87f0ea2), -S(247f0d44,50e75f8a,724bc9b0,821e7e62,cfcc6983,860b1997,c73b7b90,515cbb1f,6b861e4f,2f5e0cf,38d91847,f5d159b2,25b43236,2e67771f,da2dcb2c,d79644e2), -S(2deabce2,d1d31515,86894e19,1a5af1c2,7fde9b45,455910d9,598adc57,e46c8823,77016b04,643d44f8,6f279dfa,1a86f3ba,428493e4,89b16462,62e018ff,d70efd8e), -S(97bcfcd8,dfd8f0c8,e7c09773,746ca7c9,de813c3f,14f6e39e,4e597559,adfd7ad0,5f948bc1,84d2ed00,ca4d3be6,6972c568,916e7120,cedb84b8,29f35cd5,dba65e35), -S(d2a6e659,e88b061a,e26bb48f,10e4f1ea,30da5df7,2e9cbe4f,451fb413,c0eb9c00,d6c0e56f,cb2d383c,dc77b93,2c41566e,acd21f2a,93537f4b,683d2f72,547d9779), -S(8a3069f0,b374dda7,b7c1e34f,80ade1b1,b439e517,595a5c88,8e3ab8b2,b2541e36,b13ecf0d,729b7cbf,aeb2ea9,6a80e6ae,32f9d46f,57ce4114,4c24f61c,b0c7183a), -S(6160e9a8,a3c82af9,bfe8468b,5142d7a7,32d00cf8,2ced3a6b,333c188e,ee6c0df9,9c174f47,42f0d46d,aa03966a,e00595af,355c39d6,a7b17ab,637580a4,ab9802be), -S(ff32347c,eb8aed18,ea6c314e,15ba2437,702b9d8e,a775f6f,a1b84b27,83837b2,d09e3f86,e37d1190,9f6ea512,44f9225a,6b8570a0,c90b8511,7a1eab62,f3220a37), -S(170d2456,58ccd0fb,d8c01df2,a84132d8,3eb94d08,d8fb7b53,a929fd4f,38ad26cb,a83ab99b,176dcb0a,e80c5f50,5a454f15,12622c22,e6f7309c,7a827a59,944c4e8a), -S(8acc0889,91014a93,e3649980,b6eb6172,44f56e10,8094b6ae,a7f16e19,1e566e9a,ecfb977e,a900e0a1,f6b8247d,703ebeb1,4524d5d6,95f6e46b,85ec9e52,a5795a85), -S(f80b78d9,22cd9e20,83569df3,ddf58b41,dadcc3d,2a3edb2c,e31cf234,5a31cbf3,fd1ad87b,98a42acf,273a268b,c4f7493a,cc28cb9f,9794c833,153a0947,eaab549b), -S(41b21d40,5602d26c,78028eb1,acb7160,9e53fb02,7215c405,edd90586,1fbc1a8e,55480fb1,3d718aa2,59f4cf19,b7eb7638,2d07c372,c9202c87,b7037993,90f309b8), -S(3d49ee22,22bc61a0,9cabfe95,bd981686,73c2b42b,5d22698,21ec7cd9,6a488ce,2d461269,bfc6dae,48280ed,ae07ca1d,cb8d3e8,a1c9404a,971e416b,d2a5cd2d), -S(7f9812f5,30f80bab,f35a5df3,ac0c4d68,7227fa14,74ff6057,1f8faee4,32cb8c74,805fec79,b3607318,574a9308,831c4db,1fb1cde0,c0094b6f,6e19b924,35e0f118), -S(d5a33585,6c8da16a,6ebe776f,3cd08d7,e32fa2f5,c484a299,6abb9e84,60d0cd6d,fb1e3d96,f95a139a,2c968563,73813e8a,7cfe6ca2,bb97ed22,1e374337,9637668a), -S(a138a71d,854f2f76,5f8d681e,84e91b52,9940c342,8f69184c,d469edd6,43d2ce2d,ddecbce3,a48b0457,66ef7511,b041f6af,f2df22e5,51aa033a,8325faec,bd9ef061), -S(d9a0f20a,ebb51238,14e55212,4b6d723c,1f972951,446d736f,b4d20e5e,a9dc2304,fb63e167,90c817fa,40185611,ea346e18,a12fd1da,fe3266ba,c8c8dc1f,2312797), -S(31b4f50a,d3476189,62a34537,10a1a995,e9e25283,af87725d,e2767e08,4f276324,98b32741,c8e1aa6f,70655814,ba0f34df,7f2ac7d9,40604bb3,4216d8b6,9e03d07a), -S(23105202,c01e6e2,6fc5da32,5d65644c,e067817a,6b54779f,fb9f1faf,57b15a5d,2da13e2b,63b8c792,56a7b49,c44e0014,9f461967,7f2b4709,d158aa38,189f08), -S(2e9bcbd2,8fa1b69f,76193011,9ecd8f38,c88d2c7e,f051780f,cb82d587,8e5fab55,93ac2ec4,33abd509,fa71237e,9ab6a421,4d453bb,9fed86c,2bf9b727,a84de903), -S(7a560f5e,d2952cf3,342a1273,5c627eba,49eaa668,f3ea67d1,9a0bcc92,9b172ed,32d1b9e9,5e1df2de,4155bca0,bc404615,957b16b3,45568590,74a119ec,a24eb984), -S(10d8b5b9,f230099,9b15ed43,17282c23,dba62c42,6725e112,6cdaa3ba,f07564f2,3e5d4465,4ff6faf7,3d3c5a64,bf27251b,de0320c8,b8f5e7c3,f2933225,4f0832d7), -S(924850a5,d61c8491,6ae458ca,491d87ac,ca095e0c,3a37e5d,528785e9,10730e8a,6f115681,341d7598,552d8eb6,7171ddda,40594be8,5da3b9d7,7918d2d8,3316c738), -S(f36a988d,2be42bf9,d39a2b40,c2447f81,6dc2a91d,20edb89e,c8b00c97,c972d837,56ccee9d,619f4b0d,2fc0ec9,ed60ef01,1f10b55,2569dcf4,dd922917,d8912764), -S(7a9b644c,a0b45902,39849b1c,b03687be,75be77e9,b50685b6,1c9d7052,5933ab2e,ac13dd6f,d4f8cfc5,27990d16,cdc88720,4a5a14a7,f15287e2,7b5b4c9b,3ecca461), -S(e9de9ec1,40076c59,afa8264c,e4ee7209,5b88b08e,dcfc120c,9a3e9003,72542abc,284d6201,15f1f94e,54bf097f,b9407695,c62e76f0,f2138bdf,932da8cb,86a13865), -S(aa9ac192,d202973a,2074a2f3,7414ec0b,6ebecbcd,f201a6fc,e43d74e7,8544bac6,95fb5730,f524225e,a7af1ec,8e34a6b,b7300dc3,7df97888,fd0bdfd7,4986e2e5), -S(31b66efb,b2da072b,16d9b35d,5175dd6e,96b8c227,abc0f2a5,94e02f9,e693a20c,e3c18398,aaf7bc6,776f306e,23b1f001,17fdf03a,72474f2f,ed3b0d6b,70cb5baf), -S(7eda3d4e,2257ae72,abe80be1,8edf5496,3a8bea8a,a2be745e,8402734e,97d19d4,ce5e61af,de4301bd,974ea8ed,8239a368,bb8f0b57,1a6bd9fa,c3327594,c4abfad2), -S(297bab00,4b5e8c60,b27fc169,257f1217,48af6f99,65caf54f,67ce172a,e69e2b4f,eee4fd66,57a4aa8e,5eafb1a,e95e466e,976cedfa,b32f8f4d,31a820e0,cc470eef), -S(389f8ab1,2be46a3f,e5d2fd38,9598890d,cbb8d1bf,fd36dc10,8cdf8532,91e477a6,530394ba,2647c712,aecbe545,dec368b,21eaed67,a9d694e2,abfe1e83,1a2ee1ae), -S(36122688,726cf2a1,b2ac26a9,375608c7,2024a751,6543ce67,2393159a,98fdccaf,661b4134,4ed2bc7,c3596a83,b812fdbc,ca95cb74,f7b322a6,ca1b8167,aaf34666), -S(ef5f9544,a9c4148f,6a637ff4,39bff5d0,9bba2824,1d115c37,a5918070,d02f9a8,2111a85b,369cfc85,6db8941d,8af8a357,869712d3,76ac94db,55f3e0e3,e5e8770b), -S(d2c7599,c6bd388d,def00aed,b0cf74b2,b41646ff,5bb690ee,2f72ef10,1f55212b,ad863280,67ab378,1fe9c59a,bc54b06c,9420059c,6fcea9f5,f0bf563d,2f87dc8f), -S(67a35c0b,fb6a1655,23740a0f,23b6a8a6,854c22a4,113a665d,1c35a2ea,c83b72bd,dd5b811b,e4454aa,c7c9adea,b7368235,f3dc2bad,a6b7a2dc,99e86f97,f9d7409b), -S(6b667d3f,158c02f7,32ebedd6,552ef5d1,443df008,2e1b724c,dbaaf43b,efbd2480,c920f76c,c082ad16,d7564ff,9952fca8,3fd4e059,5e11a711,2337cadf,f5f51cb4), -S(c8cd3584,214589f5,62690e9f,71a63e17,64b0e3c8,33f26cda,8388be55,6e336296,c5d0bcd1,7b737bd1,66a2421f,8e1dfa80,64b3ede2,5ddb4ceb,cc8f9335,6ec468cc), -S(8b2f358e,b781cdb7,b8db96ec,7d42b75d,56c494ce,7561daf,b3d0ba8,360c281f,aac9391b,cbce3257,1d01e5c0,82eaf632,65628c28,77e72671,161fc2d7,21425e61), -S(55b0917d,f039f139,bda403ad,7fe1ebd8,912c0434,379ff3a0,da5996b8,bf2b2f7,f592415b,3ec3a143,c9b681b9,cf8c8139,2ed67439,ca67a162,e083cd76,27da169e), -S(c0eeaa0,81a38627,16dc09fb,f8e154bd,6e70e14f,a92168eb,93673780,a8fa76e9,9824a6b1,fd3df6fd,94ef8e7b,b1d9351e,cd3ee62a,e70a1eb9,91b56527,7c695e23), -S(fe75017c,665e766a,13b2b632,cc29e61d,9bd5755d,b9c4f065,e764d658,7204997f,157a23bf,72c25ace,ebee10d5,aca71726,6d6c4cfd,983530b0,3d47e6b4,9027d0fd), -S(bf4458c3,ba27b2c0,cde6911b,6cb61a6f,53642c6e,367f83d8,e294e3c5,2b18e13b,8d34a93e,e7f7ff98,3196cd08,c8344cd9,eaa83481,3f606e8d,9b2f6ef8,bf91ee64), -S(7254ec2a,c6ad1be8,2fd75bca,ebdce771,f4ebca92,eadc0bbf,3c5146db,a8d3760d,6302fe68,4243ed5a,887eb664,46f709c8,e60a6db9,ed062c33,1fc556e6,6f87cd0c), -S(4eae1e2e,b75b8cc5,73688f02,bfd5af22,ca928244,6dc8af5b,9dcf1118,f37ea23a,2a98f93a,613b9b1f,b3725d62,60510ce0,e718d07c,f913fda5,3b4f8b28,ddca064f), -S(b929111b,4b6b6caf,184238e0,82fd9a3e,8b9893c6,ff80a091,8b8e2b22,da6e0d2a,5a207daa,f75abd10,142948a2,cd2e806b,23322e1b,1f52b739,a9c7ab26,2f44e91), -S(6c57b3ba,18fabea3,25dd2711,52e5d857,a2853fdd,5f73db49,cc2e1c25,c98caa91,5a3fed55,397696c2,a0e98573,a30375a3,1b59b343,35c77918,3908ba58,4bb96a76), -S(607ff89f,3c3e3635,a6b83591,546594c2,a20de4b2,e59a01f2,696a9d25,caa0b1ab,47f4a3bc,ec375b6f,2510df4,7ca3d932,524e7c9b,656beb5c,65603c9b,1dbc8a3c), -S(a5f8ae36,a163ee23,d9c2744f,1f32de1,25744a64,f0e21009,445f08a3,9dd8aabf,274fc698,60f62f3,cadab3cd,23086876,31dcc845,43c98f65,b826ba0c,5b27352), -S(bdfc9b7b,ea97cfa7,4e97a822,fb6d8dd9,cdd2784,186f01b2,40db0851,95e1a07f,b02f7e83,56b72dda,81e38cf3,d5cf071b,e3c4c595,118c1cf4,61f01b1d,fb678090), -S(386bc7b,42591be5,41547b61,f0c96e13,6b168ef1,338f0f3c,ca2e59bf,e4f902c8,aaaccc7c,37655f05,1e0bb44e,396b2512,68bb806b,1e1ae4ee,598ab2c0,7b920f17), -S(14b9ba9a,c5eed3ee,9f4365dd,56e703a,2bc35d0d,af288bd8,1b9ceb03,82444a69,53d17e83,d76141e5,81c03eb,367076fe,a831a4c3,3a756cba,e564c851,e71c9a84), -S(e8b86b8e,f0424769,d0a6abd6,f0090030,7e851f7b,11a31012,b404e4e4,c062b1ee,f829b4e,bd2a0a55,253c7fce,73b27cce,9e31acd,fd8345f0,b973143c,25ef7900), -S(ed4cf2fa,b4108d10,c07630e8,333fdeec,af062396,eee23aee,e06365dd,ae880631,8eff37c6,5480bc59,6271ef5b,41743d9f,89a4685d,d497bdc0,8f6a11a3,56d07535), -S(6ccfba61,23d3296e,acc2f6ac,ed746ea3,6c7ce287,6e758fe9,b38603f2,3a1ed8fd,86ad0ff9,ee5d758a,2c2736ce,af4b2d50,a23c60d7,d952409a,9bb0c836,34dcf7c3), -S(4f3dad6f,4f718586,f2ce5239,b7ff5f05,ca384f7,a3171edc,6b11103,55a015b2,20858d8d,ef722f1,3a6e11d0,7d0a1db6,257496c5,e1f64d4,182592e5,f57334db), -S(ebe62fea,9af5d236,30dccf98,cb1eb472,38dc964e,5a145831,fd7b65d7,6b55833a,f828d7a,d18cab39,1af532ed,33cb2ae4,3b677836,b95bc3a5,2807d5a7,7df2eb86), -S(f4608ee8,a9ff5e52,15fd6257,43e58f5,af5ee536,9bf8e5fe,9bb8d371,e40e86bc,44dbb6aa,c7bb3a3b,fdea778a,7a6ce04c,dfe22a5a,c054951,2a52ac0a,499a5962), -S(63be7855,faa99716,cd77c389,5b2eb8d6,ae5d29eb,f64916cc,f7eaec1b,6f81ae30,b1463e0a,44d15252,21670fd8,4a1ed48,24b6effe,f6820787,ebc76cac,68db082d), -S(17306e73,c5487073,30f41a4e,e94370ef,36c07686,c55ce03d,ab6cb6fa,ef1ae2b5,b3f971de,6e09f1a8,7b083dd6,44c5edd2,a67449a4,520dfd5a,6742630a,8fb258f4), -S(81dc632,ba371e74,18cb0986,8a3e11fb,738f7857,9210bc06,cd0f9e73,4c91a064,cac8a551,b5ce80dc,2e5b400a,f10e209d,9b1864a8,ebf554ec,f36056e9,3b99b69f), -S(6ec14358,b2734ab7,3059643b,c60dab0e,d8d46c41,5ca1815b,cc215408,19b71e71,3f6c7c4b,24cd34d0,aa9cec16,cc17e321,76e2c0b3,24bef53e,9b6f3dc6,a4f4d617), -S(dc7cb981,dd03dcbf,66e63e85,158aabeb,db7e2aa2,c4a04db8,e88e8628,28000afc,d187b91b,be3dc2bc,44f29d22,e2a5611,6c9ddd2e,6a946077,deff44df,6109bc4f), -S(8a49a003,8dd13eaf,7223a2d5,50503fb0,ce0f5c2f,a7a03d5d,5ce03517,803899c4,47e6b637,1876be40,dc5b64d4,4bc5fb89,966c49c6,2d4f85b7,c7867ff3,1819f8de), -S(b252b5d3,a75c18d3,79ea1959,67559d02,8b8ab87f,c4c5bcd,842e5de,8e2c406c,eec6b95,c2d5af38,84ca69d4,2134d318,646774cc,4d05f78c,7978e8f0,80072b54), -S(6c30393f,d1f285d0,37f412af,38411133,c1bd1db0,6bef205f,12fa94a,4eb35412,b8c88541,acc9c862,c0186985,cf58419d,1c24905b,1d1abbf9,2b59a381,829fced3), -S(aa8b25e6,583d6898,6ff108a9,a4be30d,5a5149c4,45387abd,e9c1cd74,f3246ccd,1c51efb9,e6225d4f,b7b67bf,1b12de21,718fc945,d18a1679,f5ff6ff9,94d158d4), -S(28b46490,768800c0,4c94fd8d,8ef8c29d,fd66fe24,f379cfeb,a0a9b9e1,53acb33c,7e348f08,308e1ddc,6ffc48f,8e8a137e,785a0aff,fff18285,bc5b7bf3,54ca8253), -S(54b0ae43,66382f3e,83a01082,7e08e596,de37fa5,8c012e90,20a24347,ca1eb5dc,facb37df,f0bc59ba,72260606,d8e94f7e,3f71f600,78f6854f,2fdafffb,cac30332), -S(f8f03b0e,b981e371,a0994d64,6ed73e5e,a36d74e,7a349861,20e25d71,7f43c6b,642c63b8,96d9e995,32dd3403,40f91e0b,35f5d990,f6cbb768,253251e0,d7965737), -S(9c1be533,26c1a43c,f0fc5e13,83627414,89b4df8f,71224d24,6bc07c1b,f22c89d7,4d420abd,af53f191,f1e6622e,bd51e638,9e2cb2b6,a7c51885,f21937e7,3de7e73a), -S(c9b65328,864d0371,86b146d8,fc208126,dac6bea8,31778af6,e944f338,3c72553a,db91182a,b8a8ca07,3e2fae97,41cd81d8,d17c8776,9f2c0492,2b76ee93,c42af5a0), -S(7d945104,a4ebd202,dbd4be75,1cd14d8a,e07700ab,804de7f5,1cf6d254,bbb9489c,77231839,b8d9e627,ef6ed20c,e88146ad,7addbc91,f1522399,da31b84e,7b21a033), -S(2b307a7b,99ad1892,cda61d2a,10c1d972,b5855905,a64309d0,6397732b,c98ab549,8c38783d,51162a87,8e84554f,9b6d106e,e3064b89,3d368341,f96faefe,9a0ceafa), -S(2e7c5d29,c0393ab9,7b93a628,8d6b1da1,d212687,5d45c961,317665f9,9db55ed0,58b9c7f5,19ba5e3b,5d988b51,d50545a8,9a74bf20,1cbf0cb3,64936a06,7c8110e1), -S(accc9c09,4ddabe8f,81433d11,852f2583,85dc0463,9618ea1c,b06fe50,68358940,80ce4a4e,9ae09021,b8945aa9,1e4401f6,aadbdcce,421f6f32,ce7f1317,508cb799), -S(a67ecfd4,3735a152,4908375d,d21bdbf4,824be481,a8ff6201,8145c624,c5cf74db,e993c3f8,5aed69a0,f9b44ffb,80b5156c,33f809c5,e9efef1c,fbeb7b25,c6152911), -S(42f5d252,3d508a01,e7177947,29eee1a,fb7be04c,90539d9e,afe32638,b252e158,7194bfeb,f9ec8e1f,5039d582,ed7d28c1,99d5b07f,bde10b1e,e3b4bb64,148b5119), -S(15bc89ec,5d3b2889,d26e77c1,33eb832f,bded1d29,ce975905,d9355b2f,d99ea1ce,4e0d28ca,7aa69933,6f41e3bc,57a9639,81e2b92d,7b80794d,4787251b,f7fdb0d6), -S(7d68bf90,45c79869,5a8ef33e,f7fc4386,5ac90c37,8d3beebf,6ba3973f,e9d8e507,d14998be,f5bab5fe,fb94ebf6,9c0bf133,a6606b43,f621c861,ca1cbbb3,ae3fccaf), -S(82541ac5,9196f73c,99f9ee01,ef266c5e,908e91b8,b341e052,ae2576eb,17b90025,29eb3c8b,8ef826a5,6565c9ef,c2b2e47b,94e12736,131d1e0d,5b235d0c,169c2934), -S(242399a8,9c5a056e,8073a5ee,45475787,b31ff7e5,3d451f2a,d0437580,a479239a,19d5ce74,8c9a4a09,606e7c0b,6b486098,b743d018,c45e5e5d,8f39a966,fece6ae8), -S(cae84567,8cb2b2a8,de8040d4,3b32e0c6,d42dc902,3db4aa,273d24d7,17a85e7b,edca07ac,15d81467,81185e1c,4829951c,2569fa15,3b7e7ddd,22b58ad6,3b736094), -S(5c3711c7,e676ef0c,f889ce6f,57d9f92c,1cd91023,2b6fa410,75fe70a7,ce4b3db3,9b5e75c4,eef0358e,6732b7ad,56797ce7,82a21fb,d13aede0,d563638e,eaf62eab), -S(bade63a7,a4a443d,26d58900,bec36c28,940f4b32,fce20afc,2adf307c,3ef9d71,3c801bee,78daef8b,5cdcd5c6,bd0e63cd,712c2dc2,8e34cfc9,e01beec,b198d687), -S(cff82bbf,2e6412f8,18af5ae6,f9947aef,5d89eb32,cd8e9961,848f75f9,f9e4aaee,c0624130,346ae6ac,e5e76b6a,a2d836f,bb2f07e3,1467b8b1,76af0345,d8f5a137), -S(b3e4bcf9,f9e80edc,c4249cd4,58794fd3,921ac31f,a5f72c7b,e6f7dbfa,29f5c7d8,c045724b,8630771e,2772cdc2,53b2842e,1ec994eb,52296f3,6e2061b8,b32b9d3a), -S(24c22e2e,55f24320,65e91ef3,503bc571,c5290bab,ff95329e,17644e6b,8ef22386,2f91c5f5,6184c519,6f945739,4f101034,fb5fb146,ea61e009,39641a9e,d8178890), -S(29de67d7,edfddf52,6346fbdb,62e87e58,a0ffe4f4,7ca14a47,426238a5,3a3e2188,69dda846,e0620850,ae6d3fb7,1e6b9f00,814a0a59,ec7e94e5,e412a57d,ea4b02b0), -S(c8377575,d34b474c,de02b73e,5cce9eb0,c80c26c1,a925f090,d6b6804e,accfb653,306f4844,da7b237,38adcfc0,3ae9ac48,206cdc73,7c97eb11,c48c7951,52a9cfc4), -S(bc1c0c6b,b6a169c4,10ad87f4,d1f6b25,3313637,8d766bae,ee9401fd,b6895515,7d794eb0,81d9476d,c4d3cf0b,21b99537,9446a6ad,788f0f94,8acbba71,b20df5b0), -S(8b49586f,e4b4f33a,82ddfa9e,e83b7f94,177c1f39,30707f20,95a3d841,bebe44b1,42fe0fa6,14cc26a0,d2608c6a,31fdb1dd,993aa33f,6d32bdaa,1f9715a7,3e11340a), -S(fc52e593,28af4bb2,ae6abd18,8ce99b49,d8cb823b,7c6418fd,8a5f9757,44ebac16,f130072,79a1eeef,5483bb81,2ceb9090,35fd5df1,b757fbe2,679e2d1d,16d5a5c6), -S(43fcee45,79e58f65,d25edfd,f429d89a,f8e7364e,c0f2358b,83772ac4,27ccf626,907821bb,e43827ab,c210b2f8,c984d6c5,def4ee2,5761a9f7,90049477,874ef309), -S(2634e802,fe58e3a,62b9105e,5e37d8a6,f530831d,d4bba691,a6753df2,1482fba4,5d9b9de8,ab3f68ba,1e681048,c67274d,d1fe0cd,4e639454,a2fac6f9,5cdedca8), -S(56f19f08,a31f7d57,2bd94314,4a22245d,9ce74a11,30920573,9ca68569,76b35dd9,b453c349,678dc948,bdf804a8,4f54373f,c4891fd5,7058f1b,43296f59,b89d1fd2), -S(6f7c37a7,b3b96ea9,daae285,31763ca5,d481c1cf,42237ee7,a1ed6554,68de3aff,eafacefc,292a5d0f,b50cc875,ff7c8ff3,aa1923db,68461f1c,de04bb6f,729715a2), -S(59b44c32,ca7c1a74,ca69dbe0,c47f6199,79b997a0,df691d3a,4c7f3a76,9a543723,3ae06964,698b97de,fc3af051,9f13559e,813e7839,c893a0a9,bad75ea2,bc35e302), -S(e7acd0f0,d0560ce7,2d6cd805,d197fe6d,4948721e,b5e4c40c,c2014e78,9bb5c8cd,c95b5d74,5bb6058d,80ec04da,5135d92d,a447ea0e,9154b1d,93a5a014,ae2faaa8), -S(7ffef78a,e04da609,6754fec1,11fbe130,5fdc80d0,3e7b801c,28e23be0,40cb4e97,579c1fe7,54812978,46f2bf3a,57e1f850,ff4fdee8,8d3949d9,68e81d2b,792b39da), -S(5d068102,af4129c4,49c1e749,91ac0c15,dd2a7e29,fdca33f0,84f228bf,f19f5ec4,75f0179e,d77c3cdd,3cd1ec37,3e2d6d60,5425c215,ff009f26,66b8f7ba,77dc07ba), -S(cb90c398,7f6e05ef,ebee67e4,d9725200,eabd14a7,67c10cca,6fc546c6,ca67996d,c6a9a0cf,d18bdee9,8e054e4d,9df247dc,55ed473d,ed372138,cb21ebce,809d3a96), -S(5faaa0f9,63293ddd,83c2a841,6363cfe9,e102c0df,f4af7e81,c046540b,2fa3d653,66548b52,dd344ca0,2e0352d3,f14578a4,cdfd3a32,b410abee,683d316,61205e51), -S(35fc3454,7f04856f,3fd3ea4c,63c07a0d,bc0e6e2e,37216712,5da6347b,3c53b8ca,a4e3cb12,bc29dca7,800893c2,cddd4482,f3334d53,e215fd91,a01c0f4d,45162cb8), -S(ae1fbe74,e44c15b,263565ff,9f578ed2,39741d8,960e82bf,d8788a95,f744bfdd,d711400b,3b458a9a,75e416fd,c4d0efe4,5ba5666b,9280fb38,3d2bfdd5,83a89a15), -S(76f8768a,5ecf11e6,15671063,999ce164,73286582,c4238ac4,f8ef7e20,d1358f67,da94a126,d55ecf1f,8c899678,cbd7e53d,1171d7f0,6d72ffd3,e166374c,58b4f4d5), -S(f454c1f2,b7b447ab,dd2b0308,472a1e19,c1844e63,40225166,e5ddf571,e8f93d52,5ac5010a,1b03dfd5,baf4bb7a,943f0e16,4aa1df65,5166d021,c9db0ee6,abc3f425), -S(3366b897,99dc33d,a1f900ee,57c2c316,d6c2fc16,f71355ea,219731cc,280c0c7e,dd29b0db,9449e2c,7f80888a,783ef223,bc8cf8ed,be82f1ec,c45bbfa4,b054a77a), -S(2a73966c,9b1aa2ac,7b5b310a,bac40490,253f6cbe,29c5250a,dc57d979,f660741d,77359574,39ae6d7f,157723bd,ab2e1181,209f0f6c,fe5f4d0a,a9b0ebc5,cbed1294), -S(3885f7c6,d80f0060,1d60a213,923e2591,f055ff3c,39425d32,43302b6e,82a0cf2f,d024dd79,fb17c9f1,7db519d8,2dd4012f,f353fe5e,c81025cd,deebcb39,65ed069a), -S(ef33a6e0,f5da4ca,904aad24,5f2ada01,a77a93a9,11935aaa,68bd32b2,a6bf81a1,2ba2099c,3af09778,aeda97b,be4c4311,cd3e1636,f2244580,1a9c8ced,5ac81a52), -S(c8b25a4c,bfefb603,34300d02,585c729d,fccf541f,4942b040,c7b0c442,3f8603a3,480ac47a,674e42b3,a884dc55,be736c23,ca69e81,1af56106,efa66122,78214cf7), -S(6e0f7e4e,e4eacada,cf3862a9,8af74f97,99060f9d,73a9eab3,f3db3a77,20a945c7,4bf3222f,eccfffa5,5afee33e,9d39602e,e0ef3c67,870817a3,a9bb5b31,78469272), -S(32a987ef,6cd9c989,aa1d1fcd,5997169,2db6ba4,f4c8ca08,4b1607f1,697b202c,5c4eb708,50a58a74,5b91143d,ea849068,ab8b1b77,6fd2ec80,eef53d60,2cab45fb), -S(1299c334,60ee62bb,68847930,82ce6c49,bff80a9f,4fe33196,7b09a05,b22aa04,50ec11da,9d7a89c2,68bf0314,7b67803b,824b59c,9d496a5b,8c0d9955,31c8626e), -S(ce9f9a2,55aa6b62,a3184c2,8ea5d204,581fdb7b,1945d9db,2c245e6b,4d0b0d6c,c694fe1f,f93ae622,e5816c37,cf581f3a,4832442,d171b413,f86d4c25,ccbf0cf), -S(ad42db1,1ebf460e,f7954df5,3d7cd6e3,a7eea34,6ea8ca1,2ed4d5ce,83badabd,7c0538e8,a29f66e9,d2b3a235,9b00bc42,6809ceb5,11d476b2,38719673,a70e7b09), -S(fadae65c,500d39f0,377ced91,b0a9c469,3db78832,b31b14bd,78996dde,4b764bfd,a4b8e5b4,e398a8b9,90ddaae4,7247a975,2f2267f0,41a867e,e3b0774e,1a692ca3), -S(14e71e8b,76377b2,52b60ee3,f089d612,402ddf9d,92f2046a,cc7474db,1cf56f69,7121d880,5bea69c8,233dd120,f86b914e,cd080537,649b6cdf,74830f87,73aefc55), -S(b15e94d5,5edb91a1,9883f6c7,5bacc56f,2dd2c1e4,950e267f,c4415968,a75d7730,dbff7f2a,57d7072a,4a076dc8,a2d26233,1eff662a,ce10d24d,e3c8ab57,8251765d), -S(e343c0bd,240de1fa,f1ef780b,4922ddc5,453649c5,7a08e9cf,99f162c0,ffc12e7d,b9b65d5,3861e229,777bbb4e,85ea417f,32354b9b,8796bb47,2f6eb67a,2e3d22b6), -S(c3ce72df,4730b13b,95398abd,fa02c834,c5d20e37,9ebce9bc,b77a777c,f9fc3299,ec87a4e7,71c04584,f6dbacd,10fec1f2,c8bbbf25,9954d596,2309f0de,48ed9573), -S(fb70a931,895d44c0,e31a9dd6,bc2a1cb5,250212e0,5ed1f55f,5c668e3a,8390677,d86125a8,cbc9437c,561ec1cd,95b5190,328588be,6bf7a25a,94271547,1fee6a69), -S(b150b153,be5afb36,f6bf7b27,ec687612,265e3177,2534bc4e,8ac92607,9a3ef16d,571ee1f1,7c499be9,89b86781,229abfbb,db83272b,c7496f17,52719c2d,b0812c40), -S(2e71970b,913e3006,84eccff9,aa4c914a,22c6cff7,3bdeddd5,781f68f6,177adc4d,829fcbf6,1ff72af4,6bfe69ea,d928283d,45db7cae,b1b59252,7dc6496e,22a6ffd0), -S(d361c4dc,3df5e874,cb459096,d319957,398e2a5f,337208b8,6053315b,263ed230,5225f55d,49f2d8b,ffdc241a,b54b5a43,b3856b7a,60cde97c,5e860561,f2da2861), -S(3f30591c,d464af5e,ca79c060,7e6a8ca9,c6a2c2f2,86177290,fda65a82,522566ba,fc41d72b,f20b86e4,6be3c20b,890fe8a3,ceba4805,bfc61c7c,66532693,7de90e22), -S(2f6a706d,f5efe7b2,bf409606,5da98b97,86ceef57,36677935,c08e0b8c,b125db55,99bf95d1,b348b522,a1cbfc73,f2a4e692,1836256a,97bcee77,51ff5091,6fcaf620), -S(c8c72176,255d0e32,ce4d7caf,aa9b7467,ff49ac94,34beb017,9883b22a,4254620d,580ea490,a94a8310,cca59b41,43fd4740,40ed92bf,7eb25bef,a87cf930,a974c943), -S(a5d65fc4,9bf06fa8,6018067b,7ade5ee1,a541bc2c,bee0edc5,6a144f0,6be32808,ed70ce9e,16053764,35c0875,5cbfa6b0,d1fe923a,fc9035c2,1d26fda9,58c36ccd), -S(4a6c4b07,7c6c9dec,d7d6f98d,59eface4,ba2fc654,df7d14a6,57f108e5,d3f91d29,2d2a4b3f,1a9aa787,cb747f7d,961c4cc3,cbd62de2,ceada2e1,a71648ae,feadcea6), -S(97d610e2,8b3771a3,204235eb,faccbe5,29d1a6fd,5003d6d5,4b37cfc2,80550354,a441235b,593f0649,ba50d405,fa597b25,60c2be24,2ff43ff8,3b635327,94e67c51), -S(b9f1688f,4161e507,d8f540f9,4294a967,739231bc,a89c7d8a,c54ee365,1ab65111,363ad626,e5ff0d,7f43aadf,5228fbe9,b60efd2a,336518ae,53a0e36c,206d5d0a), -S(1b748bf2,690e8cd8,e06c5200,5a654bd6,38bc62d6,63ce1194,c4bea3e2,82f2c351,db0ce849,96bdfcea,497bc8ef,dcbd6e89,d0305b1c,4b6dac31,4e480b45,a5a9cbeb), -S(ec9d3d1b,3ac0e4e8,c01c8cbc,5d498201,1f52cb5f,dc7dd0a2,6f447457,aa9da7ab,2934e845,ee13267,b3dfbd3e,5d77cc77,214779ba,51bf7f67,ac3cb131,1000369c), -S(1b28bc0b,ac8ce96a,a3d49611,1f66c77e,b030a49b,e9ee788,d8e395ed,495c037a,ad5e12d2,bdba39cf,5efafe12,f7588e5d,c5f2bc82,c7a0ea88,217307a5,c996378f), -S(6e2929b8,1060c4ce,c6b3f071,40c8b23c,48a87efb,9765f292,13993cb2,9c046638,d68c4ec8,ffac30e0,f2642595,aee701a6,5c254247,a1397726,b0c40a77,1060a8fb), -S(122307d9,313a11c0,e411e78c,d66bd2c4,5aecfad2,3221b558,d124674d,1c66489b,f5713161,cb284025,efa004e3,a70f1374,b1ec2450,78f2252d,6c7da11a,ddb5ae11), -S(81df90ca,92efd148,9383a7d7,c69d4c4b,bcf5b781,e59834df,9ca30da7,cbfa1ed,fbe1932e,421a7a67,30e4a7c9,371ee8cc,a985fd2b,dc1cd465,769ef494,b0c8d6ad), -S(fda38e5b,f685c939,6a2a71da,b66d02b1,a1da8953,c659c880,bd201879,d275a01f,2c729bbe,39467247,601c9b48,80dc7ba6,193f8270,a742ec1,5076da82,65db9bb), -S(45aab7c3,69af7188,9986b609,e16493a7,38a255a5,d4c27a3d,96888275,54bfdce0,4a512b2f,77c0aa0,e5aa021e,2bb63904,aa7c74aa,daf424d5,da8676c,e043fcf0), -S(14b463dd,57d236da,fa835f57,6c4cf514,73180d39,efec4d18,9a9cd1e5,91df4f57,ac3bee1e,d77fb0c4,3cc852e0,90fdebb3,1bd87006,7129210c,9334beeb,896e66b5), -S(5a8fd8db,833621c,e8e21f81,e2f30db8,2a98e6e0,8eddb80d,6a2e63a3,fd7da2bb,6f6c8e76,d846f5bc,b53a88b1,349b95ed,34239991,1e552740,1e58cbb3,bf42c8e9), -S(62b727f8,6bf49290,2600e83b,5a24974e,c35444d9,92c2f083,7bc4dc53,d3ed119,d7daa7a7,b8a0d462,598be5b1,6d36aad0,c07aafe5,600e3955,81c352aa,d6135b21), -S(1cfc0220,cb0f64b7,51fc05a7,897b3840,fb2a1c33,777fedf4,7ebb4c9b,e6059ee,d3a90002,d2f8c20d,1174fcf7,8591ce07,5e2b34f8,83d634f4,7b27d5c4,3680bbfe), -S(89efac24,9b798548,2c3ada7e,c7792632,fe872f4a,b6001e7d,48605b12,cf8cecd,a5d062a0,1e40b4eb,de2e10e6,684d9b6d,2b860f65,9cb6c51,676ee74b,40e5f612), -S(cbddc8ab,e37d0494,cecb4878,cb0bad9d,da00c1e9,c0876437,3405ec56,2318afdf,53ec167f,d0f1123c,3ebb9cac,476c86d5,94762b5c,7a365153,776695a7,169f06a3), -S(d020dfcb,c5e78a1a,36e1f8e6,3530d03a,5b53e1d5,41d05a46,d4e24318,706515d,cc811700,740dfdab,752f818a,cee554e4,d7e142bc,eb5f6e77,9399e160,c7646048), -S(2430846e,6e768e57,d4776cda,448ab651,c876cb6c,aa8fce63,34cfa4b0,826a0e25,9bfdb42c,e711af1f,a0cfeaf5,8264cb52,4d4d9eb7,a9fc1328,4351e209,8818c559), -S(7d3eeede,5d8e3320,80d0dcf6,3a8c6929,4951e765,d881e0af,febaef73,bd9548af,a4b9e695,85b2921f,fd651eee,e320eeff,52df838a,17efeb60,16d5cee6,d4475ca9), -S(4bdedbab,af06488c,28fa5a7d,ebe15b63,759986bc,535b4ccf,66f28e8a,1126803a,e4ad8238,94741e42,c28b330d,16b16d40,d538d081,41f0a5c,92890934,e3c09dc2), -S(65569131,959b4da6,d2b52217,9569e44e,cd7e7ca5,515ffd71,fb4b3444,246f925a,87049181,3adc7c36,9bcb7696,f90485f3,66beaf52,9cd09e04,36d51cb1,6e84514c), -S(7df015c0,7404bd5,518ef8c0,1aa4c5e6,8773800f,fad367c5,5b10254,45e720b,6e936006,2fad0fcd,a52ae9f2,bb7e3f5,ad0ed702,50e474f8,c4e6b62b,93885bf8), -S(90eda060,55bec90f,ae0545c2,30fe67de,99da2fec,f158aff2,ff4c8a1d,419eef9a,c5a0e7fb,f8f5f20d,25f09076,6a8741e0,5e7c49c9,c6408dc1,fc02e84d,79ee165c), -S(b36d9a3c,1a6c46e2,fef6dea2,26b1bc6f,e957849d,d11170d6,25746bed,bd3d2846,3ad18694,f8c0e199,77d0a56c,161a71f2,72d9090d,96a376d4,7d6ee99b,5f3ae29f), -S(7fa2d360,27f7a698,e5e4dece,16f7f78,5878ccbc,dec5f03a,8041805a,609f01ba,2bc2c266,d8d013cc,c215e3cb,8afc5b8f,254b0656,98281044,8f946d65,8870703a), -S(fd314b51,71ddfb60,16f3dc94,859aff4,5b01e7a5,5ebb3c0c,a2ef8262,4c41fd08,28539bd3,657ce721,4f6d88b8,f8f85565,996ec40f,fdce88a6,5820a8f8,4e6271f1), -S(6e37f52b,ab64fbc4,a22cc014,b81151c2,623069a6,6c617fec,f8d32d25,38e23f9b,fe6910bb,2e2e366f,28ef13db,183bfea,924603f9,58847477,ebf816e4,33cbdd34), -S(31ee76c4,de143395,a1d99eb,98e8a579,d88b3450,69ff0b82,8335ad2d,72dda523,155d6f31,9548c9bd,62cc219b,db6f95cd,23295ab0,253e42b2,cbc34fd1,775dc0dd), -S(947c2b1d,604787c3,e30cf04,31fa2b4a,7d823c84,584feb3,5f68545b,639df62d,bc50bcbc,dc6e530c,45892e31,d71f719a,1d515060,ecb123d2,a37eb89d,45fa682a), -S(8a8349c8,46a41e93,fa097893,c4fcbd1c,7c25e3a0,afb17929,72a7a872,570e5abb,fdbfe661,fc2940e4,b8c0fee5,7245915c,7f8c9ba2,1f548bf7,d5c654c,785b94a3), -S(7733640a,13671b1e,eccf3527,3cb9ee8f,d79cd08,ea57eacc,97b39bcd,6ad669b1,7ce5c5d5,abb13079,486bc91a,ececa9d8,d0d1f84f,a5d74e57,e4727db8,833f8c05), -S(a9ec8a22,7c262bfd,f5b00b9f,1acc80fd,4f5d46f3,d24d59d6,7c2cd83,3be94a38,f0d9bb94,ff97aaf8,54b3640e,7926a99,8a731a5f,4800c573,d1279d14,5e4d422c), -S(9837810c,86ca85a5,ffcebe9b,714d4b1e,f5c0ab5b,2650e163,d62fc668,204aa566,bc477f5e,ff56a588,bc68f7dc,42644fea,532d7a25,3f84d17a,9ef7a91d,5f3113bd), -S(9020fe03,9de18af6,61b70206,5b615ee3,de3ea6eb,a8c30d9e,24d4bf13,56db96dd,3a0ac3b5,d1832113,8421bc8a,f978771c,53b98110,6c49afe5,711b4b54,f9fb8567), -S(d769695f,f6f22d11,99224b69,f66aacef,8c6cc911,e43fddf9,481b46d9,97a2ecf1,e8f2a6b5,f05be025,a84fe0a7,23ec54dd,b21c32b4,b4d5cc89,5bdd8e66,d8ecf934), -S(a7668280,48ab1e2b,e843b0db,7a9462ee,3ff0a5d6,f7c12ce9,496b302d,99a23042,42a1296,92217f3f,d7de8cb6,df48b8af,11d8d089,5c93703d,a242c7be,d8033dc3), -S(ba26a7ef,1e0b979e,3541227f,2dec3d6a,7ea6f8b,9e9b46f9,93c02b3e,fe1d9611,b0d283fb,1adccd83,be7122b8,b59e6d4b,589204b3,e96adb4c,a6e19ec0,ef1c142), -S(175ba624,70d63d4f,6a3a030d,a1515677,8e589e8d,80ba62d2,1719a906,68293971,211232fe,97508523,4d0dae11,14831009,229fb25e,51f97182,476558b8,adc218dd), -S(1fdb147b,860c3254,b4ae5513,14839573,da2d0272,be69628f,1b395a03,bc8afca1,b42d0b99,325acf05,a3564d77,55cf9c9b,3208e5ec,24e5ef12,b6180fab,8b3f4a4a), -S(986d3acf,c5cc74db,c844c28e,d91276ee,729a5588,e1f504f,1e6f96e4,a7a21607,7229d56,4a9dd4b4,79f8d8e,17951887,870a4303,53707369,aa8e8d6,deeefce7), -S(39ad0832,b18dbfe,1fde87e7,c5d3b948,75fd76,9941c2bc,d605f3d1,beb94e29,f85bea41,f0c36603,8ea8038f,874d612c,43b928b6,4116550,8878515d,fd74b6c3), -S(3a318109,745a25bb,c6e45068,ed37553f,b2591404,3a7dbfc3,9e67d1e0,24bb2f12,2cd3e0db,d2545332,e4bb3e99,8c338c8b,66fc5061,81c6595c,37804541,8c507a16), -S(617d3fd8,87b99438,6eec49af,4358e73a,bdf52dce,f26ac8a1,52be64f7,e0e8b2ae,a45b906a,45c2207,e4db008,e4fa961e,6c483c24,3c0d7fd6,b11af11,e5f8b444), -S(d1171cb7,e5a3daf4,7b7818a3,2fceb153,58c87d4b,84488cc8,1e930bc8,adc467ea,bc725547,a2d40dd,8d8ed471,1869d711,38118b5f,bd00f0e8,3e1967b4,880da3c), -S(61f610ef,de8aedf,f012a109,5e5ad596,9d06ed54,214e6f33,c69643ac,50df0ca3,405ed3cc,5ae1b566,fcd069f2,e8b67520,74700b94,689eaa7a,3fdacdf6,a798e091), -S(8caab88e,e5fa3cf3,59a8ead3,2d80a4b7,b57453fb,e90a75b5,ea9e4f0e,5ffcb7ca,8b7608f2,c7480114,d8b04bc3,7f089f8f,2075fd9b,5b4a49eb,bd0ab1c1,8ce31a9b), -S(b73ee255,bef7518c,12be7d6d,36314c8,3fcf3c7c,5b0bf2f5,3a1add92,82bf729a,716c6c00,5a82e1f8,1f493753,f4e2527b,99bfd9b9,988b5e94,f7652ffc,6c32b7f9), -S(ca72f63b,ff6ed94e,c1fc4f3,427e90bf,a16ee627,b9112358,1620c156,6f95c1,a554deaf,c8bb3a56,d809c044,49efd477,7d083da5,690ba56d,2a4e2679,71d6b0e3), -S(f861644d,d5693cb4,b4a8256,8a5297a5,595a64b9,5f9744aa,683dd91d,8d58b301,66223ae0,99284fc6,ff5bcbdf,cb0bae0e,cd954610,d4c152b8,b979b08a,c4d4adb4), -S(ffca4bc9,b9a2e17d,250d4357,14c882bb,7e837054,4bee35f8,818e696b,7a7c2c17,4c57c13a,e3d97da4,8644c47e,2cdc4d15,5f6add44,5544a853,f8e46bef,271399de), -S(c36a0163,5935ea3b,f590d4b4,656cbe2c,2e62d8db,ddec2eb9,ab867de,8d9dba5d,d9ed3116,dfe337c1,44025ab8,e607256b,f870c4bf,a885bbc7,3ece4b29,ea6122ac), -S(bfa4fbd2,c9fe8b16,9520ffec,277fdc19,cd53dced,1866d5a9,404cf89f,6141e4da,f76e0423,4fae8abd,892368eb,e48945aa,a3684136,aa5b7a0a,d85d0d07,79af3ce7), -S(fa7be3d7,db544548,45d4bd1d,43c7960,89aa1eb2,4c0f81c0,16645d77,83ed508f,b82cdfcc,4df4b465,4c95530f,d621435e,8679aee0,9918a06,131775be,8cf4e324), -S(818a90d7,5939e32a,af92c601,af9eb717,88443e57,b7759bd,9e7e2be6,238a699a,c951ef89,8127b426,1c7d6224,377fe63a,2706636c,525ee10e,30e11a85,c160b50a), -S(ede3411,d3acaa0b,650aee14,29f910d3,5ffd5684,eaba0280,8971f2f2,330e2880,8a2d5c96,ae4ce2e9,739ff957,c595591a,63a58132,10b86a62,bc4cd164,54b8bc7a)}, -{S(dd7503a2,a3e15e7,39eb9b1f,856d6e33,be4890b2,f40cfea8,1bdf516c,b942731,ca9cd04e,c3789ab4,5088b819,953e08a0,b8adb8b,b2b6f7c8,661a2d3b,83a54c77), -S(b0aafd22,9e0fb326,b5ce8cef,578803c1,da2be933,1f47b343,370c2e22,18bde7d6,570b1e28,a519d9a0,2f9d06b0,6637bd8b,6c7f7e51,5a7c541f,7263e05a,87270081), -S(6d5417c3,2d66d6e6,a2d2c599,366ab000,99cad0b7,55f8f3e5,15afc018,98b9efff,786eee97,bf1a1c9,a57de5f4,94be0a29,663b08ef,5162e971,50dc240e,59d9d489), -S(9c64eb60,9a9469ad,fec8d298,50a08f7d,d4e99710,37c9e7c3,7eab2eab,cbce5b4,60569102,1deb5b10,705231c3,e29dd6e3,b613e6c8,eb313cc,68fd581c,eab98ac3), -S(d219f302,cc6de5c9,8360c088,881465e,22fc572b,8217734c,742231b4,ee487bee,89710994,239f6120,df848623,489173e6,f337c99a,71fbc319,75e768ac,43cdf91d), -S(792810f6,6b9cf54c,ebd8ff1d,159f966a,7da61fb0,34651402,e878e5aa,2b044259,9d2d44c4,b52b24b0,7c3dd127,43fb81f1,e96991f4,53c06839,cd86a2c8,faadfc68), -S(c9913dd5,bef25d08,327d7441,b0793f4e,e3e89b5f,15cdfb3,483f8663,3644d75,e6f5b61c,6beb820c,64beb375,4d80f3f2,6e7aeba1,f4a490d2,e6dda2c,b3131e24), -S(a836402d,582230fc,bc8c944f,18d5391c,3c934e1e,ae1a5f6,2cd6ce3f,b454e6d4,dd8417ac,a9ea2e51,13043d8d,10c8be13,e48a17da,e1d78f84,da4ca58f,d07221c7), -S(46b82270,4a808581,f9dd6d4a,ac7cf765,90dc3308,dd54a6f6,3d4c49d7,f5652310,1e8ffdc8,a786fb63,4a56eecb,ed370af5,9d6300b2,cd05c1b,5bf28d4d,69e64c9f), -S(eb25a657,ff10f29d,4a0b336d,feb63364,774f28ff,8c6eea04,25df2e41,1cc8c49b,6547a11c,9cceffee,5d43a330,69034c93,94777b74,63c1f774,167423c3,2b53bba9), -S(d1548f7d,b928ce6,86e8e71,c0080731,3a1cea63,838c013d,5d52fda0,17af443,b15384ba,3d62a403,920b6936,54c30a87,7cd359a8,2b63f037,64ac24d7,2a8fa367), -S(ddb36d9f,c6c6c026,6c79f2c1,50eebf46,36737eca,d0091321,c1b293b,52837cd7,8e0cf327,fb2f9548,4905200d,1111da22,aec01189,c8db56b4,6680c03f,4d938f29), -S(46737d55,d4b1c924,c58e100c,161206f5,84e01948,22853e82,e641825f,4eb1023f,4374a770,809a9424,12e75c89,75b98345,48e6579c,8b4b1314,29cec398,6b2eb00b), -S(35772697,7312b547,60f2db9f,443d8165,1cb1fc26,dd977dae,3c659685,7330d3f6,813075b9,d73fd95b,78a9e1d8,a9f24595,98b127cb,90c942a0,8b451e71,e40ba38a), -S(17bca82e,46ab960c,193dab14,7eacf706,4326205e,7fe4dd6d,464d359f,6a0f4229,b882798a,dc357f06,4a98dc47,2eb3708e,26cf45ef,48f28c9d,11456658,1e49c7fd), -S(e22d5891,b992aba4,ef31503d,bb64d447,1cbb4013,86f69d10,37770b8,7c04f855,af5fc7cc,3e92b04b,3b61297e,d7c66dd4,47b81728,1f455c43,bbfb69dc,91396744), -S(3960875a,16521b2c,89c87efa,c0ef7a5c,7a1332b5,a84c34f4,4496c57c,d5c9af0f,859ec9e1,f08de5c6,2fad60b7,18533a9,d18cdc9d,91174ef2,c3eb0653,f6c3e5b6), -S(96e92234,e193254f,5629fd37,aef039e1,1457988,7b18ca19,a578bbe,3a23826f,afc02da1,3693bd69,738f991d,9d2e9b96,afb01e67,b05857d2,3054a7a8,85d55f44), -S(f032903e,40e7c8fe,fbf79c7e,a4eec837,6193c3eb,cc919ef4,ec867909,42c8188c,1406b7a3,f9a284aa,c0d48b95,47d0f934,2b6d3c43,4c6b78f5,4b1d9bf2,ff7a14a1), -S(59f8f5e7,1bbd9631,ec5e86ee,e78dc60e,71c74037,db8e32f,4932ea11,9a153973,7b72a4ae,87d78ccd,3758f961,12cd4287,d18e4cee,7abe996,d51f3276,aa28a3c0), -S(8f4c4baf,36df38ed,da5cab7a,90b5d3cd,fb7a6b85,bb000440,35d88928,27b811f4,fab6a3ae,f7d0d7e8,a45367d0,b1c9c4bc,9b6ecd7a,f6739401,8659560c,8d1e6d8f), -S(f19b8fe6,a84b2993,a1af87e4,313208e0,ba301270,3aec1a52,8ea60bb9,eb97333f,d8610a62,ee6014e8,b0eec123,c6b68ae4,62b0be9f,c79788ff,631f7a38,f134a74d), -S(a382dad7,66c4cbe3,336f2a2b,a11044c,31f5de9,6a1fa90d,479baed9,8ea9eac2,9f7b4cb8,c17383dc,ae9e8e71,81cc9f77,6823626a,f8da9b87,e5773edc,9fbb8a67), -S(337af005,48b956ee,58867d93,d230b0f7,313229de,4adcab17,55a24f02,c3c86210,41b3267a,48e288f6,42ed4fa,357a9d84,f77b1e5c,67a6b20,8e8596aa,40ff3cc6), -S(48e35721,f03fcee6,e50f875c,57fda488,75c6b2e,1e0f71b7,da97866a,de121d49,65070589,1a1e0a5e,d2df20c1,bcaf00f3,11b08c8c,a161e1c,7db290f0,a24c1a3b), -S(2db6b295,1a20b609,819d9e52,7d7bbfa8,d47a11a1,33a54de1,49e2994a,ed25d800,d16c6aa7,313723b8,e9c49f8d,66b0e9b2,6ce3ae04,5f1da4f1,355c02c2,4c1685fc), -S(2024d4ea,eb5c75a5,d26263e7,7803fcc,77fbe3bf,ab6106d6,ba134f6a,18e2794d,57bd2c8a,5c3b8289,d4d39930,cf2092a3,2e9b87b8,f8155eeb,65ae9b88,60b92159), -S(3a7aba1b,95085b3,89b07280,219011db,10fad2eb,c003f17f,2576f166,4c0f733f,2263ef94,65065e4b,36ecd1d6,e77fc8ee,2054103a,28434207,e02669eb,df00e444), -S(d476e308,a3456bfb,3ea08fdc,357addb0,3b5f3102,248e63aa,20b8af78,e5e27566,827fb49f,ac326d69,364a3ed5,f87e3e22,297d752a,8c77d399,7c6300d4,3358c19f), -S(b98a3bcb,5ef6e7d9,c7bb8fac,6d5de4d8,c9770950,994dddfd,c0e5567c,bcbfc6aa,c2e6c22e,ec6e855b,890bfd97,b916ae1b,d7f38a9d,51f1ddd7,fb11c44a,5ec058ce), -S(95af1e4d,e478a281,46edbe66,972c1672,815a12f4,eb975fe0,ecf7f988,d03bdf8a,9b5a9c50,c9616d82,98f43a56,62ed85ac,bae447fe,60985627,b6df1ba3,7600fbdb), -S(eaa4b025,2304fdde,1708446,df75b2b3,2ba9754b,ad68af41,515f5228,91a2ca3e,7d04324f,2a522df4,c8686ccf,52086869,8e892ec6,aec91b83,b6e460d3,b0e39d23), -S(113a2818,f9099722,36d3eaaa,14d52f54,27592ab,b924dc45,d6ccf5b4,a02094ef,8fe91af0,62011fa8,cd0f6ede,c5467c8f,d8bc8043,f9760d9d,14c31fe1,1fea3f1), -S(bf5b27b,81d5bc7,ec597a53,accae88b,bed993a9,fcb78a96,d0fdb750,66f90baa,7d7f5fc8,7c6766d9,78a359cc,5a486844,e62003fc,7756ad34,3b5966ae,cd9d7bde), -S(42d53197,4663cd32,c80d71d8,15d3655f,f4e8911e,971a53f,9ba1758e,79fcae1d,87daf2ec,3cbccd53,84bcc89b,9668954,a73283fb,5d5608a8,5746ff2,de26a528), -S(946a933,98ac78bd,a3f92424,f6bb6383,ef7ce19b,2912457d,b26e7654,f25012ff,ca7d7457,b0a52c33,4656671e,c6e68e70,b283df8f,7a033a21,7f013cb8,8259df8c), -S(1c53769,28cabbe6,3b6e52e9,a7577c54,53cf4071,e1050257,6e7f4609,763d1285,95340099,49a53bd6,44045cfe,6c17053b,7cef08e2,6cbc1975,c2fb203f,7810a4b0), -S(c31bab3a,c9cddb5e,91a69aa6,95545d25,5550a6cb,ed8d55d8,faf94523,4edfc242,2786d686,771c3e6f,a04ecb04,cab881fb,bebe70af,1c83f7fa,1fa2922b,2dc62e0), -S(81df0d06,1f3519d3,3e8f7743,8b917498,6ddcb6d8,cdeb5bca,2ba03fc,6d1b2bf5,183ade12,f68baa5a,c702b5d,2ada2794,bd038524,63796f7e,c885b5fa,96dd92b), -S(3825dea5,f42fc36e,37367606,1d8c4589,48aa11a5,12449590,22cf258,acc068d8,b6286350,2fa61c64,9ed1f3f,d64cdf9c,bb882d2e,82723e11,73628333,4c2354e9), -S(9aed85ef,5bd25a21,46007433,b1131528,6510ab0d,7918224a,dcb81585,ebece06,73e1712f,d6b3d56c,53bda6fd,acdee776,aa87f994,71c8cf28,17c05fc6,e5512bf5), -S(3b4c21f6,c0a815f5,80a75488,5b02087c,eee77de2,704b1661,d2c42329,169ae892,997bc30b,1e5ec3eb,df3076bd,d7ff8906,322c229f,fff17b5f,51316dd0,4778f062), -S(bbebedba,d7fe330c,1e50de77,62dafe8b,70cc8cf5,11c44dcb,1cdd55ba,82ed870e,27f2dd33,573ea340,355f9a9c,6cffe63e,44108290,f27fde3e,7c934d52,febe1af0), -S(babf0cd8,58f49844,5902a704,da20c759,881df7a7,27842f98,f3ace994,1937a7e,8b05b19a,62a9b997,4b0a9668,d598c929,c4ec6493,6015fdde,c134720e,fcb32081), -S(a420c65b,33426f3,674a5859,cc16d583,96b3c325,22fd2dbd,3ac9e179,1e5bc48d,695d3557,787ffb5d,8e69293a,afa250f4,6a0bbdbf,7fae0540,94f43885,d92d2544), -S(a31dd94f,9fd72006,abb783f4,c9c8801e,400c4d3c,f4f81906,d853fccf,e3c1cf77,8b49b9b2,8c513ddc,6f31577f,5a576ca9,bcfad648,fe0556fb,30aa3dc8,cf4c9ee4), -S(d4ea9865,929456a9,20c3a461,c3931efc,e73479f2,e63ae5ea,6e1fc227,1bbe518,f214c3f3,844daf1e,8aafcab0,89e1ddaf,6621ab0,975346a1,b04642b0,9a5be061), -S(995c4191,bb5b5831,e32ff6e,6be060d1,339bc41,50af35f8,e69b03c1,3ff55505,a4c0262b,d585aa19,26009953,34f83f21,951dc3c1,a5b9cc12,c7250fd0,c8619259), -S(77ea55e7,8d08e3b2,233db269,37d1259c,ce4acae,5989d056,d4bb4bbf,a7ea1cfa,637a160b,ce9307b5,a21985f6,6bd9c4c1,8f0a0679,3dc6c5d6,d491a2d,ea034f50), -S(f42d8da4,9862d140,30c9e4a0,5349a650,166d7904,97ff4a6e,403908b9,d95293ef,c1df830a,2e091a6c,e65f4443,f7c5d51,86838e07,dd90b0ee,f90b0134,b181b30e), -S(10e6c84a,53be364e,92542b00,2e5303ab,d93507e0,5e3699bf,aa865838,8df504f5,4f191ec3,974d9a23,28443d0b,a6ad8ad3,4a04e06c,608d15cf,d3b50d54,70d2fdb9), -S(2f27eea3,7a95ed63,f1a1c228,4ce37d72,a8e116cd,b5555f10,52307156,818b7162,ffdbcfd6,4b71c526,5c19b6dd,4fe9f0fa,e993bd10,a727384a,84807308,7588fd8a), -S(4ca6d0ee,294e7961,b9716d8,3d9065fd,a362dd0b,1ee95784,3e33c27b,464cbef9,6e37c568,801d5be3,7bc240f5,908229ba,bf7f44d3,26591bdf,58ddb69b,742b417f), -S(17e3a714,cdfa9919,b3a2ab6b,faca1a98,819258de,53877067,84bcbaf0,8e38e807,4422fc06,1df9484,7163efe9,f6a75626,f1cb4db1,dc563dc6,6250850,99a2d1cf), -S(86db66f7,2e0897f7,5a78295,45ed56f7,f94dabd6,c3ca13fd,4b715e78,24778889,116731bf,d85bc78b,277b09f0,5e341374,7ebf0977,587ea430,7e4fb0e4,b3c1d864), -S(5a67a2dd,e738eade,230815c1,cc2e259d,9c0e750b,1d42ee3,c4636368,d2add861,9c5b305c,d9dc561a,ef396711,faa7b196,b149f7fd,48c7f608,13d96ab6,1c23813), -S(bc5e682a,cb10eafc,319401a1,deaa5a8f,97d8b1d0,d65b847f,fa396df6,5f2d3cd9,bff7f649,3404076b,1c978bc,22b56cf,de56a233,414bf112,39ef0c2b,ba8c1c4f), -S(55e25010,b08cc417,3062a4a8,20b00001,fe53546d,bbcd0c86,ca21c3cb,22291201,6ba72697,9becfa8d,53fcb128,f3193f8f,74a99a7d,82aab685,cfa1fbac,8f1d71cd), -S(4b53215d,7c5d43f2,ce8e109d,c98d2f5d,af1ba4f2,7a713d04,22253cbf,c9dd1f4,2e96d,bc79001b,64a12093,67c36c77,dc8cc188,b9f632d1,56bd53a0,462bba31), -S(8d71406c,8eba2f08,efe9a88b,72faee9a,e149c857,d625b710,c443219f,c2e24997,68aad2e1,dad539d9,dcfd641f,be7c1ea9,d4239e2,e881e6af,57260011,bcd0d61d), -S(443ff7d1,5f92816a,7e64e005,f0fed100,efad65eb,cfdd7e81,a6d4df72,a2a91932,3be7e0e8,bfbeeea0,e15f1a4d,cd9b1f7d,85d519a8,1215c2e5,319db187,5d3c5c31), -S(a3081493,6d7359a0,bd8b0adb,78b79ec8,388f783a,f02b2759,318b0178,870ef633,5d89f521,e1029655,432a688,aceb1beb,ba824618,f9eae95e,ee0f56da,21364207), -S(33eb575a,aa3d6ecf,eba5869d,b7eb1340,bde18656,3ff4c32e,bc32793b,4bf50129,296dc28b,b33aa01,684894d4,d2766575,d420b02d,6cb23152,79b370bb,8836181f), -S(4c09fb9d,a61435e7,9e2f9faa,37cad82e,ca906e27,f5d17d,da991e54,e7650e12,1c3e8af,ff50589e,ee448778,8157fa7b,570a9063,d76e6eee,df6b8d98,140c3322), -S(8c0f258c,9162cdcf,9d60168f,bd98b995,8fe2c59b,fe334b76,2b05d397,8ca4cb29,8f04e391,d6abd5b3,1c3de519,2266acfc,c3010617,24a204f3,f209aa49,96ecfc54), -S(e7e0ec2c,d18151bb,7d46c17d,b34b36d9,c38c0e78,4d6c4a53,5661ff13,7de3ea5e,b569bbb6,35f01a5e,c7e3011a,95fcd613,357328b0,f589c77c,a49550cd,63ed698a), -S(33466e36,f172c0c9,41af8635,80f7393a,21111ca9,9962be43,c96aa29c,6418d949,e434328b,8b94157d,72f0329e,7d8497c2,a189a23b,8b663e5c,c6a6431,3d9cb1d2), -S(74546f84,2d5f2f0d,56c6de7c,e25dad70,47664eff,8b53139c,2101b450,ffb7e83e,72ade537,f344465b,349412b8,c5a52396,b811b3c8,64b693c6,995b168a,3d52a146), -S(2a057c20,49eb78fd,6b1e101f,f1ad93ec,237c31d3,b9eb5a61,cfb9707c,10aa3fdf,12f3ed71,9ef62004,29e31f76,50d42a26,3ffec21f,18618ab7,a1978341,34e628f2), -S(6ef7e589,77b46681,18725285,d6a80278,af326e69,37a1a2ea,c38db58,5dfdf391,7b7f2f2a,61a36fa9,92c25c9,de3c375f,1e653426,21657b1a,46e73afe,185293c6), -S(bb07cd89,749683c3,d0d1822f,b2044a0d,89295a1c,489a083a,d4e0d686,5fdda7e2,93217977,cd636dd2,5dc61a32,278701db,488d4b0b,bca43fda,5f616ed1,bc853e67), -S(86a512e6,6aeb62b4,a3f0e3ff,b3ab705d,55da48e8,5c83fcca,8bae1ed2,c7c310,69efee26,59130cad,c307d137,348dc40,5e797bc3,c0e08888,19381382,7c9b70a8), -S(2e98a430,bcbc702e,d038c769,2d0a18a2,9e68ce5a,33297dc4,d0c6b344,55141fc0,ea01fe68,7ef121ec,d612d3c7,95bc2b4e,aa8a79de,a7a6421d,6d0ca841,4364a8c6), -S(1e94d53d,8f2efb80,fd5f36d6,48517bf,a81f5eea,6e6cc95b,125c0f4b,7f6b544a,4c6da236,bdf33222,7cabe303,ebb08be,5d72cc94,ffe09f83,7f89050c,250055cf), -S(8436f6c,1c597134,be20a252,3808f764,a77cc015,92e2c0fd,d99af978,2ef98f0c,5d088601,2a449b15,e7ca98cc,b12c14d5,e56dcc11,21eab5ce,8fd64442,735202a8), -S(dd438a23,a4ba1fa5,8691429d,7a20119f,26b998ad,bb041770,4fbb7603,7fc939e5,c371b95e,1d2db347,89ae43cb,ad439c87,c75d9cad,370dab9e,771ddb8f,f50fee46), -S(a50a202d,dcf0fa6f,270ed4b4,47ee2d09,55aa5ff3,50bde518,b5365807,5e921a1a,13357652,4cc6d018,e3cbae93,d87adf36,15a518ca,9421d847,92b9b6a8,fa45b5e3), -S(7dda8de4,b278bfd5,3b7d4573,1c3df0d3,a32c8459,37dbfd55,6176c034,359b6054,249585e6,a11e174,ba72b6ea,cf02bc58,f53ad9ea,131f22b3,f273a38b,2ea12e71), -S(8c34d5b1,77080808,84081f8c,f36340a6,2526ad47,8402301f,248cab43,c59b510,d3370606,3ac61796,a8b55004,64e458c6,36c6fae0,ac4fc255,b99e03a7,fd39679b), -S(f2af02db,a23f80fb,26dae144,8c01030b,7dd11c7e,e670731b,5a3c8d43,cf70b3eb,3b91daa6,e360244c,ecd16f73,ea6b2ec0,e2bf1af1,1fee0530,7d031861,6df7cd6a), -S(f52e29a5,fc161198,8ab924dd,300a2063,eef50892,c8aab719,989a7c57,c61b5472,c8d317a1,e4bd73e,1520b519,bf5e99b9,537d4014,11554768,ce1c8d59,dfb6485d), -S(ec3bfc26,168616da,7521601b,8213cac6,ff0525f0,bf1e9480,bf74ca36,5043aa50,b85fb266,cdc767a9,9256a2f8,fe3d5f67,13c46dcf,db0e5668,c51e57d9,e40c68c1), -S(2606e785,bb3bb8e0,e9509d6d,d3f13edf,cb945c27,4b170b8e,f0a1049e,c6324d,1eec7f74,981f1afe,b519e261,a9459140,fac8c0f6,798c4bb0,7402b03f,a9f9c4d7), -S(643cc5fe,b10472c1,b7767be3,3d089e97,6e1dae65,766f64b2,13ca7308,fb1a859,4001bf5f,5b1f1152,41c0a5d7,7c402f58,81466079,7217151d,ca52167b,98cfbc6), -S(7af91d3e,31685c25,e4665b8c,60857fb1,a9eebfbc,b119995,bb30886d,49fec506,ef793e78,d32b7dca,50fd2281,76e9deda,fba1ae5c,51012a9a,5e0f11f9,efa36d02), -S(f92595bb,ebf4e875,5a4c090f,cc7479ec,e36df57e,54d02703,77492a59,695dff86,3d693004,acd31ed3,edc6b849,f0276908,3b62f97b,ffe2ce1c,f030bab7,8edf42c), -S(56d8be78,ba1b90f2,f1e2bdc6,98676605,84ef5cf2,42061f99,a372b8af,3bb81492,37346441,7138d5fc,827ed55f,7342e423,b3413d18,a9450670,bd9f7639,e3f7d1cf), -S(5e72a946,f62a82d7,e1a6bdce,d4563e4d,d11ade3,630c48e,e7dde8f,4431cef9,f963609b,37e6e3a7,647bf3bf,370016d8,e6db7c3,18194eac,b8abb926,1f4a6483), -S(915889dd,b578d98d,b96c9d55,e6d10bd2,85448210,19ad5652,5ac888a6,11ebd12c,fc5c61d2,2b2a6235,51af62ea,56e53daa,a4ba1d57,e1124834,e0c3e547,da8a00fb), -S(eb8dbbb4,b11a53ca,4b00a8f0,6bc5d957,9659ed80,df9556e2,99d77d80,1372996c,3f7d9ccf,b1229e71,fd5d3193,4af913d5,e645050a,91095df7,e9703fc7,5552129), -S(11d9d597,213183c3,cb33f43a,36289f32,94fab62,eb073b5d,9ad2b71e,a1a4475f,80f85384,db3424f3,707412a3,6bdf4e67,4adcfc0,4b2e3957,f9ea2e46,416d85c9), -S(4bb5ac37,b29cde8c,a1c39e5d,b3d75401,26617089,c82b5aff,c61f8122,1e5fa6b9,6345048b,ffa2f89a,4e008daf,91784b02,5bddf7ba,3fbd5357,ec1f8c04,f8f9ae5), -S(542f585d,616db634,689e86e0,bfb7b3f6,58fbd6fb,83d0070c,bb13e85e,17e1f793,8858748d,b65083e,9946ba84,3c842492,475e508d,4bf5bb08,6259e5cf,b47757fb), -S(518c6d50,6d72aaa0,ada7bceb,11e1bda,bc0cff3b,2008651,fc50eb54,cf4207fe,c0415146,d6bc2c5f,9f5bc476,a372c8cc,60778f04,b02d580e,64d37a9f,5380d3ab), -S(92931216,496359a8,4a9f2efe,f2032335,1588c283,3f9055d2,d107b81a,7a689f61,3070db07,ccce7e90,a9f20897,fa4c7e27,fb86bb5b,2b0a8a2b,a63e555f,1fade8b5), -S(e9ee9698,eb0f0b82,763be736,798cc34a,4d290a96,db7cf297,7d067d0a,3989d715,ae81b62a,52d7ef27,29fd82d0,1c0ad810,bdfdd46d,d8052126,52b76eea,ac196035), -S(8c8d5876,6f4419ad,5015839a,4c7fb487,dae2c7ae,990a889a,af2d6e88,81a3808a,e5c71696,20452ab,8e38e8ad,8bd8d5a7,e3d1107b,df7d8756,12bddf2b,7f83f05), -S(98f6e4b8,211c9a68,f912dd9b,784ede0a,314a9721,92dd0ea4,540a9e35,ee10b93d,14e8736,c7ea071,8d864e7b,1ba92a0a,101b333f,b33c0978,59151f8e,f39b4341), -S(f76805a3,925534d4,2188dc28,e47ebbf,18a783d1,71dd3b0a,88115ba3,3bde61c9,7a35dab,99b9991e,73e17ebb,47a231e1,66f8363,e27911ea,aa1968b1,c9babb58), -S(302be8a1,aaddbb7,8417d663,ade6d83,160b7107,87193f1e,46d1def6,b6e5a279,cc2a879b,6235c998,a97d50f9,c495dce2,d99448c9,6dc6075,d20746a9,d73943d6), -S(f53ed104,dc5d432e,61057264,4fdad4ee,57b0997,419c4df7,20206a2a,9e14f479,f05e2aaa,14bf3414,ccf324c3,1d8a91ec,eb3296e3,8e2efb1b,8d18ba9e,cee03ad1), -S(bef68e21,4972047,4ada606a,5b8615bb,812bacb3,f2214104,1ed69ab7,4ffc6389,5ddec4ee,3257d388,c1a3f5eb,39440748,480117e4,9787eadf,6d3daad5,7a30c95), -S(4ebeaac2,693c7ba8,bf0f03ba,1455dc46,bcc77b6b,d0a49e24,4a691880,ac38cb4c,f327fd30,55273e42,35f77b8,d081451c,60206100,15da9086,88e9cc82,6e547fa1), -S(51848db0,9cc33ab3,767adac0,11c1b94c,832b85ee,632d6f41,d65d098a,becbc89f,673a636,c3990364,af443053,77a5e59f,fb39049,e4ab37ae,53a1007f,8c064153), -S(bfd27c68,24c034c5,c153628b,ffdbc62f,afe32fc2,caa5d474,fd1a5b9c,d1cf8d5c,30928327,debc1be6,eb58b381,2132154d,5a7faaea,b3a5a522,8d1496f5,fbc4ccd0), -S(deed81fd,719445b7,37fd23b1,f2f98f8c,690ad80f,1c50c719,79d41526,34bd1af8,14ca4015,7c9371e5,8039b307,6ce0142e,79ae3ef9,5686882d,318a61e5,8afacc8c), -S(83e853f6,d88bbb57,f2e29871,7e3d3e0b,bc23f16b,d2ec5488,4cbcd3ed,de170518,14829326,aeca293f,10f54ac4,5110bd37,d6adc578,a8e6b22b,13698e55,70210479), -S(c2a957b3,3c8b0ef7,15b8ac0e,f8781632,63e90354,86e96e7,a398f59b,91e4292c,5cfba0bb,f943c955,54d31994,630f3ee3,599b7192,d869bcf,24c9839f,806c0bab), -S(2cb61575,18b65cec,dc17545,e8dacdb,28f81985,85fae30d,857d37cb,ab0c23a5,9bbc8c4a,5dae47e0,6ae03f04,bcee9600,2c17f719,fed38740,64734ce,3470a600), -S(7b1c1fd6,f4af2484,25cea23e,840ac8a2,ad8839ff,5c8c34af,9d1d72fd,30f80b23,6c51b243,7e523306,abd95216,70d6ced,235e0bfd,3b9e46e,b4e582cb,d1f1b76b), -S(f78fc2b1,6d61cbd3,4687e1a3,ce9e97f1,dae8a483,75b338c7,d595fd05,db40a4ef,dea54b8f,c9b55943,b2931963,a895bbc4,4453cb1c,d1530d41,19e506ee,b0702071), -S(1918eacc,3658dffc,ef195768,c1819559,8c550cc0,33333796,714c7eed,1ce780a2,c0a289a,22ae8b28,87658b8,41a98c47,71f317e8,cc972ad1,155fedb,da9f9fa9), -S(12905e26,7d6a0007,df0d059a,f285061e,d14f756a,27943f28,1cfbf93c,b343e7b,433b1923,cd4367,4b6b9495,42dd097e,7a025026,7dc060c3,ed3a1778,1441ac62), -S(969a637c,eb80c1af,b8cffe95,c6b6fab8,6329ba73,dc7e996d,a0617f90,48a39d37,6e751f3,b60c1ba7,57519dbf,fa7ac98e,6ed094bb,3bd9cb44,f65650fe,6e8b31d7), -S(5933a9a2,b818cf0f,d39633e1,9641697,410bef1f,127bc9be,cd183d1a,f85f44ab,b42ac6b,c2de2526,5e3c1584,31e92065,a97d6e5f,3602185b,1fbc1589,757c86e5), -S(54b58e7d,a63c1993,2a4c092b,c93e4d24,c8abac,76488fd1,9f56dae8,b943017a,ac117398,ad4ef6ce,d0166c50,69804db3,78bc9b84,a9f5f718,b0311beb,f08986fb), -S(77004384,69bbc239,8a70863c,1d7e31e3,b2f1dcff,64beb2a7,c0a083ae,8f4240f5,8a8649e3,7f3ad219,bb164490,529153a2,aab7185d,639040c7,1b5ad628,d3ee107a), -S(768e2c77,32678997,42c6badb,4d87ec8e,34af657a,4f1d6376,d01b456,7f0f9828,56078dbf,1128686a,1a1435a6,3dfb39c8,91c270a,2b230754,4409e9b2,1f2c7a03), -S(b66b24b8,5248a97,a913e1da,6d0d1454,53e0fc61,66ecc62e,2bd39ba0,c3639f27,3037bbb8,e205213a,4bb524dd,49c667f0,408b69f5,428e4caf,1ec811e3,cf5c68b6), -S(1ffc3c5a,d8e38090,ac36e8a7,c44c6ca4,c0a227cd,1192bbac,2804d033,c50534e,f2d8a481,63ab76fc,391ed0ea,de7b02e8,1580058c,8b84886f,f6d7032d,b95b503c), -S(94b3d61,4d0a5e2,9e7e9ee7,1e2ee7ec,87b14085,cf6f9fea,2ed31d31,517511c5,33c88c8b,8204f465,93acdf8b,a837d4d,5a388670,fb24a861,dd4f35b6,b674ed4c), -S(3a94b6b9,b1b8a82a,267f7ac5,9b52bb7c,52b790fd,ee341265,ee1b6e34,e3e7387d,4db0480d,d2b8f2c7,2c60c55c,5e050e2d,f86bbe1c,98b74bc7,f1d3a44c,3b1df370), -S(2b53bbf,2bb1cdf8,44b25bf3,d1931ede,9e5e1450,78dbaf68,7f4e7852,6a6716f7,70be0ac3,170f7490,cabea8a,63a6fd66,3f1ce8fa,efc5343,566f4b1e,2ca08e6), -S(e5183136,cfc8b732,3f926cd7,95dd8766,25a8c155,d5c8c457,53777c9,beb13494,93c62979,e67f9f86,cc0ec570,273f2c7a,876fcb5b,f88022bc,a8666e1,814207ad), -S(c4c07268,a805e384,db81b877,9d1dde0b,9af6e197,b6bf254,db6aec02,94dc5bc7,2127f162,e2cee5dd,96055ff4,a7bcdb57,19a00742,f295007a,b839eb54,eb317566), -S(2a89c94a,8dee1950,3bc5e772,b2ff9608,a57c4ff0,dc6f7c0b,c1d2b76c,26c9610f,10da34f9,eb14e294,8f2a06cd,dc211eed,93c670ea,47592135,dc33faac,bbf8a170), -S(35b035e9,8cc6f96e,d7dc957e,e07c7afb,fc936653,72561568,25e44f5d,fe4ea0e6,4818477d,aeed402c,870fc50,6197a0f1,5c72a378,e42785e6,be38bb21,6d4ce91), -S(f0a3e92d,647c07e5,5a435907,34c0ee65,758e09aa,bc2a81c9,f6d6926,c03a9cd3,18e7a09d,720e65f0,b1b8fdad,66d4322b,99733bfd,f8c5fba5,afa930dd,f441f095), -S(4db3c367,f3ba6727,fa274289,675d2fbd,1ec7ca8a,94d97bd0,46815f04,368407fb,d5e0dc2d,80f3893e,f1871740,dfff1589,ff75940,e163f8eb,115e4b17,dc1cf693), -S(9a0fa624,b0eb8dd2,f50ab259,cdd9b17f,7a6f318,93786640,56a49867,89a5d27,68e82527,18684672,ed4df389,98b830ea,1547ff45,f48cff63,5d291bcb,e80f3cd5), -S(19f72db8,e604db7c,ef2e8478,c04540cd,c3806c1e,eb9e8071,38f0a272,275d451f,3cc5df1b,dd845f6d,a4747261,f8e1f821,c7e6f2d9,d9cf9a90,d3c7edcd,b6fb940d), -S(306fc07b,7e543dac,ac240f8e,7ac82cb3,df70a2ac,1bdebc61,adc65fb3,e696743,f27b90e5,a2a5abf8,19c90983,51521f03,26532b1d,37875466,f87289f7,244a3919), -S(c46e7e67,a036ae7c,b30ae479,d0f87d7e,6cc8297a,3bd4c1ed,c2436e6,b52f532b,723dc476,426eea8d,2179eb11,35599275,2cc391fd,4c25ffb9,a3942356,a56899a8), -S(a950852b,587a01aa,7a1d4688,8ded73c9,cbadc922,e44fce64,61a5aa5e,dde2366e,79a12ef4,18763f51,62ccc65d,86c94012,363cc21a,61d12982,ebcf2ac2,c6337791), -S(8cad422a,4ea9d987,48703d5e,eb95d48f,1f73d893,91c7c239,f96a7155,98bfd153,111116da,fcc7a212,a1e6e0ee,4e824611,a3896543,aee02f46,61bd5ace,2a67c652), -S(3b922988,8c2bd057,785b4013,fd14446b,7261928b,a8907ff0,da433d2e,61302362,4eb99bb4,d152e218,8cf3464a,68fa266,500dec96,5842c2e3,a3dc16d,e6edd74a), -S(36129c09,42906435,56970a6f,ccab5f71,113b82b5,819ed4f8,451ff01d,209a9cc0,b30ebe06,b9b4a4cf,8451d8bd,7d9534de,375a396e,b2d7bc21,67a56f42,6426d3f5), -S(8a0a960a,e3bf57b2,ae76893a,b665856c,e09a6f0e,2748c703,2d951cbb,6ba038ad,e29f3916,4928405d,84dee9fe,973f613a,3c5e1c97,c6e5e814,a927a6ce,60efc2bb), -S(641f4fe,dc351cb1,93a088c6,b6ad8867,442cb913,7f0ded13,4ef0f2c8,d721b887,600a51b0,f80a351b,ce7965e1,eec4c8ea,9feee470,80b920f5,67e4c979,84b48dcc), -S(cca5d72b,8d78990b,267cf3eb,246545e4,d416eac1,600078,2861bf05,c0132b3d,7ea6d271,f01c4250,d07e782c,32f0d6e7,177d7714,e2277282,4968092c,e0444f42), -S(c6ca654b,fe45c9b9,1f3869de,2f96f27e,351a7f1b,4839f7a0,9db2966c,f81f052c,894661b7,2d156df4,2b307506,d990ec47,935b0605,9aa97bd4,26b0df6a,9e3d2183), -S(2a959d49,c5161f7,6ce10ee9,cee3047a,be9c620,569a702a,9827dc66,84f6f35e,918b7a8e,e283539f,cb52fe91,1f5039c2,321a6e8,be0c4449,66bcd7f4,594d1e8b), -S(bfa77e7e,3dd28fd8,a04842e6,6f01a9ad,476ff448,18e4a3ed,ab2a8b6,9ba42ad8,d85cdccd,2f5bbba4,1718b70b,c10cfab7,272377e2,5a578ee9,be991b4d,583cd62d), -S(6cb9b861,de296ad6,363da904,46618eae,fa852ee5,ec1df0a,d0a6955f,7b9c6d97,978d0afc,29cb0cdf,f2ac432d,cde6af4,1aa6bb4e,219a0687,11924142,deae9f1f), -S(83446c25,f0496ada,69354c67,8a1ae34f,154afba8,318be7e4,ec52e5cc,ce9dd139,7d4c3e81,98a8905b,63572a16,5fb7701c,c8f0c53,3a01f47b,532eeced,39cbd620), -S(590279e9,f8a2ccd1,c62b85a9,87b528ea,d746a42a,fa07b358,3c5d6349,ef678b13,75627950,5089c0de,33822465,14565c8a,cd131b14,949626af,15c56e47,bdda7f1f), -S(311d1ac6,4b7b1a8d,7c6ba19a,ee5869b2,2d769098,a6e4ef1e,3837082f,ebab23c2,c0b9714a,e1627902,45649db8,b7eda70e,25cc9905,57397adf,39c2c1ba,bcefc497), -S(f63f9d45,10f232ec,5c1f3831,6e16594e,a82d133d,6dd4c365,1da3f34c,c8197be5,ecbd7232,4e732295,750d8c5c,b0290d04,9c778707,4cab27ab,35aeb978,3c743a7c), -S(b772d2eb,c76f6f99,7722aea0,fb55cd6b,592fc0f,c8b87511,d85226b1,845a517f,6b4b0363,7186cb53,ef0d2dbe,3ec16efb,df0b5de8,dabd4d9e,871f7174,94f80538), -S(4dbc968e,8697c131,7d9bc180,f98a1320,bf69fedd,24d71b35,c1e87c95,13420335,f6ea65ec,44c5e25a,549dad16,ff129abc,153393e0,e76b20e5,c1b1ebc8,9ec169bd), -S(2acfa0fc,a5377dfc,21519105,a5f434f0,914fc259,95bb811f,1d17dea3,2345bac1,682e091a,47b18d6e,7595bd46,28130bf7,faef8df7,e8224e02,3d87ee03,b3be8ff8), -S(d77801d0,eac64c02,cbcb795b,f030ef,37a131ca,f07ef6da,2f3ed0c9,f7c8922,166fed02,aeb1395f,bca109e8,5d599f9a,df684cec,418c7576,a4e67e3e,e1abd7ae), -S(92006fab,e11362be,2c89d0bf,e1250e9d,3c5282ea,38be9206,f35cf913,496c9481,2a5b39bb,755a809c,f76ef97b,7e59f00b,70c94a4a,9dda4bf5,523e3cc7,2ac83832), -S(43af4cc0,66155b9c,fd9decf5,e95ecc50,3c69e99b,b5dde00d,bc859732,f4f7d79,7415eb35,75c9e0e0,c237dfbb,af245290,11f5ae9d,63ced644,f8c5af7a,c3e59c48), -S(c018d581,152fb656,c43eabf5,f4e7aa9,c8c5f722,f5352fc,3dda72d5,dacbf451,f9bc1975,acd5aa76,f2744c85,22a07211,daef05ca,8ab0c200,6196acd8,29fcc9aa), -S(968bba6e,77c83e6f,be7272e4,f6288349,329058e9,c3b197e6,f9b56dbb,8587f2ce,3a841d0d,1066ee35,4fe70855,3bf034ea,4da917ee,87d27a0c,f60f8e99,ca45e065), -S(6481bb71,dce335a6,98972f0a,bef2b4eb,5302893d,175e1f53,9a93dec7,53d8e4eb,94073fa3,98393d5b,ab446695,889f9805,6fd31d8b,c14b5ef8,8669736a,5586d3bc), -S(22d38699,cdd4d0a9,ff6bf179,d611b831,647bbf23,5da1fb6e,ec063070,d5420cde,fd4c6d72,ffcaf8fe,3410a0dd,27497df8,98e02920,272a4daf,8967d547,4fd2cef5), -S(acaf068f,34b0fdc4,b86f606,1f96d172,69f63e48,c739f1e3,46cba1f6,9e4c6164,6f9cae55,559fad61,e20bde43,ae671832,85e83ad7,429f031a,b365cc40,349ee3d6), -S(1d2f237,b91c5642,d3dc3c47,9db9716f,47bb34e5,2bdfb7b4,1640e517,f83778bd,9036f65c,eb367bd7,9018993a,9e01b350,fc903bb0,ada247b3,26761011,bd70e0f9), -S(42bf9891,9c347e33,65990f49,6cb09a3c,654b7a09,29cc483,e9028191,4797b6ee,56ed030d,f2fd51e9,98c63f3c,338892b3,49b2c30e,9ac6b3a9,a0f1c18,16b5bada), -S(b48f90cf,18157b0,de5721e5,c0b1986b,1c16f2cf,1b973578,d8b3a41d,6d18f774,40c392a9,c94e2ef,aa5aa88d,36eddf6d,d01a1e37,60d8e391,4ff19646,94557641), -S(8ec7123e,551695cf,c1668bce,86377900,f79e7311,85c5e39b,9d24bbf2,e6409313,f2f58364,339fd734,910c9b65,be0574c9,2bb9efec,ecde3b50,67850d71,d98adbff), -S(7dd11415,1359f2ae,81d4b18e,5afc6657,788d2bae,5c76728c,d1d25265,a2dc2801,32f37924,4f7389d7,7f23333e,4c4920a5,5658254f,dd7febb1,2c3d9d9b,ba631c09), -S(33556f01,4bd89b67,52e7e1ca,1d5fc7ba,faf6e25b,8a49f57e,51c293e8,6cfc4a8f,5c8467cc,3553a8fa,1e322b04,83a0e3b,fee08772,69582178,668c51ad,f3661454), -S(f92da876,e7df1d95,cc2f820b,47921a26,413cb84d,ea6e05d1,da3c70c0,6f5151aa,907d6a04,dae7f625,409e9d3a,8a92f636,f5496ea6,c15825a0,c9d6d6ad,54068a45), -S(77810caa,1e90962e,31ca5e91,2c310bde,cd010016,1f124b73,81492437,5d24f5e0,205b009e,d933e873,a2e12c0,5ced5536,c9b8918,2776bcbe,b297a955,bbc892be), -S(5740459c,5ba49bee,db0fbd8b,5a5dd0a5,24d47dad,ccdbb28,567ce303,58e70b22,7092b9d5,a3c96984,da084d42,f2bc5f1e,a51cb1e4,b8508c18,6ec7066a,74141f68), -S(b7cea84f,84d3af1a,797d90b1,f7a460d8,de9f4a6a,2f2887ab,8f464123,bf844cf1,22f82480,7b05e21,4b885ffa,e8576fa4,c44a3824,5e256d55,cbb1a5ee,343f577a), -S(5180dbdf,73208c2c,b5e605f0,9f6403d9,ea5bc592,29007598,bad6a913,a80f5493,247992bd,bd823a2e,6ee55330,57d78d36,913654d,c3e089b3,fc042fec,15ee0262), -S(ac413c18,ff3bb767,9070b698,e2108268,9bc59a13,1f011baa,59799d9a,daf43cbc,c2dc42e9,78569e63,ab08b155,1e4c52d6,9f770211,86803f60,dc752573,d536af5a), -S(f7a5bdb,71b339c8,19ddddf6,10ff7be4,6af7dc87,6466473f,a01f314e,67bc52e6,6b572fee,bdeb8cb2,9b72dc1d,5df185b6,c50f5ed2,5e95a61,c1dd4822,72ca2adb), -S(6980f38e,6b164eeb,8eeca173,15c6874e,c35bf6ce,78779e4f,19327df2,b1f57dfe,e19f87b4,4e72b29d,c55a47d8,2b5d9621,f15d51fc,deac84b7,87ac2ddc,40af3935), -S(98adb6fc,879900e8,2ede0825,32da151f,b7a16a5b,8d2b9eb2,4e8dadb3,46ac67d5,a7349dcf,c4786a3c,2686fee6,c8d43a37,b91c1b82,886f853b,fcb6831e,c8404262), -S(c46cfd35,101d86ed,965d16b8,55992ca0,932822a,550a71f,54543922,54b00e36,72c03b83,34d944f5,9c4f553f,c25ff5c7,d887d5dc,4e82f90f,cdce7e41,52977e32), -S(71caf0c8,2402b643,ff0b26f5,7060658f,d29294bb,7695524e,99692495,b69584ad,b11c3736,436c04dc,3f4503e0,27ab7a76,2ccb1bb9,74922f92,8fd63012,e174fa68), -S(cf46226b,243fd1b7,984a38cb,f27a7fd7,e7a35a9a,e972b0cd,4b438c86,c6df89a8,f40d1f01,ed7ca764,11a3e0ff,55d702d6,19a68ff,88d4df9b,3f7d9c3d,b96738fc), -S(d8f271a,a092d515,176b611,25abe9d1,85a15d55,b486818d,b571a5c6,4c51b493,3878f749,5d4d9981,5ba550ef,3dabec35,fba40c5e,d10c4b54,fcf63b23,24b91e97), -S(6d60b710,8fb40460,f893c53a,34c12054,6a02c037,821f2a31,55976104,11657d48,a03c71bb,788b915d,9ac25950,30d8c31,65c0c1c9,ed2abde8,96d3c985,3f14bdd9), -S(924f3ddc,7d5d3764,66b47124,b75361db,8afc0eae,7848e860,debefb75,452ef586,c594e3d2,15f58f5a,255958b1,4936df62,3b68a854,4fba7aeb,58a54905,b19c5f25), -S(a668983,5487c800,a1c34b9e,ce7b2347,1e4f5f5b,3be7b591,3390ebcf,2928308e,626c8044,942f74f7,8d255207,5f9d18ed,8982a341,583f1314,4f53dbba,40c94c0f), -S(7fbd491f,ec466132,c2838c46,a5d6ee7b,9dc0318e,3b3bd3ef,88d3cef0,6465cfed,6cceabee,fa659f6a,c083355f,b14cae2c,53657f1a,3c536b4,193312d4,d4a28e36), -S(85122c42,ebe8457f,be82707,e49e0b1c,be3995a1,2998ccd1,629b84ee,935efa56,1cfe76e1,922e4cbb,1023dd88,2bc03dbe,c0be2cce,9fde0797,92adb2cc,925dad51), -S(3ac4d527,3be6b39e,d6326132,fc212640,450791cc,9eb43b39,a77c750d,8acad644,f1d8d690,c1011f,46f003ed,6f9a3342,ca0e918f,4096fcfd,406644a6,2cca296b), -S(838144ae,70bbc188,a05f03bd,9123b93f,e4bf4485,8e380e2d,5d6723e5,fe955cf3,9d8aa248,2bebcfbc,cbcdf87f,c2342618,74e99bb0,507f472c,e86a1b5c,59307a64), -S(4551b877,fa1d9811,e9fb6afc,acfd873f,7507103f,58ccf82,feeab7af,8e893ee4,ba0da9c1,1fb2719f,9a81e745,fe4ac1a0,221b01dc,7e3eab5f,9552027c,87b2fb30), -S(baebea51,e0fdc8f4,cb3bb20b,cb3f4bf2,b37ce31,121d6b5a,7a3313fd,29fffa44,41a4785,df2c9ad2,99b0d0a4,2032b8d9,2f56835a,7bad7ac3,68370046,52c66446), -S(8c03e4da,5be53c8c,6c6c1dd7,ced8fe99,b88de276,73ec3ee4,f5152a70,d0bbac1b,bef7a8d7,df0651ea,1d328729,b0f85ef6,a22b3d66,64ff04b5,fa1c9dda,2073d25e), -S(8d23846c,34ff8756,bd30eed3,1befcd53,4b171dc7,da0715d6,df3104ac,23104ef9,49ae984b,be3cb83,1c2a18d0,f527df0d,27eae720,922f34a,b270888d,9361b708), -S(362c58de,902d1c62,19da8e4,e8ff33f1,61d7c001,202cb2e0,add6bc30,dedba48c,235a0ee0,909dd6da,d1d8a8b,f5f1720b,d6d7e38a,b2b5bab6,788f1983,a5de3137), -S(f836b56e,2892fe8a,a88aa77b,e345c48a,572d0cc4,87d75ddd,99e3e471,bd0461ad,c4254af,e34e6705,12d3652a,38801946,92a7b170,be6fc60f,555c3835,84ca0611), -S(75374bdc,ddbdd08,2e408d8,4fae0652,bc6d1e48,89a7f0,bd1d2257,d75d4f4f,8b77030b,4ee786c4,2973b7a3,905d207e,46448c36,c7d7db5b,280f5936,eed70ee8), -S(ec299deb,26cfa600,a6385db,f04c5b0d,128231af,6453fe62,29bf32f0,71bd1733,be200050,afb2e277,5f4b5688,8ceb6af9,50f901bb,b9a7dc2c,34f9df46,297cda1c), -S(c2ec7bab,4350cb7a,d45f3c55,701203ad,bc00f9e3,17c2465e,efae7069,fed17a1f,33b1bd74,3375dfd8,f4c69ded,f7232449,4c376132,5afc8e6e,a6b67aaf,b4570355), -S(62a96481,d4d9b559,e9ccd855,2d6307b4,8a5d03bb,7a9e7ec3,de8d193,c33ab2dd,c14bf21f,58c2f112,f399e6e,ada45660,6c80fcb,debd967b,e3e3af90,caa3d1a), -S(6da7531,4b8bf8d7,7d72a367,63696a33,4bf5dd8b,f192e2b2,aa646277,f0d6ee3b,70da7974,1576f5ab,da432280,f269ad51,5369a399,5a7de050,ac7eff5,8b7f96c8), -S(af59c78a,126296c5,f19dba32,b9e414de,dd2f1c34,6d6900d7,3ea52e56,5e9cbdea,35b963b1,94d1071d,7769e4a4,3fee70fe,4a63a0c3,bffa2c12,88ca2a82,a7c38bf8), -S(a86e3627,551f2831,b88021d7,d8cff6cf,50fc07b8,5fbb0889,bab026b6,6fec63be,dd205467,4213f012,d45022fc,75de7c2e,b3c71348,efd536fb,1e5f875e,1ae55c63), -S(2c59179e,d9c22abf,b8856e9b,311abbb9,7ec61cc,7ab145cf,5cac94fa,77d65004,e94a1b85,fc8c3c8,aa86338d,819f7139,96a5b72d,68952a6e,8ae48c47,aef247a9), -S(f406f78c,7be2e678,d8315272,e7d861f5,250a4bf7,354da2f2,dacfa22c,d56e43fc,fe719c86,4d66efb5,16a49af4,a86bf463,6130891c,7fc7da01,4394a319,d66b0493), -S(c89f1828,1d899423,83dc622b,7e6017f4,cc02b55c,5c48c824,5568aa3a,c3c25566,40a58eff,8043e3f5,753f9f54,31f170fc,795ade25,d6200e0e,bed182a7,8012de93), -S(36179740,ea6dd2d2,d2a537a1,c9aebd8f,c9a570cd,6fc25453,1d58866c,83ee051b,80643869,fe206f68,4824330c,18073366,9b2b7e97,51f1282e,3c52fbf9,f4899a90), -S(ab5d8e67,7fc654cb,88458b7c,e43b830d,74b441da,9a1af152,9147dceb,13bb2907,b2ecd95b,bc828f3f,53af76a,b5d60dfe,aa681270,74d8ca61,2558c778,ced8aae6), -S(b1e79103,da12fe0b,51259b9f,3c4b74da,1d8075ac,e1aa912d,ed6da9e8,2bb14706,b726371e,7c872caf,42c049d2,96f998a7,c928d991,535550d,a13af044,bc61a1c3), -S(9792e304,67ce4e2d,77f288fc,34c6b2fd,dde99e31,4f0137b1,f2da1d7c,603f5754,d880bcd2,6a74445d,4ad0bd78,2963cd03,9ba288b3,44711889,2ff00de9,4e966be1), -S(d8180648,f046c427,db5a9912,6d54a1c2,915ffb17,c686704d,38fbe1fd,d60cf774,c4767b5a,fb34dd33,e5de912d,b0619e5,c39fdb89,2c131bf4,97cceaf2,aab6f2af), -S(9aeac423,159b5746,565a65e4,c00c12ad,537385ed,9fcf267a,802e2290,ec19633e,7990008b,db7ff6c6,cf110dfa,96249b74,c5173d7a,f7489d4d,86424749,5ea3c63e), -S(2aaeff31,78bfd5ce,b9aa4af4,71555de6,7b1c2bb6,61bd9aa,8591f15e,8148e97,629620c5,8542d054,86245859,e608b5e4,55c45fdc,32177c19,34eb9b6c,23554f89), -S(bd0451c9,211fbabf,21a6b969,29edcd7c,43f10d34,219c6d16,1c5910d4,ae8b5928,23d4a749,b11a1fad,68a8e65e,5c940315,ff326947,868dd92d,9f6f9221,44a4a642), -S(205c5f6b,88865d9b,b53cf8e9,7e97d781,8e038c60,b8177ffa,9501590,96ce5592,b8848543,287401c7,7229f94c,840e36c2,bb93acb4,eecf9ab1,5bba1b49,97d3745a), -S(a3d24c8,f351ce59,6f2da6c2,def943f9,6ff13d0a,c7efb29d,ca3c39d6,5281b96a,28d5fdb1,a8c1934b,a98508bd,8b17168a,a78cf549,1b3b3636,8164e95f,17e8bef3), -S(468f528e,8f2b12c8,4b90df66,8c401f4e,634b2b9,421d1a1c,1079578e,2739160e,3070d8d1,9cee21ba,510b72dc,b17b7e72,7c0adc0a,baf58150,a24fb409,9f203f03), -S(6a106a2,ad8bf04f,a0ea0c66,179b3a4d,df0eace4,954a40c5,ad3d611a,ff7965d,fe893d8b,20f94be4,ed7b20bb,4feca170,75d2e5c3,61cbf44b,387947b3,8d996a91), -S(e59d055,1f1f0a40,6e94a2ad,c92b1e5e,54b74ffd,8d0af6ba,ad25de6b,97a470a8,b0693f96,9257ca3a,da93a54e,f3c29a62,20cf4c33,a9cc6915,f51e4d50,8ceb7efb), -S(ee7f4a6a,6e37fbfa,f7db77ef,ae9e8745,c5ae64be,338a6b52,e5138ac7,860340dc,c92c0a11,17b2bdc3,d043f6e5,b90f3cbe,412a9a61,79ae3f00,7c397589,69eb1616), -S(d42377d8,5dabf33c,99268106,f86e7939,c87ed35e,affacd68,d211b4ab,70ec2c05,ef130233,589a5fc6,5a23a029,e1857b86,d6cb276a,8f37bb8c,996dce4b,e72bded4), -S(e21015b4,d76f0245,8dffad7d,f67151f0,ff4c4d1b,ad5e13f4,a6e197c7,2e4c31c8,b78e9d47,31a4c0c,3e29e9dd,2173ab2,16a5b8ec,522604ad,43111600,bc3e1733), -S(53c5434,9f0270dd,4c76d116,eb2df817,b66b504,87367767,d4a796b9,e4516f2c,5a4b7adb,66ace9af,59d1286e,3d89b2f,de525b27,6c27c1d2,1d7a38b6,b1b9f1d5), -S(df9917f7,6cf50cd7,2b8b06cc,cba9a47,b7e0f64b,481adcda,a6942a96,2319e81e,171d72e6,cad16682,bea2a90d,72b0aa4d,899e1627,18b96109,4a501515,2b754453), -S(79eccd0e,f2d48da,3ccdf12,91269dc8,21453173,7991bd38,ec3ebb33,56a594df,72371a43,74284937,aa92,6eb5e8c0,6911bf1d,4efb097a,8d78f46,da1a87b7), -S(3a472336,4c182521,81f90fb,66d768c6,a1a46cd,85c86108,3a09696e,922dcb44,bcaefa87,7b8d963f,d6e535f2,db3d189e,4fdd8626,94b0b60f,136b25f8,14e3154d), -S(edc9be56,27acba38,178b0c6f,cb7ce6e1,f6ecada7,a592d6e3,e859a16b,459c6d7d,bee091af,de809fc6,9b819ff7,1691f13f,321dd702,3944432b,a278df70,4ea02eef), -S(9adb48f1,439c1850,1895ae30,649992af,3ce3d085,13c6a92f,5226f3c9,ec09e5ef,3dd78cea,3a3169dd,78afb39c,ff690eba,e9cd5f3c,42d7c583,ef093a57,635a1df6), -S(942953c3,b620e636,63f2bb83,6c2c3a9f,6cf4a931,2587f57d,9489ffb2,38895bf9,415c121,6ed101f2,698cc0f0,9c3ec0a0,c0e8458a,3aaf5879,87ff1b0,89992932), -S(92c539de,88e6d094,e64c4b25,51da4149,19677124,d8d1e53b,4d0a81a8,53501619,c9b5c7e2,dc61d875,4f33243,de28ed78,adea8e56,e193ab0c,d1f5464b,e9003a45), -S(29d33ba1,e9972c80,2f135a4e,add34b21,408be4ee,29d7be7f,c7f8ade,3ed07cfb,847cda60,a3e6627e,5abffd6d,b56502b5,f26df3c4,630f4f76,aa868899,63566e7a), -S(727abd10,6aeb6f80,f1dd6319,4bd4abb2,2db5d8cd,e7676273,cb0b4246,17983d2b,476962db,5de3493c,58dcfa1d,fd206a44,11f590a8,2c7aa7cf,3fb377d8,623c9639), -S(d898349d,89eb2d49,f2865e19,88c3b5e9,f43ba281,6a0ae0d5,b031e186,b23fdfa7,4d3083bd,681a3a1b,988d3bfd,70fd6b13,3a1d2264,feadd852,b2298450,f729c471), -S(88526dd8,a52010d0,fdcd0223,7db54b43,f73b7195,cb3b2081,96257c7e,ced4649,686926f8,6457861b,4eec6999,626115b7,f9e29e0d,74e44027,5df2f583,7b75699c), -S(6b64ec54,3e5c83d0,b36711ec,b0a4b8a9,25fce55e,4923fcd8,6dcb48f5,43bcc107,8a7d84ca,e8431663,3d635a78,9598a22a,532465e6,f86e6eff,108449d,a5b0ddd4), -S(9017d917,e7e80f70,e5fad8f0,3cf0bcf3,b20bd8f7,95c4728d,e259bf0c,933088c0,e2a9c53d,e1278404,60828e57,eb5de14b,eea14cb3,41bd4d6e,4b960ae2,807299b2), -S(2f7b4a5,591268c6,eaf64c76,5a8321dd,2485ee36,bb1b338c,b1473535,658c376d,8f2cce5e,42869466,a3658460,c0ecbb46,5d850b26,85642b52,e01f3b08,544fb94e), -S(316bc4ba,1dec120a,7a10ef1a,aaf40d63,9f404948,ba27f46c,58763508,4809c78,3522dbc9,f861c154,771952da,7dc04ef,5b5100f2,b4355177,b62ace04,a717d056), -S(69c07c8e,2c1facc,7ac6e08d,3b74f1df,cc24751c,ada31142,72d2e313,78d76683,474693bd,649a0877,a3eba75c,910ba3fb,bf8aab97,5fcae30f,cf47a51f,e9a59f24), -S(154e4dbf,787e808d,c19031a2,df25536e,4bc6a71,b03d8f77,5c652812,75a84a30,e79e1a4e,2440cea0,c6c63098,ecfbc52,f5cbec08,39589beb,251af76a,50eac221), -S(61c158a6,b963f853,66598998,908f85f9,bda6ad6c,827702ba,f81922ed,2b675b4e,d63cadd2,c63ef3af,7c8e9695,4ebb28ec,48dd2c86,a69505be,d06ab3ab,c4bb4fed), -S(97dd50fa,eda2da43,aedfcde3,9d55b52,de43af06,13435b7c,6744dcba,81cb9b3f,e99138b,1c86d820,70ff2e82,413b19ae,d83eb23d,636c4380,70116490,bebad75e), -S(b2a43ae1,947e0e8c,e2009813,eae3e500,ce67b1c2,cc19701f,5b6cced2,e775cd57,291593c1,dee03645,4d0b8be2,642cafbb,cb3b7fb,a045e402,2006c702,3532167e), -S(20580468,68663d06,568988f6,17442d5a,6a65762f,cdbe91ab,128ef99,990d722d,ea32d66d,56f1fc93,fd559c0c,e8b200e8,e423d097,26e564f8,8f53b3c5,e8dda8d4), -S(c2b98b13,bbf661c8,f4cae855,158f095a,9b62947,134c5da0,9dd2d377,959ffdba,3d6386f6,915a7e26,c63ee1ee,6970928a,6f0e4e29,cd3ad665,fa4164a5,a8b2cd7c), -S(fc6c98af,7fbf38e,53690a78,34d82a56,170a18f7,a4e702ec,6e918510,2700611d,9ccd38cc,f8aa409c,1a9e0b14,d01bc9ca,69b5ed4d,7f92a177,e42930a0,222cc755), -S(21157d1e,1bca5a3f,2dd0153d,b9af3079,e1e531dc,9eafb9fb,5042af2a,e67d7000,254860bc,97cecac,b4cba1db,79b13fc2,199f037c,aa963d4c,bfa2b9d5,70456cd), -S(316ea33d,dd576b35,e45fc5ea,5e384070,68ca63ed,1149807,68a7c6a0,d6c628f1,dc236dc6,d0ab4c12,63124830,633729a6,9b20a22d,7d395af0,38d6bdc4,34983baf), -S(21b825c5,44a41bc1,9f048a0c,9a532a6c,18df41e3,e7cbf6db,97c871d4,a3cd0039,9d85ccda,c67a4a39,ba10128b,382925d8,6cebbc0d,70354ffe,aaf89ae9,1fec461f), -S(65a4b32c,e116790e,f671e6ef,8ad317fb,efb815bd,fcc1708f,32c0c078,2ed41140,634c9efc,6470a929,8844f082,5a9d34c3,ab14778,7969f095,a1b45f1d,dec806bb), -S(cbdce03,45e01ae7,77ebf819,41123ae8,b4683169,246c5156,6afd6a54,e9eb6844,5414d24f,ecd1a159,70882003,3726c1dd,ad939df2,9a12dee3,224fb9f0,a89f03f2), -S(9c4d4ee8,3a36544,ab38334a,46586864,bc7c301f,710d67fd,226d6e59,a6532374,868f765d,3dd5823e,7e2e6791,21bcd41e,9b89df55,27e191ad,c5016463,ac7c7991), -S(4c890df9,dee96da9,7ad0b768,16a50240,2c9fad7d,5ea13a04,3eebae41,678214f,397de76a,319e758c,199e2343,6990a34e,79b968f9,1139324b,66e5f7f0,114cc9b5), -S(c7f4c3e3,f7ccd93e,2449c653,393ff2f9,c8d362aa,3dd01128,9879c983,f9b49229,d2ef30d0,68321b54,91519698,79d8dafb,8d2c5ad0,9117687e,10c5a57e,ae4df846), -S(e8c810ee,daa58b8e,687fa493,6d833930,e7de9bda,f73f11ca,23734756,d4d05af4,2690ab19,e6c9df94,349600a9,269c76aa,633c4dbc,abf24604,3cebdc83,1e117d03), -S(a3f51d28,ad743812,3cf9a169,d6581d9a,3d41a131,a8109eb9,a38bb3ad,9f66187f,3f87496d,d5f9ec37,2e3d0e79,7c12e7e1,c328658f,49cbf237,a4e36415,76b89e75), -S(ee0baf50,f62282d6,b560d1ff,c18196a1,a038b27,f081da32,1d82f3f1,82c27b17,4e4dee4b,182056b3,dc809d4d,2160a5a2,b6dc8ef0,e933e45b,5bd1375b,c677321b), -S(346b4fc7,535f3a2e,79330614,e0618d0f,c2a44ffe,a684076c,704764b4,8ab3d95a,98a41f22,cbe44fe5,37116f8b,9ee68e3b,48ed63d8,33cb9567,278c520a,e400bbd2), -S(55fc8976,b796bf67,9de4b2bb,aea29d6a,e3cd032f,7611e59d,75b8ffbc,55c32b79,2e5d3a9d,f8b32c5d,bde33229,f2e9c852,702dbd58,31bb1917,2e47685,c395ad1f), -S(4ebe6051,7453c3a8,a7b65c1f,fa7d0b89,c4cd4166,f2b8c670,3a71484a,f62dc563,6fbc68f5,a7b3431a,1dd6ff18,b7f1676e,a42ca708,f56e50b9,8700ed3a,560b3850), -S(14bcdbcd,73f2896,c8b37bc7,e06c195d,17349c69,9be4ce19,3fe4e145,a79e20eb,2bacba55,a4611886,7e3c11c4,4f14bfa4,d5c702ab,b2385584,e07d7b08,42a8ec61)}, -{S(c8116b60,1f8d72c6,24957215,46b844f6,bf6bae0b,7575a77,f1f6c6c2,5524fa2b,b7477ca6,de2004df,34882c65,3a46821b,53372f13,ed822cbf,40c20bd9,ddd1d6bd), -S(f59c22fd,8c5a2e,c990f3a5,e6adcd12,f7cdc433,88ddc16c,aa41b9b2,2fd8dddd,8f63f807,eb1b96ae,ec9a49db,818e1228,b9d9da5e,5b1603b8,f5c65900,782a6c53), -S(effdde86,efffab86,6d1da179,211a52e9,b3ce9fcf,c5c3282a,1a87cbf0,aecc882b,57f4a91b,b88d9746,1d1ea75d,4eb2501,46899ac2,ca707ae7,88f35b3e,9f6f8e36), -S(6a4d17f7,3eb94a48,a369cc8c,4c827003,8967190,3d6ac75c,cac7516c,e78a8da8,51f297a9,23bc21f2,ea576db0,15b49d80,27fb1ea7,597179d6,fc47d749,5621d8d), -S(7af337ee,d52f0c7d,ffd0628f,7866d621,dc867661,7dade077,2655f1e,3c331d6b,9b202463,320d18f9,2db990ec,e41aae7b,112d6390,33418eab,7f86c874,a040e2c), -S(4a9b0428,2687d362,66d8f33,8cbc38f9,8d6e6f8b,bd5dce2,b911d192,2e70a583,c2646913,7c7023ff,abadbcab,4da4b90e,8ea8736a,fecb569e,dd822733,8422d74a), -S(53a776a9,e10f53a8,454795db,bb340cd3,fd0ec50b,51a164bd,549ac834,ede835cf,1b976c44,de266928,49631bc2,950b4d24,f11fce3e,a728674c,8713d3e,35f8c0cd), -S(48ed6e74,c75c7733,1aaef9cf,ce06038b,bb405ffc,160c5711,b98ad6e3,44baf62f,fa56b3e6,b826b847,667ab6c0,ade30415,39d67509,61c0c199,14715bb1,bfb218e9), -S(65db9062,2328f7cb,e9afb758,294e0d63,d0042b6f,7615225,ffbd341b,16c5acd6,1ff10083,e9f66f89,bec1330,dc309813,2d434191,2eaff4ca,b3c20177,7001096b), -S(be836639,aa622020,9ae01ae1,f96f9256,9ab7aca1,2f5a7277,903dd653,18f9dcb8,293ab5e3,c50f117c,71dae650,b16fe28e,bc14eff8,38fac552,6adb3393,e177ffe), -S(5ceb4539,42c966e1,65c0e346,2172bf2,e6e167ba,261d0e61,b67df26a,9857b747,88d78492,95312fa7,ee43ffb1,775282f8,f692a83,c6b4a72c,a1ebb44d,28983f00), -S(216fd6b3,c5358b4e,831327fe,2918d70,ac627bc2,e12ce34a,adcbb23a,c0ed2a8b,d450d01b,83fd1935,f0a7c919,cb91d162,dfd14cdc,3d15661e,a303952f,ed70e684), -S(354a9835,50c72d71,37f8d393,2895f1c3,b2e6bc19,1d9ef2ec,3a2b7dbc,3cd2ef76,e4df044d,4ff91794,3e6d4c59,90095781,5ee0338d,79329ffb,ed74bc19,103fdb6a), -S(4215c5e7,7d2cdd03,25f38b38,8a204013,62114d94,1bc57216,56e57878,b2750502,b4d82696,1aedb8f9,60da2950,cb5b489e,857e30e5,20a8e1b6,84dd4032,d8b6a494), -S(79bb1258,ef4deb1f,4a2baa34,91d9e27a,7b75774c,133b9112,3e5fd848,37a57aa1,d467fc67,dc932c7c,48d69609,f955701a,e6a30205,42a51c2c,10591fd2,134bfd1b), -S(eff02038,49797c99,68c8d63b,14a4d84,f4852504,2ab269b8,182b2207,ba94eff5,79a6fc31,e09c939e,f69a345a,56b90c39,2dd58054,e3f23e9,c16f84dc,ffde8e0b), -S(856e40d0,54323270,3ae30d75,8405401b,72f7ec1e,96cf59ec,1f3b8465,23466dc1,d1200346,5e56370e,96663479,bad5f6f,8fa4713e,79217649,c48eaa8e,4bfaa8b7), -S(f020d944,14008a39,59feeeda,49fc388,d41246d5,39a5bfc8,8f9673f,8b0213a0,e88d23f4,5919f0b0,a037f4ac,aad9de03,3f070c2a,f967fcb6,e251c17,69b62658), -S(ce486f16,39af644a,c70dfdff,6955db6d,ffd6f69f,1dc86c40,a318729d,e6823239,8c0fe4cd,debc1c38,37325664,f8cb0235,b6f32ba3,809dab3b,60c3119c,ded40b4e), -S(2cd69598,f476efc2,4b65aa98,27607a9d,3c643033,3cc78072,7e3047ea,a3a7244d,d287d0a3,6749cc57,bac0159f,1c4d738c,a965dadc,be36bf2d,f3f55372,6ecdbb3b), -S(f7d9e16d,c71c9b21,be93bc6c,b00888ab,974c7568,cc09479,16b09532,7c486850,6e561ec8,7e17d433,22163af,8253b659,15d04fd5,24a941c7,a186ab15,4be2d0a4), -S(e1f1b231,3a8bb5e5,e030d6e9,ec921515,6004a01e,f6d737ca,ae4ee585,80377a7c,bdb81500,9c94dad7,69b8744a,2d19cb59,8335ccaf,d840ddf,8817d4b9,735a8e3d), -S(677543bf,d07c8fce,d24cefd3,bf38bd0a,40079c68,1349bf24,c8fe25b7,26365fb4,3a7bd8d6,c442438e,3a1a53ff,d2a6b9d2,e0b3a565,de374417,189d0dc,888c02ff), -S(b8a18d49,b1d4593b,d103b5a7,dcbe4845,e0ad2644,41d1d60b,ad1e9252,1dcd773e,78ff6195,aaec6cd6,cbbbcb23,a81c6ac1,6bad7a54,7b0ca465,5e1db742,2a0c8edf), -S(b8f4e588,1f4155,b7a4fa26,1e34ac3a,3d776ff3,d5a69c44,6774ed8f,e57201a6,69dd7683,ab9bca83,a64ac013,ba62d2ce,1ac5866c,f9cb046d,84f69b34,168896cb), -S(4520c74e,5c39f18e,47d16c21,51f90013,395f2cdb,c59d7f2e,fa40be99,e843855e,ebc0a6df,bbe76c29,d1f32546,cf7038eb,ab3a5e2,bed16a31,acc587b4,41051093), -S(431f3a79,57636916,5d1e1b7d,dcc1be51,6138a26b,beb1a3e8,5c49f42e,fa6d9c88,6cf98a2b,1f747122,2f6835a2,116b8e94,8dfbe5de,72cd9e7e,7499493b,bc5e590c), -S(a03b812d,fd8291ba,ef0d00c2,25437a90,d8362fd,6c5f1b03,965cb3bb,ae9664a2,b3a8f60,a26d6adb,5e761692,a8cf3738,3dc30e79,6417e4a,23db565,487ed88), -S(2440160d,4b874cac,adf4e1a7,6eb079d9,810be0ee,2a8d6cf,5f9756e4,936608c2,c5823453,f331649e,45a228eb,4b524ea6,89047e70,31ce2894,61f119ae,a865ea7), -S(c62fc4bf,ec4f9113,1f5d3c0d,36807b15,35a52246,225b3959,4fdb8f3d,d8539bbc,a7257908,497a26c1,484c0d25,75052095,a1d71db9,ea5b61f5,e8c4257e,291129e2), -S(1de53f0b,82e708fb,369fbce6,72595b67,5ccc73a6,15797faf,333ad7a,7ab16b,ce3ad57a,99b253a5,ede23b7e,e39c7c8d,e5a1cbaa,8bba04cb,d11d1183,c226bdcc), -S(e7ff8510,10f96b2d,80fefc2e,cb1506,3e29d450,13dc39fa,524dfd38,4e1a5ad0,eb8ec381,58f629b4,79599ab6,346fe86,c1159368,161d275f,e55810d2,84d3d768), -S(e06c81cb,ff536295,a2c025f8,6bfde632,ef52d427,2c4d002d,dba88b4e,82570c1,590c13db,1df2b414,d392d8ed,d8b2a303,3d50460,4f1b921e,1099714,c6e2fd1f), -S(28a5c19e,1a67cc90,f5cb15f8,b969d5ca,503b20fb,e5a52dd1,4304c5ea,4ed6ef5,66b9f844,184c75ab,223c5cb1,8b4ceeaf,490969c9,8cddd8d1,122c6e87,6b2e590b), -S(a7bdb9a,631e67b6,9474ac3e,fffdb6d8,454df8c3,87589e1a,7aa6788c,ba47f72b,99d88a77,61bdfc23,271675fe,5dfb2e70,6a728eca,dc83286c,2f7d0d2d,b14ebb9e), -S(44d3cd82,87cdb65f,90f38467,ee478633,8ba82810,ba9ff195,c55b752,22d27fad,35b7a398,80755784,57b41ad,43bfba60,78d7ee48,7d6cb190,9070c80a,3e1dc4c8), -S(7c42f052,87446002,3b609b2,8ec61849,221a62ef,11e6e3c0,718c1c25,27a03bdd,c57bd1a,a31b2fd0,690e0551,6ff9e744,243e0bf1,91161aad,8e798b39,2484d707), -S(f3555643,f09b3164,6c415bbf,c2031605,eea9abdd,9b76d431,10e61c9c,4afcbda8,2b982eb2,a3cbef3c,d1af4315,178f7c9,236f6dd8,e4bf9ae4,7ee56039,ef9ae98e), -S(dd917a87,6382ee0d,10e22c1e,3bd48a26,4d74cbdd,ca1a062a,8c84cf76,1c59d390,2c958858,2cc386b8,42fc7041,7994e479,f3027693,9011c10c,9aa35f52,335545e3), -S(220dcd6e,447f847d,d0d08170,e9a6a817,38cc5c8a,9e911b0f,1dc4aa8f,946d0cd5,7bc7de64,70ff4484,db2696,4ff06c34,665382d6,91d25bda,95ed8bb7,18c0a558), -S(ea30144c,7ac98f2,90ee04b9,9f5fdbb6,e08cb88a,fc99d635,a3daec8,3393f191,a41b4d67,abe18ac4,79d87a90,63b7f0ca,e5adaca6,cc9471ab,b121cea0,427c620d), -S(32825a95,6bc7e979,b03437a4,efeae923,fba1d408,9ea77ea,9a1dd25a,66f63920,e34d81c,e28759c9,ba0c8b31,e57a0a9d,a45cedc4,9e57addb,b81a3c27,30b5882c), -S(78d197a1,975db98,d2014422,58784a7b,4aeacdc5,f72df33,9aea0a9f,8cec5ab1,1fbeaf4b,8c470387,f2d35e9c,36ada81c,7ec62d23,ec8bfa50,2af1868a,92f9def3), -S(e74f8d82,a67f687f,1ffaf4b7,268ac9d9,dbaf42e7,6c1bce34,9d473521,8a4d1d42,695440b7,a234caf9,1f72cf0f,255d4dae,398f4077,93f40211,bafe60db,bdb804aa), -S(de66c91e,9ddd0fc8,96fa32ed,ac4487bd,2a8fcd51,f4f14c3e,c0cf19f1,532ad5b7,3b1f48ed,30df76af,b0630c27,9914594c,58159b83,42c97763,498c8ba7,deb73aa5), -S(9cdc5f48,299b1090,e0902be6,6fffcf06,ae630650,e5cde3f6,9e719314,d75f2334,5ba9d4e,7dc788ec,ba0b53ac,3a68309f,21971371,e2db812e,566ee46,a61e7fe8), -S(50ce38e3,809cd6c6,601a095e,d5a63594,2cd40f15,f97cb332,fc19d70e,a1214e9a,b7ed76bf,a0e0687c,44b66bbc,ec0fbadc,94fa09de,5b1476d0,6207e256,dca2fd7e), -S(aadaad2b,a6d873e5,a77ed2d9,ce26cb0e,349c7b6f,6847636b,566f47bc,7ef52c69,233b40ba,b4082ff5,c7122143,a45656f5,2989b62e,391bce37,d7aa245b,6c84efe), -S(7b219f5f,8f045219,5959621d,6c161a70,b4ef7a57,cbe7c9f4,fd539af5,71b8e0f2,8efedce8,dff914cd,e050209d,3bb91af8,c8d781ef,a87729a7,c5a6fb6f,8183ab6e), -S(31dda168,6e3ee50e,4e39f01a,68797bc4,7763ff27,5fa4489e,386d9902,c6c328ed,688d2e05,64b66581,cc5b1234,20a6c331,d33019c3,84a63c8a,a6f14be8,5d392201), -S(ea514512,aecfb0f3,94e59d7f,d9d558a8,cf535464,4f2f0963,2e2c6364,b1d57b5f,aa2ed069,dfd3144b,c9aa00d9,5037b099,9c35ba17,d6ee79cf,3e9aa5e9,f5dcca2), -S(bb2f9ac4,107288f5,66be0b4b,7b294e61,ec868a7e,4bb26a04,e4f473c6,9bc8e40a,6fb56eae,bd923ddd,c5028472,aaad2e0d,b0c80465,2e59c87e,45246502,606a0f74), -S(b9401bb,bcaaeab4,9ac42f6e,d36891f1,bddbe0a2,81ec4cf9,8d5f306a,ee9a5,ea40ae75,812da94,9bfcfeef,d22fa5d7,654eef70,34d3393d,6959a59c,2312dfcc), -S(dbf74d05,475cca1b,218bd219,8b24eace,99e0c4ac,56fffe3e,6f8f782f,8f338437,95f6b97c,eed1b3e7,b8de7f15,55f7ac5f,28649660,a458df0b,1806512f,f10dd82b), -S(cbc07e16,64041096,9e78dcb6,585abe6,9ee2dcd3,3febb64c,1f5b8bc9,419023bf,513e2160,56a3dd13,516092bc,fe6a5f4b,3c2b2843,a55ab69f,12f8387e,840a1772), -S(14504eff,814dfaa2,78704245,f0b11c4b,99f0c104,1d103e8f,a221a4f2,d3354164,a61998da,9bbce03b,e1bd153c,c33e85e6,cd2c7b18,a2ff9f6a,4cdba579,593471d4), -S(5b6d95ad,e3defd6,742e2e16,f4ca48e7,118e2ca2,cce878bf,f8b3f2df,fdf4895c,841ad4cf,b538795c,32000893,e0306415,b15edb8f,d83772b1,4de4f2d1,ecb180bd), -S(de084c,e1cf681a,f081212d,7e08f5df,89ec249a,fa419bf3,189339c,8a962f09,7790872e,2b35ded2,78f496a2,8e6c4907,8867c0b7,fd0910b,900c68f4,c11831da), -S(ed4e253f,3e7e781e,86290b2e,56eed44a,47b6f73e,74282d0,b7b54f7c,d75a97de,94a21c29,5850d088,d6cb20e1,9a2a3975,b27db744,4f19d257,cb3c1bef,1a329cb3), -S(3e8f32ec,ea23ba55,cb6d0fd1,41aa2225,9531ec35,bd7f3ec2,7291b798,431e2ee8,1875388b,5a9d4571,66179379,4e7c5046,ebd10c34,9f5df4f1,ed50c11d,952bef32), -S(4d2afcdf,bcdfe440,eb211566,efa59e4b,38385f69,5e7e2063,4c3b4606,32e5a23c,4694e00c,6b55863d,693d68b7,678791b9,f09df4b6,98df84bc,69940429,cbe10a39), -S(84fec62,e92704e6,1013bba3,4dff3876,5e4221ec,f72ae24a,1e80a814,632a5505,b74a1f4,9b9283f9,d6d01827,8bad2cc6,73cad8b1,99a1dc83,bc0ec561,78a2539e), -S(8114debc,44e517e1,1d900358,d0b831a1,38275cb3,371ac707,c4334544,bf076dd3,3bb2baf8,a42a57ce,d6e1942d,8324c795,cb05b978,dad8d20e,6eadf721,9f2b2d74), -S(fcec2f7d,20af0406,370f4aef,b2bd168,592d6a21,d5963127,3f3b836e,d1d881ef,b59d480c,b37372ce,d5ff46f0,5f1700,ea5dc847,1ecd2983,42599bcf,eb696ff0), -S(c000ee62,5a6ae49a,b0226f97,dbef0469,bd02e7fa,a8e3d4e2,b509a6ec,cef15876,b13e0e83,dc9c8f89,6c82ee3d,6cbfa8bb,4beea7af,5210a6ef,1d331180,83946dea), -S(142a5689,bc43523e,6f0c2922,78b7c68b,c588ca37,aa934997,63438dac,f5662669,cfdfe57f,2b80c32,f90af575,195dc71b,b7890d94,c27385f5,1451429e,41de8119), -S(3935bcce,35fe92b8,a2722b4c,5252f5,e6252b49,2ed2b8c4,759fea06,211bae0d,23a96df2,80a4006e,9674b0d0,e44ff5a2,f7073656,3539de18,a87529c0,4640a769), -S(46c985ec,74815b72,97d7052,35990967,1257337e,efb0ed46,93a06124,6bc5d717,952cc49d,f7f79ad7,8c279195,dd24fad9,ad75413a,5ab78869,f1c686ca,52dfe9e3), -S(2770cd58,25287db7,b352380b,b894ca9b,a8ee672,5153b7ea,1f28b254,566d1e27,c29b9df,d3028c3d,b7859d8,30de1490,e1f8abc9,c95994be,13696587,8ffe9b99), -S(8be87133,6feaa5a2,c5c3ce6,8d58159d,75c54e90,12922dd3,da4b534,31bc8153,efeeea2d,440e6127,bc12331,61a18497,68a280c7,6858bcb7,3a5980b6,baa4dd39), -S(675af413,e5bcd4e5,1c522a85,9dc1f3bb,14356298,62117c2f,90107af5,496fb8ae,54678238,ae95415,219b860e,985acd37,9d501ce3,c68b208d,2756cd64,6b357578), -S(5696c5c9,6f8f3b03,f1b3aba3,af85f160,67c309a5,bf4fb8cc,586a1f40,cc4e58a5,f675529f,73ed6987,ba2b1bf5,d202554d,8de9143e,809582f1,4ecfffb8,6a0cf850), -S(2e0f5a9f,5406695a,ba5bac9c,69865f34,ee2cfe1f,5662c055,8d88b422,76d5cbbd,7bb0e1ba,ea55cc81,29b074a1,3380f9be,c67af07a,e91ac96d,c0a46b92,6148fc4a), -S(def49b1a,84ce9199,bfeae925,7a96c403,5dacab0c,80e58a7b,a69609f8,7d3a5214,54c75dcd,2294d953,cd990cb2,a2840c11,813fa97,19178421,18f9774e,de4aefc2), -S(d33f0bbe,51af9602,83b64d36,fa6f8042,fead9d96,138769ed,25b55fe0,6e4b0013,8a9b41d8,32fb7aae,dfe94380,cf2fd2c7,c0e7592f,e3a8c32f,b1cd4aa7,6112227f), -S(6ad93b61,5b5da7dd,8145ea46,7a99fbf8,57529d5f,f25d1aa8,f935163d,4b2911ae,1fc64130,7e4228fc,2354227e,60b67305,9415c19f,d2a084f9,e9caa39b,d2b5cefa), -S(2c886c1c,ba67d840,6e33ef48,6c3e63a7,c3d9610a,67033bc4,f19c0840,784a98aa,79fe3de0,7363b7af,7d3a41ff,5d3aec6f,ef80426f,be455e12,526120f,5b884823), -S(10e59c98,b357ee38,3c306e3b,9c1be538,420881d3,2de1462b,aaace4f9,d84c252e,450e954a,92655710,c3e6279a,94fcb52f,c9aac9f9,2dccb95d,97109030,49cc71b6), -S(32725d0a,dfad10fc,c95db4b0,4ba65569,e88ec325,9cdbf02,5194c69a,3a18722f,d87902ed,f0f1ce28,3bbb3fe8,113f6bb8,9976348c,965094e8,1e24c28c,911d8533), -S(b066a5a6,da035350,33888fdb,87e28292,4ae805fa,45b462da,82ba0622,e6fce040,5337766c,2ef3fe37,42571ab2,286246d5,95ba7087,d3c38332,6490feea,1863a5d2), -S(6ddc1ecc,e8c7cb21,a681be75,a2143ffd,2663b75d,9ede8a15,d0b5189d,8c52f63e,c4da0af6,8eadeae3,ed9b5b61,a73bad5d,1ae8c080,2777441f,cb15910,153284fc), -S(c82cdab,1659a9b8,2ba0414c,bffaea32,eec1b41e,615bb47c,786abfbd,43698d7c,91e026f6,781ecd32,ab59bc5e,2ec3061e,5f6af1fe,bb6e627f,167cbdd7,afca63e7), -S(d932562b,6cfb8034,ea75e656,502ed81d,2b5b80a0,ae85aee1,29f677ce,aa5a282d,ad101b8f,97aadb58,d0b3d8d9,1cd24950,de0a8baf,646e9d9f,734f0f97,5043edad), -S(ec3f50bb,efa0b462,66993e4,233e5e11,f4bf4d56,19aad9c6,37638bfe,d8e45916,d63f29d,3f7b0b6d,b8514712,2343f51a,ff1cf956,e5f49bcb,3a9ea5bd,639dc2a1), -S(b5ff4795,4d6fe3a0,22303189,6eab5c14,bcb6dd3f,497ca561,1e3c9af9,b7e9cd79,16605e0a,5a862ccd,b9349159,13da9d4d,dd537edd,817a0e24,d0d59101,61105b18), -S(b1f153eb,697dde61,36beb382,da8702dd,a51e61c0,963c6d45,338982ef,dee9dc7a,fa1ba411,1823398e,23462cfe,339924d6,b6eec980,729159ef,20f8c8d9,f8143645), -S(42206dfb,8dc8eaac,d0f04c0a,da3a2cd,38c60bc4,6d1fd148,8fe12c04,f15904f4,c44393e6,2969b4b7,ac388f07,8b997de6,d4e08893,dd17699d,9a1cc885,84f3c5dc), -S(56cb266e,152ea2f6,1db917f8,c9b592e,3ddb2643,341da585,c4291d80,d7bfdc62,f7e9f332,8e963d0f,a3d149e9,c4c590d,e835747a,b75df64a,41d919b4,4fb18ba3), -S(5e1d6097,991e9fb5,b099e173,d263199c,cc3e626f,b512e6cd,cece57a4,888e6f9c,a151698a,aebc1dd2,93e29cc6,bad03cc3,2a6785ae,61da1f71,d50240d4,825962af), -S(4acabf0a,8cfa489f,34a622db,9e22536f,2da926e6,97d72756,eff9dd84,72d7b207,5bb50941,836bfafc,7e3f693c,28818a30,825a2b7f,39282d7c,87fc543a,5981d96d), -S(1a9bd6cb,59008470,48b638e5,576d24d2,175afb0e,fdf4c499,fb4aa143,328cd058,36fc0b8f,6605f00a,9822ba7e,c97fffc5,9214a479,eb6c361e,dad89e13,7d23b896), -S(649da46c,ccf59f43,e04c1456,9db1da2b,7506bf36,fd5a1aee,6505d8a2,bb812f5a,251efafe,6319ae16,7d69c617,46e2fb8b,edf77fba,b0ba1fda,1ac30ebd,21c65ac3), -S(66e9a7b6,5682def8,a7a7db04,781614d1,3e176461,b833771b,6001dcb0,f87d316f,ae3d2f9b,442bad03,e27a8d42,fbaf2f9c,294c82dd,fd5b892a,b5aa2a54,df3f9375), -S(d2f13641,6c42c603,82cbb4e0,108a937a,cfbdfbb2,d3195d69,ae3ec647,50fd2e25,e8de2060,b52a7ed8,b1bacdfc,de026f95,a9027727,4a6fc948,76dacfa5,5db7cb35), -S(2737e1e1,5af922ee,fec76921,7064ef52,fe555f93,b01ce4ac,e03d6103,93742abd,f9e08b6c,dba1824,d1cb2efb,d9c5bc22,5a71193d,5626ffbe,9f8bdd1b,48aefbaa), -S(e7a21d74,2203c820,e7da2fac,333c1797,a90b69cf,9b909dce,7b71c052,5c690576,b9888022,82323a5f,8c327eff,d4d10836,23e53b2b,7e0d0c20,cbb48978,f2326034), -S(16acf8f9,854c5d89,5f761823,9a557dd9,320fc976,d2df1012,502437e4,7778efb2,1dd09906,c2c229ca,28e49088,dafc49bb,5033eedb,4cde30d3,8881a2b1,e3368411), -S(74462c7a,64d0ee15,cfc48ab7,874a5f91,c4788e0b,dca9560c,eee55fcc,c2ace309,c9468199,6e11ccc7,ae58428b,310a2057,9f8d686b,a15c2ed0,7f999027,5766eea4), -S(77e35da8,705a03cf,ad891f9a,a2c2e56e,c0c5b88a,38f9ec3f,8dae4c68,cea94ae2,7cde0915,9188be27,54c4a653,ae576321,5a8c442e,6931c5ae,f4657d68,3e30eb61), -S(314c833,d308857e,cc5f6268,406463e7,e2d91a5a,f536647,2382ba41,70c403b2,3ae0facd,f3d955d4,dd4b61e7,ca1f2e7d,92656772,2c08274d,cc98d60c,4ee0bea4), -S(36466998,e5449878,7b27b47b,b8dd54b,617e9132,d6252fb0,1f760e7b,dd242979,7fc61d6d,deefb379,9fa87cf1,aa05da7a,84f750c,e7a37b9f,e30bc4a,4b350915), -S(427338f3,644f6efd,e43b1069,b34517bf,af02bbe0,7638766,76c4cfff,65a01bfd,5d9113ee,13c7917e,ea760105,9476aee6,572f2322,5fcb9ecc,ce4a9cf5,bedefdc3), -S(73afaa20,a2fe0855,c35f1025,aa78f181,fd57928,b3e63d23,8b125432,79327923,d82ab0fa,1f9f08ae,551ed521,b6687a50,b4b4b530,4d5128de,172c77d4,72acf933), -S(dc9ee41b,d5ba5686,319ff6d7,62f1af02,4619b15b,c6dce9c7,3c5392f9,62ecf255,bd5653dd,11485718,68521a7f,68bdbc7a,5f58f46,3e81aad,ed200261,6e95cd33), -S(c32592c1,4a401b52,867fb0f3,6de768ec,11cf13ac,d2eeb1c0,31cc83e0,a500cc21,d9e5f61e,b052b496,b8b59217,75d47cb9,d774c89c,76d76d33,e932c50f,ff156324), -S(356db8da,9f3fe561,a9d21d23,5264fbce,bfc08242,e304e4a2,1b4dd044,7c4288cf,ca4cf6be,9c91b8f6,2d66b101,79246c20,6b99d5e,eec50a42,88d1b7b1,3bb00e3), -S(3ec546f0,fb367683,c4d07c50,c58468df,1a36ba4d,887bd57b,f574cc8f,575f321c,ecd4a716,1c65ccd5,e767df14,53aca971,16376c5,861dbb30,33258bed,fad26f50), -S(b2fa7570,216d4194,64306918,f80d6727,4dde9aee,7b801988,3e6807d0,78722255,919188ee,a4c77dfb,a460af47,72547de3,bf591a96,fae85fa1,696a3d1,dad8dd8f), -S(593ecbac,a3f6e76a,bf97d83c,719922f8,3e17a2e3,a054eb40,e6cbf867,c4fc5d49,7d23ffa1,c168f083,3765170c,7ab2f66a,3d4f8c84,1b9f18fd,f3e92918,51421656), -S(646075c4,181fadd7,937d0b14,75450f09,3f91e170,9644ff32,a71176ab,4b973839,5196abc7,e219433,bbc998d7,57b34f78,93fd3aab,c3be5c3d,20b352b8,5a6c157a), -S(6518d32,d20f4490,a605e95f,2fe826e1,1f4d6295,21cee6b1,d4d505d0,50416849,38bb02b2,2d415ca2,3c95ab41,ee54c4e9,f383e5c2,1dba2dae,a2a24a81,599708ef), -S(9c67d572,bbaa2341,9f704542,95a6160f,39b42ccf,eb46d56c,7781f3f5,69eb155,3fcad5b4,953f933e,3a7ec832,e799794b,38c99476,e85a6a8d,58a20c35,b9777602), -S(3976b774,1e135f5f,2ea4a874,11f9138a,ab02aba9,b4c54a5,9ca2683e,262e09b2,fcd77da9,dd3ddca6,6993d5cf,f997be4b,147eacc1,2bd18c4,a1f18525,fc5fd5a0), -S(508b5272,6918dcea,c92e43c7,b697f2b4,9cbd9d23,1057d116,2d34058,e08b06dd,79d3e174,2bdabd3a,1faf65ba,82477bbb,3631f08b,ab87dfe3,1fc76f2a,a4fa8ec3), -S(bd5c99bf,44d5202f,3b1855df,7dfd11d8,71d7cee4,cfe38e6b,243591cc,ee69cc81,4b15cf0d,cfa1764e,365568b0,630423c0,2f81a041,2c2aec76,7c70d441,bf35a6fd), -S(2011b669,509f7a9b,6987692f,f1ee2a86,1bc8a6c1,f1b2d252,4cf4052b,129e6683,902dfb06,4304a94b,9ae930cb,b2d28c3b,835d3852,93b170ac,b0a8fee7,4ad64a9a), -S(24f22f32,25e5fd67,6ff10f6b,c9e7a829,322329c5,d716af48,ad95a32f,289cce7a,3c39cfac,e2a2eff6,1f034f4f,394ddcf3,31efd98e,3247b3e2,a60c462f,4846c4f7), -S(a845991a,70b6c165,f465ec35,fa698977,ebd6a3de,490f7ec,6a3d82ff,72a8dc76,b8b71cbc,84975cf6,2000b12a,ad56029d,b58e828,f1e37578,73231c52,f03bd158), -S(f75a1682,f24cd7c3,f654f9c8,38bf93b5,f5519a2a,39f7226d,3635f4eb,1e496577,be008fbd,d42449f6,8b571d29,48cda471,ee3a28a9,df4ed840,756d1840,4f917cd), -S(d438d864,6173e175,9962a565,5dfc0545,3e7edf89,22f79aac,78806b51,697cee7d,bf0149a1,33476cf,b6ad8062,94a937d8,6a929ad9,f19a5929,fe648798,6e931ac3), -S(42deb8a4,38b7d9cf,2216533a,22047aa8,3666c4dc,188c1517,b506c42d,add6a9c2,a2d98969,5875a67e,18deaf94,3a73d1cc,798fb025,46949078,ef2063e5,63362ba1), -S(abc5db92,a7ec7944,f4a7c07d,edf53272,2c62e77f,30852f7c,47b34df8,41b1567c,d4917a0,b967ab9e,b05355d3,601e106c,c93d7094,e8e2d452,5731350b,11ee3c2e), -S(203a579a,3298edee,6e5b8f,be8c3a53,825f798f,447fb5e6,c3d0a68b,69dc2600,6bad56e2,c4403cd0,423211fc,38810f40,31696852,af4eb6ae,939fce9a,a2253660), -S(f69ee455,42cc8bd1,490ae8a9,efae8a94,5c5efbc,ba078b11,c79c73,492278f8,2f1ba10c,e93b9f58,a19baf63,46706a9c,78b70faf,dd55d998,c394a8d8,713654c6), -S(838a8e3e,88527ba5,57c80ec,e8818ac5,5cd73ac4,aae26883,bd4b8048,f4fafb29,661859d,6d99d8e8,17bbf643,73726d45,1379744f,4bc93c7f,b228370e,b4d369ae), -S(99d1e947,767fef9f,71ebef00,91d2b7a1,f23481c1,fa3f7d3,4883a18e,59f6f846,673dec94,4b3d82b,358cab99,2a434932,91bad282,e0c9c41e,6dcc4f7d,5737f696), -S(390abce4,4a25d121,301d79a3,dd273897,29145890,c82c712d,760429d2,c7fedf32,e2e868b1,6bb5c3b0,f6305c4d,aa00a536,5e2aac02,71649fc8,b3e309d4,281db193), -S(4e5e2983,59d53274,a2c5ea8e,ae4d9659,bf7b9919,454dfd3d,a86a3705,272e2004,db0b88e9,a3d30e62,696ceac8,1028dbba,144157f8,4073e422,24026681,a7184339), -S(5bc3dcc2,1e1ecbfc,6a14e36e,ed26527b,6f44b03f,c16f146f,23c2d1c4,535c315,d16a5275,99e9b315,6235d74e,957daf90,1ec9f9c7,de9eb7a3,ef6f8138,1b5b29a), -S(8ba374d2,f56e7da7,c6a7b17e,a4234abe,9f6da593,77b13a5a,3f1089d4,cab2f7fa,1e0479fd,8410af5f,3b0bfa63,612146cd,735cc6d3,3e72f982,2b18419c,939d9f5d), -S(6c8747af,cfdedb6a,a45b90c,bad3b269,6bf15c16,202e36dc,5b0488cd,cf954983,75e49114,df83874e,f9ad28d8,3f3bef59,256503e8,f8ae22bb,f7f18f00,94b3b119), -S(3892cbdd,7fb925b2,18e6bca,9c58426c,9a96eb2a,a5f3db54,fb861d0c,323049e5,817622b8,96e224c9,84d265ee,bfd2a996,f6444413,992fd2fa,de91ea39,aec39e4b), -S(8f001a25,19acf72c,f9b3e528,7d060816,3f84b4b4,16d377f,9b70b417,859fb58c,b3c34e61,685378c6,b757b0fc,a961763b,af2e35f7,810ee236,f1d0d7df,92000cf4), -S(4a8ab909,fed31731,50f16b44,785ecba0,af5ceed6,83e1a2b1,6be2a91d,643fa00a,ac88cd4e,26a8754f,d33646af,faff3f74,f04480d6,b988e24c,a5f6a979,25325b5d), -S(49002f29,145514e,f9f81133,284752d6,ca973ef9,daaec307,6f279b3a,6ca9d1a7,3a73249b,318fcad0,65233591,2a07d90,39d1c05d,cd40865b,eb0d3fec,a2bc7c67), -S(1ad5bdc0,2ef4ff42,6d0d079b,3d680e5e,65b0431c,b664eda1,9baec880,6604db88,cb55d682,1e63786a,e496f903,d8b4db91,c22e48e,893347d8,3110ed32,34869d92), -S(316f40f,be3c495b,9256456,1daf8f94,3bc7533f,56d09351,4052be97,fc3f8c1d,eeff684a,8a37200e,ac0f16a6,90c1b69b,c52ef929,8bb1868a,2e9554b5,cd218461), -S(e8408480,72d6ba93,3fec095a,6320008,f28a073d,73625de5,a4fc0f7a,c242f55b,6ba42703,5ac578f0,6ab1e6f3,2b760bf8,b91f89c2,d37faa1d,86fbfda3,e0cf8871), -S(b3c81c6e,d24d910e,a9fded30,a61e2706,829f9e82,87a84755,bad14bf1,36eff3f2,57077559,8581b2e9,254a9c35,5aa6e25c,fe7ff2b2,7c1e0175,38161f6d,6e3da4e1), -S(9b0cc368,c402b063,669e96fa,17dd0c17,bfa19114,966319f5,7b5ffa0f,5c0635fe,c5ecb380,a239b714,99cc147d,8087b453,b01d131c,d49f07e4,60278983,e975614d), -S(bfddfb26,ac59c5f7,f6d9693f,c5498e49,cb1c2b46,452f926e,b120c79d,f49c52b1,8cc30f2c,4bb7897a,1bf13f71,b5618ffb,18adec2b,5710c0f8,d7e915c9,abc918cf), -S(989861b4,ac8b6cbf,56d8442c,d753c833,1830ebb6,369ce4c8,95343abd,2e887fc6,f7a269e9,3ff86bf4,23265f28,d4a392ed,1c8e1383,5792d43,cf4de508,3dbec068), -S(96a6e19d,336af93b,71093fe0,a63836f0,4286b43d,4abba61f,66aaa28b,1732b09,66df4497,c453f01,6425ec93,c6858ae5,300f3757,eabd41cb,da6a05ae,90f8f41e), -S(cc2561c5,1261c57c,8ca2318c,5c5d095e,7de2294d,5776aa74,9870631,34eba9dd,a11a6b85,a79efa99,e72e14e5,c3348d3c,d27af941,305ca3c3,1c48a0d8,ee247cd), -S(9f0b93b7,8666076c,c4f75d50,c67b6e44,96d23b30,b48154f4,f0b11307,fffa174d,256dd20a,f8c0fe19,8ca0cf98,befeb0ce,ca81fcb4,7fc0822c,76bc809c,13eb549d), -S(a7e5f4ce,d6eb2995,a0c1fc5,5a644b16,2ba6ea53,20c7abac,dc36e6c5,15cbd06c,ba65401a,3e1b856,53d98ce2,3596842,287cf1c5,fd249ace,8dedb067,8553e1b3), -S(c4949322,cadf34d,bd82a36e,331145b5,42fb3109,44dca7b0,e0beb9be,8131bf52,912f12e6,5f3fccf0,34e14147,556598a8,550fddbc,9c7f9844,637dfaa6,4d6dbf2d), -S(68040ac4,351a1f3d,ec88abbe,bae3072f,bcfeb944,94ec6610,4793ae21,a8285212,9d5f59cb,316f3a53,3f7eac34,ffa386d1,c555d3a9,49eedf36,b7276e32,e7ac416e), -S(f77daad7,5893592f,978438fe,578e5124,2f98d202,ad07f6f4,1dd4a238,8e3878af,d0f7fa3a,adee3b5b,27f95fb1,4d4e157d,b524c6f9,15c3f5b,7d57fb36,e82dc91e), -S(371fd993,87312364,852234ca,6dcc7d2a,cd58f4b0,c73903f,ba08a0e6,2a81540a,365b2f9b,b4938fae,a9065bf8,5cd88a40,4ee3a651,a8b226fc,e760161e,734fa5e), -S(eab4b429,32320270,ad6e3b6a,5784067b,6439d0fc,d5f0c0ea,579ae702,9d615d29,541f762c,6d825cc,66544ced,5965b077,943e270,ec7a7e20,b1401923,12aabdce), -S(5d8d97a9,fc50bd4a,fd326a61,5492f596,e10a52dd,6dc836d,44128fee,a43f0371,1acaca55,f82d78f9,cb28bc7c,cd9c2409,20066526,3fcb4a3a,f375e44,59c68e10), -S(d37ec7ae,89fd69e1,b9c64095,d5986a7e,b90f6f6a,9daa2638,6138a42d,357c9cc0,ddd875f9,6cf1e99d,fb4478b0,817899cf,1b6cb89f,87fdeb09,c72c539b,9c850e84), -S(7db9b694,ed838749,d320effc,2ed0f86f,1fb0f7dc,e2ce09e0,a5024bb0,d039c6a0,4e74039b,b6018328,bd89a2b3,284ccb70,6d464ead,e9562946,5374744d,222dafcd), -S(b02fdeff,df11614,63c01a8c,1a2c6def,41c5e64a,656e1daf,f8b73443,af060020,39666b4c,14e7c169,3ab2aea8,993f7dff,814df0e6,73c38448,caf88486,ab0307b0), -S(c89a4af,f4141ec4,5a586aa7,53a2937c,e6ad3122,45256466,31336c3e,f401cf2f,b4b2066c,f0c9b0d2,d1cc0ca1,5dac6578,dc7cf9c1,4077dbe6,1a92263c,141e50bd), -S(fd4a625,69fb8443,fe70739,f7c6f9,3794d7ab,5d25c0c2,c099b390,ba733601,741308ef,8600fe30,b912c49e,6b2cbc24,4b84bf30,52e690e7,2f478bd2,12b647d4), -S(f5322b3f,786e45ac,6655c11b,ccda223e,d4689bbf,e5fc6253,e248be82,c0c2ca6a,69f2c31c,96afab78,86220dad,fb9a0c74,c3eb5463,93142221,50369064,1081bf22), -S(f8daf170,7075b29,bdc36d65,a5ed4256,b21cee78,8dc4776a,e3a3c40a,19a2014,7b7fecc9,c302068f,80e73041,5eb31c25,4a38da9b,a72725df,898d4226,ad6585a0), -S(6317fe9b,cdb3eb9e,b7379d82,54253a26,786febff,88b5549c,d4f4614d,40c174a6,8c52a679,a471672,d9e46d44,d69167a1,b962ccc5,38e1a42e,2bf5c731,f94f43a1), -S(5446a1f5,5a7e226d,f1dd2c49,8d49e2cf,19ff8f0a,34c6bc3b,66fc19b,ec036064,826f2d2c,1c347caf,57c90c16,582ebf72,1d02a4ad,52b78254,2f97d10c,d9238e3d), -S(4973367f,ba057d1,9fcda3b0,37d2e672,cc3cb6c3,f2ffd427,c99822c3,b42154dd,8e9b4d0d,9008ef0b,c82764f7,3cc7cac4,331b88b6,740b0590,30327699,82bb0364), -S(3bac5c37,462fc0a6,11d3d47f,b4857256,f4180689,adb7c16f,885841c9,f56694a7,486dec34,2d7525e2,6766d0b7,fa0442ef,3defbb9c,41e4e6d6,5f458191,c5cb79c2), -S(1f0d6603,c942f882,cc8c8f34,98bf9fb2,eefba019,9d95943a,2a209964,bf585b99,869162ab,b05b77d7,337ef0a6,2ff485eb,af6d8182,1e96078c,611ea8c8,338c26dd), -S(2011eaf5,4d8d9b95,787ac7c7,9d8d733a,9846ef9d,ef227091,2f0d3177,599b7f60,d66ecd62,711364c6,c98c95ec,57dca58b,2f972e63,1a759133,c6cb206c,285d12c4), -S(b016df8e,4c7671d3,44e6e84a,64ac5a0d,af2535f3,b614b132,7c9b2daf,724b2dfd,823ba8f2,ba237731,aead8dac,68f0843d,fed9c5ab,8393de12,b0615d5a,908d6d9f), -S(bb9c3029,384c85b7,d9af0869,b5f039be,4a6e792d,1e863357,e1e95ba5,fab61bbf,79fa55bb,47b97456,f0d4d754,5c6a57c4,5824e868,7eae06fd,a07f227e,b49cf76c), -S(e7cb468e,271042bb,3197a88c,bd4a4b53,5581c5bf,455e0ae0,f3f35a90,8311ec41,f0e67e9b,10717789,628cd4da,8eac012d,c7c58083,3ccb18ae,d39bdf1f,b61d0dbc), -S(738b7b48,6ec3d4f2,4fb699e0,a6a9f947,1418eca2,5688da1c,722be81a,78ce60b3,d76aa53c,4129e5ba,88881647,a9e3320a,1751339a,3c10a8c0,b879bd32,e87f104c), -S(31413f55,d4e5c14a,e091c228,74e971a6,1658b881,7dc983df,4ac98264,4b455e82,c86d2a0f,467f93af,b8ef127f,9c818700,cf54f240,e16dd738,c4e90899,d8a5af35), -S(7ddae61,d231a764,794dd836,1779522c,2be61c66,e79f8a28,79914093,8a6e9e39,86aaced5,6ab82f10,5bbffa0c,e73781fe,5494c6b4,35309de1,441077cd,93d7a57b), -S(fd5a44c3,ee4cc565,d2115a3c,16aed5fa,7b005fcd,fff3e537,3d90f226,398c9a04,1dd95003,722e3a31,991dfdd0,495160ff,ea55aab0,7109d060,d414229,c8f5be83), -S(c3a768a3,fd24ac30,4cbbaba3,7cc52ab8,82e3256,b7d54d14,9628ca4a,a8687f43,2a0d6f89,9df7dff5,eacea751,a825ddbe,ecacdc69,5c071093,ad79583a,32de93c), -S(ccca92e,d2ad3249,c5dc5881,8540e2e1,c89c6ac3,9a98401b,f719f008,e8fa5a3d,5fe2b717,302699d,fb7dba86,c368f67d,6a6f3593,d3845906,3621f73e,28dbd1fa), -S(9e5fbca1,7c3a766c,eda0755e,84bc0f9c,1017335d,1ce0f70d,b8b09de1,568ef319,9f8e25d2,8a01b693,864dac0f,ac82453e,41305f50,3c5dae08,42ec41c1,5e7af238), -S(43908294,409a955,9d02f8b5,4084b120,bb980c59,9c9003c6,4ba2760e,c69118ff,343d27f9,5120670b,ff8dc482,66646eea,6ea37813,3ec1fb06,ff5d9756,64327e38), -S(30e3052f,3f97372f,56d505fc,6081ce75,662169a4,a4743cb8,de4e3288,32cf9c3a,d144aa9b,9cc60ab8,436afaee,a6e6b64a,bc0178af,b05c3db6,42c91254,8ecece83), -S(b5b28b37,6e2d4586,c4c3a7c1,d701b28b,50da01ad,c18b91f7,a45daabd,134a1d69,ca0eb341,26746304,bccfae1a,4200420c,41af0558,596123a5,c7edbe9d,3fe04fb4), -S(4eb1aab2,b71aec48,84d626d1,8ee1d90f,77feff11,cf3fb8c8,32ee501e,48c4ae8,1247cb08,580b0c96,ae5e72fc,f7066ca6,e46c5b3e,3b8091ec,8ae5bb30,e5a7cabd), -S(b814e42b,abd14fe6,55cc4641,22d024d3,7cfa9f64,ab59cada,fcbcfc56,f1fa9201,ed8db1d6,2621bf32,23fb81ff,922a0e10,b4ab5cf3,3370aef3,df70ae19,6383b06d), -S(e5ef7b0e,270a0c4a,3f4df516,b516a19a,cb45648a,424a4967,39b9b75e,ac4bc497,7cd38616,dce6fc2f,fbdac49b,59afde1f,397546e4,1fdd2c7d,b8e9efb2,6b1300ea), -S(e0228a88,c62229bb,4fd0d563,5a66ef1b,e499265c,9163d09a,40170969,81f3c2f7,63ec23be,6c858aa,8390d038,665664b0,f085bbd3,d3fd6982,b2150d8,6695e0d5), -S(3abf7af5,f504422e,686aaa6d,86f519a4,ec6d8ad,b1c7db9e,75091545,5885459e,95110201,2b8c0149,dffc0cfa,b1510529,9bfd537c,43c2a1e7,613c4007,7a8be9a7), -S(16c5a86a,57dbdc0d,84320d49,610b637,437d8a27,5bc108a1,702bb27,dfc04e1a,f5387f3a,7596aff2,2a9ead9e,fd87da3c,68bf5efe,b277899c,7ef19394,cc698cb), -S(8350a35,c1fc83f0,3c306984,799d6baa,3a41bed8,45cb2126,ad8025a5,6f1da1ea,3abd0a5c,83976b4d,79f150af,f47a684f,931090d5,61a61a50,a4ebfa7f,d74aa002), -S(58199602,d1ba3202,bffd7311,8679e8ec,7d5dc6f7,f937eb4f,be70b8b,4379bce9,290dd5db,a4091af5,50975e3f,1f0d42e5,d375a26a,5c6768cf,7eade4c0,ed315166), -S(492c0e3c,8442495d,52d4d356,91d03e3d,133d56fa,7371d64e,ccb384af,907fc5da,c7bbfe15,342b1d6,c48cfe7a,595bbab3,d7c4674f,ad9f92f0,30e2d602,4cd10ed8), -S(adc96fa5,f21e4e6,5c5951d6,53379f3a,b2d92ded,ac038d70,ff1e644e,7c7d4de8,750faf48,16e45f4c,697a610c,11dc363d,4846564e,afef6e7a,335d5d,2af0e171), -S(9567b748,4584b4ae,21e6a12f,cc8b5185,e2137c1f,5f30deac,eadd6b55,ecb64964,b9a445c9,3c4d8a7,fb0b4469,45976ee2,cd47ea88,ca3269e,b559e689,84b1a130), -S(e700f079,11611a38,b0ce3273,b420135e,17ec189d,d1574695,d3452530,c8a59f99,e6685c21,6ed61c08,444b51ce,86681796,8814c1af,aa712a32,15e6619c,85bb0bc0), -S(c412823e,31b1f066,9d067de0,d2e2ed09,bda7b53b,6482d8bd,7f352a4e,74e4cabc,8809a001,3f12ebaa,3b01df9d,355c199d,854574fa,374a85fd,6d066377,6957e9e7), -S(50675ee9,1d350fc1,61e189e7,a4cf4955,d987c194,1b01ce9e,1473add2,ede4cde8,2f67926e,7c4baed0,e0a25df1,468c79e6,b07f8bd1,9d460a24,4233f988,45547047), -S(34f8f31e,7a6d98d9,73eb395b,3368b0d3,c566cb2,c2a8379d,bec31c1c,859dbca2,db990a81,fe7a234a,e63b751f,369ef489,aa6929d8,97a3587e,483d19da,dd1b40e2), -S(6bca946d,e15dbd77,9bed6b31,25986a06,50051c2,db72ebe4,81ed24b1,f9cb4d5b,ba942bdf,73219596,9fb8357a,4bbbdc33,c08f1c17,da37e409,50077c6,da41456), -S(3972511a,f367daf8,192f2725,8597c14f,e151bb46,5b8c195e,610a11d6,e51451ae,36f1e442,82786dd2,8f05981d,292c2241,9844deed,5bed41ef,fb0aa2c1,d798541e), -S(756e5104,3011d1c,e992ce99,76c09063,6560e9e3,a85de433,6d9218aa,11796c34,4d714894,96279d96,7ed41034,77fb1c87,db269661,8c452dd,ca0fda9b,e8c31951), -S(e5508c1a,b9e90d6a,237e631e,507bdbdd,ed3672a8,38ee0f7c,72eb4587,b4231e4,24fcc0fd,f5079407,e3c66b02,9e2f37f3,bec5ba72,25487101,b7e68b08,731572e0), -S(d90085d8,d80452b5,cb99dafc,8fa4aa3e,819c6ab9,a407beab,4bc6446,b5225596,e3cbc413,bf74b383,d2f8e92a,9d6062bf,a579fe37,e171734a,e50ac682,da75710c), -S(46470f31,77b6ecd5,34add036,8cf9724e,398963e8,573d3d01,ce3f9d5e,b14f50cf,1a670f11,15b60d70,ac4c2b27,8f7a684a,73446d52,e3c2a8ef,7a84a06,8512f6e), -S(4e92916a,a3787bda,7cc677cd,6f7d26cd,4a6847cb,23d1e3d,beb32de0,51fb89f9,6bdd060e,739e3122,a48e7657,e03ebf35,bc43f4e,3ad864cd,49242d29,fd3537a4), -S(78fec768,fbf2658f,78f21a83,5f9e327a,67d4101b,5ca9fcf0,e69e7421,d69a3045,5de2a6ca,25adc6e6,82333b72,f30557e3,f2f003b8,1dc817e4,be0ea20f,acdb9f59), -S(36327d81,a5a94289,105df5d5,7ed407e8,f14a741e,998f1017,3592811e,f052a126,3325ff53,33c1395,d2548216,4eb153e8,ed94a950,8376cdee,941e3417,f2f0ea46), -S(2e3d6f12,18373ec6,6435d58,92b54576,545668bf,80fe51ed,eee5ca7b,7a5f8806,6f2afbd6,6465fce8,308eb046,1041a23e,f4515687,64f8148d,a377e329,4b6dbce8), -S(96dfe31a,87620ab,647e0c2e,6e9bad96,4ac4ecce,28d299e7,e80f25af,da5885c8,9a1d9194,3507b674,fea7b185,21a2b70d,ac27b4ea,b370b9b3,a0c2ad0c,2bc37628), -S(298711da,2e303ebe,2cc5928f,e437ce90,ba675b2b,b896ee44,920fe3cb,e34ec55,dbe55194,8671be1a,1af18584,5db9fdd4,c4a586e1,98a350e4,c1326d04,5aa3c593), -S(cd603c3e,326a7c25,575b07cb,d86e0a9,d764675a,b3013622,12ffdf5,708ed855,f0d100ce,2690b76d,62858759,8638c992,4736b18,8beb66d1,328ff5b2,4a1fe52b), -S(5a90312c,30a58754,cfc6d248,669d029a,7da84243,9de2b1dc,7731a460,b05b6e21,fc0af827,5890da91,ac2032ef,e82b418a,2ca1c37c,4a19ed0b,8cee0ffe,7386fb37), -S(61ce7b79,1d46fea8,8f4dfb34,474577ad,8ecb02a,ab23153e,c0ece543,5c472e3a,4c5bebe3,2b82502c,8c68ecee,57f29fd,ee7f45dd,fe5bd985,2418c809,6ebabede), -S(df3ffe23,d13b2b4f,4090daf5,a51f343d,17123083,edc4172c,368ca75a,8bfbb16b,9a21d41,39e53dc,836868cf,9c1d0eef,d4660455,7ffbd379,cb7a118e,36273f2), -S(24470f10,b0e5171c,aeaab136,2ea9c1f2,3ff3a4d9,66a1b7c0,5110b734,43a363db,ce557547,69df589b,bd4438b0,14d4f4d,bfb56977,43656c25,83981c78,5803d5a7), -S(67b07bd3,c96164c4,da09d5f0,be038a2e,74ade7dc,cda4e7aa,28699156,36708765,e0183e53,445a2936,a44df51e,c6d42bbf,21369b65,134accf,c0a6ca68,9adc03e), -S(7e3c57f1,43f1157d,f06eb86c,e7a3d625,df513d2c,1187b1ef,2b4a8778,cb9b1192,81aa590e,90de3ee5,3b68d336,c6c77dcd,925742d5,642baf50,f41e6258,ebbdd5b2), -S(784310f1,462cd93a,dae83002,7904934a,2a6682b5,6124c5da,ac037d87,61dab615,5365ac1c,d2f3bffb,f8454ba6,6743cb70,a08781b8,ce95efef,b2b7d60b,fbb7e2e1), -S(ac75ac17,87006c3,e687effb,5822615f,c5608cf6,3ce43ea9,affc8d,e4a9167c,d75aedc7,42240a0a,79f79c91,93c9aee2,9bba3238,a5ac9154,d98d9664,27faa81), -S(943e4dd2,ae1d3f5e,ba7448e8,15d44c3f,ed1b2333,46c6b1b4,b6ff8386,980c6fd3,d08dfc2d,29ebf8d,30fbcd9,e93e4d70,d42e6526,bc2e7842,ce3cebc1,f8105b58), -S(4f750c16,909060e1,f7509604,9030e65,1e6a768e,a3601d3d,f2f0eef8,e18df94,e434f91a,cd77e31b,c9adb0ca,87860de7,6360c0b6,88accd44,715a114c,aac8eb7b), -S(1a609a28,76eb1228,58678cd4,57c3b762,9f0208a3,ba653603,3f887a4f,7df50ee3,99dd674f,864e8662,3ae00cbd,2a484dde,29e9de3d,7ec83f92,ba60f93e,bf316b31), -S(d2fbcb43,5c932861,2d3fcbce,f84ae490,3003b61f,c7927cb6,d7134196,f8858c76,55b6ca82,280880c8,3d66ea27,e8e24ca7,670bee29,1c4fdc11,56bf661c,2f2e0eaa), -S(5c6e8973,c1c98cf6,71d5cef,4acc76b3,b4c5165d,ce162d04,543d4fc5,3d97cf62,9a3271f2,d829451c,8f32652e,c43b717e,a6008478,637b32c6,66a9a40e,2f157c2), -S(be670a91,1930e634,a65aa675,56e342d9,15037a49,845d46d8,ac14a8b7,6024d8ab,4b4418a5,6583d2b5,6a58e324,a7b57eb7,b5111cbf,8c6a39a0,5b22d86e,b51e2dd0), -S(afb47c08,42e4ec13,13fcc64d,98fe73b7,d6bc3a97,c2ac8823,45a82507,e3842e3a,3b448b26,f1e586bc,9425fb77,37a70de7,f559c1fc,97c9fce9,5da20bd3,945648a2), -S(6de4f9b8,29fb7313,d27bc525,c5116408,d03f653d,56244f0b,bce94fc5,2de49039,653e08a0,26d7c2be,dd67b32d,5d031255,5c5e9c5d,b7aa632,c59f971a,85ea0458), -S(91cb27e0,1e60b6b3,6bb7df48,2dd4542e,d36951d8,53971a85,127f414d,67ef279b,5db95774,f7b60f6,70ac3c7a,41bfce24,6aa8816e,4545040,df4bca6a,7173829e), -S(a3e3386e,86c6d952,ad929b79,6cbcc967,2677138f,b051b3c0,53e2b4bd,2d6b7d0a,e7364d0c,b404b835,4f65c0f9,68ae823a,be5c6cdb,a02a72dc,b5ecf7d9,64eca22d), -S(fbf251e5,6b61ed54,467aa548,cf4a4667,258f0334,f6064625,b00d546b,c61f8e10,1a1c0c11,14634786,e9101685,15c0ea29,bf2b2537,529912de,13ef3fbf,3b789722), -S(e0bfa77c,21555000,4b38957e,a287519c,c222b0ef,81f71d76,9c3608aa,7ca6e7a8,fd778438,2ed98141,1254767,d770866,84c3eb94,1fd4a506,81cb05d,311cad5f), -S(6d612d53,3d7cd076,d1494641,af14db85,7db44e5a,c22ff57a,13c198cd,b2cb50dd,62cee347,915640f6,73a23081,f5999fbd,5fccabe9,b84a0409,ee85160c,93fc6dca), -S(393c515b,5d1f771a,e6134c4,c06cda2f,27b01b66,c3976ca6,9879de82,146e0dd5,147e097,83f65b3f,f5e29f6a,12df5fcb,2ae22d9,857f9653,67efc9cf,6210ec7b), -S(bb340fb,c45c7b6,8d3b1863,9ab961d3,b455a803,c7ad6807,62077c08,6fe10bdf,cb210b7b,bd7edac4,fafecb0a,82efa8bc,3b6fbf63,711d24d,2b0969cb,f39ffe44), -S(139ad93,4a0d12a2,83c50f54,99d5cbff,fa746252,6856a5bd,98bb59a,42f6512e,1c2582c6,b1da1d1c,4c8e85a1,77bc212c,ac448eac,564f0ea2,a23f721d,4c153ede), -S(b49f8e1d,ca33f0fc,5713a853,bfdc8e16,edee6fe8,eed7e310,ae0e6d73,e4483c12,2d2d0750,bf422c6,e49b12c,407bb05d,203a44e9,92e0fe5d,af596676,7552bbaf), -S(78099937,bdd416a4,8c9480d6,82a9741d,d57c89f6,a4ab2b8a,8890937e,b3f16713,b3981d6a,8b4f3045,e3d20e74,264b3d78,48b0f9ea,f8d0ebb0,2bc4a2a6,7da3a93c), -S(64cd225e,a4604ff8,b61a8c71,c3f71d7a,62423add,5c851e89,b2430cf,f6300ee4,89f2cb3f,560f0a1,c5e26497,149ffc59,cf4ea956,f20f039e,f2578092,5c2b4a5e), -S(70cd9c8b,7250da54,cc7ec051,43f087ec,c1642e69,b5b74d95,e728a0e2,27f6415c,57ac1d32,dbb0e87d,9a8ea661,87c4bf6f,bb4aa780,18f7611f,c94419e1,6829af3b), -S(a20709e7,d075779e,baa742d7,1e224373,dc7f9692,f56fa9a0,e8d81847,28e23c5c,3f269cb3,28b57b3f,48db2e3d,aebea0fc,c1d456d5,a366052d,2dec91d3,5405a53c), -S(fc3957cf,c85c590d,f2d6e797,c0aeffcd,452ed47b,57213830,20b3f3b1,56149203,65ef1279,884a1a2,bf632178,e23fd9ee,3128a268,bd75b70b,bc03a177,22daae7), -S(e21c288,805a1fbe,8c0df51a,c5360c8f,69c0c10,624aa044,c071ad18,8dca17d4,9fd946d9,8cb67d2f,200fd03f,c3f4fd77,2ee3c24d,6bdc0d89,55e314c4,8151944a), -S(3f6b8f7a,d68d5d6c,fec93aca,7c9716e5,9bbeeedc,dcf2dfc5,713046d1,1617e06f,97112f31,f5e31334,e258e311,bcee3160,3c75f8e,4a67f039,50dfb30,8eff1605), -S(c630444d,7d6a8d6,f396b431,cbad44fa,88f034f0,aef8f6a,ec8e4921,a3373204,2d459073,ecfba3c0,f538dcbf,65a54822,b8d615ef,ced3a394,6d31821a,921cff7e), -S(1b2bab7f,4e833c7e,432d81db,d7b34e2a,e62c3c43,ad1ba0b2,f3cd3d38,88d96f55,e2caec88,ec4d6660,81cd2bd4,fcad109c,fbdce4d2,c0a24aca,d665fb56,e4e143d6), -S(b6a433b3,1f1a70a3,e53775,e5d173f,3d890bb5,b7ceeb9,a62369e2,94705711,95d10503,8959c755,95d8d76,c30861bb,acbda484,9a448481,6f4931cd,34e59d1), -S(b12a9bd6,4b0f0cdf,9568e3bd,a6b7fc7,40f66c00,398ef73f,74dc968a,cce34b7e,ce8dbd0a,9ec6059d,b17f37a0,dd12b6df,6d809b9,47702dbb,a0e30f31,6b10a6f8), -S(f16e345c,70a20726,616ab118,a5a5f252,b0e14377,79208dc3,194ec16,7e8f1922,62657132,12d111cf,bbe9af4b,be8071d4,55eae6a6,d3c5e153,4efda17f,5cd66f42), -S(b4b85e71,f1ee5898,4c660f17,e48ea158,73963356,b8adcfaf,5257459b,77d02399,baf95723,70486c9,567d6258,ee4b403d,70966cbf,4ca6e0dd,b5f8772,1e053f45), -S(b43dc473,1f85b542,4a8252d0,ef1e5681,720405fc,ae4e6406,7d721eca,552d4128,5f9ae2eb,f5f08f78,12181d44,6111ea2c,ab5c66ed,1cebb8c4,2c1e4a50,f3653d), -S(3e657382,cbcbe472,cd8f7e2f,6ed72623,9fc1fde3,15633d5,b3219e70,cda875a7,ad430305,8aeb7ff8,9be1b737,260e1e7a,5d6e8a08,3ad7f5b2,2912b9d4,10ba267e), -S(c30ed331,8f2a76bc,3bf292c9,fd98ba86,3039ec2a,b3acf028,174da3c6,dee3e3dc,54b642f9,3c5ca6fe,987cd9c5,4726d4c8,f59f464c,b847c319,df74ce4e,7da24376), -S(8ca8ad3,7ac218da,1f2c33bf,73a681f0,1c3fc0a9,35bd7540,fbc3f2bf,82e0763,e48ac338,eef9096c,e3d0e679,249c9183,4d0cb3bc,b45fa70e,7aa8356c,8fd3fd53), -S(a75b601a,aeb33b04,d3e201ea,bedbc5d3,35f516f6,3c34fe6d,e7d58a00,a6bcf3c7,b1b814e0,b143a048,75a4c5de,14a74d3a,ddcae6b,b220a806,1a980b18,4a3b49e6), -S(e542c034,9fbd716,d92f0aa3,ab2c7be7,4e81d38,39bbf04c,38f9d933,33e2447d,93f4ddd2,af3134a0,89c3ccf9,34f61ae2,67530a42,12cdbd4,7641f7b4,c21e732b), -S(460de699,4c3b21da,6cb661b2,3cea142f,cee1b50d,efaa3d72,3d55d54c,60bf9258,93de277,b9acd4a6,89bb02e2,b284cf78,4731e219,540c7131,e2636ae4,4183ba80), -S(e5df9251,7e1611d8,5218f013,4f4bb212,9a0a2bb3,b65b2678,45c83bcd,60f29d05,758dda47,b25e31fb,56a8c18c,f91773b2,6bd26548,6925fc0f,a5e34787,a881f731), -S(7bf153ea,7a8cfc9d,e7558c8d,5354f7c6,f8b41e14,7ba7a8ef,4296289c,f134e6a,94367f87,3ea37ec,cf3e1be0,6600f27e,5a4c32ac,1fc4959d,f5f9a6d5,c4e161), -S(c9e8e330,8a57d46d,65a3ca70,86a0440b,1bc37ac8,8dae6d46,66c4497c,5867688c,c7f12a8,d727c5be,5d2dd18e,1a996ca6,b5477b78,a2b671a9,6fd6a391,95ca831e), -S(dc45e141,d9f18643,db12b41e,facbb17d,6d30da7c,65ceed2f,c481df55,1b6fa25c,52d23e99,46eb60d7,acd8cd47,ce592359,9216c796,320c6657,cb4e411f,e175f104), -S(f4b4ec85,6b55bb4a,aceee0f0,56cff661,eec827c8,8a452911,8bff2ace,3c0b4a81,18d14680,57ad90c7,161f7667,b512f34c,fce3bb84,c135c474,d67c4afe,49b589c2)}, -{S(e7ff8d5c,83bd5846,5c967b5,37ac0f36,b9ffe9d2,fc7531e,ef183cb1,7369c066,9a9c3c4b,e482031b,f6dc69fa,843ea90e,de165479,26ba201b,5f05b00a,dbcc30a8), -S(ad51f3f2,e91d632,a13569d9,2e0bbb82,f566e7df,cc8d5541,54dffddc,2724c05b,1039c9fc,c61bb90f,7050e8ab,deecf700,80509a64,8fd2520f,9789501b,315da78b), -S(2459de87,8ed4337c,fb77d945,4f6d2e15,7153048b,1ff76121,f5ea4fd5,cc77dec3,296ddfe4,ef31a5c9,65300ccd,6bdcf369,20e7b2c6,c1368f08,6e416a48,3d517fc6), -S(959743b4,de6c9311,b95949e3,5f20f06d,6cbdf08,ad40b2a0,5239cb2d,4fe99ef6,1726fe6f,2e6815db,96242e97,ef5dc384,b8cd9ff6,67ae475e,a5417100,bc882cf7), -S(fa08226c,62476f0b,88392127,219b071,6316d6e7,c21b3a44,4a07a2a0,cfad3bf7,f24e916,75b2860e,e6e6416f,d9e6b119,ee65e6dd,c27f02e4,3524509b,bf9beaee), -S(da3f52f6,1102d1e9,3c213935,736e4cdf,72ad32a5,32db4f2c,3e388eac,e403b3ee,93c3a997,4d4c2f61,9338054c,15f681af,d8da7b13,cd89607e,dd5491e1,9d695416), -S(893806c6,fc32e583,997b5859,870df579,dd750d08,49dce8a8,2cf47cb9,a92ded25,959c9301,c7982c96,4e4bd09b,abf38f44,bbb54529,82404e22,7b862e48,adfd6276), -S(5cf0831e,319d8690,ee7f690c,c0b15734,9152c12c,acbd82b5,49c8eecd,b4f17043,2cf5c316,25fed805,97bed5db,4cdd3680,f97d389e,c83a5fc2,1766bd9a,6f95b607), -S(7c0f67a2,ed9c4e10,7e06248d,51c79f70,7e62b409,afa37f0,2bac0b80,f2b04417,748bacd4,2401ffd,e374d639,86414233,c4b7eadd,5449bebb,9dab7248,c5dca538), -S(1c2380e3,d084e808,751c4e06,d0d815ba,a333c94c,ba5f6de6,379dcc86,79f4cf6a,2d6480f4,d237bc92,d05e761b,4818051f,afecec25,9afe2cc,cd032537,f3b21e8a), -S(411596,bca0efd6,f1262542,cddbbf3c,a90852af,80689683,47f9c0b8,919b0696,6774a5ed,2c06a3e5,d369fc8b,1c1ef075,bcd96b15,8f724e57,38ebf92d,7eb6a983), -S(862e0b2c,19500fd8,8d00f2cb,14af4628,bdcefc88,ae87a663,c9e901ba,c2cfc537,6fd77f08,124c45c7,44ec81b,e420401c,399ee4ca,aa8779af,9f4a9b9b,5bfb3c66), -S(fa787fe0,faa2a7fb,8dd1ec29,f81171c4,82e893bc,2aedf4fd,4a762bc6,dfc26752,428f4df5,8e057e0e,491fc4a,82cae796,1cad059c,9ef367ea,a15a4a24,42d91241), -S(e15885a0,2af497df,34b4c324,d22c88dd,a3e34da2,74de0b12,c2c9ce12,d566d33c,3ec3b7c9,209357e6,1f360789,a37b4c78,910d2518,3d367ce,5af7075a,842a1e08), -S(9c7f6bd2,8261d396,97365037,b57f2767,91ae02d3,4de1c089,646423e1,404fb32d,844efbb3,e720a3dc,a5431147,8d0aba48,221d48ce,8a05a385,9505f4a,458f7fb7), -S(b99277ec,fc7ced54,58300c7,783d1d43,67d40dfe,48cc1743,e99540,b46eed6e,91832791,f0aab15d,a293a4e,c107bf69,64895eae,ef0b7b4a,4db1de1c,f8f7bb97), -S(ea5c5c32,6b221ebd,47bf8838,91a0ab8a,abcbc30e,982a5add,5f7517bd,58f68927,9258ed81,2f732f1a,43aa6b76,f9982d24,8be669e9,42cc5f92,90925d07,b96c651f), -S(c8e45dd0,37f1538a,ddfb79e3,5eaf2d1,f5c43535,50857741,481b8bc3,b00270c4,46183384,f3460d3,702632c9,bc340b42,2baeabeb,624d2aa8,1275ced,e2d04df4), -S(2785615e,b34e2395,5fef2170,18ce8e9b,8520ff6c,7f0b0654,40e2e44a,99b633aa,5f4d2fe3,8f56db89,5052ccad,b7e2229,5295ce9c,9028f37f,709cc9ca,6b86368c), -S(bdba87f2,7b750cab,87e4f36b,f2a4ca30,49c5af49,d11d9562,fd67ee3,5215c2aa,507a9b83,dd4a40a2,3aa5970,673f89e4,3dc6c387,28b3db8a,78ee2c9b,40a2b99f), -S(bb358e33,a07a280b,b87b703,6df7d832,6e531a38,c1ff6f48,5c955057,e97a2524,d62efa5a,435d192d,c40c39a7,2c654e34,a6d8837e,b33a602a,1097f1ed,40f1dabb), -S(bc59cb40,190d6454,c356e22a,af552e02,a6f7f671,8e56ab94,10ed6e51,539ce74e,3a3b07b7,2404e40c,96c561f3,ce227241,e7035c13,29c7e566,8cb92126,c6543af2), -S(19654121,d2e13ac4,dc087c0c,373c8e98,e4447c5f,83c976ef,2358cac0,d7b726aa,9832eba,58a67ec7,4d993935,b2451ff,3118c1f8,bf4f2d98,5ac9b2b4,dc4347d9), -S(2f222e27,6c7059bd,88d87b7,a7268fce,c7250741,1cbf52ac,7ac1ef04,dcfdc769,5d7695a4,37686bc4,df42d1a7,43a7c025,820fde6a,1fbdf17e,846115b0,3e64ddc2), -S(9a34f22d,628e0863,52860024,7b4e3b76,60d2c88e,e663a6ad,57f673c8,238a7e6a,86c1a12,29bb251,c6e87b37,d135cd90,e2a7d01a,4a067f67,6d8895f7,57085b46), -S(e526e57e,73b17b34,8288e79e,4f26f864,95beed8b,f9476dbb,26cda51e,b4cec5d7,5b7d63de,97200b0e,e76b2bf4,82e01ed0,19324e63,16e5142a,8058128b,6409e8e9), -S(7a28a623,cedd623f,37b33b39,149858f6,ff7adb4f,f06b1661,3dd23da9,2b68626c,41144248,b2f62a79,e9019071,aacbf63b,b8ba1238,a6738d90,ac6429d2,d7a485b0), -S(cd3a96eb,8c378c46,de954c9d,8252dbaf,1db12f7a,88a55190,87d046cf,58df5665,9649b78b,22c76b71,919b8a2c,7a0d6a4a,5be2f0be,4f1b8a2b,ca2e898,15dcda74), -S(44201d8c,23ae0de7,6e9ca9ed,e0a052e4,753a4a12,87129b55,f33ab4ba,5bf095e4,730f8bf5,53e528e1,ab26d7df,a5767a04,b3fd8653,7769cd0b,8d1b5f49,bd95692b), -S(1d5fd8ff,14da9436,118e41a2,55df6bc,52a69e6a,755d7e70,a48ffd3d,ebc4c88c,a53b538,a3c553fb,4bec6c1d,259fc11c,4259126f,12a61f5e,1c4bdfb0,de34b167), -S(9f96c868,f95bbd10,486cf72c,a1bd1cb5,e45768a5,8a5142d1,61e03b78,8f1c92f5,7a9f8938,fd39796b,6eec3f74,a970b183,dea912cd,cce14843,86ba0ae5,e6b2e785), -S(671e2f85,60f16300,f60173e,18ff716a,9028b22e,8937c118,c21fbf11,f54b1e15,58310025,7287d122,2a866a6d,8e85a041,72531a92,7d727e8d,77c33049,32f50d22), -S(59215ba3,afb0aca9,1f61f7de,d69ac95c,3b0a6ab3,cc5fd312,2d23b287,7d645805,433b9b65,197f8360,d222580d,832c2cea,dedbc92,610b8c0,4e0ed5b9,45b52583), -S(ce3be955,ebf0a088,57bc0859,55898466,8b428982,ef1061ca,a564c48,9fa8b57b,81ce7ad6,224e95e4,d7449cd7,41628408,48249b,d2e5d0b6,6757cb73,7622def3), -S(5f6145e8,1cb8ca27,a9d1fd53,9058f5f1,cc423d07,a23f79e3,d1256541,689cfd5a,f129799e,6a9044a4,784ced66,40285789,c8b71aa2,2fb9a2e2,92a73f0,b7686ee2), -S(ae14d7e5,ce5ff7cf,a419effa,9272aef2,7e0ad99f,1b440679,9d362033,2640672e,5f8670c,cdc2b366,90d07259,9fb1e560,5e71e079,2bf6a2a0,928a8438,1c42beac), -S(61837dd8,7d096602,62119a7,f102eaf9,d01edcd,8c6a9335,488b5c80,535573d0,dbd49194,1eeecad9,3bb5688d,6bff2bd9,fb4573ce,b21dfa1,2766de1e,1b63c8c2), -S(3ef98234,eb70107a,f69be2f6,b3f935f5,f1bec759,2b66262,f048c8a0,8252ee83,451acc9e,7c4c21,346e9ee3,dcfe4a77,d35bf00b,d0f2e3c5,42591441,c90b5354), -S(b1e94abb,912be054,1c38bd4a,a954ccba,f92b41d0,82a74ca8,59ccbc21,755d00be,e8d76ab,ec5aa0f2,49b33481,ac6abb04,700edc61,da8627a1,26812abb,ae5f67e7), -S(a0cdddf5,ac430d5b,f5fd1755,6025d4ed,4f9a0471,83749ea6,232a8061,f27672fe,3c50bac3,f0c01cc9,5c10cc51,b14ef6d9,fed1a7dd,b6d07721,947cb606,8ac81cc0), -S(c0650540,c32945b0,8e42c487,50f2dcde,8c35dadd,2069dbc4,28c8a318,48c0b841,660e38c9,eeb11cb3,aa2b61ef,d7ab4796,85161be4,f4b1547,e701fdd1,bb3dfaef), -S(fc2efae0,77ef8607,286aa5b2,5b114f1,fdd82e6,ef425b23,5170fdec,5d95ffc1,f96a8710,7fa5aa8f,6fc0cce,9885840f,737e1b12,4d6d35ff,e1dccab2,4a863901), -S(d420dc89,758a24be,dabeda8a,27651138,2eacc153,3395db23,71ca98a1,8fd72f57,83f34a52,7245d018,d2d599c1,299845b4,42a06b9,c93142f4,74935632,9052fae), -S(af32c241,a6c86715,471e3ba1,4bcfb60d,c9c33ae8,84ec4403,97b35281,b36ee336,9fe0c80a,1962f8e5,5c2060f2,eb24a7db,1187037c,662cf832,18e0381f,4f92083b), -S(cc44e6b3,c7d4dd22,b4e24310,ba7fd59b,efcb05d7,1411781c,979aea2f,635c62ab,cb05b4de,c8ce6dfa,2f229629,48edb6e4,ec0f2a8,aa53932f,94cda08f,b81e3da3), -S(a7d3a168,b175a11b,ca46067e,c603ccbc,1d7cf852,edefe1ba,ae633a38,318bd97d,361fb00f,5344bc31,450732cf,30b8d728,2aa100c8,4c52b160,9b0dd3f7,66405a2e), -S(41ce228f,e6911ef6,5b93a0d,39d4c4ab,1b4f9ea8,9f34f190,56b6edc4,90834b65,85f7677b,61323fdd,7c0b21d8,572c7029,4118fab8,d432d330,dbaa24df,bf506964), -S(a3532f8b,1137f907,19baa4ae,b0f6f909,412eea8d,290385dc,9c0465e8,a3f9f900,94848f20,d1f41d8a,c433f01c,74a0f120,15f2423,23780597,6c6ddf2b,a369186c), -S(d51d0609,2a9316b1,495c380f,78cf6b0f,53f11fe3,b89399ab,6120d494,b18ec5c7,8efa991d,4a35009e,1b0f7adf,72207c6e,a1ac67a1,6fc009cf,fb25f63d,7706efb4), -S(2155010e,7820453a,4e18b616,6439995c,35e9f1fe,bd4b8c98,31c2f062,ad5db9c3,d951af7,792f7575,a0209ed7,3558efc,8858aaf3,a7dbdd05,1701538c,e0abd925), -S(b02e9c81,6370cd9c,a78da82d,927e1d43,ff27a07b,a8a3e773,a66fa344,331d1d1e,e184e2ed,276eaa1b,40cd9696,a98c41e8,7eb2f0f7,fa3039ad,9a18bfab,48141331), -S(d79e98f7,724ff7c7,13510c81,a00a6056,b769dc28,25ddb5b6,6e21540f,a0b9df8,dae7bca1,8896e67c,9f8855d8,4b2dc1f3,97e47230,d4915e99,33897687,c1e7ab0f), -S(1754242e,1719e21e,5dc63a64,5759d3aa,5003d20b,db8a2ca4,a5375e78,308c4423,7373ae8c,97c5def2,fa602af3,3491f50,b26a986d,b1255f63,9b3e1f26,3ad0d856), -S(a7b70ad8,4807a34c,45adf85d,93afb7a9,30ad1b1d,25d58847,c278957,bd96d64e,9cc8d7ca,d66f00c3,5e0c9476,ceb4f915,76cbf1d,2ff34b80,aa913e5,758bccc7), -S(a4e7077a,8be0e97,d322f62f,74fb5112,c885975b,4e5d106d,1df93a05,10382a76,52580b99,2959cfac,bb27800c,37e0605,7a26bd85,c97154d7,c51b5b01,f0496749), -S(14371fca,1e37adf9,3593be37,2e634fd2,69d004ea,50d2f412,77e0b74c,d82491a6,5130d626,4d570bf0,a9a1511,af29105,eb1937db,fae1f027,45a2e725,bd63589c), -S(3a23c190,995df13b,12556cd,90c4c05d,5bfd4154,8016d31d,85ea4506,356ca3bc,b32f623f,a95922c1,9579f532,9fe6d0df,b3b3c63a,adf1f56e,30b946d0,e6be0352), -S(643cf33a,9530502a,65e26491,b895ea3a,27be865a,231dc0cf,b42249b8,b8eade6d,58321730,ca9a20df,ea6be90c,a7f056b1,ec3da1d1,e2befd74,5a39a46e,24257f04), -S(35fba1a3,f33025ca,96401513,b443d042,c5036ca4,3221b0a4,ef5fe943,34c1a27f,5f5a4c87,a7499afc,4de8a475,8651e50b,d97c292,f5c4fb16,6114e871,d0d651aa), -S(fc62b528,b601895f,93e27224,843b4d29,9d542c5,2235430d,c3e85c1c,4a0685a8,c5ed07b5,4b4f18e9,26be84fa,9d1653a2,716c8e8d,3a0343d2,e6b78e92,53a411c7), -S(2b15210f,b126f37c,6bc76ddb,db6d24b9,dc39d531,8527a917,ed1553cc,524ea86c,deb7b72b,256402c4,24ae46e0,f2e4e09c,12471358,3b73f41,79fa737b,3f53facb), -S(1e011ea,5ad8f791,e430b18b,d302d3ab,b229f715,a68f3d49,c1c2f3b6,285fb369,b9dd2a2a,25937c98,6905428e,73d811c0,8e1d5729,bd6bfd8b,50eb91e8,4ebfb1a4), -S(9bbdefcf,cb0c9e8d,747180aa,6aa72af,917fbd5e,ee2e6dfc,f05bd301,56496e4,6824df9b,a8ce39dc,e7da66d1,a430be26,9faaa54,a83f5441,2d5ac6d5,761bc83b), -S(691a5651,e5773488,24a36cd3,755c20dd,289a17a5,953608d9,905976c5,4136d4d9,c03caa0c,a1bc376,b736d2b8,812966f,6f1b955c,1e68a8b1,a12120ba,ec4f12ab), -S(f68ec286,730a42b0,4ef5c596,b0235e5b,50eea2a3,94ae6f9f,a91086da,47acb9e2,5ef0b31e,86dd166b,f447b7f7,2b82ceb9,668f2a90,88a190a1,6bd5a230,8699a54f), -S(33685765,121d623,9f73b969,efe2ccb8,ad715377,c7f110d1,579fbcca,5b005ccf,cf71270c,c3c8d129,8d6f060a,f6cb343b,b7c807e6,580779bd,1df6d7b2,e90d80ac), -S(18c1347a,cd1a2eeb,7f42bb9c,de08e166,63676348,fdd4c533,d3f51064,b940dc16,a9ccae7b,d22c73ef,eca3a4dc,a56c3cbf,eb3f8177,d9e5cae4,48568a5a,2d83a31f), -S(9235cbd2,37fd6ddd,d596bab0,e2cd4d29,98a28d5c,b3b738cd,6f79fa76,83570357,60bb571,7ee5c69d,7ed19477,94b8d2aa,7901b993,89496993,1e3480f6,89d37742), -S(8d6f63e6,8b7e79c7,1d62bb8e,8e1f3ec,8c5dfe93,21f5ff57,c930ca6,f9d255e0,a1eeab9e,f6bc9a38,45836630,4a1021d,ab2d4f66,4c5cc6d2,c50be827,7fe61915), -S(e34a6e35,8163ec00,f6abbeb5,14b5453,9c7ea2c,8afac9b6,81402ea8,de5947f0,375f0fc0,882bd435,1f294812,b0fdcf5b,8f36b772,5bd93994,343d1bab,a3db8b33), -S(7c92a80e,483c9c33,bb18163c,7b4e7710,96e77f5,c182e4ff,95e8737c,9294b2b5,f9775ba5,6779dec8,dd5448ca,ba1bf760,5c531e2b,f71ffe22,2b8c2b60,93cbe3fa), -S(15d91f0f,49153ad9,3fa9bd53,71f98b4d,84d0bc8c,13310859,547a510b,94ed08fa,c0b61781,ce3b4f30,89e99387,e084827e,b148be8a,cfaf6a8f,1251a5a8,ada84194), -S(68f00c8d,4741c078,f99595c8,230bf510,bcb84a12,9149ba8a,5b495d0b,d3307226,49004e85,f9eb6650,83b1ed05,12199ba4,2da74f30,a70898cb,2ed05253,fc5a809f), -S(c2cf12ad,851d4a49,56a2f861,2cde0fb7,caf83f2c,41af4d98,b74f039f,b2a95bc8,f4643722,186a375b,be0e17af,9832042d,62132982,ef33a626,b6a02f84,f086b59f), -S(8d378751,b5f13626,2fb3eae8,5491a3a0,b3af4b01,f759f06d,4b418116,c3ba30a1,5a47d6f8,878671da,104fb6ab,7101efa1,718414cf,2017221e,8cb171bc,a13d4d), -S(cd4e82f,2592b5af,1cdbb44b,3dbcd3ac,76d0ad92,fca50789,f1152722,1eb4f3ae,734884e2,6d207cff,a145ffda,2f3304ca,3697958b,b1f5ad2c,9cc2c812,99128107), -S(b9983c8b,61629cea,2f44717b,3139b3c8,ad1dbbac,24f8ffc1,db9078b,92e8f8b8,1e0b83c4,349dbfd7,16dcc892,115e93af,2cc1176b,7d386686,dfa7a2c9,a56810a8), -S(1d2d687b,ddc2f510,f0a721c7,4ff6d8c0,ac157929,189dcdd6,2c508577,aabbb982,4c3427ad,4dde568d,5ed5555d,5de4cdc7,fcb6b071,afd342ea,7fb3966a,872d2d5c), -S(9073d8ee,47e31106,718dcc5d,e0e46e0c,bdc8e822,66bc8fb5,b23bcf80,ccf240a3,6a2a92f7,bbefae74,1472e3e5,6702ab5d,a6d20993,1cd7daa9,1a3d985f,5aea46c3), -S(25d31f95,1416d832,59f433aa,89e4df66,49d18a11,1395d676,b44759ee,46931139,40aa1c2,9a4ea4da,d24a915a,7d476769,3a1881f0,d70499ac,f4f78f89,91cf3b8a), -S(d04504f8,9b93075f,822de8d2,27dd8617,f6ae2fe8,10ac8fbf,97c7d788,bd459cab,7c4d4ae6,56d118b2,17abb932,d6283480,5be6a4ab,cb98ceac,8a85085,8f0e2d92), -S(a4afa77,7e76e1d1,64901460,bf63e3ad,c84fa1e5,7ee4cc17,d8a083e4,2e587f1f,f56ac642,f7bc019c,61dea3ea,6891c962,71147228,33d8055c,954b45fb,934325e2), -S(59eb6b42,7e586eee,677ce715,c06ffd16,35ecc418,caf8b707,5e2c9192,f838e4c,cf25adbe,5d0d1c37,1ab4778d,ddb1333e,6b02b377,8c73302a,43262b5a,312e8415), -S(6fbde8a2,a9495849,c0e94866,e3cc7b7d,891738a8,7bfa388a,cda84358,6190ba65,e988c40e,b2cfd713,597290f1,7c37d165,df711c9a,f2ce6989,52204cd7,4b8cce9c), -S(186a8e0a,c9a61bc1,ffd397a7,62f153c4,fd14c2d,78a03e03,8fe826f5,eb5d16b9,d1ccfb7e,fdfa1486,8d35048e,99050caf,73bb0236,ffd33bd3,bcb431c1,868e5e53), -S(3224499b,b9712ed6,b1dc5157,6ceb2d77,356dde1a,263c370d,9a71582f,c4e93ed0,5364c748,54f5e7c4,950f5aeb,d3a56626,7da78898,e3a37af7,a2c5a528,23cdfdd8), -S(b2de,174a7592,ce9b287f,82bb4f60,3a4aa039,4bb308f3,4d282a0f,8e8a1105,a9fa1bcf,424a0d14,5e86c4ed,be0d5a31,dd85772,cecd7fdc,ba1e4b02,b47109e0), -S(19d45a35,f42efc85,283240b6,8f69626e,92cba511,5d265093,b33b71bf,36601850,757b26d7,65853163,fd4818e6,91154aab,c81448ea,19277b70,da37e910,e2bdb66b), -S(9e23f113,8a337fbd,42335454,6e2e3503,3c888aff,f61b4143,3673395e,bfca6285,80ef2fd4,bfdfde72,ab5c2ed3,6e8eca00,54d01eb6,a93542d0,6a562d6b,3342f051), -S(6b494c5a,79789306,9e236dd4,33a15381,f7ba8b42,3502efc1,896ff5c0,16871c28,56ca6202,a860a1c,25898600,eb2f2fc,f5636c0,bb2ba0db,f32cb433,b590812d), -S(b3e4116b,3d05150c,af5821f5,6c33b111,c28a3f18,8c8cf2b5,e5a5f271,115839ec,3bc7caa8,11f4b7f0,c30b0bac,51852c16,2e256b93,dff1d54c,4504fa1,eef9f5e4), -S(9f67548,4e8ce41b,e65902d1,ef56e8e8,46193052,3fcf48d8,e1f49fd0,9d9cfe91,3d8dda39,bb6e6c78,1c0861d7,73461dfa,7c19e10f,dd20f37e,a6d3f152,b1bd1d98), -S(47aa3648,91f116b7,e4115bc7,7419efb,9a267adc,4bcff4cb,1ab58c75,5eca5e5d,1f9ec89b,b253b6d2,997abf0a,46d4a3d,de45d605,a94f4ea,a4ac136d,b57eff2b), -S(b8ec4a26,53d82b24,da269a85,f51fe333,d6f6e9ec,94dd4bd8,3a90b68e,1742baa1,d4564479,b9c3ce14,882fd697,1db7d242,c91a4b8a,da63dd6,41c17bd6,77dda872), -S(ad2d7fd4,dc176f04,2c8a78a2,7eea73ea,7fcd0b16,29bbe1fe,f9eb9589,9173af0f,b4014396,2f84f00e,6210258e,ca6120ff,987601dd,80df3501,af664ea2,3f6e63f3), -S(aa9676f9,85435e57,4db82def,70905ed8,a8cc4495,539a8ab7,42f9b934,e6f1eab2,60b257d,83b39810,b6220fb4,95e61578,f264e817,71dfe6f3,7ce8363c,dbf8ea1), -S(12c23100,2fd6b31e,30929a8,e8d6b02a,593a89d0,b3f20a54,2012ce0e,d74738e,bf8e1682,8b06c853,f061462e,b5f90191,e1af5a66,1d4b01d3,a7be42c9,7f2a3ac), -S(5d1f0df0,d561494a,5e8b9566,a297c018,9562b441,ee91ed93,a43a4141,b7383c13,88a65ea,c63e0dae,244e3e7b,b7fedd20,6fc32f47,35891902,c0dbdece,5e304ec1), -S(ea92ae52,1b21942,78ca6b4f,770c56a9,59403652,39533c74,b0b99ea0,1e32791f,22358430,bf3e4aac,e7c6ae80,7c315bdb,7b7b94eb,4c17442b,bcbae6,b311562), -S(961abd49,90513726,15d8414b,d68edb80,9c698317,c3317d94,d064e272,f2e7c328,b581fb5,949a2345,f561fcb3,21dfcaac,9c235e70,f144079c,3304d48d,d20583f8), -S(41e8edf9,b2b5e7c8,86a9c82e,2780da4e,cc551d3,5f186c0a,caf456bd,fa08d7ff,8afe0efa,fb1b41ef,189ea40c,2f7c1df,f76f740,b2b4d30e,b0afb19e,92cfe615), -S(18cd2b39,1cc5a7c5,8fc7855c,51e9a737,f5bce753,bf7f35b5,3b7ac1dc,b9138f28,86493807,f42083b5,1ce4114a,d159098b,ccd4b6e8,3bbbfd0a,bbfeeb46,6f065ed), -S(2369e0f5,5cfa67c7,788b1d97,a7aed58d,ef0a3727,10a82e8,a459e55c,8cb998df,b3b5c65d,399bcca0,71829793,55d59d4a,f8dbaf89,8c10aecd,d35330fa,dd2011d5), -S(722b21ec,9e6436ba,c87ed647,2d28c33d,e4e4c792,de5e9b0d,85581f19,32f91f9f,5d757d,d475ab0d,390861e0,fb204ac5,dbaaeb48,d2a48014,d3a03ded,3293c497), -S(3b6661c7,33773220,40a45f9,527f1e6b,b3657e8f,de4d5beb,b4213f6c,130933ad,d480a018,3f031d7b,c4ec6965,5b0d3ce8,bc0f5ff7,5694977d,d2810188,f739f8f0), -S(2baa92ab,fd1b3a06,7bc34db6,d3a1b82e,afa2eecf,f82cdfd3,a2bd2da8,d5072ad9,4583b0a7,e1c0b53,c165b5e5,cd4e41f0,27179f60,328fe313,4b0c5d5b,9b32b3d6), -S(2fd0279e,bb08f28,5e4e385,6ab7bca8,dac262e9,968c2341,9049611b,6db8374,e377f24,92d0bf24,89a8094,5516f528,4871dda3,26e6d3cb,a81c55ca,41d62d5f), -S(911e62fc,dfbb1636,bf80d445,d711e328,4ea6c362,629e2aa9,f8f48a4c,8a0bdc32,2339b90a,a771f035,4bcf1f38,d7dbd8d7,643f260f,65f4fa2a,bec27e3e,ce6f8471), -S(5ecf9075,7d277b40,fe4ef091,a525cafa,fcabb2d8,da8b7670,d3d25680,b1c425c6,9690ebc2,1de37095,9abdb2e0,37b3b34b,db367933,888d9db3,e903f8ff,c5b85d7c), -S(270a9301,2167aa21,5c5da736,fe3e32d7,efa97b65,f7c89a7c,62a6ed28,e3038e3e,445f24c3,8998530d,39964c6b,d51d75df,fbe176f8,91b606ba,d4557cfa,a71d9f9e), -S(bc9e7f14,8244cfe8,b408be81,b79d904e,bcec0cb3,f4e540fc,f6f469d7,f73151f2,5dbda6e3,49377393,c6d90189,26bef6c4,59fd597,c50848eb,1808cf31,13b7e704), -S(163e1b86,bf0ecf2c,61a630d9,428f2fbb,7772032f,df990bf,1e276e98,a84ba2d9,3c25bb36,4f1d6a0c,c70cfb84,70604f61,4bad22fd,bf305058,667dd0,5934711c), -S(1706ad54,9dc1b0f9,bd1e5fd2,729802a9,8e6f6d96,24694b2e,3d37615d,b5565999,b16c7d90,403b6d24,65ee6526,54ab19b2,5c43cfef,fb6b33fe,12c56912,5618df71), -S(7e66578a,356ac4c9,636e0369,a7b1368c,cbe06189,602aa938,95a48826,a5c4d2c5,77e51712,195393c8,f95d032f,2bf1d39e,60b805b9,f5aedc31,a511f1a9,ffd976d7), -S(ddae1e49,1e8b0572,95884c3b,ef5ffbaa,dc6a7ecb,d8849521,177f7d81,868caca2,be7719ae,508d035d,88cbc2d8,3ea232da,657c78ea,401bcb05,9382c39e,959d5251), -S(5b44e6c3,a382e500,2a53ba57,fd6e92ed,8296341a,2e81095e,8ca22a18,fa76b450,443bf958,ffd1fa9a,1bc8ee27,ef49e457,cb23e6bd,dc6d251e,8e28130e,e6ce6892), -S(33d32ee9,f66d00bd,85d7e24d,7fa3172,8352668d,56be6f1f,71cead36,b1035f4,d3372856,106025f7,aac97103,4efc5c51,4c6128bd,6737fe,325ff277,f25fdcbb), -S(7bbc0b90,9491363a,cfa10e65,84d693f3,8b2a2164,1d2d886a,3c348c86,d7f98e11,ccfdd17d,532ecbe7,c654ec54,65928836,1dd2ee63,136d36aa,415fad03,f94facea), -S(a3da83e8,db0f8d0c,ad680373,f92426,26aea70a,c68c641d,648b2d94,244d68eb,305b0d91,6337a600,4f17626c,835a1cb4,c5d97f35,f75e7e44,ae3ea4ae,10d5b40f), -S(f5155f1a,2b196a3f,aa07d4ff,5fb91890,d37196af,1354d1b9,88ea4412,c57e9244,d060c7fa,f1666aae,f38d5256,b20893b4,961c3b4d,40fa9739,7a52cd00,4a2af8f7), -S(c948aa6c,ee9b8481,fed5b207,5100f0df,db799e6d,76d1af83,6d198f84,d6a028bb,6943ef15,988941,3b274855,1e0245c9,52172cce,8eb29444,e7728c20,a8da32d2), -S(518ae279,d1dbc26d,3b940b7c,f7c98eec,bc7660d5,af24dc72,ab8e6b0d,329b0d32,c8bf4d50,74471ad6,2f4ad9f,df065490,c81c1ce4,6a8b8847,b1e1b826,99b5ebee), -S(82fd524f,467bd6f8,bf84b427,d81b643f,ad38940f,ffaa2da1,f659dc6e,263ffb9d,2ccd7ea0,ffe0dea7,f591df01,5d1ae314,71f2cc9a,67c610ab,5bfe8f46,57a0647d), -S(250edb5a,1b6e4778,4dbf0bc1,510f9716,f5682aab,b975826d,2f715427,8d56cb5a,a625aed6,663ac946,ee805c8,11328923,9aae6503,1efab534,e152ded,e4d1f138), -S(d13596ab,e37d242e,ec6a50ad,95a171b9,c0cad0d1,5e6cf674,35cc87d5,1be1a6a9,fbbc5a7b,b3592ca4,5a994365,cb67d31e,68d2cbc9,ff790d44,366a6a6a,f85d80e5), -S(70f6d617,e21a9df6,370d044c,53804f62,9e6589d0,5900b9dc,849a8d05,719fd55b,5fc30143,ea245a03,ec0e9f01,a1e99f5,9ae16eb4,e693e3f8,732fe9be,b2c9b4bb), -S(f633f446,9b1617aa,8731ebdf,2b5e98e8,8ec97865,751bf6e1,f509842a,aba63251,3de28e7a,de2588d7,bc53ede7,3e9acbf5,5688ab6a,2cca8910,2ec03998,f70a6d28), -S(e3364ef5,183476d6,757ddd79,39447825,e06491b7,9fb5e6b6,c98e3280,e9dcea5f,f061aa9c,c5bb20e1,9084fcf5,a8e799ff,75670c3f,3fad80e3,ba3973a,be12b76), -S(c98a303f,7bdd7f06,3e09dec0,e9b5f449,f470e4c5,cfa11162,25517636,2ad7cf8c,94dec242,a375b65c,b1fad8a2,ecc6de3,c2f4be0d,e8751764,f320ad9e,35dc5de4), -S(fef6c023,5025dd17,5c8f5f02,78f7d9b4,515b7915,359e1c8d,bfa29a4b,67c1d654,9bdaca13,7b42cfba,f1075814,3409879c,249d5028,b1ef10e9,77a73c2f,749e9ce2), -S(c4413aa6,18fe751c,a50aeecd,478757f4,b23e8193,5304248f,8d93596a,fa489988,7003e5d3,3bca34cf,625d8cdf,f6910bea,16a39e5,dcd20fd2,1822b51e,55098cba), -S(b9719377,b83703f4,efb68dfd,b61c3d6c,bf9bb302,3747dbe0,c5c95437,6d56fe3,e57f0725,462f5f5d,b4c5162a,9b01fc,f52ea86f,6a7a5670,3daed54c,3672d825), -S(e72c8bff,84730fb9,7342adf9,67ad5eaf,6a90282,ed52b70b,6d9dc90f,e2395fa9,10f49bd6,79c3e7ab,21aeecf5,bea893d1,9836fe8,9a228a5b,ab7289f1,5f911543), -S(4e197fbe,2d935c0b,9280ab4a,26422b10,93a0fd4b,85a686c,7abfb2d7,621564b2,2c74f5e6,4e5205a2,7efa68cb,2ae9dc38,7467e102,5ef54a0c,4acc7319,4d372a), -S(88639d8,35b91e12,f381ef72,2c9308e1,fe898804,6432d577,7d515ea8,1797f360,1a49a5cf,75b1c8b0,a842f222,565a35b1,41b3c2a8,8d1b8881,34ff86c8,9ca4dc41), -S(a951d30a,c53e183a,9d74088f,8fed089e,1719f04f,39368d31,c0cd7b3c,b873f2ef,7f9e5508,a782c449,3ce8eea6,52195560,a1dc74d0,cfd8bb2a,4368fcf2,6ec783cb), -S(67028a77,3ff55e84,d4f19a99,f651d9e4,abcdd680,1add3739,c1688c18,22ccba72,bb611a0d,d5ad4674,e9a4fa5,63c6bcf9,a5dddf04,f195a9c4,c917d36,4d5a2ebb), -S(ba7643e5,13b102d9,f8fb5ae9,cf106d11,5d97a50c,d7e5cbbe,c13d24a2,be04a85b,f52f2e3b,88a49709,352b2421,2691882a,eb853ab5,7437e712,b83ceec9,2c25d7cf), -S(b3673761,b46a0444,cf221e48,22ba2f72,36e0c3b3,d16962c4,6e52bf2,334f099f,69dfa764,cdbca112,7a173798,abd8148c,eced792,b4cde92a,833db24b,992ae90d), -S(d6815b9b,296aea82,f1504323,1e6145b,cda92a3e,915daa0a,8a179902,7becd8bd,bf3ef3a5,8086833f,c579f9d2,2b7af47e,f97ac341,aa3aa2ed,2c74eb66,58178360), -S(b5c7dca1,94b68a14,fbd05f42,63b0feab,9e1dae1d,42dcac2d,1a30f70c,bee14c34,ceada44e,540b26d3,c37eafbb,12cf0cd2,54a9528f,77d37e1b,c19cd226,1aa70d08), -S(5a73c77a,7426af6c,f2d393aa,40189923,e47eb697,58fd76b4,5c8159bf,f7f8b900,bc90f626,9d8572c9,cfb6cebe,b6700fd5,49fd0157,ab545a5d,1f1970a9,47786b1a), -S(4e38c28a,e5fce8a2,ebee4340,e0d99788,340dc758,f3740072,41a297c6,41d8aba0,ecdf41ff,e5533cc7,8a9ee3c5,77dcf2db,bf589531,ca9e1ed9,d5b9e23a,27915eec), -S(59fb08d1,c85ddda1,dbbe6b64,7745591c,68bb7a44,608a22ec,9a83902b,14acdd61,f4c21cf1,6869d2e5,355ac8a3,227345d4,eacf74bf,af742fc9,413354ef,8ca1884b), -S(62ac0b80,e2040117,14a508b4,42cc0564,40f38eb3,e4f0e19b,4d8d05cb,bd19382b,e0d4ebf2,5bca30dc,95c0cfaf,140a0d67,29341751,881b955,9e03eb70,98ff11ba), -S(ec16d69,b7cd751,c44ea4c4,9b7c917f,45cf3c57,efd49263,58af0837,70c32498,8c8aaaee,14344b77,23c17e31,752dd638,fd8bc3ea,cace7522,3c712b6e,82d1316a), -S(3dd4a6f6,9d614c5f,87de1bc3,101beee,8b66a1ca,749842ac,dfe5ed3d,2d4b780a,2d5e6b54,464bd991,113c5ed6,50ff5af3,ca2a18f2,ab43ed6,5437ea13,3ba99fdf), -S(5e404405,3710c999,a77d9048,cc651c54,718936d2,d4d8d8f1,ef416a54,51861aec,c6c2bc4a,1e8682a,2426b02e,92bb7094,2f8db6ff,fa6b375,79b50146,66f31f7d), -S(66032f1,f55b606f,fc68ac3a,92683cb0,d447137,430ce435,9d1f06da,10954f99,fb14ad80,f168e517,fdacf38d,c197fa71,6ae1157c,ccf0948b,a7f0914d,ff8d040), -S(25c4c534,8ee76e19,799d3f9b,f56d3566,57332560,693e362,b7935ebb,85d7056e,1d7b9e9d,6e52f220,e82647c,a560c02c,ebd3f608,f11260ee,c9b16b58,76123b6b), -S(fd70c030,435fa972,793551b1,e409739c,6f148342,e833bb16,c4dac4a8,a853f0cc,10870dde,23c4097d,505f2d17,d3dd93d6,eb9c1300,49cb0fa9,2ed63c0f,feb73e80), -S(ded2703f,3fc6bcc1,eb96a925,650823df,583ae86c,cb43836a,19ca31e5,69c1cebe,5957989a,db61c969,8d61eaa1,938ad6b,cfa3543c,e13811dc,cf5b4ba1,24d62a5a), -S(9943048e,7097dc4b,709012f6,d298137,dc8e471c,a66ccbb1,f023bcb4,938c02f4,57fa4b31,b80df627,b9c212b0,4bfbbdd8,d1dfdb03,ece420d6,35d0ec9e,4e86384c), -S(313dc488,9214c7ef,960f2f95,b55b8083,d1adde1c,775f7f6a,62b57c01,aed5b95,bc02f247,668a334e,349d8ebc,6d7a1ba2,1f99ff1c,ddd10c2b,59aed3c0,815b1e5c), -S(1b9ce18f,9360e5db,8da1fa8c,f5ff96a3,1a898f19,2eceb059,c39f6cbd,4de5c920,84937b84,5336904a,4047c917,6d1f54e5,4e1a15a6,52a97668,6249987,82f230c6), -S(4bfacb3c,18ebd5d1,bf71ca5f,b1b6bde7,b314d2fc,ca1c05bc,f4021595,e15c6cd8,a33c205f,d4ac1624,d4ebb554,816d6435,86e08ce0,6ccc762e,232cc7ea,d65aa5ee), -S(f6843448,522403ce,a3e4597,30648835,2399f699,421db1b5,2fe33bb6,d21c614b,ce80913c,eb14f530,d153104f,202dad87,2f000f16,fb60316c,bdd40c79,4c95ee85), -S(930816a1,ca19458b,c2badcc6,3cf66d0c,6312f52e,853b5365,1b829b3f,2666ca70,4b29edf1,55385f57,63dc4008,77c846b0,4c810747,4def410a,c796f58,f61b849b), -S(b9d0798f,2ead9231,7face0a8,31869066,76711e1c,f3a9a465,8f51c039,7f76c066,4ecdaede,bae33f4d,79240d11,ce0b0564,62ad9f0f,51b6d7e9,e69a283a,4770053c), -S(1e8a7b02,60d58ae8,902fc57c,5a1648c4,e14d1a6f,696e7aec,c2cbe5d7,2e5439a8,e8c76d70,913dafc9,d157d030,8ed328fa,e08150b6,4a48754b,907954aa,4aeaacd9), -S(ac754bcc,c9c7b4e3,6551b654,a0620086,412db1de,14e422d4,c9111c64,c8b08b0b,3a8450b7,e841959b,93d3bc25,ced04aaa,4df90b90,d1ccbcf1,2fd88bc4,fdb366a6), -S(7e04fd28,1770ae0a,8fcb64d5,6e911667,a50170a8,3fc691d0,b0a8e1f4,73de3c2,73c37d99,cdfe5941,62b7b620,34be369a,c7da1d8b,e7d863b9,a90de407,24acb7b0), -S(ff903b99,13bc9005,8f237e9a,50f83707,a6f7d24a,d62142f3,16fb89ac,fad9ee9a,37cd140,36415c21,6e899a0c,2e8ccbd5,8f3eacb8,c88b1182,8436888b,899b412f), -S(d1edc0e4,44e92bd6,be858374,8f8fecb9,dab0d6f7,c74d410a,c412865c,9bf95d00,c10e796,3dd91bf7,c1754154,ec82460f,817d919,d13c52f8,d6578e8,52a8f87c), -S(62ce4177,9ba5fd6,332d188b,3a8ed98b,3883f013,731ec72b,8b0842d,ef0d5e58,ff141435,2b26b61c,ea78f67,de7ed56b,7895c03e,e3c28050,151b5a67,625b2d5c), -S(c8e885bd,5d0d5399,47addcba,879e7fa9,b075f871,e484f7bb,69081c47,8540c845,2d0d3f40,77cf511d,f93a278,91795dbe,e5087584,eab4fb83,e18e5d76,8d939dea), -S(62b1a52b,de107e62,4567357e,de49b08c,30c31e8,9c1743cf,a033fec,6bb8ab3d,9ed15063,ce1c8d00,1f19b388,ec678025,9cd5d951,4e263453,d5bf98ac,bd64d1b8), -S(88589c8e,9d35e6b4,5788bf01,bf3c6672,32324529,3d8014ba,525f016d,6f721e1e,be4804a5,d5b49ebe,8dd127b6,e55a7702,92a1c0d1,dc431fe,f5e4e873,103e1fea), -S(75e47add,7a7f2099,1a12916f,9ebe39b5,1409e82f,67afdf7b,d1d7464,1b83a85d,786b9b83,818e81ed,e3fefad7,c7203e57,99b4100,7cdd291c,321adcab,31b57bba), -S(d56588f9,982aa917,ce28e887,44ffba41,4cc1046a,a0122d2d,afb8715f,a9afe3b4,b14c6ab1,3a1793e5,68b171a5,1ecdf179,d78818b7,9cf7b1c3,97841a64,97b5e3c3), -S(9be8f7c3,efadd410,8c24dfcb,3a14a279,8cab4de9,8f5ec786,de7a4448,d9150e52,705ae8a3,a554f092,c677eebd,605661f7,4c463b81,97444d96,a5bda8a4,60315337), -S(96c95643,ac2805bd,421dfbf0,8a4801fa,69b6815c,bd31156d,f12207fc,48831c43,656b790d,35e598a8,dffed7d5,9b0b827b,3c46bb1c,3e5163f2,a4b71236,c6bb1b64), -S(9dcdb2ee,239faf20,2bfa036f,5d6adf4f,8d1add19,8def404d,a9447867,b126becd,3b727773,d3587698,7605dc66,12dea6b6,46052652,abfc3ec8,576740ab,81291e89), -S(b33d2b97,e31618b4,d9273d4e,82893e01,d85bb2c8,7d0d1059,f989bf3a,7022d2bc,2c447cc1,6e680637,12a4789,6ecaed55,83cc9e94,525d7c19,9e47416a,8569d5d), -S(74232d9,547bf3eb,fe4921dd,92d77131,3f5c97c,203c0db9,12106698,aa9d5c8e,6fd43ac9,ac04eead,7566e40b,3d04975b,315a36c6,e5b72cd0,14d365b1,b7a3836), -S(937ffd12,72a7df14,21df0c9a,3e015d0d,be72932c,3489fa2b,d34f72f2,763469e8,55e9e0d2,54d3379a,a6e35511,acf9dcbb,372d5b8f,271bb7f6,4c2cf77e,bf624234), -S(1513a5a3,7aa52a65,d659a7f,b0e762fc,67a8a196,8f2b6ae2,bdb02955,5d92476d,8d99d771,6cc3d831,9eca3b97,8c91d239,a7ef6b03,a13eeb25,ad94f4a4,20ad3eb9), -S(c7464b4f,bdd39bc5,4ce45b87,e4db3a3b,22fc52ac,b649266f,f7dd69bd,65b2843b,bc0d264,e48aa14b,bcbdf505,9a35fe99,395f03d6,60635150,cb8424b0,c93eee25), -S(cfdc9326,cede0724,5a89824d,1cfe590,c0945793,88812f11,4bed6577,ef7432ce,a8df1cf3,5d471afe,ad43f88e,46e5cd84,ece5fe8,fadc55b8,e79d6eb8,2466a270), -S(aa5529af,861568f8,cd4ac26c,fb1f5e3b,5ddf564d,ba4f3b5e,8d3ec5d2,606530f8,3273795b,31e53e0e,e34ce1d,aaee7801,309c0315,926eacba,fbb0fb6,4f0a948b), -S(206bf37d,599c665c,1bd20187,93f526af,1099819b,4780f2a7,6f5c3797,4eb404cd,7de063ba,3271773f,56ca358d,335a015b,8ae8a45b,b4a9cffa,2f20872d,9bc654b3), -S(3f21852f,621d5a6d,4c91f27e,82018b7b,4369c15a,69664cc4,6cdd8195,1f3ef14f,db8e7b5,fe7d9972,6da564a1,78131727,3ee6e005,908513d1,3903aa3d,d036123), -S(4c562c1e,9e4bb491,17948e93,f94b4146,c918554f,7d351300,5ef7f181,2c9900e3,1809f902,c6f694de,7909c8e6,ea4e938a,c1d9e6af,7707bd05,3a7d8560,24875012), -S(a692c8a7,a3b306de,48481c93,8f0a9814,e081bf11,6857f217,4c1ccf1e,a8448a30,7a660fa7,def1429f,4c72e44b,9fad10a4,7639942f,56a647c1,d609f3d9,26a40a9e), -S(981d35b5,5998f57d,58a62d9d,af65e53b,419b99d8,2d2eeea2,bede4da8,ec400a2,d20db6e,211c3ffe,ecfa43c4,79a43ab3,8590a142,9d9520d0,62f1ec1d,9f1c574a), -S(8afa1616,3350087b,1e286bfe,5d610463,41adfef8,8b0fd809,336137a8,92d32e45,54924c6f,5c2dd61b,e5b1186c,7fb8519,29af1989,f468049b,bd5c3cbd,387a28c7), -S(ba7cc113,f1e3bc3e,ae14c2cf,94fb1ee8,bdfa60ab,52582ce3,595df63a,d08c1e17,ffec33d6,d42e2233,baf02780,a60272f9,3531b1fb,158a4bac,6c6a488c,fc23d03e), -S(166f2dc7,661c9e5a,aa51582f,4cd08cbb,47c6afca,143c4231,36144cf8,ce69ced7,132e0d13,6a292cb5,9f0503aa,589b37a2,dd1c9244,c492b8ef,647d79c4,778bd94a), -S(bc9fd332,f66ac57e,46ff7801,a7d38b0c,f2befd5a,2513688e,b29fc5af,902f1c07,8f58e1a2,2958600b,dd64a428,7b6b25a1,dda32351,dd45453d,d03b99ad,e406e240), -S(e363fb9f,77378eb9,2600491,386a884a,24839001,cc516bd6,44cf6e57,b1e66507,3f83ecdb,907afc42,b47ca948,fdfd3b73,dfcf1e5a,7cdfe1dd,41a188a2,1b5f8b1b), -S(c8883193,9b5b7ab2,2af8763d,52efbd5f,50939606,920325e4,805842e1,3faa3cc7,5db2a08c,6e8ad455,f542d2b3,9b8203e1,39c5b0a3,d1fb1ac,763ee4b0,4b9c1f7f), -S(76149173,1a20a975,16607b53,501c45a7,f94df1a6,e0f15301,bb0bbd4b,eae97439,e75b67c1,fc2bda74,9f834d8,c9439b43,c33aa4ea,f2fb9116,9804615c,8c1269c5), -S(8c19284c,f62a4116,a40ec5f5,43cdc2b7,e7615400,d1090f86,2f378ac5,81f4b5d8,bd93accb,5c42ca6d,a4e6ac37,b2bb8359,42bf659e,a0e6beed,bd754e5f,749bce8c), -S(7664fc89,5d8de0b7,b19f18be,cb9a9b1,783f97de,3167bc39,7c03d007,18311a7,861d8f0f,125d051c,9f808064,346bbfad,410fdddb,aa31aad,cda7a713,1d65a3a), -S(7aef0296,33664cd7,694a5d0,aecc0466,541535fd,b1540c38,8f0e0e9e,24e96b77,e02f2ba1,8e92d161,33d29d1a,c087cf29,3a91acac,662c7208,b9157032,d0c829ce), -S(cd222d7c,b49b957,e5252c06,7f649ec2,dae145c4,d82a82b6,8693a242,6b7ba40b,c261f956,dfbed5c0,e876492d,7325b964,3dfb2075,68ccc93c,14b1e8eb,d3fc1b59), -S(5055e224,c61b34ec,9cbe93e8,ea4c9488,19d94338,edf6daf3,72eda45c,da9f0971,4fe31a71,bc782d4c,720add07,4cf97c47,dbc1f38a,3a9d9cf5,955e1760,5f185651), -S(23a80902,a97669c4,4b20f49c,fee841a6,b5a99b5d,d423f4a0,5d573a3e,4833984f,6a57ed,265744e,f4d18250,435f695a,b80b944,d0153b77,e9e9a20d,bd98c659), -S(b9879ec3,2ad8fecd,35022a2,1625c159,a31a72b6,5d3f3c67,5dc8e114,c5f59de1,439d2afb,aecc48f6,310e18c1,2e31c9c0,cf91162b,43b153a2,f901a19f,1efe8e10), -S(918e367b,531fa89c,8ca89c2d,cad34aba,c937cc00,be3a2b18,bd1585ea,c4678a4,800078df,6b700c11,85418749,27a8402a,db41811c,77d0fd4,aa435c2b,7a3f0a2), -S(6cd0f4f1,c03f35c0,65815638,10906fa9,a41bbc26,da1bd7c2,ef39a4c4,66e49252,ef644bd6,ed42cf0d,3ad17638,5c239fca,61056021,b001ef9,dcafd370,cdc06156), -S(8a0c443c,3e26680a,3dc8483,e0a067,553f7ffb,af939922,1c35a766,b12286c0,6c30af1b,9a97958e,11d1e24f,3e8ce846,1ff37795,556772d1,56514015,a46951b1), -S(563b11b,a7f5d351,729b8537,1fdccea5,d7081262,8c1e265d,10c29172,d9a3252d,81c0a2c7,8b36ca17,29c9c02f,8050e3bd,ce46607c,5409c50,10f8031a,ec872593), -S(27e88b96,29eb9d92,e57ce3e7,75063c04,4a1f9f0a,dc94a139,abe56b05,77718f94,ea04c851,41e06d26,31564122,80c86d83,89c1f15c,3c7e98a5,610e52ea,19b1305c), -S(95288e29,a554b7e8,15ee68c7,16772a5,4320a7b1,20a38865,f3838345,f9edd5d2,d81b97b4,2404966d,3c4160e1,59f275ef,b91cae46,d9a33f51,34455ca0,496e4472), -S(b86033e8,e3bde32f,859f6af0,bb87b72a,b1b88648,776e1e14,273e52d6,205e0186,e120cc94,5de7563e,915979e1,15ee7cd4,4875d50,bf6b93db,8a133cac,227091db), -S(644a2090,82c7984d,447eeadb,2b21fb36,599d2c1f,366a3af3,44afd230,9b780c8e,b49cefa2,c0865df5,f6f6df65,24b39f7d,67eb07f6,ab6e550,390351a6,a2a1a00c), -S(1f2c4207,2e803f99,d1389efb,209ab0e9,2d7891d2,531f6710,60371c19,7b0f41df,98db8e40,69dab24c,4fc6e13f,37e805bf,45d30c28,9d4455f1,9670299f,a6c6a804), -S(dab5435,220297e0,e738e798,f1f8375f,dc813874,7a633f05,1be409bd,d6a3b8ab,91b6c193,de219ec3,ab3d6635,d4c41a1a,6059372c,a8afe185,7013e474,79fcb382), -S(5ae6a897,467fd90c,f693a5a1,d89d4fbc,4f11680c,86f5f99,30af1866,a1f27137,40612777,fde69d15,7d51d85b,137fe92d,c269c42f,4423531d,548fe248,44d0502b), -S(9bffceb8,9acee7f4,68cfeaec,6d597672,6f227197,6506c5b2,6c5cef5d,7545265a,a265cc26,fd6332b3,fe6c7487,23ce3d5c,12eac750,59947de0,9face60a,4df250a9), -S(f38cf54,b77eb8c3,2d339dfb,df288a11,3058b4e6,2f8c4ffa,2bd29e2c,e6c7b677,2daff1e4,54069fd7,63f422a,15e9cd91,65b5d97a,ea0cbf55,103dd751,9faa55b7), -S(350d6b26,8058c8ce,4684a5da,32e3eae8,caf387be,ea9c95c,311d0209,47122dc3,8ff3be71,e94dd657,281c9f28,780b015,1a2abf2c,2c2ed9fd,e7d0adda,6c5e0690), -S(1ab92290,615207f1,34859fcb,26ccc8c,ab9d5ba9,f30d12b1,ecd7210d,c68cf573,2f1c5e0a,53d449d8,3a5d1507,9992dea1,b481e607,e6c99f7a,5e0193c7,2a426d61), -S(9e98be16,cf2ef9a5,fa3a320d,5f844cb3,c715420b,d44db10c,8f24b0c8,be65cff7,9ff6de6,ea416ea2,72d8e438,e132a86b,a03c272f,378a4726,aa72800e,d0214a3f), -S(9e7b45ed,8f0738fd,58784c7d,a42312a3,53f12676,9fc3ab56,9c4cc69d,25a5b1f,22be7dc,e6e513c6,1a733f45,980f2f60,ff4653cc,49391baa,f4b27174,98f79668), -S(6b6c1553,cab82490,7c5c480f,88daa7f2,7e57b870,5110e1e,7e7a5be8,4314844e,4c10d4fe,d431a4d9,6b719188,b2027764,53885709,eeec2837,32832497,319c9626), -S(1d28f09b,37cc3c4e,3f7ee903,6adefb71,6423e5e5,8840c6bf,d3c03151,db723a1a,acbaeae,cbdc3e9c,85e36db4,aad508b9,9a152373,547613c7,a3455769,872e55b0), -S(55e861ef,3de7675d,857b8ba4,73aec3e0,de0f529d,3a9f4a04,11ec4d4f,5a996d75,a942b32c,44618065,af08a1fd,73e052a8,78df075e,e54cc160,eb9846b5,d46db7b3), -S(10f1258,4bdbfbc5,6ce7b023,78a5e908,9457956,65f4e49f,a53f7143,3deda9a,4ce2f90e,efc88f33,f12edecf,1af91612,e3f84dbd,91f45bf4,5833012f,63e02398), -S(48ae6885,ed275a41,2bc61a67,399ed1aa,cb968182,2775dcf,9012cdaa,a6b21ccf,8b4b5cab,e5471381,46c62a82,102d43bf,5b83d993,41d026f7,c1525ed0,8c2238fe), -S(c6f5c5c6,73642a35,59c06df0,18527de6,7fdb9f4d,75c98f01,8f45913e,932c1481,4a4d4894,e31d2adb,d150b184,51cf16b9,cf7e3741,c4ed2511,c0765480,2f59fde8), -S(f38923af,ff4cd9d,cb16d571,3a68e18a,7fc163d0,8835d283,3676caae,5156fe49,e36986c8,d7e07fb5,6a1f4266,d980c113,43cad9cd,f7e4619e,17a45642,6425eff9), -S(10883b32,87b20d7c,7e60048f,13f179db,e169b82,f9a95f87,5271861b,36170d85,59be5146,d328574e,d837776e,c0748043,369bad42,b38ebe6b,861861a1,8c5307f0), -S(87262e3a,832a6c07,d6d32fe5,8f0e85c7,40591c6f,21da8ae1,5f8fd137,454a383d,7db37cc3,11decb91,cb4fcb0e,9e73bf0d,c91b3a5,53292f8a,f5036dc1,baaf4473), -S(cd4b75e4,7fc954fb,b71c21c8,28322c9,a54871f6,2ba2a803,780954eb,46c9c54a,6cbe7868,8b5722e6,ac75f9e,c93a7a4,39350a67,7ef31f53,c4c73b33,cdbfe124), -S(468fce11,bbde91ec,fa738924,9a07a39d,b0851d0c,3cb60f96,cbab165f,f5c69242,93c66305,d55a21bb,e14bc51e,be8d9c8c,14f0e8ee,caef9b49,567a8f03,6b2d06ad), -S(f5d9aa66,9cc173b5,5850e784,fbab08db,d0f11e6c,fc3243d,ff6d1a7f,89f517d2,aedf8598,b11b8c00,34f1e3a0,ed4c6c2a,db1688bb,35bad212,ad692896,2b045d13), -S(48276e7f,91c2068c,161e97e,7587a30,a79ee120,cc30a9a0,571da1de,53f9e253,a59189b9,306aaa38,848b7b7b,4653e6bd,68944d6b,46a4899d,44ed2367,3ecc241c), -S(7709db32,f9a551a,23dbdb7e,824fcc7,720f24c0,3c58c68f,d2b5ce2,cfb59cce,f8b35a2d,ec4b7698,58fe791e,c240f54d,8b5ffde7,f24119b2,7ab20fcc,8ad07f0), -S(a7b6e973,d1c62f03,6eae2674,bb5b37d6,c5ce3187,41776833,d7f3e8c1,ed2e6ac0,116042cc,3b409748,162db6f0,69ebdb11,53aece8b,37c277eb,28c9a2ba,c7c8224f), -S(7c5f0e06,652e8870,74d0bc97,e9c0023c,e2cac507,659d1a07,5f9c9fae,2d77afc0,e9156afa,24565d92,fadc1aea,f49e1bc4,b28606e2,5bcee2ba,f7c9a87b,b510113b), -S(14a0e517,1a796c5c,1bcfdbc6,f0431dcd,6fb7a8ed,4d6f1621,be01cf2c,64ae0166,231ab7b1,1c3d84fe,1e35b994,43d7f7da,a0bb4e46,834e92d5,e5c689b8,427b24e5), -S(fec19af0,286c251e,82aa7ec3,c5a8b048,9ee4b6e4,8e62c59f,7cec1aee,45b7323b,18cb5d01,5506074d,c94d0a0a,261301ce,d042405c,e4f01f39,2bfb40c7,62b47a8), -S(5788e079,beda8301,e290a04d,dd11c173,6112ac99,76c4857a,ba479485,5d457873,e2c6e721,b5bca7ba,add95284,9257927d,86877477,e8468b6b,9235b30c,557fd7e3), -S(513c9124,d7e1726f,73b39525,377c2761,48697c71,594615b5,f18c6695,b4d589a6,659ffbe,fb3ff7b0,2e5ee01d,eee0ea65,8a562af,722076cd,3cb2ec56,16533beb), -S(d96da66f,fa79adb0,80d06968,bb9243c1,dc6dcccb,1e9250bf,6243a1e0,9578ff8a,76eb65d9,6d520da1,34941ccd,8af2f32b,6050feb9,2ab39835,931b901,60a5e481), -S(37033146,69c7eda3,e598a616,12c65c76,8b5cefd2,3371928c,191c3d16,4d1b495d,fb886600,ffb6e95e,dc704a62,f5105795,474ce36,45d54d24,8cc53fdb,7a28e978), -S(493d5ec5,ea8957ce,6608e59e,66e8a6c7,a8aab1d4,fa14230c,8c3a6288,37e60b2c,594cc0df,dd37f4ff,d235e2be,1cb98f61,8485e453,6c301d21,11267528,3bbb5097), -S(71e0fd4,937ae3f4,84d521c4,86f01485,a94bf45a,6a0d2472,d7c5b97c,19d99068,7551009b,73422956,afab9675,1dfa7eb3,9feeacc1,4d220714,1cf157,78f7087e), -S(fe36f2fb,971a1eb1,9a158190,cab6d80a,60601d96,231b5aee,b4c4b332,b35c7031,f72e5fdf,b8ac9af1,263f5492,2caec24e,dda604eb,953a3b02,4e29d70b,55266f87), -S(c734995b,fd73d82b,8555fa56,56465102,b6b14813,272103d5,2de7d6db,fb9455ce,713ab271,3c718906,3faa274b,dc2bfc7f,4f65dbe7,80e07c0f,7b625d70,89f31714), -S(e56a3832,f58b284a,6454f8d1,73f2dbde,b8212cc,a9196524,e1856c98,6dfd76b8,cb301f78,26b39496,6d9f9953,7302ec8f,27af592d,fb8e7e1d,acd5242e,ee2b8cb9), -S(c511bbd4,e242f5fb,a2202900,45f4f125,ab2b588c,f9b375d4,4910fa55,be8ca373,3b96300d,7713d05e,d22eb08,bc039eea,ba2f36f5,80398e61,b3a74581,5f884408), -S(f7ccc53,75c59fb2,90408676,ddd9f1d5,ff6d66fa,1172e0de,cba38ea8,a160a457,45081507,f4a14598,ad0f4278,1f14b8da,72ce889c,f23b52c4,ec5fd1f6,9939e054), -S(8219112e,48f1a2b7,7a03f20e,3eeee016,ac69818,f22adf72,3679e2bf,3586dcd5,205e4b4,2b9ed249,a63d4a5d,853ecc4d,4d37b0a8,4841e959,d46ca7ed,f42a7c40), -S(34df67c5,b0a9400b,9b9eebf2,132426c6,281bfbb1,402cd49c,1fd38bfe,c19f6afb,34066c5f,d45751fa,df681c95,791fba62,79bc76cd,a70ce02,92ba7c41,34fc5d58), -S(9b969626,16414928,6cd8ba65,75572291,f1a885bc,1ef82fcd,7c445637,da1654a8,12e52b50,2fda57c6,ea330d5a,415d47d0,a1e5a138,b7968c7c,3543dff2,9578c13b), -S(68add94c,a17a6ef3,85d23fbc,5d7763b9,15c29bc6,2a520139,24154a60,66d0eafa,281bd1a5,71629916,1a911be9,88a13f64,e8065610,219bdbe4,5271f4ce,2113d77c), -S(143eb857,7844f677,2b01db8a,d6cb84d9,fc1bda3d,638325d,b29d280e,16a7f36e,a50cd3fc,f771ca36,58f2b9ee,4133f17e,d72383f0,94492358,76bf04a3,296b7df2), -S(7b463842,1537aaf7,2e6f0800,cb9c0428,b1dcd22f,73694b83,63f9b2a6,86d94bc,3bed2d2f,c7b5a092,e6e8eb33,1f945a24,65936fac,90a3f244,942895be,ff42895f), -S(1857638f,ef86615f,7bf0665c,3b5d9cf4,c51690bf,c96481b5,78d30131,8a32349,64adcbbb,22267bec,c7a40d4f,6eaf66ad,9c133182,b4af858,6b0c4aa2,e30a37f2), -S(bf84f3bf,d726e0f7,2463bd38,4c14b35d,f9502148,4e78f001,b848fdc0,4d7a823b,4cbaf2c8,71bd8ecd,4439fba7,193a9bca,d26653d7,a4dc7a00,f0a35189,e1949139), -S(4482f7c7,1bc8f76d,9bfe9148,77ac76a7,6131501a,55fc5556,c4e95ac7,68c9ef11,f5af5b16,10733ce5,bdadc3e6,d1df5de1,314495df,3185f7c5,14151c94,908ffcc2), -S(715e384a,100bc5a0,20857ab2,57a352a3,b7ce41e1,a742cdc0,ab1354f9,d3483e93,13703919,b85f567d,87d2e6ae,c2ad89d9,743030f,9b32f277,34c3e9c1,4b5fb1d8), -S(ff90a61b,98f591b0,ffad3ad,3dfc0432,1093acf6,18b0f71a,f637a335,e9627726,908c8caa,f88ae7a,c215cc30,7d7fea86,1d69ca24,7b1c0949,57f022c4,ac130335)}, -{S(d8f08d18,ece61855,5b06a3b5,ac8e7cf,a6375446,cbc7c8db,ad924f78,69e7f00e,46a91d23,910957eb,db830624,73839954,2cea0570,2f67a09d,d7d19217,646606e), -S(fb32ea9c,4f434cdc,db41595e,58f16466,7fd92a08,8a182823,137cd308,9974551f,415b1d67,d845a304,a92f9f62,65d09c20,32bcc521,4303d791,95b05cab,95ea05c), -S(49523899,174fdf41,e4a551f8,423da35d,f3cf0ffa,1f2b8b12,d2a51764,9d8f8b91,6f9c0b72,c5c6fbe4,3fc3d956,7e4bb980,975b744a,dc9ecdfa,8ca42f46,d7164130), -S(c02d61bd,9ca243ba,f2907638,3dade862,bb6ec35d,861a9829,10a084c7,7dee331,fa82b2c8,f015d9c7,b7329bcf,51f60a93,60d54d5,2b24506b,db542d9b,23aa7e6e), -S(a344867a,cf07375a,295cd97f,68093020,af6a1da1,d871b330,a52ab3d7,b4cd0ae,5b1c6f72,531ff281,88ace548,4f193dfb,b8fb233c,b251c788,22dce3bd,3a824c5e), -S(96ba694,48bd703f,a8aa21f2,4257bcb6,2e98751,42d32af,63bb6a37,4ad262c4,35c74902,7d4d0a4a,1550b7ed,cf791da3,7aff1aa3,a446225b,5ce2c0da,aa85c82c), -S(278eba80,511ce15c,f00617ca,21d62211,35f5c4c1,87d959aa,cb098b7b,4b56e51e,ad903485,bee432c3,5ec613a7,68175d93,4f0e855,28b76b41,1c6ad8a5,510510d2), -S(554be9de,b938c4a6,fadc2fb2,77178b95,37719f20,8b7f06d8,7993d06f,c3500bdd,931e3263,34c1e96c,a4c88583,92a8b7a4,c17f7582,e4d0b7eb,6cfef36c,7e2d6f0e), -S(26a4f40c,968bcc7f,cc4002ca,b7ee20c9,3996a600,b4f81df4,66692d3d,5a6c19cc,67f7c990,ba734ebd,af5b5263,cc28624b,9014b7b4,443ed322,fecf49b3,3760b5e4), -S(67a90211,86d66afa,172fa6a1,dbd9b3af,9e3fc726,e5ba6916,59f066f4,fdc6af14,23ddf5f8,96203f49,9be9db01,5451305e,57e51d54,95672895,3968ae1,fcc835db), -S(d3bd63e,d5555686,fa88a122,294ba841,33be6280,17a21f65,285d4651,214b1ecd,f0fd835b,5f27da51,1216ebfc,f5af7740,8fc053b7,dedbdb37,40f6fef4,4cec8bf9), -S(f0dccbe7,ce8362ec,e7f8d550,b0967d4d,fbf6f9c5,1ee4e7fa,b3ab9b50,2b0411e4,7e63fbef,ed68f1ee,6f3143e7,a8e5f2e6,edc77db7,3d34b821,1e062b36,6ff0b8d7), -S(56cf2a5f,d7f41d22,cbe716bf,183a9eea,370f9bb7,5620f460,56c9023f,b8402952,600de0ed,c86b4f7a,93423beb,6a2b29de,749d05b0,4725b5c7,2fbb60e9,7fcf815a), -S(1a60d0d1,73316260,721542e2,33c6be2d,e0088476,e24fc61d,3d0cc619,dd3c1564,bc90efa5,3588b420,2cd46e61,a826a47a,b9f5e45d,eff920ef,100efa34,c179743e), -S(bc406d21,ba9b9a12,a38b6572,5490462d,2be4d0c6,8922fa01,b02e34db,ebfe8e71,6ca29bb6,878fc1dd,13cf814e,c9bff5ba,12a3d55b,13c3aeb1,6d588ddb,371c1981), -S(376ecde8,891b479e,490c80b,b81d15c7,c5b19a7d,4f838db8,b580338d,5745e583,9296ec3d,9256e491,3ccd38f2,e6331513,c7040e20,4d0e8344,6e9e8de9,42699fe6), -S(64cb1c7f,ec791b1b,7b94c8b5,969410b2,52243c7c,3068eb11,99d2a56c,aa2c1330,f43fdc60,76e80c11,4f19dba5,4f51da94,822a98f0,986ebcd8,6160ec7b,b249227b), -S(6f089f0c,2b95a26,e3cd8d95,98469f,c0795e0a,6be85b5d,fcb47071,c5413db0,dad7a3d8,e61e2a7b,ff7f9357,314d4405,8cdc1aae,c1bee22a,461c6b41,23ada4e2), -S(90b30e36,bfb33081,d54a5383,c77116cc,50e1a333,1b319150,98736d29,e4bad6f0,589000af,241a4c83,bc2defea,9b653ce2,988fe376,77b31abd,7f384762,758e98b9), -S(82f0acf,4a764dc2,59218ff3,397618b3,2e341ed9,6f4961c5,f5a6d559,654194f8,ac0f10a8,4728d82f,b8784cfb,b72814d6,868006b8,1d00894,26825a0f,3c3404b6), -S(3460815f,6036aed,4a2e264d,8e17b1b5,6c10d77b,5c021cac,69ee3a4d,ffb3df8f,c11a4b6a,c66ba79c,e6bd00c0,286aa96,de72f162,3a4f8d3b,1a4bc421,c9f33340), -S(b8c0311c,c21b7f08,46e66ebe,f3dcb726,53de4e83,4e450a06,e394d25d,195cb7e,64d4046d,6ef0fd1e,30a71c10,d85f0f07,8ce3113a,e904764c,c5a29ef6,c983b327), -S(f7bdf7b3,b610fcd6,cd2712e7,7a30d38c,2df3bb69,183ee96b,408bef1f,f57dfc59,fdb15f4c,61f276f3,343e2ca1,38d69b12,339e7e5a,dcceebae,39c768f8,95a0bf92), -S(ea32acb5,b5ef1dda,bdd4ef41,52ee856a,6e298277,f5f9c95b,e1adf49f,cba85262,1c0c5f11,3a3a033,790b073,9317fbbe,874afb39,72935a3f,52a309fd,6432e0d6), -S(e184d302,f708d25f,5af8d023,cb6b416,ffda5bbd,9f592edc,ab4f1890,3671b604,21c74686,4200438e,9cf66cf8,19292129,dda4fe13,965becca,8a1fd18c,e753abe), -S(69e75799,f0c0098a,3225e598,a7e8fd98,1218de4c,42aaa680,4ccf7c92,a45fe071,cdd2c796,c85d0930,8aeaa1b6,9a535c5c,6cf9d607,b2b296db,33d0b61c,b4d7711b), -S(a70c1082,119c47d4,75af4a96,1e61f0dc,284733af,c89e403f,9a5dd65,d465980e,3193967,8665bfd5,b37cd1a9,62f86cff,43b5f058,ae9045fc,c571cd62,bf390e9f), -S(f63e5154,9819926d,254f76c2,6d4a7b95,f01e612b,8b885073,f7ad23f9,dfe82d32,57521b53,d9a8a71f,71ae4b31,df7999d0,40395ce9,f0b70cfc,396bee62,40364b68), -S(9f62320,94d674fe,3959eaf5,b947df18,7e894594,8becef29,28bf7aee,983e108,9430b33b,5bf4d79f,1683da6d,ba74adfa,dc19489a,be9eb3f8,9f00a793,37fe9b38), -S(9802daf,4ba214c0,d19ba4de,77d92223,7f120914,7595135e,9ad3c75b,7731638e,98cbe71a,b035839a,3a2f3449,d6261dde,c14501e7,53523afb,4406c657,1fe5d2b4), -S(e86c5944,58017291,318caa82,8fd86a2c,d4ac8a67,c42dbd2f,f57b2b38,f47c9e0c,9e069a55,94596844,8f5bc2f,f97d9660,62f99bac,f74d46dd,5196b37f,f8503c26), -S(40d57e52,c21f1daf,3ea1d981,5f4da45b,807f083b,9e68f2c1,ec5b6d56,e2921871,99115564,76906b4e,5deea9ea,29ef8dcd,c1841b15,bd662ab2,720a28ae,d788e9c4), -S(b797d0a7,4ed78f63,475364cf,fdc42fd9,8a3fdaca,19c7decc,cc7cf10,7cf2f8b9,cbae44e4,773eae4,70f777ea,cc108650,fefdbf31,723eeb6,a77ccac1,129c3cbc), -S(a1b4bb86,61ba1626,c55158af,f04dd2db,b9bec0e2,943d91a0,1b043756,3fdea24f,fb8977c,b1088ff6,e6a462ae,1b8cca01,a0f6c737,816c3b3,d28d8ad7,b42630f5), -S(862cbd75,f1b8115e,45497c3,ce7f1058,200c3bfd,d9cc6ac5,b65b2e4d,abc06241,ddb98861,50925a0b,1c3445b6,a7f418be,7d5ee05d,9b7d1cf9,2ec5b633,9b0a5002), -S(45a2e88b,38c2439,53a33a6,e75c1e83,22a9f14a,bfd6e7cc,db786490,932caab4,23c86383,6a2e35f2,b9b7f8e7,a88ce40,f600eaec,af84848d,10ee1739,7341516b), -S(ebd1c9b9,e01beb16,7504b3e2,80c00ecc,6f44e085,a86a1b71,fe13fd87,3df558e7,d5ef72b7,10fd592a,64020176,a4aa890c,99ce47c7,f3d01e49,349aad20,b6e38c74), -S(1db6b315,14f71408,e876aecb,be1ffe74,a09b8e82,9f05c3eb,18186e9e,b461696a,c7236c85,b7436661,c2edcbb,5247ecb3,2a7d62e1,6d4cdc88,a7648b29,62dca534), -S(51704f97,7873b83,2e36660c,59658078,5acf0396,d29e046,5717ef5d,129a3cd2,672722c0,18401e21,e053ecd8,a219a972,b57b4b1a,56a8c767,7c6b53a7,f0c77a8c), -S(da77e611,fc5ca13a,65bc55db,af4c6c9c,43a7fc41,b58c57b2,4d25925a,99b22bf4,cff8b8c4,a8d3227a,919899c4,201f1bbd,49cdf4bb,506ad705,4c8e2f1e,a6c9dac2), -S(e7daaf33,ef909752,654c1b25,376be54a,22d0b5a6,b35655d0,87a204e8,d1830449,718d5a10,661fda9f,e6bb3fb,a1d3718f,fed1e441,64adc00c,f752ff1d,35e4b020), -S(ea15fe2f,cd9ae892,ff561ad7,7cd2be6,cff695e0,5cbbc15e,444cb45f,10d13269,d3d9b9ef,722dbea3,20a07f39,bd1b52f3,271759b,91bcf24a,caa6945,47d05cb4), -S(60dcb663,ab81db6a,89176bec,5a6a381c,bd6c8b66,de4dfda2,6d50c407,964492b1,42cebc,b7972c8f,e97e440,fc64c330,e4cb21f,114b852e,6cd7dd35,e9c7eaf9), -S(a975633c,5a609935,9c63714f,a474b40,72862cdc,1a3b1bdc,dcaf646c,1197dc9f,51f4cdad,89e63175,49c37342,d757b326,2b1da11e,1617f4a7,b0441c6d,8a1b9664), -S(b5d14a97,7e06d85c,f6189346,bf392516,56f9e92e,3e3b95e7,200cb68e,7a9bb4d2,27979c8c,d556d442,4d128608,8ddcc444,849df743,ca3ea38d,e077f8b2,71263654), -S(581cf880,1cd23788,8be62ec9,e99f814b,939fa6de,f4497b2c,bcfaf8bb,f9fb217,a211bf28,117f8b31,28f353f0,a3ecd2db,d35435c0,79b39b9f,2d2ebae3,e39c2247), -S(38e354da,80f408f3,48af877,138b8b32,f18c1a84,a5323e3e,6a275bd0,34a18ffa,b22ceb25,690855e3,e4e75553,b6e9d619,302d7b8a,f00226d9,8341e406,4d5d9e9b), -S(a62c3ca7,31e863eb,f630dddd,c75f7a7f,315b1a5d,8ebd7659,7d63294,7651524e,bd2de025,270f22d2,41927db1,b2d83c3a,6c4593b3,c93bd192,ee490b0e,b4b896b9), -S(cdf7529e,32b73c24,39c5e793,cda2367b,8cda3ec1,12b68572,5fade16c,5de12859,34003733,4953c33e,3aca52ae,7578a837,64218bd7,661d15,e4e6b150,88f5372d), -S(b00ee5a9,eec1ec97,a673404f,b67e8b01,26051e51,df23ce94,1bcce1d7,c9c0be80,d0ecff3f,45fe1bfb,7d7eac6d,1b27f465,80b22bfd,2b2b0853,c382c06b,df1b1be1), -S(bb7bd0bd,f9b827ca,28e7ad35,e7e42ac7,ac667dd6,5f64f18a,2af8b385,774f7382,ca9903a3,6fab02f3,31afea78,71802d82,6e45fc4c,e7f1453a,ada65ac9,fd15942b), -S(c2e32d40,c675193e,a8097d9c,9beec3e3,64009574,11e46e7d,520b5fb8,44119d69,63c49dc3,5c2ea496,894da7ff,d8b33e82,c70e44,d0b51caf,6e9d6235,c8d78f57), -S(20aa257b,4fd347b,4361295e,bd969d65,60366497,bd0f17a5,5f9b8142,827081ce,c8a82baf,9b95576b,34b6b80c,2ee4669,8bfd4562,59ec9911,4b58bc74,cda90533), -S(35095083,4f7f8218,6e0a8085,2cf56948,3928090b,84d2c068,e0c3c4ce,9819c4fc,1d0bb1ce,2c061784,35df09fb,c21596d3,2334bd77,ad1206ab,41515089,93589b81), -S(4f731112,8d44033d,7380e5d9,71826f5c,1f1cc587,fbdd361f,be8974e2,2526a2c,69d35d5c,e051f2c2,54c8b68f,40033467,b516378a,573d7f22,8ad5e070,f497109e), -S(34746007,54abb4c9,2b9f1a9b,33b51139,114bcfb6,ddbe9e2a,1e9182a6,ba52cc5c,29f6bf7b,7b31c57,b83e9f41,a9fb151b,744f0bf4,bd2dfa1e,5a5ffd14,e3528ded), -S(62f72456,b06b6bbd,70c2045e,8c1deec4,d1ca74c9,aeaf68c5,52d424f9,be280edf,13e619bc,d667afc5,81d293aa,3bcb80e,fe3212a6,9750e45b,94740aa8,286c72cc), -S(b1d18497,47415d89,7fd3b791,9e2a1cb0,e47efc1,2f6dd61b,93da9d5,99cc3083,19eee106,bf3f71ac,436cd33d,9fbccc4c,2ba50ebd,20e93478,ff0a6c9a,96fcd5fe), -S(9f8bdabe,3e85c253,40047952,812a913d,f9d83038,d869f535,e5c7ae7a,c286ef9e,abae000c,3e24af88,242df5cd,3a3786f1,7c8f1a7e,7604be96,7495b6e6,7ec09284), -S(c3d3786d,31cbaf4,57de58c9,c3ac3527,ff40e817,ef36bd5f,34c005f6,2967989e,b39ece7c,3e76a6bf,fd14dff0,a066e977,6565bc22,5c26d446,5d6b193d,d37dd7de), -S(749984be,1953ea05,318445b6,52c970bf,32cd173c,3b222686,a054fce6,787f634d,43c4b03,c395080a,20d13e6b,edd78d74,7e9e326c,c267f358,43eea751,d6ae31f7), -S(8b345416,f6b91613,4ae7c45a,de0d2ba1,75aaa225,795d94aa,4c554a66,9c08f5b,2166a466,d1ea4969,fcf766df,ecb263d6,339a8331,7b342ed1,a4fa6019,23af6d0f), -S(af805191,730b8c9b,2ac105a7,eeecbff9,497c9414,58ee28cd,9bfc40c9,5078c366,ff3dfd92,1e3c1dcc,669a3f7,799277f1,591d0176,bd707f9a,442a219,7eb6ae4e), -S(c626aa89,da7a7971,c7923825,d31ab64e,2305ff94,1b724334,f8c8f1aa,ae60e0d8,325304f9,926dc306,6002e743,e3ae4ab9,b2eae44c,ee907075,fd179222,5c051c05), -S(7f6dc30c,271e6382,db40583d,acf2d121,8803d63a,41980369,316950a3,a1490878,a1224a09,8257f494,331235ca,9d0fb42c,9f5727bf,74e98d60,f624e4b9,a742c7d0), -S(f90f030e,30cf9a10,582d022e,b148e12,d442a9fe,2345a552,564731f7,6c9aa92d,d1ec7fa4,677bcd7c,ae9602c9,2cb9a486,1ce7f6f0,9e6c53b,210144bf,608962ed), -S(f9844b5,6b5ee53f,d41b2d5d,a8eba633,1a8518ff,4f2fb920,368a15b0,6bcb091c,165af5b8,7ff690c1,e5e44f78,b0f04f89,70b6a370,8100e86a,ee82d24d,fd10ef3e), -S(b091a817,66903079,42158c,acdfa7c2,a42526c4,f19736fc,aa62bcd9,2548acd3,5e2c1b91,f6059ea5,5595a105,5a7c4827,4beb810,59c7fdff,e1365be1,a6c2454e), -S(bb291c6c,a65e98b,4f075b05,becee4bf,757ced5,33d97edb,f4920c3b,82880d96,4abf12d1,e910f80d,47c81d41,ee9fc67d,59f8b4,5dbc58d7,16fe5d96,4420af42), -S(af63ce57,fe9f7568,8422ead6,40b64638,d474f848,d26c9cc6,2b89b457,4bf42ba5,abcfd290,320b7554,fe5ebf2,2554043e,a61397e6,6b1b6b6c,441ee203,da003203), -S(563c787c,a9c7a042,d1d8e916,fa653eeb,3bb455d3,d81d96ea,6c04021f,764f29d1,4f5329e0,9aaaa37e,997c09b0,47c924eb,1a9b813e,da648875,58365385,918faba), -S(6795237d,a651f9bb,c4603d87,cf14d4cd,9ebdc9b6,b0143c7a,97a99cd3,2715cb5a,cfbcc0c8,a4ca9939,e7050925,43becf45,59d953d,840d2393,2a2648e2,e3ee1078), -S(6d6158d7,3629a6ed,9437b26a,2c91e31,fb6965d7,505ed096,ee74ec84,3a95ea95,3923c2a6,ae7282a8,dc3e04e6,664c4bca,8842a0bb,95164731,5b47b85e,2b3c8bfb), -S(88a45a7e,512c33c3,ea439da1,e9715f4f,c397125f,e26cb7b4,227f2227,628a57f4,dc384c97,bc2c5e45,5133e5f0,21c0d3b4,76680c02,41e8e31b,b1d96c71,3164b7d2), -S(8cf77e1d,7a4bf247,18c29f7b,66946820,bae990ea,262dbfb5,ed63a701,dc2bf3cf,8d70e07,e7eae6bf,47d224c3,46bae612,329ee6ff,e39a84ff,640b25b3,9877cd6), -S(5bf3fc7c,c212a2c9,a90cea06,44503842,d9f5fe28,fddc0a89,b5610fbf,1a38820c,1e64ea7,193f3cc6,c4c62c77,fc27d686,1aacd775,2b66b82d,f95952ab,ca6488df), -S(74ffe6ff,73a6a663,40e6c2d,77c410c5,c1b46e04,7ff796c3,85238675,e3eb97b4,c31e7707,33d8ecaf,bfa3a3fc,6ace4cb9,4faf3eb5,445f3701,1de882a6,2a4915f2), -S(330b3676,9e60504e,e3225ce0,36fcfe97,8b74c62f,e8ab9007,ea1452f0,6a06ccbc,cf80c153,1165f279,a718ceb4,76e90d,3394d01c,ef6f159e,1225b2b1,51bc3c09), -S(471e94ca,1b8de1e5,eefd39ed,7b5f997c,9e9f20e6,fea65549,8ba33f6d,a5976c0b,ad5b07fc,2a5a049e,fd210e27,b849a842,749c5e43,f6321e17,18e20dd4,4d228c8f), -S(b8133090,5a4ead1,dec7dd81,df97aa7c,daf67e09,58f16739,e5ab2f12,f309cc2e,49fa5ef2,c2a95064,4ebceafd,732fcd7a,3a4c906d,95902646,e779dce2,4021591c), -S(b251f7a,36774d66,f98d89be,15e553e,d85d4bd3,2a170b7d,f4fe842f,d35644e2,cc71d8f7,daa8e846,5b5d6230,e2a25a4f,f92195e9,de33e32e,6970fc54,97001a40), -S(c0ed75ca,6ee80f93,5f7d86ea,8e1bb463,c90aad6b,145873a7,2884f5ec,a18dd90e,73ca6688,b5221c2e,6e82c261,fdf19c26,fd167035,d71f08c1,9190391d,b88efd50), -S(bdc5e903,e371fc46,828133be,5c4d72c3,3f19a203,c4800fc8,59d343a8,7c844c93,ec59e7b8,ac2b2c18,c51487af,84349cfd,f6842a15,cd148e9e,ded4202e,fa0579dd), -S(911cc60d,78c5909,4bd95589,61a99522,fc9c66ff,68370934,40ce6531,e730fc97,8b7c67c7,b33a60d4,bf75fb25,a47d3942,f6c95aec,5a9bc3a,4e8012e1,1274459f), -S(a5e02e09,a00fd3e8,fa7925b2,7206d296,eeff1b9e,18528376,860f2244,1b174f71,4fda8ecb,7fbb77a,dd05273b,ef51f2fb,c9abd87,eb87b9f,50d5a3a7,835e9d21), -S(36917617,6a66b671,684334de,9d6434fc,269197ca,ff36b95c,e8f36870,6e475e8,dfb20c43,78817585,552cd193,2b45dc37,b66a63cf,166560c9,746a9f82,ec3c4fc5), -S(91ded03b,67863303,92abd862,c2f2e870,80524c2c,c0940a0e,820c55f2,175d7533,95e7aed4,46172d6b,ea382418,5f1a5cb,dc26cada,26451556,81b55f08,6bb82f9a), -S(7d5a3667,26e40c76,923867d8,6a5b5cc7,58d84663,8a8f664f,a0b79d20,85824482,cf50b22,7f9d7889,bcc082ee,30d2f08c,1c18b2a3,7443ad43,86d6cf87,a59d77bf), -S(929edbc1,75eb61ef,f1a564e7,d843fe72,c4a49e06,1b704002,56b49b27,7c632eb7,bad98323,4d603b,c85d2747,2e02f089,850725d8,2d905c2d,12d1e730,24bcfb7d), -S(179206e5,861ca493,b3336805,4eb8b46,3a47a189,d4210ff4,5b8f29ce,2b8b593a,1abca34e,f7c9b56d,d72ee602,713b8fdd,ace3007e,a88d774d,40a6aa20,6c1c3e69), -S(e3548935,e28bc944,d29928a2,935e5bbf,a0285c2,337dad5,3fa40a07,377b4de1,2a886052,358b95a9,c25af629,e6d5d2c5,a7dacc44,eb6108c4,46c07af2,cc3977b), -S(e4092cef,884cea2e,51a5a82e,ff8a3ca1,6cb38a71,142ea0cf,476aa293,f9e63303,bac63e08,b0d90160,d8d937c6,ce0eee8f,c01af5f8,a84d2970,ef2c9f8b,ad1bda9a), -S(fb1294c9,c564a667,6bc88f4,90ea39ff,e2dba6e5,4165f6ef,92c90675,138c82a5,9fa392ec,ef922e7e,6bd19f36,99682069,19e799a4,be30125f,5563d3f9,46e01132), -S(ad376df4,e6025dff,693bfe2a,665a09cc,ba64f12d,1b4f9d5a,11e0c880,ebc745ad,fa246c63,fd5f84cc,d104c8b8,ebdae50e,3b86fe7f,976c4a95,c94ac06b,9c6df68f), -S(8f723cda,9a28aca,dfa0f86d,fbf2a831,700dc839,dc40392d,61904711,1f7fbf13,9bddb64d,75a288f6,e92b8838,5affe05e,1c07982a,2c9a8519,d20ed505,7acbafbf), -S(4a674fd7,4ef0139e,d151a994,ad3f859b,aa2c52fc,7766361,949ff86,a1159bb1,f0e5ed3a,ee6a94dc,a2b7a353,dc42801b,faddfcb9,4f1d5b56,f606d77f,ea4df16), -S(6651b5c,307d465c,1fd4c0af,c6edbe5a,e292eaa8,417db4ae,82b53612,66c5e7d2,5d02e21b,68dc7c4f,414c0cc,650909e7,cd46add0,fc91c7b7,98e00907,2ab85c35), -S(e6229fb8,c2a0a7e6,c9aa31fe,71e75cd2,292dbf2d,2c5461ac,a57bf13b,f57c073d,86aef20,5c78e3ed,6cba8445,49aae8d,cb548182,f31714ed,ba2e0b02,2d594429), -S(aa55bd38,39e91fd9,a6080dd9,46b441a7,193ea997,b1e6f72d,f735c675,56e5d7e4,66eda908,504bcd50,19a3b220,1a16f7ee,3692aeaf,ae8b265b,caedff43,19abb2a4), -S(8932bd7b,b1d9bacd,2fc5aeb0,6ad7dd4f,989a8417,793d2d71,b0c1ed64,592822b5,72cdbd0c,56b29915,54b68484,b75dfb3f,fe04eef6,5d522c55,d1c62bc8,8615f9da), -S(10f3bfd0,ee76006e,c113a1d3,37a5cdca,3601da68,1ec1758b,d1286304,a49808d4,89a27069,cb6bcf5a,8848d3b6,7d65c529,749007b9,3143b395,87318e90,4cd4b53a), -S(dca42b0,8e19ba70,db8bfcea,e52da664,956a3a3a,fff18dfc,6f9d4ee2,7194cd14,f6c76a86,eb3008dc,206d76e4,94ee3224,d345f4dc,ce44b54,fa5810e1,903a073f), -S(1251d8e4,9d6c61ae,a266acdd,53be9579,c993ceac,1c62db42,94a4ec65,e942b305,2a722ec5,5f800261,a937883a,ecada795,efa50c56,f12fcee1,20f81ed0,269cf5f9), -S(28b48ca7,c8c57bcd,4cbf70c0,81e46910,d1964ad1,af2e2305,184c3e2c,d7a6161d,3a7a1202,90d5ee64,9c4c1bba,d43d7e2e,6a5710db,924d3943,ea06a6d7,ffbb3bd7), -S(675a33aa,76d1658c,54a956a9,2e8f6487,b24e1417,a179cad7,c0c93cb7,6f8b7f50,8bb59b9c,94156814,a00d2621,d0fc87a1,be4c6165,33704160,82e825ba,62845cbf), -S(8b5b6b75,1d7bcd6a,dcc0f5b2,6e231abb,9d613ae,f80a561a,51463d22,e0ce9acb,e0b17875,6c146090,fb03f5aa,b952d904,3a0b45d1,d1a66b8b,3773c94c,1c657ba1), -S(35b8251e,bf562c69,2e0d11d9,dbe01290,fcebdac1,fdb9f467,9b5c2094,9a0517b,82dd2707,cb4b6758,ba7e7b09,cdfddbb0,11920b0,9ffae6ce,d3ad2e1c,648eadbc), -S(a9ba52e8,4bd13565,1ae96df8,bbddd59d,628657c6,2e0a133c,e2f59a01,8c8efad9,bac10321,1f614972,70c26dfe,47060b9f,d50764c2,461c9bd5,11bf502,a0b83d28), -S(eba36b0a,c20fb216,f8a4d8bf,ff21a478,d80389ab,51d6ac20,df5b2b41,834c56e6,60440923,e9c15c5f,72b7dbe8,5c3c13cc,58fd4ab3,a9a99ca0,372dbdb4,d4af1658), -S(e47ef3bb,b6f8cee6,11c05d2c,681a7fe7,2393628d,77f93adb,b875461b,712440cf,30989ca4,57112c77,2c2cdfb8,bb9e3751,343e8455,6ac9e86,db43920d,8c20d3d7), -S(36b0132d,2058e379,c9b1b23f,c13de925,ff61d8d3,4e8c37fc,afe17d92,670fb23e,5fd9aa2d,43c9a6e3,ddd8752f,9a3bb676,c4049d3c,f849274d,34a60a95,c4c19e0e), -S(dbe78ebf,6db49199,70c4f04e,56e62811,d0067aca,b05fadaa,bde4bc0d,bd2b1dbf,9b40dc7,b2a4fe2c,cba721ee,ffad0810,f909353d,ac53e731,945e418a,2846a8d8), -S(19da9bb9,e0b2626a,c9069f24,3292462f,2394e209,82a7f8d2,fd0bdf26,ecd61d00,3dea2ad6,50c8006a,f4af6848,56348dce,53d56d61,d7f03cf7,aec76a72,559d7c13), -S(25d7a7f7,24bbaa17,83b79913,25ab7c40,da5f3d91,bb13a8b7,8101e970,b1295790,1b675e72,354bd3fe,21c0884e,f0a5802e,45f8fe8d,3b0c0d92,7a53741f,231ae06e), -S(a5ad3cde,de3d64e5,aa1ba02b,10771048,8ea62934,6781a0dc,ad93f3b5,4c15fcda,d14651a5,823fbd07,4a107950,7e55089f,fab0b4f7,5e8021da,767528c2,2e37d72f), -S(b2c32ac6,925348e7,1adcc149,656c21d7,3343d7f9,a97fc90a,6c0ecb9e,4835fc53,a2fbf853,602cf32e,881540f4,eea48400,6a67568f,4d69f2db,3adff02f,9b687716), -S(de3610ea,e95e73c0,fe303cc2,9b1bae4,c3ee5009,a5751e40,6e0dc64d,c2128809,83fd3a89,3e9264f6,b0d9768f,b2137665,65ddb286,9b53279c,b7ac524e,e8383e29), -S(d91d23de,8b442f29,d0ab4a23,182a429c,299cfde5,8f2f991,53139d6c,3028098b,e00a507e,48a68d49,c489063,39942d9d,a7a81cce,6865487a,4b18b34,b1b2e65e), -S(ef90ef91,265655f5,7d776fe1,a153289,87052919,448049c9,b3342a94,9f66dc83,a44f99d9,e9e3cc67,9b819232,14b4de83,d95a65cf,c3af495a,2e961a68,21511c54), -S(aecd0136,83f0c6b2,d9434651,94d6d6b2,c727d3b9,3409887f,821f0bdf,ce30101,59b3d669,1952dcd1,bb351f31,aa281dcc,b5f7cba6,a612d5b7,7d3da3d7,92da741), -S(192c250a,31468e22,56c25dde,ed840d9f,e9da10a5,b9dcd4fa,505f418b,9993c86c,e311e20a,cd56146c,c03db59d,799a1d51,e3955b72,7137daf1,5dc8939a,3e7d0f85), -S(85aae3c2,2a26d60f,c14c46f3,d789cf89,5b23cd96,c4515ba9,87609fd4,dce41a3f,54bcad5,166281d0,bd33587a,52a16a3f,13d7b1e8,8bc009e8,7c4f59d6,e13ce99a), -S(24dfbf0,c22d29d,bb3f59eb,27dc89da,7c0a83d0,7b42445a,4993e205,43a97bb5,64858a97,8471f3fa,aa838ff1,b3ecfef6,1d47e3d,bb684028,bfd6c194,dfa05928), -S(909ff9e2,d591a673,40cc7df0,e73be5c0,ce19c4a3,24679306,995f6344,bd692f3e,5b956095,a5d4598f,9dfd693f,893ccfc7,d77adf8,bdfe9ccc,8497125c,1c07046f), -S(fe24c76e,900f320c,c41bac2,e625293b,ef871944,b0586680,3e0848a1,e15a60f,ae054925,3338878a,b1e8d268,b6feb271,512aba65,e7e8b243,7fd4867e,74b5fc30), -S(7704fbb0,13a7ccb,5b0c73d2,cf6fd87c,ce4c8d8d,f49515e9,9145b3aa,e02b2d6c,21ee85ac,405e2cc7,c9fe7a8f,7b59c71e,82dbfa33,bddbf113,64435f8,53139dd8), -S(e136bd1c,9b7cb6d4,aac07f42,1f1da3d1,eb9a8935,dcdd8097,7c137daf,869d7c11,c9d44b0f,92b5e04d,aedb2155,eb1930ea,802b205b,880db2f8,62575a48,22acf521), -S(c6efeb81,850462e,72ae763e,2c1d2f39,741babf9,5b7559bf,c28d263a,8944aee8,f6bf9cd9,413259e7,85490c49,cfc74576,c23bf0ff,9599b877,2acce426,1d3e273), -S(5d09a4c1,1c1d913d,d83c33ef,1377ded6,7affae57,899b5742,347291b7,c434edf2,15a6d501,a857e00a,ab42d1a0,525089ec,cc48d185,7f5dbe69,e3687bb1,2982cdf9), -S(9989c1ce,c3865ba2,41cbfe91,1b72edd2,ccdb8b44,9a837284,730b903f,b45507fc,81cfc11f,e8de5fc,6f850c66,21bfc5d8,9d7d2bb9,e8b9b2a,dfd23f8e,d2fe8d40), -S(c8d0b073,2930e2db,f149c156,c5957f79,fecc319e,f4abe588,860dd44a,d74779c9,bb96deb1,e23ebf7b,afc79ea6,ff7fd012,e2faff01,8f2d17fb,38fecd52,29aed776), -S(7ba25516,877adf65,6719f4ce,e867b4a7,3d7bb18a,735a6043,47d5d5fe,47be46b6,f66f2364,5fd24d13,39407ee8,241b07bf,7e6a08c0,d3a1e683,67b450b0,f3eda69a), -S(be8f83a5,5e50defc,b8357409,3b727cf3,578a270a,c478ada4,22e0cb8f,907edefa,c38ed801,1af0e3c6,55989b08,af329cd,340f469b,d0bbcbec,6504cd34,aa44ab9b), -S(9bd6c57b,438e1ede,cfba0916,d744ef9,8b010164,ba46675c,1206d9cd,67c3380d,d15ae82c,33b85d22,9df4349,ce48b582,10c1baa,689fb6d0,51721d22,334ae972), -S(e8927a5e,9f511cbb,ef935f7a,a90c64b1,666c8be7,1445cc8d,193ec922,1662177b,cb6f084f,a41e1bf8,110a98e3,bfaff1,43ef6ccc,56170ca5,de520a6b,381010d3), -S(c4243e89,4608658b,df46225a,85da8f71,dc75464b,fa29dba,6d096423,81b77ea8,d501050b,89abe5df,fb9a11e1,6d1f2bb6,d081b20b,4f0d9895,70ec128b,21e2c124), -S(582f0c51,20f5c79e,76dde6cf,624b11f8,1e9663a9,5eab0480,8d4156ea,61e70723,1f0c54b6,1cff944b,b9bbae8e,1d2570f4,315e3c8a,f067d289,3d9860c8,4885d7a6), -S(d384563e,67e85943,67725600,81f4287e,fd7c6fdb,6e29ee62,ff4f447f,91a4882a,b90fc799,7f76171,c7a76d35,7aff06b,df5b3d00,a1d6f089,bbb2acb9,e749b6de), -S(5655f9e3,5bdea0d5,d7d023d0,7a5d415,52c39f1,a9530241,55b647e7,e757e40f,4f60c357,bd0a7577,475c8e5c,9c6e099,1a21523e,821cbcd2,665d1ead,c6075a39), -S(b1209637,51d5e9a4,5bfdeafc,5aa9f45c,9c29681,2c4769fe,6db03118,cf0a2d53,eadaaa67,96ecf2b9,57944958,c9fb1cf6,986f387f,50d1387b,d4b94eb1,aed1e625), -S(bb6ad704,477295a6,710cdc87,f7df5c4c,c3b82fdc,749f8464,474fc61e,b307d4d6,7d0d1fd5,ea113783,7071f705,7bb783cd,a4b55908,9af6eb59,1d6c18af,434ddb34), -S(3daa25bf,5223a09e,fbfa63a3,405e8c76,b059bca9,38d513cc,693bcfbf,514cbd95,e876c903,22d97d60,fdb0cd64,cc9ad575,cebde9f1,41d67c82,7f542034,5c7c6ec3), -S(b32bb726,3f40831d,a8e00e27,db8ce14e,ff1ddf5c,4e48eb4f,deca0531,3770c016,916fe7ad,2726bc93,c242f50a,4e3e69bf,db965402,55440262,ccc5c055,136dcd4), -S(a7f331b5,26d74b9a,67ff3453,2399ba79,4fdd4d1b,1b99dae,1b7806e1,8a0a7f11,786b90b0,72c5a702,12db8173,2dd486c8,ba59c937,ea9182dd,f85275e7,d6622c6f), -S(30086238,dd36b617,f8505367,a015f6e0,2f14079,3b4dc5a4,442d8628,1ac8caf1,9b87d837,644f4ec6,c161c8c9,ae923bb3,f40f6cb9,6538c0f8,aa8c4ed9,42eccc8c), -S(1ec0343c,f9afd13c,57ef2b2b,4006c740,dc03bb3,62ee8129,c4cb35a3,299b1ab3,8b645dc1,91012651,3df47f7a,e33f201d,35cc1d73,2184952c,f605f68f,ba8a2e34), -S(e8059ca5,3aa197cc,3468c797,81b36245,4ebd8b86,7227a9aa,21816967,52d28587,39f9b33,e91eb4d6,fc769d6d,1b43fc0d,ee8f1841,8c682c96,5beb1e7c,9280d23c), -S(fbdc998b,96eade37,61e0b0df,a6c4fa5f,7794576c,91d5dc52,f9753e3f,748c5afd,4789bbef,e1f68f8b,2058e41c,c513858a,29a48cb7,be41ce56,248ffe3,996d043a), -S(3ab5a2fb,fbf2acf8,2becd224,4239ff2a,808aad64,41b1b47,1aaa9e67,12bbc29a,d20c99de,14e44cc2,18a42ee5,34fed723,25f225ac,8c68f2ab,d6c19341,5921e5b3), -S(94b611e0,63334b9c,195ff7c,894cabc5,2ce902ab,5b17a572,1a697c3a,8a4903d6,d8d70dea,a7d8fadc,da7eae42,3ea8cc29,285c32c2,30a8731b,52710126,dd03769a), -S(2cd6e98a,65c1ec8,6596781d,4239a71b,8e0c8a0,4c3dd8fa,c7925a07,2c246e3d,67bb6602,75d229a3,a28f51a4,a19cf6a9,f138f72f,5bcc2ce7,c689d699,b23a59df), -S(500f58a0,e8929d68,f4fd8e13,5fea7e6b,afb562a6,ce1086a1,19871799,c5a4f2c8,80924142,bbe02b2a,7decc045,23b6c132,af14283c,6f715abb,113a12ac,a92b4205), -S(4c1ef59c,5030213b,dab7be6b,c3f4272e,b7d4e07e,981a3160,cde6797f,821c507c,d878f643,a0f82a73,d7c9928d,ff243584,77475dbd,2076e7af,aa1c54ee,e66ce565), -S(b69d8ca6,6b0dd8ef,df2e7c11,1dbf7876,a3ffcef0,424f1943,49256446,78ff24be,1ba714ad,96ba9f32,456e4288,5b9d018a,f3cbb43,37e5a0cf,ebcfc5db,9ad76c87), -S(53def7f5,bbace323,cb0a38f7,2268fb93,1e4f546f,a72e5b5d,2d5733eb,6d39dbb4,1533c9ca,5c0142e2,e1e1ec89,d0536b,282cb784,7ae5245f,ef978581,e3aee5ab), -S(a7f043ca,731d58b4,c5048ffd,12028f94,bbcfaa96,efc52a94,6c78c42b,748ed508,8ada0d66,1aeb2b7f,36eaa00b,56424547,ea5af2c7,954b8801,9e8e62ef,ef9e1832), -S(7d3609c7,7a0cb4e,5294c831,d05d9028,e1d16d60,7495da06,b241a87a,23fb93c3,9ade4159,fbe98e1a,41297877,383f023b,5a7973ee,afd17af,65ee4753,d24a4f9b), -S(a488a3dc,20442c4f,aa127f1e,28d85b20,5681be3,311e5063,c7a2a356,1312569f,4325102b,66f100b5,7facdca1,7973b3a8,f9cc5d97,3f018e4e,7d035e5a,5d2549d6), -S(9c340a46,94b8bae9,d7e6a922,db9c750b,3089101e,946c3e58,88a4222b,42a05d9d,cc580dd3,679db392,74ab94c,d054f264,42c9ff72,5cf5c1c8,a485a48f,8f571ede), -S(44a788f2,c070a53,5c4111f8,6cf636c4,5ca83338,e0b71781,44e7c542,c289480a,99d57358,ee53d719,9acf8ee8,b679cf9a,5c44611b,bc17a734,caa914de,25d7b22d), -S(3039da67,d1d2a063,9b92c0c4,c7c6f415,c142acdf,ce21bba1,98de3bcd,ee9bdb9,c11845fb,32021c59,8d7cb0a5,a7c3da2c,851306e2,75af5398,e406dd34,fb5b167b), -S(6381f67,a6f5e9d9,535ca436,c92bb8c2,9d8eca9d,b335e159,fccb4609,484d401b,9f480076,aa6715c8,2fc04c58,d30cc445,156b7d9d,b1e4c1f6,3744ebef,5060cf4f), -S(7ab7ff64,d2955841,1872da55,7ed988a7,ba182fef,480d36e8,3b65f1f,cf0c0c3d,76262668,bd45b55a,dd32839c,591b6a70,9e4e7ce6,e9fdcf55,c78e9e83,dbdd6096), -S(668e29f,6b3dcb44,14e4c22,cc2fcc8b,3a20c00,89f94ad1,3f279c1a,41d7df7d,4afeba02,4ea185d,caf130cf,f7f12af7,7dfb3cfb,1871d641,83dddeb8,86545563), -S(9fde56c3,ac8016f6,ef6dfdc6,da621198,501eca9e,377c594b,e063b24,e0721dd0,dea4c586,233873f0,3ebab8db,900b4c21,6df32c7e,12b1f1a7,be26d46f,880022b6), -S(70f3ea86,cf318a63,e44ab07e,a4cdb22b,929e42a8,9c1eaa0e,a0d56bb7,a9d63592,eacecebe,3e94160,bf370703,2fbec0d8,e83f5bb1,429ecb12,4f11974d,913d4332), -S(68794d4,cb77a07d,f2d09cad,7b14c8c6,a8c35da4,9cb9be35,ec6c19d0,a3e4fb6c,aaf0efb4,5be195f6,29b8ea14,ec137e33,f14cb692,b3aa59f5,a71bcbff,d8511633), -S(708c3036,27cdb4a,58ec9884,6c23e392,e7d8e1a,c7c0dbd9,d640dffd,23938a24,113daf12,a5b57f22,fbdebece,3727474a,8289c4a9,2474135e,13970c7a,d3802084), -S(c74bba7e,2d764df9,e6e76441,6b40e019,5caccecf,75c8f0b1,fb3ca353,2236cf10,a97b858d,1ada13c3,3ff98a0d,404e3e46,768ecac0,b224b965,7d620c3f,ce3aad05), -S(186dec13,501477b0,dcd69175,c57d33f6,264603be,256b3029,b5f9dd9f,fcb5ceeb,59a646ac,96924f8f,cc02e6b4,14a2234,f49d78fd,6b64dbfb,f8baa0d,8acedc77), -S(94486ee,b0535256,ecdcdc9,576faecf,9cbb7c12,8286352c,3f3f249d,458e8ddf,4e5290f6,bf22cdec,8f7d4617,531562ee,f7402174,b13d149a,390fd9fd,17ec3e7e), -S(304f7074,5b9561c0,7facf83e,8e593af3,cff8d174,2d2472ca,bcc08ee2,9b7617ba,77654948,8a95197c,612d6bb9,20e6c9e,b2c2236f,5e28ccd5,6744152,f46ddd9), -S(97046baf,d42c5a5d,b8b892cf,7c36ea67,86dee4d7,bffbd572,20f9a122,26038a5d,7ab1305a,103c1cf5,a77f298a,489db57a,2c9148c3,6a834da3,ee108971,8eb3d43a), -S(e4b52916,3f73e5e6,45c44686,3b786f53,46b048af,3d1fef24,e80ded13,ffd89b0b,7409a638,452fe0a8,7f1e717c,b0e3496d,14b9e3f3,e6f4d048,52f622f6,ba4ac2fb), -S(b9d303a2,75452bee,7800cea1,1c06db97,4057adc5,62bf5aa,41c34e5,18f5ee9c,4c818cd8,a24b7775,35ed8738,bdd8d45,76408c87,ad172563,6c536ff2,ce6475dc), -S(fc459ce4,3283c842,1a16554b,d5eac61e,3e4b60c6,2b090c52,465788cb,120d2295,2b2e75ab,10a60dff,1e11bddb,62457bd4,585b262b,e671f5de,84ec3bef,d5b0b232), -S(19828f90,5f901716,bafd9bfa,856e8fd9,c19eb83e,37c8e5a1,11366a77,11a26790,5bf76d98,46398c34,6b021018,6dec4ad8,c03b866b,e0edd8c3,9f09fef2,d7c38bba), -S(e10dbb26,999ffd14,f29fb5e7,e3b3b78,1519e63f,ea0fd26b,b1b593c1,8267dfa9,c3c04bfd,799303ad,de767ff4,2baf9759,82c48d95,5f127ad1,d59ff73d,cbfc456d), -S(2e53cd28,acba99fc,6763f788,a644e314,1df5e17e,c50003af,48206aab,d81a3396,4393815b,db8dbe25,6b0269f5,4220200d,278fa537,666b5cea,34cd8e77,854ac02b), -S(f6d174c9,60516f44,6054b7ba,a0f82557,87ac2e94,c966762a,f7c428c8,8b9de7b2,68ff3c54,a3257f1,7b27a5a6,ee7cfa88,97493d3d,b0899b47,c56d4950,ba263a9f), -S(7d18482c,704eae8f,c6a33f77,923d9063,eb3e8e5c,28ce3d3d,8ffd3e17,ebb82881,a126d78,eac1033b,a223cf66,81faaf93,bf523dc9,409f03ed,abcf241a,b0a6e3f9), -S(b2c02f09,b930691c,a017197f,bfefa1c,bedbfa2e,640a66ea,fcb1c11d,f574d9f4,19fa7f66,cead7607,d404c33d,2491a6eb,ea0d3b00,4ef41bbe,13148508,b0a9d29a), -S(253d6786,8bf2626e,acf690da,8a26d777,bf9807ae,ccec3804,e1b7808,bd16ab91,145f6933,f9ba0d51,18eb8985,43a01106,bc702915,373bfabe,4ac970c5,27c17a00), -S(6e496a5a,28a74cad,4b4fa30c,48dcc62c,3f4b4fa7,e8151a10,3540aeb6,70c20d14,c7884130,274649e9,4e61623a,ead39ff,ff3b8a4,526509b7,7ae8586b,fe315ece), -S(774a8bed,36e7eb32,8e89734a,e5c0568f,f1659e3a,73890010,ca4a0e6,dd24a4ad,cfdb3a1c,1d8bb371,2e8f2ca7,2c578568,9db680a5,68c18e5d,4e423b84,df9fe798), -S(59bc8e0,e63848e3,79e0912c,4a0c9572,10023a93,a0dc4303,7b3b9e1b,7b834762,db8ceeae,61f6adf4,ac08c5fd,586209e6,f4879fbd,6aa9a1b4,4c67b4f6,69eabebd), -S(46659043,eed0a625,42513ca9,678cef04,2fcd952e,29be4926,fedf79ff,acc8b686,3a5f51a1,4c9fd813,3f11ee7e,6eca075e,f90c91fb,a10fb251,250b4cfd,9281082c), -S(aa92c411,308d9d48,fb62d7a1,2999083f,c52b5d79,196dc91f,e829ef04,41745aa0,d70ec349,f27a1393,ba8d57fa,968974ee,ab0d8e81,a497415f,d38e156f,bb029864), -S(36382200,5bea75e3,8c2483f3,eb95f6b0,a7f53f10,32bfb1dd,537cbe0f,4049f56,c9b9c28b,c2bf0056,91eb3e99,2efd5bd4,ffeeffb3,e7fed235,79af40e0,961489ad), -S(c3e4fb46,e400fd1f,e106c056,838cfb2b,c1cbcd66,ac9c19bc,e7df1e29,a7bd25ba,96b6c598,512215b6,a30486d,9f8b0c91,4589022c,194df5ee,30d62c2a,b9e83fbf), -S(71105f47,e372fab4,81cf29b0,ab5605d6,84c00224,ae1b9449,7c8d3c59,26077cfb,f7218aaa,d2a95c0,55f30f69,3fc087f4,101f5db1,1c9ce88a,629c5711,a1f1ef51), -S(676066da,6bc50ae2,e2e46f61,dea75ac1,12cb085f,2f00ccd8,5fef1e47,56059f3f,ea9e25c0,6c19d572,8b4bb333,35e94202,d252b9d6,33a1b04f,a7b4129a,2efa83f), -S(2616418c,11f5536b,c8873830,9758a819,f7b30e86,f4a16f90,ffde0685,e91a12aa,80b92bae,591f59cd,8d480401,644ac3c,940e917b,a32e7a4f,f4a2d5c8,cc417de7), -S(3bf5d07c,715fad35,45ff092c,18cee285,3de0d50,c9d68225,3596eac1,42111d18,e382d006,2c4b4536,c6432557,afd0b909,fa047ef3,1cbf2d8c,1eff9ea9,9a95fac0), -S(5e9d4316,db96d6c0,a5247809,8b22c654,7d873b1e,a4089071,86f81da8,71d057b3,e22c05b7,dfb5dc29,c07a735a,31bed0a3,2e071de7,41d734cd,dadd832,1dfe56d9), -S(3c153e81,e6ded587,dff1c8a3,ae5758bc,58c271ec,aa9dc005,1441ab2,a5aa123b,366fff49,b67b57f3,84b5f027,83b02d5a,f731f3b5,c6e8c089,949a0f2d,998636cc), -S(187518bf,347b87e8,e9955bca,b7937e80,7c41ef41,97511d9a,daa50f3d,9f628708,15f4ea6e,17a6649,36a9c04d,c76ed314,64632d23,6fb6a9c9,2aa0a4ca,afebfcc9), -S(edae6892,ad2cd7b5,9f559f88,b2d72fed,6bb27aa8,c7351194,388b38eb,4af9a6ad,e97c8ccb,225f734c,8416c605,52f24689,fe0e4f10,2d62ceca,d78d9ed8,7bf3c3c1), -S(e8bf332f,26d4471e,fac8264,2b3e3cf0,6c210792,ae39d343,d7c7c4c7,46ce79ba,60f53327,95e2a862,f6d82ed8,5e2d652,70fdfbe5,8118033b,105c3c2e,53257b73), -S(cd1eb398,4dc73522,e791f8ca,ac528da1,bf9c908,e446fd9f,7bdf4016,51138d2c,8a845cc,74325e82,14be35fd,cf520f3f,2a64240e,18d85bb2,18d97d0,4cc6b366), -S(7d7bed7b,2dc04b84,5b9b8460,e366d1d7,a49d87f4,45998a12,b6e379d9,461b035,bb7faea9,bd2a992e,1535cbcf,bb78b955,f89d8f81,ea650384,75399ea3,fa63e6ab), -S(b9de73cf,8fe63fcb,56b992c8,668e6368,7672c856,1e9be11c,9de51d7b,8eeb6516,c6884b86,8e115321,1bb98a8,1ecc8165,25a8600e,69155f49,fca83e5d,7dc8e0c1), -S(b5622f5d,2ff1b4ac,5b1a675b,192dc2b3,595a43cb,1120f249,fa55f7a2,69e15b8f,d8f3afc1,388938f1,25c3d4fb,fae7bbdc,93925fa6,e46298d4,e0d7a3c5,451ca1b4), -S(eb0e1fb5,8a74273c,c8912e76,5f150947,2cc12c33,2329a24,a7f7423d,83a3a049,e3b4fa95,1b958a1b,92b3596e,9e8905eb,934a121e,f15cf758,a5112575,4702caaa), -S(232a33f5,72cf2459,fe985373,2de8fa5,df1efe7d,32b14eaa,43190ec7,6a9450a9,144ca6c,7a114e35,37434426,699433c1,fb0cf4a8,bb9f65c0,14011849,f962b332), -S(e32e4c4e,b57ee32c,173f08d0,ae571335,cf4fa22d,d32e7754,740f174c,d8914ac0,f0669f6b,12525ee7,3d1a6e65,af27124e,89df20,5829eb27,2bbef862,ac053ada), -S(d89046a4,a915391c,856fba77,d4699c48,2b72200,4efd83f8,893fcc1d,f944e2f6,72595560,28e14090,c76d1219,9d133bb6,156a2cd3,aa5df1bc,c18c8b58,27a2ce04), -S(ea2fe94c,ff11c532,6c867e75,7544beda,8c39bbae,c3c2b8a7,62c3fb5b,5dc0b23d,10b02985,baf66352,e86f6e9c,a2c0cdd2,cda7ef48,79460ac9,d58f3a61,16663437), -S(71b224c3,7088851,25ed762,3caf674c,5e3863dd,d5eeb116,29a056e8,b054dd79,6002d88c,2fe7340,6dbf9c34,40eb5501,3a3757d,831e5f96,b35605fe,47fffe92), -S(29568f1a,11070ddf,bedb2f41,10246352,cab977f4,dd6cfbcc,be397575,dbfd270a,a68279c7,440fe321,fabcd58a,f7ab6923,e0f627c,909d6ecd,d009d130,aeef7b7c), -S(57badf5f,dd22af1b,11dcd60,e875d9b6,86e043cc,d4ff11d1,c91089dc,cc8230b9,7507b060,bbca59a5,aa19f813,eed95faf,8569dfa7,6d2bc327,660a06ba,8fda2b3f), -S(30d84aac,10a7b86d,d55fca2a,377e007d,1f8b8cbd,4fa9d7a1,4eadaf8d,d6481491,cd1df453,b553de9,1ae59e95,d08fbf64,eb9af82a,d0d4fc46,4d1574b4,f9131a3e), -S(79ac7c66,ff73d627,62a749be,c66c589a,67e33546,7a13709d,d72d9a01,98ec405a,803f34c1,e8b06902,52a3805e,abb30bd8,3942f1eb,84433ac8,57d22cc6,4ae0b04e), -S(6700636b,cf6a757b,8afe6fd6,d26def0b,6ae61da,ba7c502b,2a34301c,203af68b,91fbf4a4,c94105fa,8fa7de5b,6b6ba4a5,f34d677e,cf732db2,b660db50,e6a654d8), -S(84ab5f25,501abd97,a9d56f3e,5fe50bb4,4c2baae,85509b98,d38a91d9,74dad801,2dac84da,6b805b3f,6ab306df,22e254bf,d6c14574,f0f42be3,8d37cefc,38dde8d5), -S(e372663a,7464dbf5,48f0d0b9,c91867d9,e76ebcc4,ccae7105,7046b8d5,360365cd,6e80f9a1,21723a6e,da7dc2d9,b82afb01,2e3b1712,c7ccbd3e,2fe5b4c2,270e58de), -S(4a9ea0c6,57e21f97,9641f891,8975dfd0,28118b66,c9a2d38f,8b197a94,bdbb09e8,815246c3,2173ced9,13a82877,393df34,f8de1b75,c2b42abc,7dcd80c8,d19f1b5e), -S(a05157fd,f91c475e,97e110c2,969869bd,31435fad,2aa242fd,c4ac2e3c,c845b0bc,76d82bab,176ca9f,c3cb1b25,541e0407,91b79739,2581c4d9,fdff832d,3685ac6f), -S(bbd11f9a,62d74bf2,49e4831b,fb253ceb,8e94eeee,bba1d08b,b88ee5ea,53e940c4,762540c6,24e7ec7a,487586d,727949bd,d4d7162f,b5d1dd69,3a10f6db,f41193e4), -S(a7fbbd53,62d41020,6fddadf2,36782aaa,f33d5945,5bc00106,9ff41bd0,41cc53b2,aae57e60,607a0d7f,5d12da7f,62a51075,5aea3686,5b12b678,3d27456b,6a2f8a04), -S(6d984c7a,816b611c,8731f553,2ea1e6ed,54717a1f,4163ea72,9825bbf2,814050b9,c551d373,8b815e9b,5256a8c6,4152db2b,d8bf881e,c10254bc,a584f7c,f5dde7d7), -S(ccf5595d,81440526,6244e5fe,87eb293,3dd5e684,b90d58c,1eade733,e7c1d2e5,862179cd,ed77b0f6,1adc0f6b,334f6942,94d71057,f42a017c,9920277,3021dc16), -S(e0b6855a,e19ed610,51c9fa8d,4bb9834,a27e999a,81d4584,1945963b,8c5ba5cc,9626aff2,cc89288b,768fe91,3ffa5ca6,8a99b9ef,d904677c,fdd02892,815ec4fb), -S(4b3347b9,62a0b644,4942cf83,a30420c2,f164bac3,7aea2003,ebe5d232,58dfa3d3,5e38a814,d2ec02b9,7f12afdb,ff857692,e9ff35e1,1ab85cb1,613393cd,3e36b365), -S(646ffbff,5ff88f03,863722db,f554d9d2,64a4e14f,d2ffce79,d9f965bd,aac5c401,335e01bb,bd97b4c2,36d18b0f,53ff37f7,f5fc39a4,79092a76,1c159e56,c2162340), -S(977b9528,ab51f6b0,1e7a33d7,2a85216e,e5fc37b3,c0acb9b2,de3ecdef,38ea1e77,b16d9644,394c5ea5,2c7aa42b,543763b7,1b4d284b,a81c2fc,e4866d87,b1a65234), -S(3e80074c,b8c8b1fd,3dc97c7d,9e79fbba,1ae672fc,5eb43b3,c1ca69a7,8b70224e,6069492c,139fbced,707c65af,1e97270f,818af208,738a5b33,f73ee222,a90feed5), -S(15b035b1,108ad096,a201b0db,5cb152f9,793f9355,22e8d68c,adedbaf3,eaa1824,a95eee2d,e2f7fd5b,1d07c262,d07837a2,20683b29,805cb5,a19febb8,424a33e8), -S(e195cb6d,d4c21ad1,f054188f,31664108,1f029be2,22850118,8a6464f0,a2a93449,9d1babfd,9848c2be,15c89136,a3aec42a,8f85c2b,f91613ac,12db2737,b6bf41d), -S(1a309895,5513c42d,48db553b,22e27fa8,7d823df3,2ecdbceb,45ddb4c2,8d874bd7,69c52bdd,8835d6ce,99e3afa4,259c1513,4f988c24,f64fb913,c9353775,7c86df9c), -S(83aced50,fd6ff475,e135c85b,c705cafc,7e5eea1b,c6b370b5,728ab888,54ec74b4,d0ccd0a3,3e276d64,90079d05,4aad8732,6de6b6db,5e909fa3,c2546d4c,aa9fed40), -S(f2619c96,b0e5ae71,fa78c661,b40f321c,f96d6b25,ad8cd2a7,53fee657,4d41b147,9ff732f3,4c68e66e,6940e4b0,e5d0d94f,f223d53e,6900c80a,eeb60778,1d64f77f), -S(a49c15bb,3f6c8aa9,11117942,9f609456,ee4380eb,3fef3073,ab0f6c1d,33a4e3f7,70874663,301c27ff,551962a8,6c561ba8,6f1b36b6,20325864,a76faa52,31cbfa26), -S(e96fc9aa,2e1032b9,2a9f5263,4c35b7d,f583ca,fe774756,97c33a2f,703197f,54a1bc34,1fbcd484,34d1254c,73b9533c,8cc11db5,92363fff,10a996a,864f79b8), -S(64489edb,18791a7,f1f4be16,ac93de2d,e5445cce,ff8172d0,bb467dd8,e7971d14,5c343cc,b6723d79,ec75ad08,69aa1308,4180518a,679bff85,6e8b0e3c,21c41115), -S(9ef3f569,84c53365,8bb39b13,9271e54e,c5d376c6,f9f533d1,adf94921,ea7c066e,f87998e8,831d20ca,1b611314,7e426acf,768ca63,f6b7eabf,a4e6fca0,ac33c377), -S(5391ea1f,ba16db25,999f093d,c8308dff,a2ef9aca,17cea315,6c974bf,28540218,36dc27c7,c3a74f8c,332cb471,cdbfe71d,22b12ace,a2c86e6,24104da8,bef66212), -S(b98831ce,adac19c8,2787e84,cb443685,4208f189,b24040ec,2bca6366,6c601c5e,d753c01f,8410fff0,8278a570,16bf736d,a5ef8a0,f1d9eec0,c17a0f22,74f8458), -S(f2f9050e,b8d42461,b8d11189,3a3de4dc,425a7468,5b34a0dd,7bd3ee98,284496ff,74dd4077,4f0ea177,ba875cc0,f8b504e4,f7d352ea,8ada429e,bd49510a,c155cb9c), -S(e76ddc1c,179ef377,a8da15d7,8c3cd8d1,a775089b,8d542e42,1e6220c2,4390aa35,ecc8baba,1cf42a6c,87918ed9,f70cd24f,b1a3deab,8ed86640,fdc6ee89,ca7ffe76), -S(e1c86064,1f85ad29,afbb6092,9dcfe648,82fc149b,952d1c2e,d50c6a44,13b2d5fc,1d418333,15eb3b54,9c067140,97283de5,fba554ad,2ea510d5,f1c12d83,e730e25e), -S(9dfc52d9,e3e55bd4,2bb21cd1,74a54c02,dfef16e4,758c10c7,ccc0bc81,af509ac5,be552b18,e576d5ec,6961893c,1498253e,c1539068,aeebae6b,80994a10,8140d7d), -S(24e672b6,905f5ba0,186acbbf,6a344c15,f3c59291,8c23922c,fc928b2,5aab8ad0,3b4799ba,9e23bc85,b622d248,9343f39d,59e80244,e25806f7,7d919504,89c5400b), -S(e4be87d5,2cb2fc8e,bb793449,5c94b07e,65aa86a1,6f9b63f1,b24a859a,c0737096,ac28b858,a4083916,eaafc195,81dc8f7b,e163608c,1f69c9d0,87a76446,71110b4a), -S(4379567f,ec797600,9a98d7ae,e3ae123f,dcbb167,2de5e367,bbb40e9c,ab87fdcd,9a2cd1d4,7ed65b8,c2ce95e7,451ad868,c1ffd81b,929ec58,49d82a1c,753440a4), -S(923722c8,f0b1b91e,261a32c6,75fbb26,ba4522de,b9610173,25764974,8c8eb107,b51b46ae,8a3951f2,7d564cd3,395a6d64,27b5232e,2c5b9ad3,6419ef5,d4a5cbaa), -S(7f749af,3301792c,826a1162,b3e86f1,35d1d9c2,e82275c2,a112ecba,bc0f374,d31fcb26,20b1f7b2,d671a52d,ccee8b1c,f47858fa,d28bfb91,475c6889,dc19cf47), -S(c657ab98,6bb3b2ec,87c09d23,530a9136,e85ff051,4d588230,bb9a2326,b058a052,a4f46786,410619bd,60d33aa8,1d8b7def,62c47ed1,bffc872a,941dd1bf,198c8ba3), -S(7f6ff017,2459d2cb,4f305aaf,ff17cac6,5a450ad0,d705310b,418184bc,7bd2b6b0,7ff8f3c8,782d2bc1,8e466df1,f3463a0c,a73dfd06,6cf874dd,65c8418e,91e6c1ab), -S(79b46336,478f2d3e,60e8d0cf,2c905b8d,c0b981af,6ab4cbc6,b36d238b,9d5acfda,7a31811d,95662ab,dbbef71a,5a0672fb,eb34ef37,c39d9ef2,e6f4f27,6e1d6514), -S(df51181e,5ad2e6a,5392c92b,14d762a3,f823123,d4243b57,21c1fa89,bdb2c386,210b2061,bcdea7ab,2e2e98e7,66fd68b4,63330ab6,9e7b1349,5a349087,fd18dc63), -S(5d60493a,4becf377,f66ff41f,9fd3a6fd,5603e504,b4d436fe,bb53c1f6,9038b75b,83de8acc,d2fad488,aef0adad,5a4c314b,6e9ed8b4,9adf56ad,57bdbcf1,a4dc947e), -S(f5b49912,1eb62fa2,c8db16b1,c3cc8ec,f89bdcfc,fee6c5c4,7978bfc2,16ea8a2f,5b0d4f37,8a436098,6b4597e0,a90557a8,a272c668,ec1ad310,c68e30f5,8a409927), -S(67556489,5729a58c,719c2c90,1e6ed73c,16909594,74100b06,2f64e242,c79a1ce9,2df2fd1e,ca39c5fd,a73bc75,bb9e5ad1,ac6571e3,322b433a,1b09022f,80ac4e63), -S(b6e3dab4,d13b42c,54238d14,4a47aff8,782562b0,28422017,ab775b2e,51baca6c,ae4adb5d,67855986,92c72c0b,c617ab63,4c65068d,d603e762,a75c273,e9622722), -S(b62a111e,6f15ec98,6c570b78,316f8857,5f59844c,deaa7fb4,3f76642c,8bc4b064,16a1dfb,551d006c,ca3fb15b,2d250287,41c2a5,35944e19,f7f1c2c3,59b0288d)}, -{S(ca3c008e,cf9efd5f,75cc1035,f9edaa7c,46b17d25,9895b0e3,b3523b6e,eee9daaf,a676aea9,3ce9bb,128ffc34,deb96b0f,72179d28,77406d04,6d0c8b5c,3572f4d2), -S(cda11502,15f6a502,96b3e042,445220f8,54e32a97,32f1e883,e41cb082,90e51c56,ae62e394,7f16dcaf,e5a6a54a,5beae349,a620d996,599ff570,36a9b6a0,3be63dcc), -S(43a90be4,b0efb9f3,422e5374,69fdba07,6f746874,b513f247,854b78f6,4937fb15,4799a0ff,b4026ebc,f57c8b5c,137d4373,ace4fad2,4e2c1705,34940b03,c6a2f0df), -S(612fbcdd,9f251b85,c43ea00,57b847fd,db78f2d1,6031505d,26a81920,e4c32619,aeb8a7f3,332bb112,fdd78825,fbaaedf1,199431df,929c5cde,b5a173b6,721fc139), -S(a2417653,34077e0f,3201dc47,f6ec3fe5,546b08e6,4f12dfb6,3e0ce0e6,18db62fb,271d6d97,9f686ac3,c4191cb2,1a3cfc65,66471502,b9e85207,47948345,1199a73d), -S(fc216e07,b2bc34e3,bba2f0e4,db770bc,33676cc9,1a5f24f7,cb2028d1,7e4c5f9c,fb16790c,386611bd,e567b83e,571a8fd8,97332566,6d2aea7c,903bb4a2,b5354b5), -S(6d44d409,e5f13c7b,e51c1835,f5b223b3,801b3895,802f6164,63f5a51c,449da3d2,6389e29d,957a6961,d796620b,23ad36f0,45dfddbd,533345e6,679bcf06,9ab214d3), -S(7783276c,a37fc014,3ce53700,c7ec741d,33c5222f,f4a10434,270fe9f3,cf70e9d3,9939b8b4,1c64a8e,6efd144c,78334bd9,33b86122,88ca1de4,22cb361d,eda16a82), -S(89339ebd,e4693665,ca9b88c7,f0a4c76d,2639e81c,86c349ea,aab9b974,a618d2de,6fa55c4c,ae7d0246,4e6d6f05,8ac772fe,1456c5c5,2d2b008b,afa9e4e8,bc7e99ba), -S(1ece996b,4408d,f01a9e25,7a6d8746,cdc75105,e614f6b0,5ac9c66,1226e55c,ab521d8e,effac213,38abac36,12958256,316d6858,594ddc46,9de7718f,d2714f48), -S(9c0434e,e311b25b,e1c4f60f,52e17c5d,59563a8e,c1b5278e,595e3ab9,32ceaa6e,a56270e5,c5e402d8,a1b84f23,6899e35c,b558ad6,3a168172,e1d60cf8,da904791), -S(87af4f94,912398cb,174965b,ca3e7e1e,957c67d7,fec69db1,a334154b,39fb41e4,5e981846,bff7a54e,ad594fc9,4cee7666,1a532bed,77e20165,12b58a3a,208fc410), -S(7bc7f81f,98686420,9b81fee2,aa157f6b,28b668ce,440dbaa6,f7a84fb3,5f3efc42,fc60d70a,908353ff,2f59fdcb,83a02ba6,5e20e6f7,5a73f0c0,b7cc096a,9b745208), -S(6ab61063,7567c0aa,c32da688,1d8e1918,b50a359e,c480a235,eea76e03,56d3472b,455f4f81,d6b88c81,72011644,f56f97b6,f2e0d2e3,e93780c1,ab0fe6ea,26388c16), -S(ff71967a,d8766265,b45a9cea,ba7542df,5bd35c9c,60fb5306,4d4de071,e0157e15,edd9241f,19d3bcba,c2470941,4fe7902d,14ef2c17,b3a2cb3a,481e4238,1618e94b), -S(9d4cc871,2f95c218,52c07b13,5c783ca2,3d9d2dcb,e8f2a78,8c9f042d,4629979d,ea4bbdfe,b3fffcad,9ff3426c,fafc59c7,254b6977,601eac7e,7355bf3d,ab7d7ffc), -S(e19a2aa5,49b720ea,2002b863,47dcccd5,b764f5c9,9bf63760,93612d03,cb5627d1,16c930a,b0dda080,45b0c758,4ffbc063,37a9d42,27fa5d8,33f61e9e,356fbbb2), -S(fbf6c918,fdb5292b,17df3aab,e54664b2,80e59ec,e9ed6103,e5f3557c,e7e9320a,84454694,62f6d530,4a82cdf1,3310527b,50fcc8ff,13751550,cdd6da1,ccf20b9f), -S(f9912cc9,597a48a2,7a581be2,c72cf767,effcfaf,c0ad7a04,af2aa105,8fe1a19f,dd2c8c9f,da952245,1e9521dc,f5899430,51f4ea56,6ce31d67,d2936ad8,209eb005), -S(52ea2681,cc2b8988,3d283a50,77ff1af3,95ba85da,3c70f20b,fd1d6652,1f9aeba,c6440e0a,8d700973,5c5b6e1c,6aac224a,76481a30,5f732630,30353cb,4cd630fd), -S(164d8059,3689a410,d49574a0,925192a6,f1a55289,187b3c97,30030142,36d940ec,46ade58c,909d01a4,fd827090,d266362e,cf2a374f,95b2463f,e184288e,9534ede3), -S(e32e1230,46171571,6410013d,b1fb8ba2,f8914aa9,43cafc5f,91ac552f,4d8e24a7,4af269c7,ed6218ae,6c1db9a9,4e5832bf,a29457c8,4c814d52,24dc9e2e,42674407), -S(d57bdde2,6e43bd76,5a33cb8c,a4e54db4,df3798da,5d930148,37eb0dca,35e0f999,7a74180e,5225fec0,20a10d63,2cb2134c,c4109799,22508f5c,d86332ae,8ea7c89e), -S(b5bc01b6,4203cb60,caf4a7c6,e48a1c25,a92d0eb3,bac74789,cf5288b3,80839576,30403b6b,2824a95b,7810301e,b467cc7,b882e5c0,a02c28bc,bae550d2,5c83289c), -S(73b1be34,b9229a1b,bc7e8cda,6027b7d0,4c60ea20,3942fa98,98f5a4b8,98b510d1,7336599c,9aeef8a6,296637b4,13b2f22,4c5ad7d,fc00b225,9152c891,249539b6), -S(a165d932,4b255170,998d39ce,39d392b2,cbccf282,2dc1acd1,c364fe28,dce909f5,f24c5fc8,cd8cb2c9,2bed63ea,a9a2dfcd,932915d9,dc2e9199,d2626fd6,b360f64), -S(92eb21ef,fb8d4e26,89bcad2a,2c4f1e57,85a8fefb,e4b6f8db,c0fc1681,3618058b,7ed25a50,4174b429,103968f2,8f4a03ef,96b583dd,840c32f8,ee1e7774,3e9ced10), -S(6a15d7d5,c5a1d77e,a7544c52,123d0e30,492a021d,3ef16056,46dbd533,e181ebf4,d4d14e77,54a5cada,520f218a,58611e5a,dd6c4c1,755abce8,6050b0fd,ad239957), -S(75ea5369,8a9f0d5b,49a0401b,b2db3286,5a8620cf,d29212d0,1bb097d0,1547cbea,f3e1dbb3,d50fc3aa,e6c16113,1271112b,4fc78855,ea6f303e,51268c9b,2535b159), -S(a3c4dca4,1ba14d89,51b088a,5667f8a2,f8ae1e3,e0438a86,c330c484,4ea34fe8,8113e61c,bc74488e,96fa68df,12fe199f,b0b2366,de19294a,de19ab0c,a24dbd31), -S(be54fb56,80bd0b30,3d331242,63714604,36c66704,8630035e,191c4a2c,f69400cd,15a679af,a8b0c05d,b5408a2e,b3ddf648,86bfe8bd,721abc7b,8bc4aca9,f1eb0e5b), -S(ff1244e4,a157e177,f5700b47,9787853c,c517c335,7dc1f548,a19ad178,f6a40b4,db21c79a,12f90142,befed50c,e9763426,b99b4d9e,f3f37c17,25abd50d,7cadf848), -S(84038a62,5d232480,997e8ee1,5b0e04a,547e2381,74955b30,14da26ea,8aac7c1e,87552fb2,b09c56a9,a81e40d4,9fab776d,62c1a5bf,63a84e01,9b869c9,40f7ac51), -S(50f7f61f,46489c82,2a8ee22a,7e79ca89,1ae4a185,9004a039,da3d16a2,fbe61608,6eb139c5,f399d702,5094ae5e,3035d3a9,e355e4f4,2ccad686,566d298,42eb788d), -S(c05af73b,9858124d,8ccb5eb0,232d8821,d98d220d,f4ade4fb,99519c07,ac665ab1,7493a780,35acd676,966604de,13af29d0,3a78a962,7cf3bb3d,1b1663d9,6a7e36b3), -S(1f480d5c,2a1d1761,ea954284,d2a072a,a66bb6f0,738d2640,4ec9cd34,bcff91b7,10207028,def341b,44a34078,f07af764,2a879d2f,a9e3a18b,ea7450be,1d3e1770), -S(a0676e87,8944445f,d40dd575,fb0214b5,983b164b,2fede667,b36f16da,4ca3e338,6cf3c93c,9ca2fd3a,b0ac23c4,33064a6,d1a6d275,3614be7e,a72cb3ce,e9e02f0e), -S(13e73034,7c823fb6,2769ebb3,ebe492ac,243a3bb0,2f84bbf1,6de239a5,f1fe62a4,564f2cda,316ad30f,5a552164,2a1ff7a8,92ad0afb,8bf2928,ff5e3970,9005f251), -S(18a96b04,1592fdec,101b7df2,6dec0d49,6be4ca32,be96f54d,436242f9,8092c481,cf03371e,e4d2d4c9,2ea7ad23,db3f8f97,d1a96a73,13b70e82,c3ee58ea,f7567ff2), -S(9592f438,339a1044,85ae414b,d30cad38,929004dc,e73fdf8,c86fa2c6,776e5bac,40de2fc4,66571358,ccab78f2,fa40acf4,d7c98188,31d475e5,556e7b68,d6c37235), -S(bd76f4f0,b9ffa96a,1a563855,6b35d855,f07580d4,45d10505,b1e5f546,255429fa,551cfb81,d1d05bdc,e66cfddf,a4843228,423540a4,278e5a9a,55137a9b,37866d6b), -S(fbc20168,bd1f044d,2ebddf8,a7dc1b2b,97d7399f,21d29fef,fba5f8f2,fb60b84b,d459b367,6516cafa,b6dcc1b3,8ddb10f3,8ea3ac,7f73b4b1,3052ff45,6d624c2e), -S(240584b5,5c64bdcf,4f233adc,eb7c9c7c,41d1863a,b0ff7ba1,68f74c8,1ddff33e,221e273d,ac154ab1,f4d259f7,e5803f5a,dcb297a0,48a39637,6e15327d,fc6b194b), -S(76798d07,c586b782,51e6accd,593a2534,70c77c59,da326d1c,f8ff561,8ab0e8c5,64ae34a8,8c9dbeb3,901a997b,eeb4a9ee,4b486c1c,b3dd9da3,218106cc,7d07292), -S(7a9f198,966c08ef,f9259fd9,5a3a198b,eddf9f77,384b671a,cbc16ba,5465b618,abc994a5,8a0c8dd,d98200c8,eb951e61,16a553a2,27ef6e16,bbb27bea,e0191a66), -S(dc8ca205,279a54bd,8552336e,31e02c72,909e4c9c,d7560616,1ab4e439,173edc73,b08feff6,221c061d,7891890f,be84a459,a57eb118,b67c4ff4,7ae62d56,7c158f9a), -S(575a0e7c,dfd55dc0,f86bdeff,7ac8a740,168f976f,be2eb9a2,2bcfe376,290e9085,5f0303eb,5d8ee545,485c945d,5ea765f9,7aeef7f4,e7d6b802,184261f4,9995f574), -S(50e48366,e86ae12f,14a9a78b,22e76176,fed8e25c,ccec2033,f85e7473,96756ea2,8af4e0e2,57b6479a,d58b2f24,2f256a20,ea30864,89b84b2e,27da8481,d8eccd3b), -S(9c98498,d5bfb24d,23f25983,952263cd,9513fadb,a91dd60a,26b7dedc,6fb42e6,c5ea0af6,4b90d3f3,37bbc24a,c2138426,bb349f6c,d8b23829,d0ea1da0,2107ecd), -S(dc253e10,17608817,898ca299,2d325aa0,20f88ac1,676e81d0,d81e75a3,884015d,add05f5,1d8ce337,a62e2401,399015a7,608c1446,7cc042be,2da908f9,b6ee807b), -S(9ccddfc1,8c88e1ca,cd5773b2,b378ee98,e4ed6084,d8fe9a06,e115fd67,a6f01671,439d7033,6ad30482,a7bb89f5,425c5295,cd888c44,b0a0bbd2,7b2b0ad9,499b8ec4), -S(3654e9ba,ff41cae8,6129545f,9207cc3c,315773d0,b230e4d3,24456721,f220e8d4,98eb6499,702161fb,feb0d263,1702bdda,52aa5ea1,867351ba,779f485,7ae3d59f), -S(af31613f,e474bdf1,7320682e,4d1b35f6,ed6ae63f,806a7cb9,f9a47ea2,fd8a38c3,c5fdf037,2cd6f61d,bfb96b98,19819aa3,3848b84c,4b1b69dc,cbb6d9a9,5e3fd807), -S(d8e1f1,d2913c6e,553ae630,64cf7673,437c2843,7f715720,3567b881,7552c73c,e20ce3d1,b6d10cc2,517dcd67,ea82d676,555e66f2,3ed742a0,597065c1,d849b9a4), -S(b3ef1895,7f8f2cf3,3545a9d4,7e0c3c4d,7e24e363,85c1d680,67104d9e,1f2884c0,8c2f8d97,32ab264f,a5d63cdd,f36cc4bf,4cf4ae6c,8e0fb04a,c232364c,37b0e53e), -S(d2d86d8a,68ff342e,a6c3c79f,42ded832,9098af79,dc2c83e,39e5a728,889f1bd6,9cd4fae9,db605e9b,fe25c52b,14d75e2c,a8c9b58f,c6c18d76,c5fca9b7,f6b9d2ce), -S(a4ac3b1d,39a44643,b0487b6c,76cf24f1,114eac8e,2163740e,b63776ea,52432f91,b2278137,c5a81c23,e9bfca31,fd6cfbe9,f11cf1bf,d1f32573,f581d68b,5acf4a99), -S(b12353c7,56fc4737,7d7f0383,6f6c6f62,594323f3,cb27d4b2,d64c4b81,ee3e0b7d,6813fa5b,a5ef894f,6fee8ae9,ebf2b1c1,c6298976,560c731a,df87fcbd,f916a837), -S(5f1a8fd7,b5299929,c5e1865,c28eebaa,13c558c,cce6f26a,edfa80a3,a1450646,b043c995,c6d66c56,77f7dc03,f7e599e3,70e89ff7,899ca5e7,165ebb15,f590d867), -S(ad4222e9,583e2afb,2c56a116,500514d1,92c0b10d,4eb66592,2334c817,623aa28a,97e34c9f,bd9650b5,a5444e2,4a04c5a0,78ced6e1,2e21f516,60a3d4a4,fd2319f6), -S(289585d2,886d9020,8870975d,93373b87,b3ab1909,21d392c,82abb695,22681e2,a40915cd,21358a51,798e18a7,9595b3b6,b7a645cb,2905bf75,db2c2438,2ad63073), -S(3ed81e00,a9607ac1,8167afd1,e25d80e1,9a4c1a23,69682ec6,9f40ba13,d86e818,59ce30f9,8f646855,ce9fafb,abf7b2b9,deb1be30,de5edf17,7462fe3d,66f02e27), -S(5c12a417,91a0f2bc,42cbb301,346b4e09,d68d4720,aef188e,7ba44469,e2e63f4c,540ad65c,9432a241,5a1e1af3,2d6f8c88,8c47a741,52d6224,f3d5e486,7a219c6a), -S(62e3fef7,6ec4db38,5010b30f,ac2803ec,27088e79,2db7f8f,72be35f,895ffb61,c0c8efdf,f9589931,14c1bd72,891e2743,b3189ec7,1f05d5e8,a0d7cfd1,753279af), -S(677740ec,ea09a280,7968ea8d,fed5cfa0,58d9564e,8f22f96b,79303074,58015089,cec6fce,30608c7b,2cf3bee7,353be7bf,a8265b2a,a6f058bd,1fd87059,f261beab), -S(ccb0c3cd,7d9ae81,f366e10d,c5444cb6,b713088c,739ca70b,fa214359,9b806937,4562fac0,408cc5a6,a961d8f3,92ac2566,cf02b599,7d645d57,bd81f678,dbd9c43c), -S(2db401c8,d474f7ea,a25088d9,d835a9ec,b1ae4f04,bedd711e,154ccd12,79a5e68,654a9bf0,ab608472,51922ffb,aea4769b,29894a4e,be1d175b,973fbdd6,7393bce3), -S(514a03c3,5204855,f4339a8a,d8894a5e,f0f7f8cd,b02d597,6d4ff85c,7a37fd1a,25d67f20,94a0f6c1,49999c5b,dd4808ad,d49f0875,882bfbaa,b391a8ee,7f7f32e1), -S(90e74327,cd112d5a,b93ec168,56b3292f,45eb178f,5578ea2b,a51a8b03,2b51c78d,fdb46efa,92e1972f,7c269259,3ed95630,74752c76,cce15d51,c1fcb011,19b7f797), -S(a9ef7f4f,857083f4,1eb3cdf1,76b738d7,f25b8c3a,e4705a26,21d791c2,abdcea1f,8dd007cc,7c6da435,267329ba,17435394,6319fdbd,8cdc9ce5,2250cbf8,252d8de4), -S(7dc56b22,14d62402,1c42f6f4,f148c146,6156c1f7,7d14d505,6e65ac0,693952f3,ba58259,523d0aba,a8bebda7,dfc67df9,4e28aa03,957357d7,235725ff,bd6cbab0), -S(11f8b2c0,a75a1423,42da84dd,4d04e5cc,e499f5e8,cefd2b5d,e73ec422,1718239f,29e26227,6ed2f32d,7824ec3b,5b776fcb,ea5800b9,2acf0a31,bff27cd0,7c8cee02), -S(9d0ce33,8fbd0443,3de6d15b,6dc3605c,edff75a7,4cd08e53,7e078ed8,bfd3a1bd,ea0b5cf,3a63c7ea,6b17dd3,fa19139,9078d02b,760f7d2c,f56d4a83,a8f0bffe), -S(9116520a,ff9d1ad1,e6c1031f,f9388b1,b1b2bdef,52f49937,a93752a0,75bb21d7,2ab7c4ff,47368f76,c1df0b33,54bdbee,157d7b2f,df4e19d9,d1f09c87,75d95c0f), -S(89c5fbce,ba4859ae,2706d0a1,e4ea2956,ebe71d40,3d1eb34d,7042291e,6f584015,c3a99137,2fe042ec,1dd7c83d,4e915231,cd5ad4dd,5bdb3877,bee1f9a6,8dd368c), -S(2f4fba9e,eba5a0a7,b22dbf3a,9867bb06,ebf3c4d4,ca5353ed,315b1752,3163d4bb,6c156492,d245e1cf,7673aa12,e78d0b45,d6171dc7,be574418,aecb9f12,3d6e8ad9), -S(905912fd,599f59e9,a3009b0a,7eb38034,fd9ab746,336831cd,a1985ba5,37d39931,9a7716b0,3524e8dc,714c76b7,a486660b,2ab30e45,b3bed8e4,f24e62bc,d1705272), -S(13cbfa57,515d5d33,1d8823f2,a8b5e083,19239bc,b1920aad,42d4f6c6,9934d0d7,f36e2353,700f0313,9236618a,ab0b5fde,5a8e14af,8e5e12f,47fda9c3,79ac150a), -S(cc939020,199611b1,c97458b9,cb9494cd,a9dfb14c,a2cce863,3ea361b4,68fd0857,a33978fd,e5c6a683,90dc368f,37e01e76,e2c08a1b,512fd2bd,d71abb9c,87ab7bf4), -S(6ff68519,e62b3e23,744a2136,2292bc79,3c7bda5c,4ef1ad09,81843ef7,183dd564,6d4676cc,baa85268,a4694ef8,55e86386,1f0f5a3c,38c8cb94,4ff81c53,c0737da1), -S(60a82e4a,5084495a,ad08d440,45639dbb,e0c34867,6dc3bd33,4f447815,6702418c,666c2a2b,ff70a40e,c01c5f34,cca48f00,16896e55,f14d21c1,e2fa80df,d4352943), -S(57231292,66d1532,f352005f,b3e789d7,b19409f8,cebec41,b8b43330,cef1a7,5904c51,ad1f7ac8,ca6a0ad6,971588c3,42f98ba8,6fab3f9,b07b648a,26f3269c), -S(c50d8b68,bb031e89,131a9be3,1882c8dc,bb109fd7,6df989d0,4b0009e,cd2db9e3,10286cb5,875480b9,3bc78987,9615095,9126c3ee,c66e23e2,3b21231f,d41fc039), -S(ea74572a,bb5ac532,fadcfc73,b85328f5,de42ce24,d79950b8,7f6e0c98,e6fec3f2,c68a3ff6,254bd3c9,febab9ba,c6dba6f,33d34551,d8bf2c14,ffc29c09,10ab374c), -S(430f73e0,8eec3d03,8bab8afd,9b30a5b3,5008ddd7,4cb85aeb,7b836ade,3f25f6da,27e179cb,ed69a2ff,ccceef02,cd1b8b9,6591deb3,b94a905d,df9e0df6,f6e8fc7), -S(dfd0f623,61e9baad,2fede6ed,9a6dcff5,3bf259fc,704c37b7,6b9a3665,a0296709,a9ed876d,5cfdf560,d3896579,57ce1aa6,13795b86,1e2e493f,719b8cd1,85e11f84), -S(f486a524,89f858be,ab920853,b27e5ef,945ebfb1,def5bbdb,8a7f1761,451ec105,f50aa3d0,cc587372,a1e941d7,608c86bd,10bdeb39,60cf57c8,482113a8,d3039da1), -S(3ddb3b7a,9b0218d0,2fc62004,33d21317,5d811aa5,a5d6b9cb,53ceee05,75341982,84017fa6,1ed2827f,f65d3bc2,3343effd,403f77c0,4524be5f,4c763bcd,d04b70a7), -S(c5938802,42f1bf38,5f5574e6,815ea291,b13578a6,cf8a31ca,d516d3fe,ebfb1488,5c0f3858,e6dd3b7e,f68b4368,dc3b5a95,d866e2bb,fe269527,fdf4b3af,e9196375), -S(11c60556,d6584b79,882f75c3,92e036e4,2aa702be,1f545e15,403eff6f,e27cb59,8544c8df,51e9a3fe,790fbbbe,f768e45f,c8a39319,1b18b4f5,8ae85d17,eac28fed), -S(ab609b1,52efce6a,eaea4c68,e498d414,9fe8aff,28196efa,a39a897f,5969382c,a4f7fd94,e87c1a0b,b9502f5,438c7a30,b6fb836f,17a19720,ab07e286,f94c8eb4), -S(7c188bb,109dc167,bb66cf50,58f263c3,ca8f58f5,66c9c0b6,b838bf9c,7cca26b9,1236a5a,bb04ef11,81b22343,327607c1,8693eea2,3c129a3c,377ee493,d332a5f4), -S(bae48149,f37ba68,24c47e5d,1fde4ee7,14f1cacb,8cec8ae2,de547927,768699e7,433d31de,c9619480,c2984475,5e7c3813,bfec984d,b0d9fed4,f25e94ea,8e747cd6), -S(88ec8b53,d57f2ff3,db3661b2,46989ecc,63c0f757,6acc7c17,cd0f5792,b006b5f3,9f35942c,28f0198b,cc3afbd7,b8f28ddd,1dceafa1,4db9557b,35d4984a,e80160bb), -S(67efbcd0,b5cbc215,c453d642,d1b19bb4,437509,33ff6afa,1ef923e6,cc83768c,6575c0c3,489a7bc3,7865d32f,dd8f2a24,a4be1df3,ec7765eb,ae09f10d,342538cd), -S(12f7791f,4b9310a4,c9d333bc,eabc3472,9762040a,5713829a,9a58bc72,47e51db5,15eba5f1,e156cd5b,409ffcca,876dc51,9f4f6e17,93ecef35,7b32dedf,fb12b402), -S(bc145b46,130e431e,18b357e8,a47f90a1,c38842d2,7fadd3b3,58d21959,daa3effd,4a62a5de,d23f1d44,ee86ae12,a03e4a6,5d1794c3,d7621871,cced4b58,116c97e5), -S(514fc2c,e7c864fb,b54fb8c4,545dbef7,7fbe45fc,d7ae312f,8866c608,12658866,552ca131,45466fa8,b6ce58ae,77c01a39,1f9001a8,bd9e6a4e,fb434b6b,9d63b79), -S(7c2bfe51,f4a9a32d,2f7feae1,96fdaa4b,45670ed6,f9c02940,633680ca,afae3f88,88bb43f3,996bb5fd,ea4a37d,e8c5270b,571644db,e1704bf6,aa207aaf,cc2742f1), -S(7710c58e,36f3ca17,8b96dc57,21acdbce,e37f7879,6f9f251a,df4c8dbf,599c6185,f600262d,d2a15427,ed6ea68,4482efe4,f57084c4,ce1ca445,8f85f646,4d954696), -S(5d4cda56,c705e89e,8afcd145,5490d589,63de5bf3,79d20a4c,acb1ba1d,c2effa6,f6a2f87a,cf9acd28,c7b12c4f,a42bc4d2,3e5c726,1d404813,30b99d15,533cca94), -S(e3bff796,4e38d5a1,946d54a5,5a7c9999,8faf4e08,2eeaf460,7dbb37fe,10b49bcc,7d6b4ab3,5d711881,a26d7327,bcd8eded,61cf85aa,f56b244f,58d4106e,8558f3e6), -S(75b80f78,c88f6e67,9ff252d3,e7c10a87,c2933642,53fcf204,1625457e,542c9398,db3b2fde,be9e05a4,a722ad7a,aeca21e7,3ef934d4,372f192a,a07b081e,c6419681), -S(4f640190,51d6332b,d29ab6c3,7511cb28,ba111146,189e4ed9,8b945e96,d4ceb5a9,626d0d0d,ef4192ba,a7874638,fcc07075,fd65b688,4615cb3e,5c63167e,965293de), -S(4f90520a,ee7b050f,cdbcc57f,cb03f361,f950e5f5,bd723d1,33de2990,df09219f,f12a8382,f2b1a67,c9868b2a,566e8734,2ac332f3,87d7864d,23ab4d33,395c4144), -S(f5ee8ddd,c044fb9f,babb5ced,4ab56f0,c4d357e0,69066828,23b02321,6fac446c,ec53db7f,cec7c393,d8b74749,981f6f32,c4462dac,6f0a56e4,34d52b34,d97b9d3d), -S(69727ad7,b48c376f,cb2c4cb6,b5c0e4ee,cb1f5925,f1928599,c55c4f2c,b31cf7be,39b486c2,3804bb69,b39d727c,eee110be,966da862,32eabbba,73ef17af,1c8df334), -S(23d1da9d,42bd74d7,cccdef4e,aa79e725,32fde7fd,b43522cc,b0c8166,1090f19,a168e435,f673bfaa,84115cbc,85a25973,5aa26ed8,86a1136e,ed3fedaf,b939e9d1), -S(8add82ca,322cb7d0,68e98c5e,d4f66993,50a2b2af,5bf0ba10,4e012389,f90a38,cee02a7,1df433a8,46ab9f11,503702c8,b93d609,fbf882b5,6465a9ca,445238eb), -S(874552f4,f2b5552a,b9e9dd9e,a8bcd62c,52f3036d,2b7d7a7a,3bf206db,18490830,12197e8d,de19c33f,37f50ba2,362642a3,87741090,68b2ba51,c5b13fe6,5d3b3a18), -S(7b5e3f54,d959d208,17c7c518,62628a07,ae2ad59c,6bc4458f,467e213c,ba145fe,bc3a8595,527be77f,c8cad2b,e9cbd810,8fc7104,9eef7ef1,924255de,6aa6fce3), -S(298e18e,d4790215,d0a82b37,b09d6b7c,90ee8408,13f6cb33,b150a3ea,d14fe41c,a2504d96,a1345a22,8e14e82a,eb160798,c7bb5cda,6ccd4bb3,74093c69,93e0294a), -S(22bfb660,2b823430,e44d0358,300a5fd3,853577ef,79b73104,12122749,74af1edd,ee318018,3617fc09,4d3a3707,df38e9a1,bf9ec587,45e251fb,8a127137,3c9b3e85), -S(41dcf360,e9b5b5b8,bee689f9,1446a874,5a4df0fe,1963c132,5d05227a,313d08b,103125ef,ac9a3fcf,f8033bb5,659b81f4,982a2f31,7382c0bf,b4c4a73,8479da5), -S(71b0f642,7f6127ad,77318fe5,27f57c41,e34af0dc,311669af,fe695a46,102dba7f,b6bb548d,f92c9087,c1f0d543,2737e853,d5a03e2f,e607057,352084ec,3060d823), -S(c36150f6,be139991,3df1cb29,3324da28,bbf75056,aa8102b1,e2be7e8,a669eaef,ec869956,1d5d9e8e,73268641,d7a7d01b,f1613d5b,145d2631,97abaddb,ae8eadc9), -S(26c0a835,20d9ae57,77ec9e5e,af9836fc,389a671a,6823f705,6eb5562,bde7193b,1939de0f,da69f7c1,fdeba6fb,f982cc12,b39640b5,f92253ce,9c84667c,9e75d56f), -S(5cce3427,e2cd7404,2cbf501b,2349bcdd,e1e9cc1b,d9ac179b,e848dd89,7378be5b,8148375f,ad9d42e4,6562dd11,463aff04,281c00be,12b40b8a,b97b638f,3a525901), -S(cdb56ff0,9c36fe2e,74546bcf,44b996c7,ec11862c,a5c0f0a6,1c352bb7,771f3f7b,f97dd0c4,6d0409d7,3559d6b1,a450a8,ba5e8d5e,dc0f1a32,df840f06,20348fc), -S(379abd64,fa180ad7,9343b3d,d2b6ab31,5534a19,dd59e25e,9a37271b,de58e2e5,512f6ce1,c2fa1202,2a6dc666,25f3b8a9,56c1a5,ccd5ddef,6c1b94c1,1c507472), -S(8c32725f,d1fa4998,794bed8e,eafeb3d7,c24caba6,4a693aad,14055160,e0eb4df3,e91ae4de,54a8db16,bfdf48de,d3835586,ed1cb6f4,f767eb04,343cc260,c2a008a2), -S(6f6c310b,c1afe979,cf032c40,2f594512,ab074b31,f336579a,b9e52fcc,6543e882,87cd5368,561c5897,d00a2a97,2166950,5b4f9e1a,a1aaf8f3,cd817e9,5e48df08), -S(299829f3,2cb34343,5caa2fb9,426e24c0,5a84466,2c2aa34a,ac75d454,50b54b39,3bbd3e13,50a11a04,31b44d63,24eec80c,64065603,3960c6e8,b82b6711,d660bed9), -S(5275ff78,3529d268,51fb398d,5559b300,ac09ddfd,39cf0bbb,e02f50d4,13fe62de,7d3356f5,a74c829a,bbd294f,cb302d69,c30fdaa8,64c1ab4b,fc734e5f,ea8f848d), -S(3e04cfc2,e7cea4e8,4c3ca490,2ce0ff69,883e19f1,6952252a,51edfda3,6ad04b5d,39536901,283e998f,ed4ecf2b,e708d5d3,9b19c290,c76b8faa,4cd4f94f,7f05e813), -S(58273a33,3dae61a2,71970034,3c72d8ba,697a1fd3,527bb291,e098ad6d,173525ba,c2f0e095,98d4d04,fb156dda,49676761,774d09b0,e43fc92c,7957ae66,396e57a2), -S(4f43ee17,95d428aa,ddff7252,536a7bb0,29fab5a8,cb60f3e3,21ceb52c,410e49a9,d17315b,c0288557,c4a9a48,8372722f,ce0bfc3c,4ee0572c,6682934a,18fa2c75), -S(b8b61408,4abbb43,10b2551a,8fbd7503,9856cc49,4f793567,cd7c205f,21cd9174,b45edf3b,ae914c9e,cd7fe61c,bee4278,5bfd96e9,c6493fae,b465e10c,8e6aa815), -S(9ff66284,41cfba00,c15074b4,aaac29b5,c12c3d0,59009391,880db30c,69bb700d,95f71bb3,8875faad,373a2dc0,b18f1d31,cf161cbb,b1d1d5fd,fe2abeb2,e1a6df69), -S(69176264,329a1ad7,8bbacedd,3b99a5d0,c3694973,c4a5df27,d7facc58,b25b3231,10fd42f1,1bf91b0a,a330bbfb,b598b7,be2c2faa,354e148,b3903a6e,697bd350), -S(94546c5a,b4a5dcc1,d9a8fa0,ac117012,470247a7,913d0acc,e8c7c2b0,d98ad04c,7894e112,11e816e,a03586c0,33a737df,8e11ec0,7c85295b,1305f575,2a9bf9fe), -S(fc476882,d286cf0d,3e29b73c,744cee4b,563289a6,c367fa59,ab3e93d2,b0f71314,8680b7ec,6d633583,ad923db3,1ee3dec9,6b4ddd95,c331a670,d759ab82,ffa07ed3), -S(d5279e6f,62490fff,5ca2f0b6,7a8153fa,3a5fb95f,2262dd3d,4e62fdb3,bfd116ff,831b6dc5,7f16d6b5,c25c6b46,9111fa5,48cfe44f,76eeb9b1,55614b7b,aacec99b), -S(8174add4,de57b198,9a999ac,9ccfeb1d,78a21fa4,bdbdb88f,792829f6,3d21923b,39292fef,300539b1,ec4ea7e5,9a943b18,e4cab57b,36c8fcb,47a96d0a,73facc18), -S(dfd1f8a1,88cd5554,6cc5b417,c2c30cd3,c34ea95e,a9087a9c,cd240cd0,9d6b8494,6616b3c6,881b9cfc,cf0438de,1e9bb54c,f213c9c3,d0458ce1,e49f3da7,17c6ff33), -S(40d6faf6,aca0880b,6f639406,a187f116,6e1d1656,763a223,cf2d9805,f8059521,26402921,86884ddb,59030708,d12a34b7,1e1f592d,b8316aaa,50f3b95,3dee82fd), -S(a06e4e4e,df868121,9ee140b1,1d688bde,1e9f0050,cb9e122e,e12bd046,b6fd999a,76f0b3b2,522571c1,28cd7423,273e0a0d,5ce2e41e,dcf844ab,3a44b18a,f29fe0e6), -S(8ed7e5b,efcd7322,7b537ffb,728d5c01,450445f4,5f187ff1,5182fd57,817c7e02,fdff3f74,179e2229,a680a538,73288b80,17819a8,953f358b,25ee7b8f,c2c1a89c), -S(1b7d6838,d0b5a412,9c0fd19,cc917166,c9c351d1,33d8db84,7f39ffdb,463dcfc,c50a0eb9,a20ff1f7,67c21dde,9a74271f,2d2e7c8d,3a45251,8bd61ba7,9953c58), -S(c991fd97,ac37ffa7,968bb26d,1793ffde,49ed283f,699b4620,7520849e,cda25769,9cc861dd,b39e36a8,c408a09d,cb2b22ce,c0302a6a,3b1ed1a9,d89f9784,e0f0b766), -S(849cdec4,66bcc09f,9a689c,299fce1,d1b37e8e,c59d9184,3d519da4,937d2117,c759660a,92c29619,70188f0d,8a539585,88ca929d,f9468ed0,3be6d6fe,cbcded23), -S(4ced9d61,7462a2b4,3cfa38db,1e4489f,3e527425,d48807f7,bf73cd93,a731e351,a9954e80,fb6c42c7,165b4cee,976199ac,2e6871b3,b088fae0,f040f09c,b91a0ea7), -S(fa952014,80bed20a,514df1dd,6d8541e2,f7bb05f7,4eda2a56,ed1d2a0a,6300ea2a,3e887eb6,edc0c858,18b1bbb4,8a54027a,aaa11988,c8063f14,98f7d1a9,64b8d818), -S(aafb82be,ff591455,e3c11ee2,ed724caf,46f86053,708699f4,38180f5e,a0156d90,63bd1026,f928de57,cba2fe5c,890d02b8,1afd2eea,2ff8a5d7,6708c70d,6172dab1), -S(9788ab96,c57bcb54,3797c014,a20704d6,56eef193,f0459b4b,b2617a90,3ba30842,1e81188e,28ba4be6,d244ae0e,2574d0bb,ab51fdc1,5ca4472b,b7b82a9d,dab005a6), -S(58fffe9d,6d6e176e,d006b35,52133322,c8e95d2c,4040fd4a,3a04ce94,dd5d0241,6f8bf132,7d0aee77,4e88f397,e2cd1594,39cd3c32,5a0313e6,d63e5e52,5974a647), -S(65d3d1c9,f10eb74c,6a27fbdd,f39d4ec2,8995aa50,3bdaec76,2f7051a0,23190b4b,42c3128d,959d7b3d,b585043e,3d042252,6e2c1b3e,714a2938,42cafeae,22333ced), -S(5240e75a,419ff988,d9e9a27,1a9719be,3d2c960b,eb574aee,fe278acc,5466fbbc,56aaa8d7,76953819,904cecbe,cbfd680e,99df80e5,c6a9100b,1fb8a570,6d28fa7b), -S(6f00eae2,ddbcbec3,cdbb2079,d7300565,12087a6d,b2f5df8,8d2db4ec,9358a8b8,81ae19b7,88ada62f,dd68da42,fcea16d4,699467,dbcfb314,51cfa318,e71388a3), -S(a7c58025,ec88b71b,bbe8a9f3,15b3b182,3ac7ea83,95ff1ae5,eb0889ac,d7a5aeb2,4decc4ac,78e45b5d,b76f969f,59dbd448,c0100f21,79aed6f9,bdd089c4,5f02dccc), -S(f5534fc1,b0bd55c7,e0af5eea,c11567fe,b5694f1,cc60830f,cac6ebf,ba0bc0b2,a7ee28d1,7624a2ae,32841821,e1ca4934,c10e6087,819ef9b5,f0b56e1b,4467a9c4), -S(f43aa167,8f4c4a1d,2fe2551b,33c4eae9,5d7b12d0,276d37cc,a4e68e01,71521f6f,a64c65a7,1c7db76d,bc11cb6f,e9842c12,ba6653a4,2cf0bd8d,46656e31,feee083), -S(28cd19c8,3d8265ab,f0d38cb8,9f8be926,ee8df072,f096a363,94193af5,d16d9923,58625794,ac267f89,a6734390,a6bb719a,d5e9e2ae,6e0ea241,aad5407,7cc1bc26), -S(572703f6,5d834c93,d0e09fab,e92b1add,34245158,33682bcc,2e62c218,451ef85b,44daf6ac,a9af4ae0,a7026240,8074e4ae,72ad4d79,8145d431,760b26a6,33d05799), -S(27c6a3b,92bf753e,ec6b35ec,491fcf65,ee5387cc,b96cd73e,651b9b11,40b347f3,a881835a,4d28683,670934ab,95939dc9,5a0e5974,7cc9dc4d,c39d4a9c,12fe763e), -S(30a0db50,ecc1bf4e,3c34a171,ff648cd2,8a3fa45b,786cf15e,de01aa47,33a99eee,cb47e7d0,cae5a279,702aaaa3,a2865888,1676d851,9d15805b,cb8bf75e,23940a1), -S(d27e417f,f83b3a04,36ade27f,1b5448a6,fdc91da6,342584af,47f2b8c0,3d21ccf5,6d304d52,c9ddda31,14b68be0,49b57d55,45d43d4d,501b07c2,8d295a33,8f8ec396), -S(5bd5b0db,57c473b4,de32fba4,fb7b68a3,9f6e6c46,c6e72e50,b6ae8fc3,259331dc,cafd77c8,2b16bc35,a46a7c5,fc715c3e,cee644e2,4c000335,b472aa5d,4efc5a7d), -S(37e99dea,23a18371,1f23b80c,1e05f3ff,45ba6351,10c9fa7a,b927c808,e3e6fc45,3dcaf312,f8dfe055,ef6abba1,3e5eb0b6,70ce3c7,5724fcbf,67c61730,629ae0bf), -S(6b001dbe,be7a3db,6fa70b38,f46d13cb,77d759d6,ce6b7fd,153b87b,aa67f94b,7cbffcc0,f3d48278,d9d6b09,7923f646,b56d9fe1,77ce1111,d2abd2cb,6244aa85), -S(e4bfded,5c81c0b9,f1ae3fb8,7ac88e1a,d468ef72,bb3321b3,c3a4d549,fc073820,dcdce7a6,76b0b3f0,45b6331b,fb75ae0a,610473e4,b551a001,18674a8e,a3ef1d73), -S(ac834f65,dd566124,f837f049,bf0d73bf,4884a1dc,f1756462,3cbf375b,6c57aa9e,1bd6227f,c5265e61,53d0f350,6c698bc,a973669,1260d911,2e918308,48cedf1b), -S(d36b1cc6,e6fc735e,6e83957d,87e2c74f,8cc50202,ddff7610,fbdde385,22f40d3b,293f6494,c2ffc78c,8955a544,fbd4ca05,898e3560,e05f0949,cb6aec2c,a18994ae), -S(d2a214c2,b88a5126,1284b25f,d7f5ac2c,e04f8333,144ce351,dc057262,c9a1fce8,17fccbad,720577df,1db1230c,e2c68fb3,b603ce29,a26a6370,4fba4060,8c4dac60), -S(f3f9329b,ebaf25c8,7efc393c,66c308bd,461f55fb,c721975,6a504edd,f46d95c7,799cab78,1d1c65f9,2a5193a3,e6124166,586536c,f4389a35,d886bc95,f033ca0b), -S(3aa1cd82,ce4a7838,4cbfa6a2,85fc66f5,53edc1a3,2816b1eb,85142e86,528e0cc8,4b24bf4,3a8266ec,4223b77d,3452f3b6,72596458,11c5cd2f,8f043d71,88f87dd9), -S(4abb7ae,40395b18,5a1017e9,d8887ffa,480f57c5,41c9eda8,578f7e16,538c61dd,4b96d913,161669fe,43230df9,a18bc71e,e8d36dac,de48c3b,d9600b46,a29babec), -S(89ebe2c1,845fd4b,461cb4,bf9992e,5f08ca21,d9d24f32,2733f259,c53d8a92,dfeeba58,f1d23a91,a85b3405,2b875f04,e056732c,a576f8df,aa5dec9d,2dd747a7), -S(92915a37,29c505d7,493cc142,b2e16913,6c8d2015,fe68992c,eae45b1,62d465c3,1ac2d867,24260b1f,396777cc,61f0261a,d8a603a0,e3efbca4,fbe5f485,378ef947), -S(5367ad90,3c5d684c,920f38,76c3bc32,c0b42a65,e1ee8d0a,e59de048,15bf8e80,82bcfbd9,11bdc542,306c0a1d,dc4aa5d0,353bb0c9,3b36d255,8657e40c,85e121e1), -S(dba0a47f,2fd5e7c8,5c2c8bc3,69981126,15769156,852b0f24,1e6ea83c,e56a8817,7a8830c1,377a2973,35a66c63,40cec55e,7e57648,29f32586,3f4ca9ff,8d95c0ed), -S(ea85fbf1,911e9827,59ec5e0f,a87b1c39,ff555ef2,ab294982,1aca68a3,648251d9,164f58be,9b8c16e4,ac9001a1,815d5f37,4b7e050c,21cad8d2,b2be4a19,ceb0c359), -S(84e3099c,ddad8d5,82c7dfbf,df03f19c,54e214c0,a0d5e679,7feb9f3b,dd32e43,980b77a3,1d08480a,5ef191d0,5c8cf0fc,48d5039c,583ee3f0,d37a8151,c49fcf90), -S(edd595e2,f8cddbdf,71f39b87,9a063da9,8ad70ea0,f030d9b7,28bb666e,54eb9286,89f1969f,95953dba,a1ad1cc6,29cbac93,a4620a8f,5c9f63da,a62ee923,98ee0f49), -S(1a3f3b62,26834d98,23f80f02,963e0878,90d60328,d911374e,167c75e3,51247b23,afb1a632,652762b3,db6b6259,ca8452c0,b194eb76,f16e2cad,1096539b,2386ee41), -S(dc425571,5dd53bb7,f572a949,895fa277,23f6c177,a234d2d5,e3c6a67a,fc458f37,f1c54b9d,54679c34,dbd9452f,f5813e9a,138d56cf,c7d8162b,c1eecb9,20edf717), -S(f86b4286,8b3f187e,4ba6fbab,91b83a4b,60acae17,b800e594,cc996004,138ed24e,7ea7b45e,b5a2340b,92fb24b6,f02c51d7,14c02c88,e9fa216f,595253dd,58e6227e), -S(46d26f41,447935f0,af56788d,b33b640e,e661de65,ed1a49f3,db91ff13,48aebe29,5e79cbe0,80117377,6db73c6b,eed3fe8a,e7e30979,2208cf9f,e6c40850,f7257fc0), -S(fa42a015,e023a7e9,cbb36e76,b94593d3,2306a05d,9067ca2a,717c8ef3,2740575,9da9d901,41de45d5,52c6bc89,6c43655f,f8a35748,ac145c9c,ebc09dce,df93b9c), -S(d03e4507,fe4c815a,ea50b0c7,1469fab8,e1215ed2,c32710c3,ef90e85f,8123314c,d3676737,18dee1f2,a1c4444b,9f1f1b8b,c049717f,9c4cdf50,3ba74ec7,3d404e50), -S(a4aecddf,221518f7,b058d538,918281e5,7f36b313,d00aa7d8,d6277fab,13f6ac95,77738ad8,eab86a97,1711b719,21edfee9,edab979b,8799a123,b16d8a58,354dc0ac), -S(f0c70330,433998a8,627c2116,e5352b1e,d9754c24,3d775132,b48d3db,e150a7e0,5392f238,cc30eec0,aa887b99,29759f5e,1d9c252b,dc6d8989,3e46008c,4129140), -S(4f34fd4e,155fb49e,7f1d2407,f65d8d94,5ab8bf,14c33255,e764579d,28252d6e,29f3e40c,2fc42f54,dada4b65,3d103afd,e38027a2,3dca44e5,15e6c561,16bbb839), -S(ae34daf2,44babaaa,fe89f02c,8ed39b2d,ed4f09a0,db8cb7ba,e4145e61,954ca965,16b58ef7,f394d988,24c7019d,738a7dba,5be8afae,45bcc2f2,4cc7dd44,f60561ed), -S(4637fc06,95c91eba,d195450c,4067cd74,14c646c,8885beae,e99e6338,dace2e20,43a38d49,362174ae,52683128,ebc753f2,71e398d7,fa906f5e,22ff4dc2,2622171f), -S(7cca0cb7,f940ad95,6a0a4d4b,e040a3c7,4b7304b2,975eece3,eac0b4f6,fa240c08,34845b82,6a4df5b0,10f4ada5,b6c83ad9,5f932a33,8b319027,92796374,35c0ed9), -S(bc374aad,71cf40,8a1eabe1,20d44340,faf0f3a2,774b378f,90f08faf,3a7c626,4bd1b099,9f649446,20c7a58b,45081f50,178626c1,5f00451b,b3617b09,5ecabf74), -S(cf3bed1a,37aade71,b025c9b1,dfc46205,51b3dca3,10ff6bf0,4a89a492,85c6f4c2,7ac96d8f,1b856617,3896f216,d6756362,bd5a9ea7,9e521668,b0d3a05,f778f6ee), -S(e36904da,5d6970cc,44faa475,c6dfb02b,579adaf0,4612dc2d,a7c9a166,e7c771ab,1f164e1e,24a1452b,af2dde00,e8ee182d,2c9c84fd,1cfa67e6,f8ea5f00,376cb404), -S(f6b29ac4,3a3b28f9,453e5a58,ba715cda,7691126,bee6af97,e1c5bee4,199cf34f,81156562,89bd32f,f74a1484,15390fc0,a1451536,99ec5f72,97b191e7,98d75e12), -S(855b98e1,be5557c2,cc7825bd,ceba8296,4921a391,12ec245c,3d89fb52,a443b680,9d4d92f6,af921190,1129dae8,15e93939,9994d482,ed93bea0,a88ae69f,c3614f22), -S(c534fa2f,e0eb93a4,86a708ca,2bacdb6,74b17471,11fae4a5,1d4dc063,ce06873,9ee94f74,b1239ee1,cb96fc2c,4269b1e1,7980451b,881145a0,9ca5511e,985a57e9), -S(1615956,54dbb60e,9d446655,7b673,c5f7b662,ae1bd976,2096b356,1fde395,5cf45f18,5d88f4e9,3d8eef94,aa64996e,1648cb98,3bca5ae3,8f5d2a96,b1cd241a), -S(61ca23d9,875bfabb,d23096fb,a12f043f,d036053d,a4fd7f40,ffe63b5d,ca176fb1,699b75c,1391d3da,18405c5e,825520a2,d0c49c60,b07417ce,89bcb2c5,15ba1a05), -S(8ab48e3c,5cd1c014,473ed567,89edf015,917f7b09,47fda85d,294e531d,89124079,58b7a6d8,2bce79f4,189f0b43,7d009e06,43127468,1dd4d50f,ca2ac326,99dacaad), -S(b56e89d4,28960847,be87d5f6,59727e68,80f71a6c,a023dcd7,c5f0878,e3146d99,bac8519a,5d2c472d,ee3a2578,d0ff2a17,5e6801f7,8eead578,116c59b,f5bda8bc), -S(197dd8ad,b359a388,b7920a8,9395aa80,1c98c278,888dd30,cce2f2d0,2aec4d27,383205d4,8c7b943d,2e66c725,979acbfb,d5a62947,bd251407,e4481ed0,d5faa6e7), -S(b8388b28,61f8c667,18653876,526d02e5,27d20c29,e612002d,514ba09,853f694a,7963e44d,997c532c,bae94319,74aef26f,b5761b3d,5c8a2e76,2d35907,cb3ffd28), -S(5f6eebb,2ca12aec,b80ad8bb,b926fc93,53281e26,60660c29,41ca2cd3,b16c428c,5e5c92d4,41644c68,4d68e47c,c63c71ff,54634805,97955591,b8f68915,c506d92d), -S(cc4f7d7b,8e5b1d1f,f3c166a9,51832dc0,9503cc2f,e0fb1784,6f4910e1,eccc396b,a5701729,65400983,90d49ee3,10629444,b53f7a5b,3e31bec3,7eb99ddc,f02c8d95), -S(1bf0da05,6984e8e3,3741cd04,16e74372,2cc918b6,bfc964a1,1d63d0cb,590c5c86,e461a594,368cb7a5,4c93c589,67928a37,b6037b72,71113804,b2e64d8b,a840d00), -S(217cd3b7,9c1d9727,fd781ced,dbe735b4,2d655e69,e5f7ba8d,ce5eb68f,feb1913f,fe3fff21,ad8744e4,6e3fad85,4bed0d9d,f28b0bbb,96df1b40,b711ea21,b5241985), -S(55b99e36,7b8f7cd6,24ace387,2cb2675d,c25e6226,b1201b4f,4e1b039e,38365d75,706543ad,5c20ce2b,5501e8b8,4bf1d26c,fc07e60c,f40ae25,951fa46b,9ceee474), -S(db0bc491,688dcff1,6c81f280,a80ab2f6,c5efb3ce,2715f202,3f999ea2,805a59bc,2096cc70,588ea476,613ccb8d,c98a1989,8f729420,9adc1a3e,c77b126d,b277ecf6), -S(d961e10c,a83ebb9e,f39e3019,c1b378a,d94cc902,6eab0f3e,d203585,92a8e44c,87f46ee5,14689bde,3821f844,9f97a2a2,bb1db0f6,d2916674,1cfa028b,d21f40a3), -S(18ecc615,8d15a17b,50737a0e,6bc6953f,ee9f18cc,e20de26e,642a434d,d292032,63ada9c7,e3a8e367,970af87,20417ad2,eef85059,70b81b76,609fe8f7,c3a00ca4), -S(6ff356d5,262df09a,33ec10f,eb2e48b7,db91d6c8,dcc92f9e,e4fc39a3,813bba67,5bdd7a71,c46cc142,7d8a1835,e7ffee23,d0e025a8,e3027b1f,4892af19,2a2f0e0d), -S(49263558,22218dc2,943140c5,3a706f11,46faabef,f0fccaa9,77df5f99,44a77b2,d4d9db7b,7999d45b,9b51d776,6235e129,80c2d936,1943d867,65c4a54,5fb58e14), -S(ba68fca3,2b5e907c,896b3d2e,b9869a09,9d0f0fd8,bf8e06d9,64a6938f,3175f281,694d19f8,c8428ae6,16a78a85,57c9ae25,96a56c8a,1bb9f679,33d6e351,4d59fe8f), -S(5c461a52,3bc37bc5,39ae9769,5b59599a,86d3046a,36f4922d,a6f68212,19a89bff,d98b7b7c,5190ddee,481a5c3f,7982b4c5,b483822e,a211ccff,bc44d03e,983295ac), -S(43e3275a,bcf17dfc,7560d135,22f3154b,ccaa6090,245a79e9,373bd867,f48da149,fbb015d6,9f2aa00b,63c81226,b9165afa,1ee6be9c,8e680adc,4d2e5256,6c7723c8), -S(384bc1cb,8221098,4ff0a800,dbc85225,cb4a5f1f,477b4228,5c59c7bc,262c29ad,21061a79,e7dbb527,9ac6fc8f,e2d87642,cfd71eba,12220403,8792cbc7,9d8bce1e), -S(460c55f2,fda793b1,5aff59b4,cc819f12,de803b1d,5c938a2a,d30649d4,a38b58d0,832f6713,e63fe5d3,dde9534b,29d216e7,2434dbe5,6f54c9cc,ea683b17,33075c2b), -S(5e4a763,28fdeb17,b7cd2a8c,47b58307,538c6f17,397fcec,c9e5a377,6a39383d,3b3eb0ee,d7e28701,7bf034d1,dc1f239f,64756481,531d3692,bf639eba,2ad6e02c), -S(5ee48142,c3cb1ee5,45f6579,a36c589a,f886719b,c0b7bef7,c49c7a93,f3b610d9,55192e86,467835c4,b488b869,3f6cb7fc,94e49b03,8272abf6,69cfaffe,234c783e), -S(13b5072a,bb3d2943,c24fc4db,5b5759c2,290d6c92,11bdb80a,3b729478,71f3322f,ae8e7641,39207e9,ca438902,e75cf685,641cf5b9,674ba9a5,e9b26195,30180497), -S(2f2fa1fe,582dd71e,3bfc0e34,f1f5e8ef,12598b52,1ac2847d,90b5dbe9,152ba45e,82967c82,1d7dcf0e,6c624483,863c6c28,76ec8adb,43bb44ff,b211ded5,e7c397aa), -S(1b7be0da,e6633eec,f7895c64,29ea8088,1c2ec66f,2a273819,ec3331ee,830d7c1b,cd884cee,15652542,4bd8b512,8c05a77f,3c292260,c8d30471,8eab87a2,46f75ad0), -S(247531dc,f0bd40ff,7208bf59,2fea5982,440e3f05,8da7ba03,efc7cb94,4b48180,cdbf3227,62033470,e47cef0a,a5c9f2ac,9ca08b01,82140d52,549d24bd,d0f17ccd), -S(274ea538,f2e50569,9f52a7ff,bd058c83,95fd75fe,98fb66f0,ffab658,a1e1556,5aec461e,79c048e7,794586e6,43d10236,37f8c376,7d158968,16ea0ed1,56fab125), -S(82935503,db88453b,8794b70e,9b5a3e37,a804547,48d80c3f,d2e2a85b,844ac085,d507862d,98c035d,c1dd3d1a,3a7679ac,bd80df3a,4e8c4fcb,5b5761f8,c9605d7f), -S(cae0cdae,216c0e62,e8324d9d,95b15285,e43708a0,dbf435fd,d355fcd6,227d2536,f442e7f,d546d149,d0075926,fbd6e15a,805a85b0,a78ee674,c15ba3a9,a6d67b70), -S(a5a0080e,55ccd7c5,d6f708d3,34a78c49,b22442d3,5bce311c,b660af79,39cc70db,c71d761a,98c974bc,570f303e,d64875c0,d9e64f44,63d9db4,fa2d0e8b,80900c12), -S(740c4a8d,2dcc8a6,b11feeec,8f60afb2,e59b02ea,788d5f4b,62da8397,dc88733e,c8f3eb37,de1a1332,c6e010e1,913ea2bb,14b10e1b,d139dfb2,2858e760,eaa16f05), -S(551b7b30,507b2df3,c07955b7,ae91260f,86d899d,ff28e68c,67d8abf,cfc0d936,4c21135,c84fd85a,ff5839f,5192a854,25b18720,4a92582a,1b4308d5,a4c0db9b), -S(e11dd54e,f04d524,7ebbd72b,edffb50e,d0d4ff23,8cdad3fb,f1ea8067,93378b5e,46bb0d5a,be23f71a,3f16f455,c25b19c0,49fb9d25,9db6c94b,9b6b1f17,6edf8fed), -S(570d4783,29cc718,55de654,48255925,a5b094cb,5c55f10c,4793e532,60c9163b,331519d1,e5444f30,a4b1b753,a769eb4,d21d824e,a8151a40,2fab9b47,1c2d5625), -S(20a184e6,df5a35b8,30e97ee7,c3d4390,eede5a69,ce1c36c5,a77948f4,edc4812f,e46f676e,7b524c40,a6135f3c,7474d8f3,c3b0d45a,1a5ed4ec,91308a8b,b89b5a9e), -S(c7daba6a,960243f7,ef0664b8,f66ddb24,8a7686a1,2095370a,36316ce9,a4f5abca,6207f622,619ff1eb,fbe5264c,7f7bfac1,fd0d96e5,fe1a8298,a7ff4d3a,83707327), -S(b9d8e4ba,50549b01,491df2c8,dd596ed2,4ce5ac19,deb88450,a69a8237,d45f6507,5aae938a,46a3b4c7,6dc96894,798d2dc8,443795ad,6a393f31,a042d5c8,83ec7d12), -S(5f9629b7,ecbc8b0c,62374b50,620146fe,980791a,dd24d2c8,b2b3b786,9800a4c0,1ddfd8f1,ef4083dd,c6da5173,d16d68d5,7425fc02,e3943d9,a594e98a,ec06285c), -S(33d159bd,d0610753,10d3c1f9,ce89bfa7,affc80c4,5d193df9,55647519,357095f3,42c8b3e6,9b81c478,57a33b1b,1cda5b68,3662c1ab,f99ef9,5ed1b250,9a5cfb90), -S(8788f2ac,518a4024,3607d127,381f1a1,ea3e581c,89b8d90a,2d2c6e70,f94ddf6e,14112b9a,ef954527,811f9249,5de47e6c,eed1858e,5eba4aba,b1580360,fa05af7b), -S(804b97ae,219b7647,15bd259,255d3275,a5d5cddf,3e750578,13354081,6d9b6f81,abc3a542,1e195c33,88c0c4a3,f8448ebb,ca3ff868,a41c7c0c,2ecfdfa6,409bcc24), -S(195bde17,6cd7ea62,9611d9a6,c55ce4c,e7cdcd37,2d64ae45,f7d449f2,ea32f6d0,6005b5a6,890e472,af884f6f,6d5c8111,1003e809,6e66e22c,1468c962,2724111d), -S(9ab1e545,c9808482,2fbe050d,bab124f2,71b16028,e6e21247,ccd63332,26500c42,cb6bd747,4b6df912,e130b611,c762583,c81f7c5,38dc9766,e27f9194,6d1aa02e), -S(e87cfa04,8fa5bd1,305f73ed,971c6d23,81fa39ad,3d583744,c243bfb9,fcc9023c,7fb05d17,d789734f,7a9c1644,21a28365,3321f261,752025d2,b91cfc70,703e50e9), -S(5195bc3d,5ab8164,4ec40b0c,ff5fb1a6,c749064,9dad884b,ba48e92d,6f35e5fc,2b7ec6fa,97b441d5,ecefb879,35e059db,55d0e3a1,6d693899,d3c0b213,4fb04981), -S(eb2d3530,17df63b4,eb17dd73,ee58d282,78d01137,34a41020,cdf0444,8556792e,58a4f4cf,9247f908,3c28a9e4,da38e8b0,3cbf9e4f,2b92715c,28781d86,771ffee3), -S(8169465c,2da73cfc,daf3f3e8,538a47cd,ce088ccf,475af747,11585bfc,14c39426,1665d78d,e7ffa7e4,810ea80c,f12d3925,239b5c6f,69652fd3,44ba8bf2,e0126db3), -S(96d8634f,aa85174c,69e313c6,430eaaec,bd2ffe3b,55a1a0ae,e78fcb66,af33a3c8,869f9e70,344df870,be6a021,8bcf5e71,afc8a290,51d875d0,5c76f72f,e8fbc0cd), -S(3a071936,1f0234f1,9cc3c7df,40eaf836,4669615c,9520b0e9,c56ab987,dbb36bc7,e43415dd,cc244c05,fff14e0,f21cdc29,dddcb403,5678584b,1a3c5484,e98d9625), -S(cd3f1530,5cc9a03e,d05ab14,a81c58d,2485785,289e2b1,7382d45b,b935ca4e,c451f28a,e7aeea28,ee7ae093,46b352d6,bcbfc3a9,b0bc9d62,9eebba56,877ce9f1), -S(677e2061,8d0b42ae,6c38532,669cbfe2,56ac4b5a,40f1de16,42d97a45,ae34fdb7,ec23dbc2,bf750958,9be01e95,ad253816,7a24b700,1d9a8a20,218f0866,2dc2e378), -S(f816047d,1606074b,c54ef03c,e205dc5c,cc8182f3,739ab8b2,7dd09fa0,50d2912f,de012e8f,89ab0ca4,d8f8e323,6e0c2545,a6105fc3,602e978b,f42a5652,fffe864d), -S(11f9ecb0,4f273b9a,a699a3ff,4588ea19,2504c00f,55145cf4,10cecd40,b5f46f8b,168c4fb6,afedb0d6,b0bed70b,610c5538,e796e0f5,851e6d36,99fc49a9,f62c5b10), -S(efb9a14c,f6a30d5d,f30de8fe,f9ce92eb,6f566f8b,b65152ae,323ae56c,88da79a9,dda5df31,f184601f,a45747b0,3017ad22,e49c3892,fdc28c7d,c0d7e099,7cfad33), -S(e7b66913,dc55fe07,a9941600,17241de0,7867a77,8fe4f998,19efb096,8d426966,adab1d03,c8b96717,db800f98,e09ae855,2c653266,84886f3f,15c08bc2,10bab6e5), -S(6fd3c1e9,6c176c59,f94791d,fb9cff5e,901f676a,fd7e66e5,f69184ab,7b4e31db,ebbac252,36e640f8,df593a37,817911de,b85a5597,bb0d902b,7a97ff4,18689609), -S(2667971,943d720e,7d64d2b6,3d7fb50f,525c9214,fc89c957,7e00c007,4c39a907,9c1fb427,29e57196,33af3187,ee109b46,fe708cd8,5f222b25,bc0c5ae1,300ca331), -S(e34d8507,b11a4ddd,9fdd654a,ea6c4876,5473bb13,c9f18e6f,c8b6e3d1,5eac015f,d34c6080,22a54602,fccbab5a,e1cbd5fe,7ca599ee,75c51117,b9537c7f,44f90268), -S(e8b6557,441ce4af,7ca27f49,75107ff6,3b108058,d42d5e08,86bf3bd3,46e52e24,b15eb15b,b3fcc5f7,e3fcaf48,8f5048dc,a4c587a0,5b982613,c78965ad,b0d2027e), -S(b49f84fc,3ed84f9b,3ced0a5,7f953116,897c892e,d0249365,d8c733aa,b97d4b95,4f0a63e,42aae565,32225dc5,894c6fce,15f2b25b,e762f49f,a1d74d5e,6a23fffa), -S(99b0e1f4,cf7fc243,ea34dd0d,73705809,935b6c03,c0a687ed,7bf8d69e,d79dc2cd,b61a5574,17e236fc,a0615fcb,4d6ba1e2,21fd49a8,4003e8e1,b4e4a648,b6a088ad), -S(1fce8906,c4c420d3,75ee3ed1,2e603855,fda8bcdd,f47cac56,3595d3ee,6b4cbbc9,daf0cedd,acfa2409,e861d1,5cb260b1,eb84e1fb,22f8f483,e4524750,8c3bbc0d), -S(df85a7c0,fc08b916,43ebcc41,6bc86ac,bf4581da,fe0f7418,66704eaf,c24efce6,5d1866a4,3f06fa8e,a36ddf3f,39afbdd4,97372ac5,2d13629a,d546d4aa,ce7af9e2)}, -{S(8a4e9691,3533875d,b8559500,65c90785,a78233ac,ef24113c,f6ed543a,e6a40024,57d9444,8d091df9,602e6c7f,c3f88934,d45a7c76,18da574b,4d4c15a6,6925bcf4), -S(f8922b8f,c310a77c,c3e33a17,d88534ab,ac952dea,355fa763,14e2d886,44b70136,dad313f1,5e0ff701,acc8fdc1,b849a1d4,569de031,6a6cb83c,51629e89,99aeddfd), -S(d9e5586b,cdef070f,978bcaba,36cb7828,8ba43e5c,f0273389,750c95b8,4cf76c,f04abc01,6a060cbc,3a0d1d8c,240995ce,bb6c0d2,d9cdec87,fc8b9f39,dac5b50e), -S(6a206413,757143bb,c552fa3e,180d8e98,cb96a816,136dbc2a,8cd4c7de,6f508a44,55ee4d0f,189bd91,5323aad,b452a7be,298c183,b6843f5,25cf7b4c,ffc7b6c), -S(130bf00d,5caf1767,83d11a2f,acfc3cfa,ed0549c,5ecc381a,d1927051,517e4e88,506fc4f6,8b8be0b4,9537efba,d532f50b,156f5370,725c23b,66b0b758,50a45c71), -S(d85e7a59,54c93649,44d0aca6,8a534e68,42bfaebe,1806bb41,1af01358,d2d4f47a,8a8d3741,21f7390,879a892b,fba08959,23db88ac,867b9ea9,6888c43b,b651642d), -S(88c5e26f,91f4dec6,5d222318,81d7eb57,d3f7e498,fb1866f9,5015e045,d0108eb3,59d66b66,cb05e136,95d5bb41,d25e5b87,6b02af1f,7f29fc10,c67001c4,4bbb7cc9), -S(be062a25,7cb5ede8,e5926608,9a762e30,816d4463,cc5b2338,f4aa6309,f7722aad,16f30af4,c27c3f38,82219d94,a49468c2,3e8cb1da,747ff22f,e23c7dbc,b032d3c1), -S(292e8df5,2c77c161,6277b962,e10c43be,1c820aeb,80f083fe,879dd961,51cb84ef,7c7bafb3,a3bab2bb,2f9dfda2,68904ee7,823e6fc2,2077e41a,af16ed6d,e2ac43ea), -S(b14d3f06,8a0eaf5d,6dfa519a,d0a692e,3020b5e2,8c31b79f,ce6400f0,12e0de71,c383938,630762a6,ca5646f1,f2f02e6f,939575bb,353a9dc9,2a42d50a,857ded94), -S(f41b4e53,7560be3,b604d846,558b6990,639d00da,c6c7e98e,c07d1574,a71aa7f5,c34e8e3e,8102f564,fcc5f376,94d80a65,b616dcb2,d025b701,fa615539,6a105255), -S(5fb4006f,35994912,403a952,a1f53d15,202d8305,389fc093,4e4fa6f1,236892c1,1c5d613,e61f1cb0,e0805743,519fb564,5bf14c51,e61e6cd8,bf08c5b4,9417b96a), -S(e4e428fa,f6ba9c36,1593230d,e73afeee,9b580d5a,ead54f55,2e464031,bc6dfa24,ab8d0919,f7e8a7b4,99719862,6943e144,25d15360,ca0da2f2,637d8542,10158268), -S(53e304ca,eb03205f,f80fea6f,3ea38010,531e1d2b,c6d1fd25,804ad799,e2f05984,434777cc,b848ef4c,f6c205f6,621d5cc5,97c8c2d8,34ed12e2,28e3fc02,4bc4fc6c), -S(664a810a,a0894cbe,2f85817e,93b1d731,5a4047e8,266df3b2,e8ab5aaf,b790e0b7,f5ebf5e8,38f7fbf4,b904e874,48de1d1d,6befad46,ca68db2d,c08f8d43,4b6e57f3), -S(4a697e76,a5db2e31,34b646b7,a59e8ad6,9ca45eb6,b77aee2e,2f82f113,4d698262,8d5d47fb,76769327,7b24d6d4,6221e67f,cc9b937c,31e30fba,9e5ae198,597cedd6), -S(7e227b69,18cf61b2,e33e5996,192a0ff2,89cc6853,9e8a5ce5,65163662,83d8c423,299b7e8d,d2e45efc,166a37f8,d1036a60,40c5b43d,d88cbdc8,729669c1,98d5847f), -S(88afc703,96dc444b,70b8c36a,a30f5a6e,212dfa93,d4eacd3b,11e47e25,9bc7d42d,844425ba,79016a22,cb99d0ee,6ad40ec3,d0cd5639,1717eaca,1425e3e5,98db73ef), -S(75ba04f8,349f8c8e,69aee4fd,662eb9b0,aaba10cc,555caaeb,c12eec36,70179d36,fc0a0931,cc6d5662,ac8bc2cc,c7dbcdf9,db139e47,c5ba80cc,8778d11f,ddb3caee), -S(85c4f2fc,b3f7103b,6970a16f,8ad3d1ef,e1cedc24,3c576235,d9af669d,5f7a5a94,b575c9df,4162c450,4b61412,a3887a44,94bf88db,cf4c6ac,52af5e0e,52382ad7), -S(5a3265da,5b752377,50fafc55,e2affb2a,b2721932,c9021dc8,5bdc79ce,66d0bf0d,8101544d,688db281,c9a7588c,dd72dd63,734561a6,a91bec5f,52641a23,d4e091c7), -S(6177daf6,809f918,f8fca135,f71b89eb,e8700dd9,47243c2,c36fa883,182df3b9,8ffaf7ef,3c8c6422,33d7d43a,c01fd1be,a74c3dd8,3554cb81,7939ef62,cbc8b592), -S(3b8f7e37,b09e7276,36068698,fd87351d,950129ee,eee44a88,9c7a7e39,d49e2c5e,8ce941d,a2ba686a,e3264228,48a6e76e,a0118a7c,55fb37d7,7fd6b9de,15b867cf), -S(47892789,cdde36ea,29dfee45,74173afc,11515dcb,fc53a82b,5c2b29da,9201c8f4,d4717288,94fbd69,44c690b9,97ade5ea,d2c10917,4fe36517,57118d6f,b6264461), -S(f8dff091,8493e499,fc13a155,933384d9,fa83972e,9b099bc7,236bfc07,6e24966b,a06048a0,ca130916,94217147,1d803d56,99cd9c6a,cb98ee56,96637e5f,2a7d923b), -S(dccdbe61,aa1ea411,8443d950,3887f76e,c5e09092,de7c9c7c,642c5755,da678a79,f4cf61f,c7e1630b,2cae9d87,6eb29ceb,dc9b24a9,76c9540,f7845233,c9998493), -S(da4f38f8,13dbfd52,b45af510,59377f94,7f8f0158,38135451,d9713746,80e9c3cc,da4a6ea6,f8526f63,46edb7e0,cbdf3ffa,586f64e3,280b8052,4d2c19b9,f343976), -S(999029c2,9badca65,16360432,56f3bb93,f1b608ac,5084711e,242d9b76,2b1bf371,dbd72bca,1f01a2a3,2a760f89,e45df463,319362d4,61df25ec,1ec9a71c,e85140e7), -S(6c502c,1cf38e63,65275058,dc610392,2bceeed3,ee0a1aac,2838327a,a4543303,f0f4c4d7,b68d69a8,7209c888,7b725b2a,2a8c2c5f,b7c9ecf7,6c1f71fc,e398b92c), -S(9c31fb8b,f57d654b,a0ff1bab,9fa0ee2c,9bc86017,67876b66,83cd8c09,1124f421,b6ebd670,b4e352b6,320134a9,fd765d26,b2e1f109,f5f55958,23d7eebb,d1bfdb31), -S(fbc3232d,c40bf025,1a0551ef,4f3ad4c8,51ab66a1,f2c709e4,70a751b9,9f9cef27,552b310b,6587b1ec,1b84242a,3df96073,e35d0f7d,d47f09ec,b3021773,1fdf308d), -S(90e71b55,cdc8e2d4,f12fce5e,4719b8f7,5da7966c,4480557b,58e567c2,eaf48ddb,ff989ae9,1f195713,886dd3bf,6fcbf0bd,70d62153,9d4b4ee0,b0d2d15e,65340644), -S(829c0322,efef509d,a5284d8,96d3df37,54c21f77,f83a1093,1cf2fd92,a1594905,8b6ae670,d9b03d21,da2ae14a,5e09e0d3,65d31b3f,e1da61ac,7499a908,47715ec4), -S(db748c28,5a6b3d42,9b9086cd,8a50d16e,15788a48,2f06a43a,2b7da677,d41c8f60,f4bf5a7a,bb4492b,4dfec99c,e7c4cc15,2bf32cec,78a3cf7a,4833c10,251f411a), -S(e44f84e3,3d2ec8a9,2d905c8f,1d6d46bb,f8b730f5,a07fc25a,47e3eb50,4adbd5f1,d1fe0cde,a9becec4,260d0700,7ba21d92,cb7e069b,4f81bbae,bab8da7f,9ba68594), -S(3e9c39e6,7d0891e0,9cf7eed5,b0abaf27,b98798dd,c926dd87,12be6af9,6610f6dc,c04e44ad,a09d96ab,5d38ae1,94d65109,ecb95d3b,6b79d019,9641dc8,699789d8), -S(4fed63dc,b7587725,113e087c,fb0b25b2,6056314e,690b6312,1e906e0,5d98c34a,c69bc4b2,ee67000b,b66b6f6e,648cd1ad,ef9ce6a0,4add42ec,38e0156,dd8e8af8), -S(501c9927,f0b4c19b,6b0a9595,2387324,b9f31d90,93303544,ea002f57,4b83c51d,14770577,38a701ed,c15fb98,c6e224be,8464e4e7,1f0e3350,899bffc9,c1ccd33f), -S(98af3ab1,9c4fff23,8d70f1a,efb4a80b,234664da,ec2e44c4,4df93226,e7aaf714,f84cfcf6,9cf1960b,6d13cc27,aa875a5d,3b29907e,455d5925,c0a3096d,44924405), -S(849672bd,d259016b,8e07d627,e57813a0,e355bae7,ed64ccd4,251a36e4,48d0821c,8d0366fd,764169a8,779d21ca,f53ab78e,caa8a627,32b74612,5e831d17,9147d2c), -S(34f142d5,744dda88,aadad850,e7f469d7,140dd5ee,fd3dba28,86f3503d,16fe60e,3c3d20fd,c13b78fa,d0b7fe35,3bec2bea,b1509a12,a03b1e79,c5ad2294,41292728), -S(ffe5fd9,b78378bf,4738931,e03752bb,75855c54,f4e3dc8c,c369c070,450e24f8,dc57ffd6,b87dd1e1,dc466dc,6423e1e8,4174a5a6,c014e069,ae812d80,3c6abdd6), -S(b43a85b,808e6d6d,32d56edb,5d64af6d,cbfef633,2cf662fc,cd137d2a,8b505c0d,1e61d507,8ee9ec4c,c6be2a87,657cd3a5,f30d508e,c35e459e,e2d0032a,702bf4e5), -S(42be63ce,a0b6e88a,5d98661e,c99d493d,dbb78f09,ccc8fd30,eee4e148,ffb0cfdd,38d7e392,19f5a87d,e36b4937,8f1ed166,23e93619,165e2968,84294946,adb1e9d1), -S(9996eb8f,f8c8bfa,d4a4c502,2d8ccf86,f59dc8af,750734e7,e054f783,2b6c0f05,f1c9387d,9720275b,171a93dd,4bdb8ef0,7b73763f,5323d5df,df515ead,2bc40aa2), -S(66f17b8c,fb9b6003,b6160370,8f86f93b,3555c338,d3a346f1,fd9db3a7,37c197d3,4d0233a2,eb52e023,33c7d4dd,53703ac5,c566ccd5,b1e76b2,423e891f,60a8dff9), -S(ffd5e8b1,b2587ba9,79e90dcf,c6acdb82,86328779,224a4edd,dae1bbdf,6db06568,d75d57a,4d17dab6,43fa10bb,35857dfd,f2f7afce,f6c5bebe,7e13645c,f6f8e3a1), -S(ae1f1297,8a7a37ad,87a8aa8e,1e89f0d6,15040c25,d6d47193,e33f12b8,e28baf60,e38669e5,18c7cfef,4ee61807,b51fe9fa,403f1528,ebf2b27b,af0a15b4,fd39f5bf), -S(d330d887,3bf11a6c,f9b0c1ef,46ea64d9,973f14a5,a93cdb8f,7d84f515,33a34b90,b56e5c4c,8f236f34,78ab2620,ace7ded2,1395174a,76c5c62,2ac50b78,da16ae14), -S(1d2ff433,4e908a9a,fa5572d7,8dca2a81,8f8a651f,4bda506c,ec0aeec0,91a4391d,292d6a4e,5811de83,e318a6e5,861581c2,192b1f59,30f42d1,40893a20,efefe2fb), -S(8dc6cfa6,cab6f691,bf468059,7400efbf,8dfa76c1,8edfb8f7,ea78c24f,3bce2bf7,78874b78,47543ed8,2f983f80,c1e83ee4,b0dabf2d,3fb7d695,ab1860a7,967ffb10), -S(5ef0e616,b545e053,21bca097,ef424f4a,ed40b6f9,93a550e5,e11bd637,59266713,c739cd37,7700a1b2,6dcef2fa,c219d05f,646d86a5,850505d4,21ba8b38,54d0708b), -S(60b3faed,cd527d8b,6f806cb0,f234a3ff,df62a755,87d3f543,efab95ef,e6ab104f,e1e0cf1,e737f246,c1c3bf6f,92140a3a,34c98d53,32ed25a2,d7a48247,98d5ccc8), -S(d160c9c0,133d78bc,62a2e946,49cba513,783682d0,dad71915,ce208a9b,446a303a,bf466216,73b02b7,a782178b,f7113433,73cb299f,233b11ca,4d4014f0,2fbdafad), -S(201b7a0d,5f431299,34172b40,1744d18f,477d0724,6ad2016d,c8ac7d3d,32ce0e93,1fb192ee,55ebdb37,52b6ac29,c7485a7e,f8b8a0a0,a480def8,fa07ed29,d3afdb4d), -S(7d104d3c,62abee57,1f2d2243,c95bdca5,dc702807,fb060577,bcd1e50e,697c929,a680c234,1c12a157,f604ac5a,b74ae532,5fc59b5c,d8ad784a,5d66fd27,ed3958bf), -S(8e279e59,c87df705,b764c456,563703bb,1836aea8,93dbe8d4,b0249223,13e3801a,aebc7cbf,ea3fb75a,6f059f9a,57bf8ea2,d0758d51,c0d57696,f5eb4d38,6d1d61ca), -S(b206020b,a960cc8e,ba4d0263,bb0f2241,a91341ce,f0102509,7cf7ef52,97f96935,a249971e,6bcfd543,c4b603a2,70ea667b,8524c136,c15913fe,91bb009b,796da003), -S(1e6cb8e0,4b998c17,b0887731,24ad3f44,ae7a89e9,b33ca730,62233a4a,a6b8bac,a50a3841,9da361b1,f89a8fc8,f29a3fc9,a6f8aa5c,36516ea7,2ca4cc15,96330dc0), -S(449005b9,3279d7d2,9965e131,50fb7cdc,18619541,759706ac,6908ff71,ce5c2cd7,62f1e74d,1f31de28,221d0dec,3d063f76,ba5e742a,52d0b48f,22d01ad,58791862), -S(4030002f,2374d275,3e9176d4,3bb4c2a1,c7a4821c,f6b7119e,bba2d4b1,2e4b5bfc,a80b25cb,a4a75603,af82a624,b493ba8f,c46ab68a,968bff49,a0e1cf8d,9b7a4d93), -S(c75f32b4,8122b7dd,bbfb4879,30fe0ba1,99072105,6891b932,e2c7ea3c,eaf270b,309afd60,f5a0f780,5675646b,37029da9,601468d8,71ee3685,cf6a3ad,104f5017), -S(77a73c5f,1548cf98,9c284c5e,9f1ecb9d,ab55d2b3,982750bf,65eb7097,ed159e1d,112d6329,29e9aa4a,83c2fe95,531c0717,d84c9ddb,87ceb9b0,65e9328f,83c3699a), -S(f6a55eb6,d05a9183,d3908776,40a5bd0e,2a6b83d2,40cd5840,e25a8bfa,d2116328,ad0834ef,8672b707,dc99c4e7,1c9fc935,725ebc8a,df45cf00,99cac306,4a56796), -S(cbe913f4,48359096,dfb1b168,fb42d92b,d873b82a,956ad9c6,5e64a2b6,d826614b,893edb65,d2262b17,f5e466f3,88592e96,ddd70b65,65606ac8,289cf396,991a25aa), -S(f29ae654,8a6aeb10,849191e5,e87e2c0f,d8e70af,a15b8ec4,848407bd,36389d06,1dd72984,6e220fd8,90a1370,38c98e04,b096de6d,a7ce7339,ae697daf,db11905e), -S(32307117,b8d2902e,e325090f,97b518a8,beb9e27a,d3cb4d69,fc0b54ba,ecb14316,7970c3f5,13f69df0,400c725b,e84b1267,fe7f205,7a70c5ab,56ab0ef5,679ebfb6), -S(426e118d,b8ff1f7c,18ae29a1,b88e0f2c,2c286658,6c1c2179,edbd719b,31399dfc,7889d383,427740b1,4c37ae36,e51710f2,f5a8decf,a456d0c,a83ac66d,230828e4), -S(229c2322,7c4956af,938ac061,9640e04d,2c647692,e0e985ee,28cdc767,96f260a6,a056790,cbf36663,b09cf7e5,4b622f74,b185454a,6682d9b1,6cb2af2f,3ca8a7ed), -S(bb7cb68,23726026,12072e34,8cd4504d,50a3d286,669cb748,e69cd0ab,dcc93e8a,9d537ff4,532cd020,17756733,72ae3cbb,7aaac7eb,901c1e69,5fd57f02,9c336e5c), -S(d3460edf,f1405cb2,ef9c9fab,eeb71796,c9d48f66,96f8fd20,56a99863,2d278e8c,d9cc7b14,cd657e73,e5fb7207,9d421490,46266a34,7610b3ef,b631c78e,ed02419a), -S(d12b97a5,d5b7d74c,c8dd8f7d,45fabf75,105ebd5d,9990d99b,7d0738f3,49db1180,51dd8885,e6131a1f,320e1516,3d6e35dc,4978fb96,b531aba6,67231968,a2f0fca7), -S(f75899e4,e383c412,f6f9c764,38d38cc0,d0550d28,a150292e,45a2aaf3,c7025ff2,7ba7f1fd,d978939a,79b482eb,24776178,ebee022b,48f66c33,e7a8de58,7fc3870c), -S(9d3aca30,fadb9f90,778aab4c,b7b88706,cfced983,ca62ecdd,4724d58e,6575a754,f0f41826,c426e8c9,a832a211,c1835693,9a1c7c63,3de95bd3,7e6d9b6e,db41d16c), -S(63454665,5133d840,de3af8af,def0395,cce4e97d,8e0030c,94f8cdba,cd72c3b5,19994348,daf379d,5c626f75,12109e43,bda0e527,137d425,9d9ebe32,2fb9aca9), -S(4ec235fa,47217cc7,9e2cc90,216626f4,2861f8d3,e61665f4,37c83ef1,acfdb8c0,d0b35b1e,ac498e36,38fa5da8,310a8f64,62cbd671,9d4b9c2e,c3be9835,cdda0a8e), -S(27dc4da8,e16e0d62,4a0204e2,3a8c11dd,4ebc5504,3cfe98a4,7d91ab19,92bfdfa7,6ad18e5,fc0e8d1a,421f6cea,8276b506,96e0308d,3983823c,de917e88,195ae3a5), -S(7479c3f3,6a4b4d1e,fea25a45,a3c4b79e,919707ef,ef92c830,6d693c00,e9ff2096,5faaec2b,a9343e26,cd32a68d,7f441d7f,3ea614c5,3703ec81,c43962f6,9934b3ee), -S(3420c98d,a020a034,e094ced,fb80c251,6c84a959,f9ddaf7e,ed889927,9d98cd03,b6af487a,c26a55a7,30552322,b73b05d4,a7e819d,7fd84873,4345870f,6ce5b8ac), -S(4afb97a5,68556ba9,350dde2d,85709057,ac4f34f0,e9700939,57bc90c5,540c61d3,1a129c50,23c3e419,fa0d5bb1,74acacc8,9aaa1114,ee38b937,406b5da6,b99fd29d), -S(e431caf2,6d33fbc7,28a789fc,ce00f3a6,c4629958,6a03ccee,e84a385e,cbae856a,9d11cc02,df57742e,d01e9169,7e5bb434,5829d076,747b065a,782c8619,da4369c7), -S(94a651f4,4b112523,3fd880a8,99191f1d,9cd5064c,227c2fc4,de1eaaec,9439ebf9,85eca2e4,717816e1,6c28a5f2,c90fa6a7,fe4222ae,f811ae1e,acbcabb7,6271ed7a), -S(96ea121b,60d051fe,d5381fc8,38b70e86,257626b5,91184577,337fc62c,529355f0,b3a56efa,b898b7b6,b2d90341,cc91faa2,24e410ef,fdd9d7a3,6770765b,c412dd82), -S(4b7e0cfa,250661d8,fc2e52d1,4a2969d3,b301de21,cc7eff3f,d7d7d7da,e2404d9f,d5d48777,c77930ba,96d179c5,10734cc5,21ca4ab7,a8d7cdc2,2960ddca,c03ecfdd), -S(7ee44334,6c87bae0,c3bee1a,273f09d2,d687fbad,fe060ce6,ff376c10,1ef266,ca4d7e06,2a28edf4,3419d107,41ab1017,da1bbb4,2e26a282,5d8d5a07,6e377b5c), -S(e31aa2dd,5bb618c4,63da1ee6,ae50ab1e,ad967b48,ff8df86c,f0c9ad2f,9e530ab4,3b3f92b7,7845a7d1,6a5b02f9,13354e6b,5388583e,546bdf9c,34cedd17,a9d4e11c), -S(15755ea9,907f998b,f75d38af,d4716cb6,4ab3fd19,2a3b62f2,f597708b,33697405,3ae19c16,8fec504d,8cf4320,c08c2dd7,605e2fef,1d8ebc74,1330e78e,9803504d), -S(2d2da66,d08289e9,f1674782,1214edfe,9de40a91,f1a378bd,e5802bc7,95023cb9,2e48b7f7,6dd20f2c,df2b0c18,1d5c691b,7836c6e9,8755aa05,62277426,53df2a99), -S(1b4bdf1d,d34b1b24,384d28d0,27c404b4,2691ec78,3949b8a0,65615a35,ce5c6c18,33590a6c,679a3058,5fd82459,f609559a,edf525e5,7eea0870,22d60d8a,dc57af5e), -S(3de0d336,b7bfa62e,5bfd8265,4a149e0,fb9a9add,6ef9679f,1e96b911,2f4bff69,ea44028d,b24468f3,bec7b60c,22c72efb,ae8f86e,90c3e2c2,b885b228,f7a1e123), -S(55d6d2b2,9314bad1,ae87da3e,e30f01d8,8844d27f,6e85a071,539824fa,dbc064c5,ae68132d,6f412ca0,3d70b23a,cf88d7e1,2443da6,cd5c2914,1e44199a,685cd459), -S(7ff2bf7,4696ee5c,fd709fa5,5d6bd376,b67fec2f,1c8b8982,64628e7,445cdc13,aa0f1082,f90052a5,c7a92350,cb3e27ed,9ad895a7,a73d4929,3864223a,b2640cea), -S(6fd69f09,3f4cf5d0,26703a,a0836ff0,2dc344c7,ba36bfdf,c98fe932,c70ce775,a2a95599,4651742,728572e1,5a9854a2,3cead0ee,c7edf4a8,f79ec569,36cf300d), -S(c644d73f,c2170115,78c4572e,9b8ed701,c36dafd8,e1602efb,8788c0df,a0b6ad48,38fa94e8,46ac717d,88862e2c,94e90e15,97a9144e,2e1900bf,1cb40218,e22cc2aa), -S(864820fa,f8975085,f69432ff,2f638054,8b972f33,7b74386f,d113300b,d672cd3c,b08492ff,37610ff2,fe86d3aa,a3c62747,3be55698,f183bf58,f67872f8,cfc9cbe4), -S(cc3f0782,8c7e73f9,a3cab59,be37008d,6574acb2,f7c4f0bd,4cefd6cf,b10c25e1,41751bc0,b9b0ada8,9d7e430b,600b00f2,987c0639,bd910c32,d1e8ede1,b183780b), -S(a7c1d70b,73e901b0,b892059f,4968d287,7026847e,187766f4,7b82ad0b,e874fe5f,87a6357e,83bc6dce,d3a3700a,1536920b,b0dabf6b,2ea70f7d,1a88917f,ec51890a), -S(f10a662,f02cab01,f47c6415,70e9a020,2584f160,8a69c02b,cc5509f,e54a7391,70422b17,3c20d128,30da1a71,57935a87,7d6db2d7,b7ee5272,5b756a5f,a0ca8891), -S(36ae45a6,efd7f4ef,7f66a206,82d027f,25b8cdca,410901da,1152b2bf,2df0f14a,ebd682f,c4cf31dd,c39b23bc,de979cbc,7000724,8d4c75c1,dea2c62f,37823e63), -S(ae3d1eaa,e04070e1,610c70e,190f599d,b2ed8dbb,5aa4be6,1af5c82a,83757f9e,6045833e,b1521caf,3303bea,eecff1e,a98477fd,ca29999e,4ff55264,24e87117), -S(8b961a4b,917a59d2,4ad0f94d,fe7840e8,f7f6573c,61de7f50,b3814920,754e5891,3a198cd9,e2d40f2e,7d5796aa,fef0b84,91dde435,1aa57366,65263ed4,5f136fee), -S(86d77e77,f7c5e4cc,dd2ff3a0,1589e422,8aa30d9c,162370e4,1ca47040,89b4e0ab,c0cf8d72,aa3b90a9,56bc8827,d3b33c1c,70707114,e3dab774,68894c31,3ecf21d9), -S(ea77fb69,a07e27ff,a2bc1815,27a7219e,2433a38f,98a05f18,9faba452,82722666,38f055e7,cab474a0,79bd635f,135d608c,c0b8b2aa,b48de933,c2e48386,74e943ec), -S(d5612e3f,304cf63e,23c280a7,872679bf,9861ae4c,965b79aa,db2e1ba4,cdecfd94,29e27659,26aca4a0,da8f3a61,dab6ee38,23e47fb1,36dcf792,181c958a,3ac24a78), -S(ce8968de,589a9b5f,49ddb8af,eb06ac29,ea053b5a,ab3c6dcc,69dd132e,5f2d115d,26f18c48,8de54fba,bd476b9e,8a6d049e,25d3d750,b8fe9595,a9eed52d,1865b98d), -S(728ccebd,7f098fd9,96bc257e,919961c5,4260365b,50f31d56,bb749b7f,6250b577,298522b3,d6e77839,97fc8fc4,5d4e853c,e530e768,6363b86e,8a68a717,fc5e4742), -S(ac7e69d1,d7d529a5,42fdc047,f9094729,45fd8af1,4ae3d71c,246a7c80,3cc7b1bc,af4c4fc2,9680bda0,bd2506d,7f64f4f5,f7b891e0,c50fe059,3246f97b,ebe10d1), -S(633605d1,9d61b598,da661292,2b6e5763,c765960f,c044c5e3,a4405449,cbd0fae4,fcce18e7,3c419aa7,85a55b57,41902cf6,855d2775,e8be678c,18388a0d,cd2b5de), -S(ea93cce3,888035ac,5a187cc9,70e6232c,37e2d0cb,31d9b5ca,33e567ee,62948add,d842a18,e2153217,98a620fb,c6e40ec8,66c9c6e,aabeaa31,7d6a01e5,294a8b0b), -S(75d25df7,63b00703,5e21753d,7e4cdde9,3001a820,6dd834a8,6e4e41ad,38e9cfd4,ddd41a0b,4528af7e,df820374,68eeba16,e2fecdd7,1378dea1,f6d0f734,8593233d), -S(b28186a4,b7bb240a,8987119a,7114faba,d163c3b2,66349ce6,328ec7c1,62ab3fee,4aa77c0f,8db9be55,58488234,61d6206b,80ca3788,f195a47c,ccfb7688,18bfb34e), -S(43638d8e,3331ad3b,9e4cda5a,fcfe5c76,b1a61811,1f08ee42,1c008d4d,187300ef,fa90b3a1,44d0f073,64734dd8,698beec8,8b916fa9,a7aa7d9e,d019d69e,5bad5af7), -S(19eda20a,1ca63328,29a7404f,51c7fc4d,93d0ee1b,76461ee6,42a07c07,3d73a1ea,a6c5aaf8,6a9546ca,81689f75,68709261,642a2d37,d104b7b7,98a4ebce,f42c5506), -S(f6a557e2,68fb6b99,5e2a9342,d5e4ab19,b95bf279,17285ece,11268477,427d092b,b10451be,cc64fc69,7801012d,7d58e4c0,17365faa,6a9db69e,fc7ae505,638e4204), -S(bed211ac,c6fff91,f1baf145,27c8d007,1b19022f,13e54f41,3fc83b7d,1c9aef54,b97ef30e,a42822fb,fde43ffd,28184f8,fd58e314,ef69bd1f,b1961314,fe4bd3ca), -S(593c25d2,f6059501,347cd47a,9658b04b,9fd81c8b,5754dd32,35ef3d51,c7ce052e,1e3f108a,c81dfbdb,eb544d31,d7892d4d,27d4e146,779135d6,eb2d81c0,c3ebe674), -S(207d923a,211e86c7,7d8357cd,19b95bd,ba4aa7ee,61d147a3,a4149942,2a23ab47,92fae109,11615ee0,9a3932c3,7945aabc,6b14e5e,a5934a92,b6dfb9d7,a68ba39e), -S(2c2029cd,d7aa039a,1b43c84c,5f0db4b8,8093192d,584818f1,f938eb4a,5c5accd8,35a55e55,41a70031,c5ac72a1,2a94d94e,1f467015,8ebfe17,70d2aeb4,76478cd4), -S(4f8e148c,6fdf65c7,4152d84c,5462eb59,e6bedfc4,3ce6382d,db24d20d,43e0927f,12fd3323,143df955,9f3ce8ef,30203320,893fe063,b17a9f58,5594062d,4478beac), -S(954cad68,1049614b,9bb5995a,f69868e9,44efaf89,5ef61aef,7d09e74,24151879,56c8e285,5df18b97,4147fffa,a561d425,c1d0b1ea,8cfae8d,4dbd3462,7bc57614), -S(d2b06281,2acb2483,bf26dfbe,5a61fa2a,2dc995dc,835a5ca2,86fd2d33,b273a129,debd115a,2a711cc2,16ded426,d442b504,475a5f2c,d7e651c2,13b79f99,74ab9997), -S(1682ab4d,ae292e8f,26520ab1,b8f8aca6,33cdd6a8,a0d585f3,5048551d,f4b6d354,80c160a0,9300aab0,f30df084,fa0bd259,fce78972,7f0a78b6,96562edf,d820667a), -S(b9252ea7,f64ee2e3,4cf31c3b,d9e065ff,1e0349b6,3f6669aa,19e42a71,72312586,4e48711b,3f0fe7a,89fee250,b116862a,e00da579,d7e29427,fe2ad3c5,e0ddccb9), -S(a1123f7a,81cc5e43,2a54785d,f1cc614b,7ebe0dd8,b6362e1f,cf41bd65,c3c4faaa,a0d31492,82dcf09b,2814c88d,d5aeb9af,2c16ff1d,3e1e05c2,68c8aa5a,8f5716c4), -S(f47f6d8c,a7950f23,a4a08d07,f5b8889b,c30e8ad2,8510d198,3dfed29e,e47af463,6873567a,2820f91c,506878c1,69e98a70,f3d6696c,455f1752,21a4e1c2,44dc62b2), -S(8efbf718,f124b5f6,807d3493,fb3dfbc6,f1c4f0a6,9ce81d20,3b13f422,b6ac1c88,6e05c0fb,77d12e84,64fe1b30,8207ceb9,a297334c,e937eee7,a9a45ea0,bfffb734), -S(56a8aa37,ece2a01,5f0efa3c,41f541a1,a9078c03,39b6af5d,9c9486c6,93bbf553,fa191d76,62b7189f,9ad68823,8655343d,71e7527f,2e72d3d3,1d25a4ce,719c7146), -S(cc2d4945,5659cd0d,19924df6,6be02e32,16e93423,9ab657ca,9003431c,cfe8e450,94a34e9a,a0814633,33b53121,3c375d6a,dd554ef8,cacee52a,a177ff9d,42cf39f0), -S(ea38154d,ee6d08cf,50c3497e,6e15a1b2,d265fbe2,cb945a09,a34aec36,35f18583,d1e16b50,cc5a8d51,f043ec05,1992ec53,d7020cb5,5d05519a,25d364f7,e498b28b), -S(82cbb42b,854e7f28,a2a786bf,6cfb4642,3fef958a,dc2fae99,5590d311,82d46c2b,96310134,eeaeb35f,5e2ae9e9,2c26e731,e0e65da6,b37124ef,c6c89e58,b7434314), -S(5f23519,92aa09d6,1ad78103,df0a060c,e939782d,774ec196,c261d6b4,5e42ff01,7e02b11b,5efb1a31,43fbb204,d63a7c5b,8a04a66c,1f5ec292,277ed353,adb8f95b), -S(d182f035,18ea0c6,a16056ae,a071a1b0,920d7a9f,37137429,5fa89f4b,1b4b229,268c5c3,f0d47748,effe1eb1,3b1b5340,4f61da2,6e56db7c,f2e35d89,a6bdde8c), -S(51e72ca2,3f22bfd0,f6405e3,57ba5221,310fa8f1,fc054e30,a34a0271,3051e9a0,307f4e74,b97c917a,281acb4,25d1df8d,ffd5e578,9b1d80f8,160c1ab1,ed79322a), -S(bb193d73,f08c5946,faec6f10,aa13f855,aee34bc0,c4b60c3d,2ae0c37,359f7b83,87cd0d87,d9d83fb7,3b382cc6,35d6dd63,29116267,5f1e3647,ca62a68,fedf7143), -S(9aa07141,e67fa1ff,cc307760,5b73625e,f804246b,a4e8e568,f0a7c111,76c61de0,b58aea99,47244021,1020a64,584172c,21c6f641,a14c43cf,377c1f68,b8ced736), -S(aba5e67d,8aa2366d,e77c9d58,1e221fa1,b0f0db3f,2d3679ab,dfffc4ea,45ad84d3,4fbdee40,48ffd408,712e17b9,2b9fbb67,ec7c9ed7,e6ef052a,b8dd0ecc,62fa91f), -S(bb9a0c87,e1fd476f,e8cac1fa,7f6cad71,78297b32,9fce8d9d,332758c1,1a8ef09c,a9c38e66,add0e7ab,538c62e,fd7c2eaf,3ee221e3,cdf581ff,3fcc1bb8,bf638332), -S(b531f3ba,bb94cf91,b492d253,a36de81c,476360b1,91ded661,7eecff08,403eefec,3f653457,6dadc53f,f2a268a0,b8389ad6,a21653aa,c4b65b72,758fd6ca,27f3b570), -S(f7e9407,d1f8f9de,182e273f,98984d57,de4f7c61,227c98ad,36589c2d,64728812,f3f15a91,8d2a5c47,d7fabf29,dd2a2380,73ef645f,924d04ee,31dea489,f6882844), -S(3aacd2b8,2013ac34,75a7cb05,e52c1853,c10f7b66,68e5f8fb,eaaedf64,342e2b82,2d33a32d,7f745929,3915760a,4fb04c30,f649541,a246396d,8cfefbe4,26f6573e), -S(f11a09a7,edc46b58,313c31ea,93364d17,4940c58f,8a8fcc4f,2bb132d6,bae01730,7a42dec,b0eb3b71,a400cc5c,4ac848aa,1e3cebcd,c38a1407,3eb6f568,6dc68d5a), -S(642ede12,2ed16043,ca028a10,e014fcea,52d6a3a2,9399cec0,afff3009,598e967d,7f86f11e,f79a0e2b,66ccc91a,3164617f,f08c85db,c4f1e4f2,a0972c43,8e15b6de), -S(a04415aa,28f065b4,5b60f57,2f665229,dbfaaafa,e8c0561e,9e37e1a0,79231a49,a32b2e0a,4e9a23af,58b398a6,56aeb0ae,6a98ba4b,abd1db60,8959da55,14710f08), -S(b0904d2f,333c0cad,9eb4f5b3,ebd1c176,3488ed9b,25f640a2,e9379df8,b4d170a1,ed8bd456,999ae102,edb20bf8,3f903319,97233e29,35e1c52d,13a52cce,32a5e958), -S(e50f98e1,162614c1,6f2effc7,4853d7b7,2fa13e2f,2fc0b864,dfa1656b,2e1a0a40,5e7ad119,80f9533a,bd541065,c1309f90,1eb49aa2,34386f14,88ddc3f9,3406e986), -S(5d6772d0,2007fbef,4d385766,ab4b4fbf,1b3fc017,6f883d5b,395e5a35,763c9e12,f4dbe650,89e165c0,1fcd49e5,5991db5d,3cfff2fe,1730862c,3f3105d5,a9433e6a), -S(c971d45e,c78b70fb,70d2e4b4,b427b82c,4c569d0f,1d9e85fb,e4703d27,58fa97f,9c148ffd,295bb61a,d3a34548,625a447,65a7599d,5d0da8be,c30dad98,c735440b), -S(f118ec13,304f8826,bb744d7c,eb87181b,fe25c3a5,ed8df1a0,eb05bb65,860b738b,292a85ae,eaa3cc59,3dd8adc,64fa9e71,2824227a,2139d7b8,5720b289,f1ea54fe), -S(6b38d88d,e7629ab7,82d2af4c,93a62371,bfaff595,d422b5cf,b12e0fd,1155f5ba,b1a49c69,5439c867,5f491cbc,e3c5971d,87ae5a60,faf13c1f,7cb9536b,37f780b4), -S(95c357d6,24a2f744,d8989a28,8bdb7c0b,241413e6,5a26c877,8382270f,c291af61,142845eb,991aaaba,3e755ed4,3ff0afed,34643413,5bb13034,43b21a83,4f3c0e31), -S(feb4122c,23e68298,f4601b3,edb1de03,b7137341,6527e483,f16a14b6,660425f7,2b7f5ab8,1a2fd416,24d3fd71,781be6a5,1e8cb43c,7ea8265e,e5d92978,30388bb1), -S(bc0eae5c,fec4873d,5d34f0a0,86a96ce2,51369a01,ad2d5137,746bafde,a574d9a1,1fe1f281,999033a4,39f4c0da,5c1cf6e2,365b139a,29f82785,caadebef,ba5de3a6), -S(93f71e0d,d7ee6b9c,a017de05,db2a52e2,d2175cf0,2c1aa194,1c6256d,74907872,1bd2c197,6108b712,27e0bd78,b0a2a036,6564c979,5d1ab6de,7a12a0bc,3913c8cf), -S(f8388a97,45191a86,efda904c,8bc06801,faa3bc37,8a2425dd,2dff9a4a,4ee5d7bd,af2b9260,c452261d,584144b2,91b5388,3eeb5014,c0fb0a89,e8b78f0,9525b5a4), -S(c7e727a4,a0fc2d3c,4a5cdea6,c93049a4,52d3646f,35951918,eb379c56,50c544ad,37f5bade,6d3d9076,45a4154d,7d30ce2e,cb77a3b5,695080ad,bbdb8a33,4c7f7514), -S(328eb6a4,7cb82340,768d099,45902d56,3707c86b,261b9ce3,aeac6734,e76c4d48,ff1a5828,4f402090,c32f7b07,7e8c3098,7c3af703,604c22ca,aeb4acba,e7f52c97), -S(beb0522a,acc84b29,e0ab8233,6ca02733,9b4df195,bfb01a18,b38dcb3b,7c8a1e21,82d7508e,9491e2d3,d74a4229,df4d6020,1c6a86b8,a3a448c4,35dd20b2,f993e6b), -S(d3dada60,563278d9,38e48e79,f2e6bf8d,5caf0f90,affbdffa,c30d6e06,3f69cee8,8dc2beaf,34b916d2,b542121d,8e181735,1c55a766,ee46f2c8,bfb8b7e3,d5ff6826), -S(42111151,45ecbd47,1c8a812a,192b3a7a,ab43cbf,ddc49dcc,5a92f350,86069c33,f9428e07,f33cbf7c,7afd7cd2,f6afefc7,b0fa30c1,ecebcf92,30e20c17,7d94aeb4), -S(bc2034dc,72217bef,895c8d3e,5a5414eb,882e8efe,3dc8cb0b,cbab0edd,1bbca0a,141caac9,de3a48ed,ac6eb47a,fb195238,f3784171,4d7f3807,8d492a9e,a70d386f), -S(b8035a3e,9bdac3c2,58da038,5de2ee25,98ca621,d90db03,4057b674,21e2bd1d,f7af5751,a8e51665,4cad2e0c,61a94970,6b5151ec,1eb07cd8,1713c716,7a44f357), -S(740fa667,cc333c48,4880eeac,ebbf5fc9,34d3ac55,ea04d8c,9365e5ad,c3a404b7,33893248,b4e2e874,8694ac43,d5e6aba1,3afe26ae,3a51a613,d7e0541c,d9ba91f4), -S(673c1c4b,16c6a75c,28725630,340aab0c,8a7b8648,4b17714b,c955f160,e3ee09a2,c3f99423,2521122,d0dd518c,d9fc94cc,5b4c836d,9665cec1,1a024995,342f31ea), -S(a74784c,dd6cfd32,972124a5,dbc0233b,f0222de1,9f90ac0,87e95ab6,f40c62bf,ef2a3085,9a86e0fe,f96b2e5e,b7a63820,122e2dcc,a4f2102a,b501f2d8,1a88378d), -S(db1d8dd4,bbffccab,bf1b90c1,9b92535f,4ada68c,9d3cbf86,c0d700fd,61d4beb7,ddaaf64a,54972f9c,ea2c2fd1,27e17223,1dc38360,6e0589dd,a3f8d62d,80c0a5be), -S(ffb9ae70,2307914e,a9e4160a,1cb68f84,3fd03778,8a013f2b,f9e1d725,b09d8b40,352b1e7e,69e5afc2,6eae5b56,b2b7ba9d,ab174019,a03df463,ba510aab,c4c9e859), -S(ed27b183,29dd25c3,4a760942,b1aad66d,a1439b86,250db95d,98799c63,a9bf2fa8,8460eaf1,554c31f8,5c6baf21,126163e2,cfa9d290,17bfff10,9d295c8c,ddf391e9), -S(70a453f0,52682a36,1dd33a79,a65e4080,7bb95541,5d0b0c72,ca3d2b15,7e57bce3,2e40f3c,25554c85,cafe5e78,9aee14a5,131ba6dd,b9edfbae,338e8db4,653e908f), -S(377a14ea,78d4f864,5262ebc0,5f55a310,6a329376,be0d567d,a327988e,4e1560ac,ef069fd6,264ab8c6,b290c4be,6558cd27,2745d9d2,7ea22521,b79524e6,230a7c47), -S(39fb1a0a,924546aa,ee6b8f4c,65218a6e,56ee0e2c,3833a784,3858eaa2,f57f3399,e4bd9a53,8419ea44,30b041b9,e93186ee,d9ba4846,b6125f1e,c549f34d,ea5c2f87), -S(d255491b,62a9ffd3,5512555b,4c413eb3,b412ed6c,9b585baa,875c5643,70d9aa00,da4094ca,fff6616b,51ed389e,a5b9b3af,641f872a,7166427d,d24c5973,be24d067), -S(342d8017,5754c01f,504e6c0c,c4c6c8b4,a1079dcd,89de2927,a3227a1c,756de1f4,de8160ca,ad4a4f31,791fdbdd,4b9ab3c9,db9098f1,2db64ad9,d6f90ba4,a9b13a6c), -S(92e8a7d3,d4e8bbc8,4427ab1,a35e5a0e,c2d81c04,c98ff34a,325b4abc,2863fef8,e8bddcfe,876f7c55,86470c56,bcca444f,fee67417,8a592e0b,b9f5b1c3,b2a7e9f7), -S(eef2dd87,66dd8259,fd821f30,3771574d,4477283a,614e463,d81238b5,b08141eb,39a91138,ac12e0eb,da43724d,686d9207,1db46682,746d532d,55426a53,87b98023), -S(2efc16ec,974042f8,b1a91132,2ea4f521,71f76da0,196cba89,12faf48a,cbab65ce,97c0079a,3151c8a4,7dacf1ee,25bf3157,48a83cfa,1f3be2ce,1954731d,a2cd56ac), -S(3d2def4f,dcacdfb0,8dbb75e3,1627baf4,6deec0c3,6c4bb3cf,f96f13a1,2066ae14,41ab6cbe,eeae8634,2f95027f,e472834c,e626206b,3e1ce1a7,71b717a3,39e5827c), -S(ea23f622,95a65d24,162d88b7,6a577b64,1abca822,1c29d23f,56e4f929,a19dbe10,aaac26f5,c8b5bf21,38a9dd73,8ce69b01,6c6b4f82,4685fa39,c2de56ca,3c58b664), -S(f01557e5,ea723ed8,2d5e4e02,f4358ef5,5b0234b8,182bd4c6,e6310103,768eac09,8bd31626,7fb3e7e6,ae828401,fd00712c,9f4f4c7a,cee8f708,4eae9da3,38e12378), -S(1f645466,d562b0c,4618217c,4cef306d,7156a5e7,45327a55,40619bb8,2934a8e3,cf9dc7d8,e7c1c0cd,28d9bf5d,83a7b33d,e1060c01,eaf58d4d,10fde41c,495b954d), -S(6fa762,97a3cd7a,9799f3c1,95f56864,c5a8ad78,f4014c53,1dc83fea,244003f4,3bea377e,9183478f,89f94127,3bf5222b,148ebfd5,7125fe96,147243a0,d07c14c2), -S(71061b69,c5a32537,d40254c,fcc5f67d,cd4a8,40911295,8a8e3f3e,5f060a6d,a980fae6,eec78bd5,3c926649,96239cff,eaa10169,7580799d,5b38ff74,8f0f7a78), -S(518db918,8ed0bf54,75234c9a,7e9c0395,8796645c,89104797,5a8602cd,e7401e3a,10c50bd0,aa0fb6a0,62b964ff,65a5102c,d6bbb192,3dfaf2d7,edfbaecc,77cefbe1), -S(6f7fc8db,8d00e22e,6f30c093,573d9f5f,fa939796,6ddf5a59,6126f896,88e99dcc,e417e5fb,b55fc324,1a283315,3ff234e0,c9ac49c,13ae48f5,b84941b0,702a7c08), -S(1e09fb70,ea2c11c8,601fdaa7,7734b369,7e5efada,77b38869,8553d4ef,e1bde2ab,b8bf422e,c93c03ce,9d9ed0e,de058d20,e0fdf535,63ba16cc,494d6648,fac3a027), -S(54bd2f4d,961177c0,dfb4814e,bf5eee4e,21b12ca3,eaccea46,e70e117,76ad1fc4,358e0d73,79368299,f33ddb71,1722c2ec,8912877,c3891c8c,bc55e453,7c803962), -S(53ca166b,2eebb5cf,59a35287,5f6fd200,dda76f66,e3341ffb,1adb783f,4a1ce584,ded51d62,7769372e,42540e0f,20ff4a3b,2d912b4,6eaec7e,4e891ec4,18fcd0ed), -S(dd28eb5f,5fccf394,81467a6e,746461f0,3e4cdd04,6e7e6f36,534f6384,daad4ab5,8d702671,6e5e098b,648ae87b,6b782374,a2a3eebc,eb4e3835,470d4831,1f7dcaa8), -S(ce29f160,90fde1e6,13cc16cd,16cc7b8d,7e6e1203,cb1f1b5e,a724d65e,4d91aa28,d44c4dc7,90586159,ed9f9d18,dccfd95,e24bf6aa,c1bc3530,ec871473,330680fa), -S(6d25e798,ea08596,7cd9e0f2,da65b546,8e885d92,ed8cb0c0,8a266dc1,6b4e222,1d18fc8a,4010f407,aafcc995,8fe38f89,fa5f6260,e3288f8d,e4d98f94,377d624e), -S(6deeb20b,cdb46236,969035cf,58365ea8,224830a5,6cc187ef,6d938353,920ffb36,b19d7a95,b829c318,96d2833b,9277c9b8,7e28c6cb,c81c4c2b,d114afb4,c5266c55), -S(72c4d5e7,68866f63,b53a27c,74ef9b43,35e7fd11,2e13db1b,93654078,f625574,ed233d0a,1994d701,62869eb2,b7a2cd20,d82277d5,3109a9c3,e6e97f47,d727dd54), -S(79efc60b,64c060c1,a142efe0,5dd75ed0,a5b4ea0,85e5a10f,c6620db9,92525420,101b68f0,6ae4a3ce,2e33f003,1ecc3b1f,11dc24fa,d9f28a82,ebb2f5f8,380b3c8a), -S(a8cb5ee,ee7550e7,41f2150f,2e458dbe,f8d32b87,dcacf424,5cd089f9,7cb6c0ef,fefde564,3f885730,d60fa2ef,c85f4b16,d86d1690,3b2a8bb5,4b5c18b7,73085054), -S(dd8e43e6,828c9363,32793374,9d29a822,66bc8b1,4e320750,3d415831,bd7373e2,5b1321c4,744cd3ae,9348ed3b,5e4cbdb9,5e1d7256,e7ddf7c3,fa1fe9dc,494469a6), -S(8ad3b3e6,a237ed9e,8f94d669,2f5a7725,b0779bb7,ae06c57d,1c25e449,4c95479a,45b978b8,500757ba,51a05069,32f17d9a,bfaecbe2,2cc63c1,5a9b617d,98b071ab), -S(cb3497d0,7c72e534,75618cbc,29224ff2,17fb9659,9d51a6e4,1559f323,9c699c4b,72914c58,8daf6396,d4d9b70e,9476d967,aa60e574,b637ea1e,25c20fe0,1355509b), -S(fb77666b,b8c6cab,ca7ecb4f,e88f1e0c,199a81f1,319b6a6e,9cf2dfc7,e9128147,f122b377,84326ffe,21a707c,a3bfe74,2e433894,7c791814,855501ed,255a2ab4), -S(f2f16cf6,6a9943b6,19b321ac,76186ac5,6e65c2c7,aa9c87f0,15029f6,36749c74,aebb617c,88115519,58f90c87,5f021df4,e3c83e22,9f787275,db39eb05,9b3d9e82), -S(607cad82,2d0a117e,cf29dbbd,c7a5c6cd,d4b67f7f,6bf6271,c58de368,50692907,f2344d08,4e7db14f,70463f4f,20e9c379,538f0031,285d9c6d,1cd33d5,beec40f8), -S(efc8352e,dff912a1,936ca01c,18da7ba2,c9397f42,2cd58738,4ce321,4baac332,52006389,6229a8fa,e24e1686,4c5a643a,425e20ef,46febfdc,7d9c43d1,f767ca7b), -S(63d31f76,805cfe95,4db3470a,1d7215,505fa39a,cbc69048,58f801fd,eef99804,97cd5656,86da7de7,4d12cd9c,6e5b0c5a,c4f7f22d,3d44b372,a907c233,8f963e7c), -S(7e64f2b7,c2083661,8f2e2d21,e86ffa91,be646231,c61ac353,c32cdc25,953a01c0,c9222645,5b1ccb79,e00e905,2bf2c9db,91d41728,58e46f84,811bce9e,8b0713f7), -S(b5f29487,3a276b67,2d2de980,c6f74a23,d7bb465d,e9bd3362,45ca65ed,f942b85f,76459975,a0569a4,8b2b463f,375be7b4,f05e1cd3,3ee33a75,61ea8292,850d1089), -S(a0f6ba4c,b52187c8,9c4b1218,b7f57773,94551352,61582217,7e649893,dc3cbd8e,94d62e8,8f584baf,f0ff883c,1ebea341,d71f8bc3,59807c6c,eafd845d,361f09bb), -S(ef4130f9,88666de0,2aa37978,daaeb7e0,fbdddfba,d8953c5,6011f839,e974d0a7,322d77c3,dcfd1537,99043ed3,339a2b98,87538059,714a459c,1ddbc6dd,c9e720d7), -S(d6fb60f6,4b5409b1,7d10e23d,4f311d9c,4af5dde4,f1f07616,11e0eafe,13c2bae1,72f99e2b,bc790349,144b0ebb,67b35ba6,a62b94ec,b8bda4ea,c32de255,bb071651), -S(4f69ae06,8930b9aa,bc2bec95,8b3f28b4,5b488e34,c3ac0dcf,ee05368d,1f7d0b19,b72573b5,b86157ab,1e414c20,c0e073a2,e583f031,ddbd4141,1b3e26c3,e3447d57), -S(9fe97728,7de04cad,e939e6ca,d32afe4f,865b0423,9103850d,688fd06b,db10b2be,60cce398,c46ae002,a34a9ffd,d2ef6045,23f442cb,9f7ef392,ed292ce2,ce54256a), -S(b328b5a2,1adec912,66aca0c1,98084578,59036c5d,be3b6e8c,a9476b95,6954aff2,355076d6,a48803b5,fce76401,4e5b9e3a,d7f3a270,a7c50cdc,442fa9c7,71a3dcdf), -S(f8d16f5f,14885b0b,c5d556d0,8f6050ac,62ee00d7,c3e5ed7f,2ff6b8a3,54e54bad,dd483037,70d67a5d,32e7e58b,dd83dec7,b5c8e14c,a26ae5fd,58867401,837a332b), -S(422cc48e,415b2e68,7ff7896a,b32fc6d5,e3c433b4,ec2b511a,42178b6a,9ffe73ca,664821ae,781b98ab,c6f08fc6,ad11a76b,aed4429e,b7e879ff,134355c3,4b4528b9), -S(c8bb5046,1e4bd041,afd84d63,998dca63,de940192,7314d666,7c19db57,a8f629f2,1455fd5a,945165b7,2186e9de,ffe01764,108d6f03,bf4007c0,53ec7b8a,a6a7d07a), -S(7303bd5a,4e82fd3c,a94c94e,c2f4a06a,7d60c272,b2dda534,48eec8ec,ffdb80cb,7c593252,6a031a82,673eea15,263523c9,44f3ec0e,975203db,7cc302ca,83316c0d), -S(3455bd06,7de934dc,301f4a47,807106cc,24e3d8fc,9bdce088,4c1d01ec,2250dddb,d48aee56,e99cd267,d2cd8cc1,ee9fc3ac,88cd3d6a,2e58aa97,6586eaf6,e2052db7), -S(a419f5c3,a053b04a,a7137049,cc9452e7,268f43fe,528d7232,f0950270,b9d5c2c3,dee8994f,b9feefc9,d1f5f529,5444214e,2190de46,5a514282,5ade1a46,c439c1fe), -S(31602357,e187796,39867d23,89962d8c,3d5e9c35,7a2ace5e,83b6397a,585d5a73,21168419,4dcbe58b,95cf6e85,dc6040bf,d62894c4,bc5abfd3,e42603f6,ef86bae1), -S(3a0395c3,ccbc8006,a889e8b7,f6de9f70,44f2cebc,5c595f40,9d632166,c35831bc,25705a8a,213464ed,38fea19c,e1ed5ca5,2c0f8bbe,debd4388,bc8565a2,faffdbf5), -S(88067788,1627b285,336ff69,3ffd3728,6d0f154b,b743e273,2ff29598,178f5f17,c0980505,2fa7c70b,fd34ce6c,f27e5197,3414cc7f,1f57afb1,18385e9d,893963d0), -S(e1e1edd,146391e7,aff005c8,8f5d1347,5b393ef5,3a017b17,84a6dc4a,e29f5b18,e95592c1,5005cee1,f27c649b,2409c3f5,71870c85,c389861d,3e285e7e,7754a3aa), -S(113aebc3,2beb62a7,6e57a820,1c3602cf,d654ede4,d58e10bc,3545d84,cb406362,afc21a5b,5155c143,45bf5b47,50295ed3,db00ed7b,ae83205a,a0c504f7,fa5a2db4), -S(cdb6f34,7ba8177d,57e58fec,f22424b,fd3a276,96d386f4,9abaa40a,7f03bc2a,8959bea5,7d63b46,ae5d4d34,358a49ee,142b9b7d,137bb2dc,f4a937c,45338b08), -S(f9e9688,15a87cfc,85c00d90,2d7ce467,5086c566,49246f8a,bc655dbe,c1c82882,7152976c,19e3aa37,aa63d7c1,b9b45111,923b3b7a,df49dab,ae50226f,f39c1fb5), -S(7e7c0a6a,272ca295,c7ff3de7,906ce47b,9470e583,6afd4218,67143d5a,ea1d67b5,b66f3565,d68d55e3,b7542ed8,2b12e217,e4b47879,d9dda727,bec58094,da9d1886), -S(72995966,366251e4,57009324,5e29989f,f15670,af4acdb9,3eca8d47,3d1bab8b,9a8dc60c,3232eb18,9b454b51,d9db82b3,dcce9f54,e30e430e,26aae1b1,221594a0), -S(973afb4c,aa2688a5,b7e4f679,e68c2e4,df25ccb0,d56de80d,f6522000,6eb4dc1c,30055694,1c0eb266,906933dc,9c1758b,7a6181fe,8c400191,bbd978b,13f5f55f), -S(2d550e3a,f5b2d5f8,3cb4c695,431ed8e,62344236,66eb0eff,7759d4bb,39fa2dc1,5f6eba0c,e447bc92,70d35709,87eb9b17,89e7721,a7ef2ed8,8f749dc8,37dd7e71), -S(ed44931c,7d509be8,706150b0,3f24426a,571fde4c,e7b2d3ae,488a3576,37f6ec28,48e05525,e9b38639,6da1fdfc,40a134b8,1e05fc60,c7bccfee,8a8ac358,e9fd09f5), -S(6de88a88,b7b34f50,a8990a4a,742bc1d5,62d6b332,810451f,1c0081e9,18268975,5c435e32,379e62b7,46ed6518,b304ad1,65130b66,158cf41c,5418e490,edfc5535), -S(337611a2,907cdd12,c6c482a1,9b89fd74,1547fcf4,ed6ee721,cbcb66f9,b90967b4,1a438459,eac97f8b,53e45562,4a25ab67,f52cc6a7,fd3cea42,5ad08dfb,31d6bd2c), -S(aff600ef,329fc815,d36abbf1,3eb59530,58e74ddb,9df425e6,49662123,d8c429ca,ab8aa32,642dbcf9,994134f4,65a9e760,ce8cbf17,540d2f3c,fba6a31,9eab56f6), -S(4b15c510,47c6cc2,309c7eff,d3124f66,d56198a5,4da997f3,48f35fb2,7250504,5cc00333,f6399193,ff90ec0,54a726a,fcc492a6,bde386b6,57e481f3,18000cf3), -S(4683f46d,b9cda227,cbff9940,23995184,92c61151,a67508f8,5629945d,42a89345,cf1e8d43,b85cd621,2da2bed4,ce556ad3,ff0abd6a,1d40e445,629d727c,1e072e3a), -S(9ee0eea4,850864e5,c8239602,f84a9044,b966f84b,1aac7690,3fd096b8,fb09145d,c4c0698,e2611fc1,c7bd1c6f,f86e0fc2,19e3532e,defaf5c4,ae79410,db9e94ee), -S(ca4b7b7f,e02e953d,e622359a,f1834997,e5190c70,c149430e,d76aff1d,e166a0eb,e899496d,bca56f10,f2823c41,365400a2,723ea0ae,72f062ad,c36c0bb5,8e6ac820), -S(cf62993,f5be553f,a7492b3e,45934937,4536aada,f8db809c,cd01fa40,49364a2f,fda0bda9,d0f450a4,3c95a5a2,1526fff4,1b63c08,8a320b2,1ee9716c,cf2613d), -S(cc35c60b,288f8ce5,4120178a,dbac3e19,6e76ebac,159e45f,43afe82f,c034f459,8a6657e2,f8b99b03,3c6e29b6,f3bf373f,c117b6cc,f7ef935b,43b9a1d0,890d8bdc), -S(36a1bb7a,5f4ff871,b5ffe08f,90ecfca8,7c19eb0c,d110d770,20aff404,95b72e0c,1750a693,51de455b,1325e926,75dfe3e8,94de9f37,2d2697ca,954944f5,87d8706f), -S(a04c1bdc,7ec653a,fc549370,25d202d3,1bb7c21c,73de8160,160693df,ce42b5f8,4dd93af4,37e300a,8452a7db,af6824b0,e566a935,632c3487,f768988f,d874e74f), -S(484cd2a9,99cec03d,85872e48,84ee50f5,2172089f,8f1aef0b,d3ec6595,2a228a86,9a65d51b,bf64776d,53e40da3,85b84485,3c780342,6952446,35a78ed6,e1cefaa5), -S(398f027b,8ef951a4,2ad7c665,f5fdfce1,831ecd67,23f45154,62c636cd,db3b8a64,99577f76,a6a3b0bd,ac4d50a2,24c10250,727ce349,856f4e7d,eb1406bd,62d9b36b), -S(d62300fd,a6d242df,58be11b4,fb754306,62dcbde4,6e86b1c0,d1419da9,99beb256,cf11becc,84928784,d23a74b6,4dbd8ce6,37a1537a,3d9d0f43,17803da6,d1bf5e97), -S(4c41dc69,be8c1aba,9da4469e,2c1e3eb1,14b07fb2,db63785d,da03c53a,faf0f147,a83d7f0d,fd92a665,d73a2f8d,520f1a2e,ad6b2465,57ae2736,9618d10d,b114680f), -S(9a5086b0,1ba7ea1f,6cbd3be4,8acdf6de,29e8f733,b120aad,daa7e41b,3b1b2708,f4eedd2e,814d1f5c,33f44080,e4d50452,4deeba2b,4b2ca528,320bbfa9,cc3c65f3), -S(a457659e,51a7154,e5836fd8,4948cb3c,227986ad,f9fb8acc,89a3159f,d723b478,5c59c117,4e9962dd,94f3b084,8a544983,54ec4962,f0d666df,889c420d,78845ae2), -S(ea79c22f,13e6cdd8,e282defc,9cd6ed68,5d39b48b,c6c13c55,3bdc8aa5,8a90f78f,87223587,c3cde568,81217ec8,ef0dc431,89af8095,d7e9f82a,86142207,d8b5c356), -S(e19dd143,cd0a9f3e,8535edf4,a3dc7e7a,4c49a25e,1771f8f0,3fb5eba,1a9e10d6,d15a39c4,86b79714,89b2afb8,13b412b7,c1de54c5,c3fd2ff7,791bfb2e,d6a498c), -S(c7b277ed,9bada568,2f7a87cd,6435e0bc,948fcb1,2551ad92,e188b664,fb5f59ca,7d1e37cf,3093775a,1b0aec4,93b77c92,f6d6f32f,a1d8438a,b75add39,70b5eb00), -S(c1fb0836,5dd42214,2098c397,b11a63d6,43afc082,16c0686,d1540d4f,d39f2f85,438d6559,d07fe7e4,1e775a3c,66e79f30,a065a62d,fdecea46,e8ec0967,a5b5b8de), -S(1a5b6bd7,152c8c0e,6958cd5c,9344bc7c,5d7869f6,bd08d698,88e69e49,8ae62ed2,166a9f1d,b2b3a729,e374af09,40bad6ff,7646504d,36d40465,2c826ed7,98195f0f), -S(8e3f1e45,42438eb3,2635c65a,a817c325,3affb9b1,a1603d0a,d3fe06a5,83cf338b,e6b26e2d,9e310afc,e702dd5,4bcc2815,1dee0a86,1e31a16b,79fa0900,f94e320), -S(ed9ffd27,1fd7b569,fdb187d2,7d1d97b1,3a4b88bc,aa13639a,62a6b45b,cfd00dc1,5fb45391,d5a636d,1d757e5e,472865aa,556092e0,870f45af,a325e26d,40f755be), -S(873a3db9,be376cc5,f4516913,d8235555,624cea02,16c3231a,72750c44,12cf4992,3d5e2304,2b04870f,d3cb61bd,2f618b3e,4f1dbd3f,2b585026,fcebe608,7f0a5a03), -S(d3ef70a,eb5ed2ad,375ca185,69278cba,3d037dc7,b0f63ca2,442804f8,1840e686,f4bae13,fd55a2c5,ec93a87d,c2b4134c,aba2fead,39dbb555,29d70795,45a9488c), -S(d2127f38,8f3b4e7c,b0d24f80,27f27e55,fca1110,288a1c1f,da46441b,21327919,18f2b4b9,69df9a42,1a87cc43,47e2ab53,146d6b82,fe3c19ef,2df361bf,579cb3a0), -S(5e73dbe7,e8961e0e,32b9af6a,4443623c,cd3f992e,b024cd1a,59bfac9a,ad6c9f4f,4d8299bf,b505c0f4,5835cda0,b7fef2ac,640a5835,6a7e498c,b0f34480,34527405), -S(b9eae3f6,9af01cb5,48cd994,db6beee7,7e45fba3,782a9ba2,83b340e0,fa89bba1,b7ad76ae,189735b,f4ad8e8,dbeabe72,ed40b2ae,2c9351de,1beb1252,d4424b65)}, -{S(458f8dbf,9cef8cbc,5d2046c7,42ca6297,e8fc76a,ad22fd3,af4f9a8e,2173d857,57074c8f,14a36b5f,6924517,6e3dc7b6,4d12a08d,8d00565,e70e0ca1,56f29820), -S(68e7cdbe,47bb0fec,37fb7860,a71533f5,5eddfd2d,8ad7c9ef,cc266009,65c627a7,3bb96d5e,f0cf90ec,13614c2a,c46039e5,e6e30782,48f855ba,8f8bce36,f66b8a90), -S(c220e26b,6d3cdf7b,b1cf434,ec5fca6c,eaec952b,e61d213,16601ec,6e06b259,3fdfaceb,268183bb,9914c5ab,ae804206,a3711bc0,d649c407,82d3d2ce,93e350bd), -S(fc458625,75cc7343,312902d6,8e160a08,f82fdb0d,60df16e,575f893b,94592e52,e2236fb4,e6af3e39,4faaf83a,3c6b418,c560abf8,eca40f29,d3cb91e9,e13a8ab9), -S(7afc4446,f445a33a,64fcc04d,269529f4,1e16f567,550a8280,4027bf24,1d08e895,3ee4443d,2cb04a,3643f6ff,90c0b3da,a43c8333,82c62d6,5a024a68,e7e7f06d), -S(4cea2d22,d19a898e,fca4a7d7,499252bf,1957379d,a6004,df9c7df1,60dba4e0,c97fe09e,84024a28,ef88985,6fa1feaf,bee116db,a88962eb,36be946b,d2da76c2), -S(633cd50e,b00633ac,6d5b1bfc,89d97e24,abdd932a,ee9f265e,95dac73a,65627e0c,750ccac8,f09d9f86,7117781a,6b20ce6b,6a4bdcff,7ab04769,a8dcd1d2,c541bdcd), -S(20224a29,28ae9e78,87bf4242,67333b0f,fd59349a,2321b8b9,c28af552,c98fa7a4,94944b75,4b6a0ba4,7c647332,e9369b,dc57f98d,5a010925,4bf6d2a4,eeaf88e6), -S(29d9b1ac,7ad67ad5,ce2e965d,e7ddadeb,43bafd47,f0fef02b,2f553693,1f45029c,dfa93352,cf5dd7b8,3e5a9646,da2a3f3f,152372bf,285b75dd,1517e6f1,7859c03c), -S(54859abe,18867be1,dc85a087,4cc7237a,597bce13,866686d9,43e6bcac,ec4fe7f5,1d956ff9,31259641,1faa0b22,b2639487,d0392514,58c5eb8,7918fc2e,26916864), -S(9c3c1ee2,ad3fad0c,e5e6ad1b,9b1f5875,1ad30927,9aefb1d9,4e8f408,c3406d42,b31e5e91,18bbb027,f3ab9d42,ba1cf854,753dc66,641cb367,7e8db07a,4b7d4fa8), -S(c4e812d,5a640e68,70a42601,694341d3,5e964f04,fb52f1bb,819166a3,4fb8732d,f9494ed1,b776c04a,769308b7,4d312781,5f9c3d6d,c7ff4b17,cfa1fa31,87435938), -S(4f8fc5f6,cb4e73e2,e24b94dc,63aef340,b871abe9,2fb53525,ef0ac7c2,e04f571,d81880e1,b3d0c55c,8d28bb51,5f1a10cd,245fb5e3,70eca394,d80ba83,d7615512), -S(2223062d,f1572257,9330efcb,2c5a90f5,6d9c33f9,87ef9b9f,9c79db75,dfde7b49,8fbefa3f,37c855e3,ca3732f0,2d0c0c60,b73384a8,3458b05b,eb74da89,acd6c1f9), -S(cb3b77a1,defe7162,63ad33b3,5db0ffa2,e80d7,e00dae7a,91abeec0,17fb2a8f,29cafee4,8cda21fd,d692d241,2358b229,559d7b2a,c93e5eec,9e4e7386,728dcf62), -S(cb520a70,3b9abc62,9a039af8,ef7f8f50,fbaaa21d,721c1bf0,d2f680ac,56061581,58643940,fc79dda6,35b846c4,fdcab298,6a2969e0,16886e,93ba4532,cb03140e), -S(c1163c31,a922395c,7afb6fbf,19a848df,ff20dc1a,38f1c86d,89e6779,3c97473,8f4e7bff,a21a812b,ed0c00dc,55972ed,173bcd4c,36476bc6,70d5177d,73e539bf), -S(82a01624,64aca6ec,17abad94,4756cbb0,b27bbae7,120e3564,c1c83776,138a1e46,9eebe6a6,140227a3,15d7f23c,176cebcf,21f61112,86dcf337,21deffae,d701a856), -S(972acc1a,194b29c7,1d626053,34704ed,95201c9b,92e5bfa0,937b7369,dd389794,48ac34b,936ba87c,1a952b91,8a82f0f0,26ddf57c,2ea44cbe,d15f6ce0,da73a4c9), -S(11c28dfa,639403f9,f8283916,dd32194a,d116ec21,e56e6393,f743ccd1,1b1fa275,8a008459,24e50c2a,d3a713fd,53fe4998,86cfe86d,2f31b8a0,b2903a48,ec16b1ba), -S(d308b5fe,c8e87dea,6ff1917b,8b853701,7dd6a46f,97c268fe,7dd2a672,92ff3bad,83ccbd2e,82917e04,fe00fd3,cf837c0c,efc34a81,54c2f068,3fb079ac,3a1dcab4), -S(f4551b7f,aef3bda0,51ed6978,45d37d52,97a9ce9f,4b684334,fbac03ab,ad0ab7b5,7ac85f32,e5cc407c,5432ac50,ee015a7,e2fb3191,90d8855e,7c5ed488,ce5c6211), -S(23daae11,946de442,7934b351,a38df422,2f8f5424,b2dba51a,98548718,3c21d2ff,48dd1fc6,ef5ca525,88b21118,7c172792,ff9aba3,d18aab3a,19d9dc0a,d795763a), -S(1d225202,4bd2b32,87400ca3,e8de9bfc,366cea7d,c87007f0,e36d49ab,32f3d389,e711a6d0,692025ac,74755d2b,46c8ccf3,1824dac6,35a48cb1,af6fe2a,ba17f178), -S(b500c6e5,1111339,527ae172,11055236,912f7cfc,8e67c4ba,94dbf39b,3aa349f4,7a65e1ea,dda398f8,5da9f82,d5bff3df,41b92854,29994d8e,b9ad0fb8,ec9610bd), -S(135294b,236c6f34,478921c7,d463c14b,92da01b0,226b0bbf,bae7f392,fc1ab605,8f77291b,b39dda82,33e6e523,7d313f60,3bda29b3,4961a6d2,4e474397,2f6bc068), -S(1fc67f92,9f12d181,73e45951,eb64aa45,627d2fa6,61a2d35,25e818d4,3d4b2ebb,f4174ab5,dd5ccf0f,d6522310,20bca7dc,553fc88f,952007bb,b5012789,ae9d1bd1), -S(47ae7668,3654ec8,a3904f7b,dd02efb0,ae4c8489,7deffa8f,a71aab26,d82dbd52,1e20245,990a0f45,9368065f,edfc7d08,ffdde726,1c8f79eb,68adc042,de1bcd88), -S(750b52fd,7ded02cc,886c9105,8dc98545,67c8c62f,c7dcddcf,ba74e552,dd8343a8,2df52ef3,2d8f79f0,9423792,341ba29b,d78cbda3,252347bd,123fdf78,5ab9b8b9), -S(148870bc,fbdea326,62c20304,aa2d9edd,91de2474,433711f9,75e977e5,d3b9cf8d,a0848bf8,6cfe26d5,3c4a0960,97925a32,d296db69,d3348c7d,71f7d5df,223b3747), -S(ea916e64,4958c33b,1610c7c7,b865a315,eede0d2,4881b156,4bd234ee,e372be92,387af6d8,4e8beaa6,a4df0813,db45aab0,6612bc74,aaf4a292,5a838322,a18ff4dd), -S(1aa70a60,273c70ba,51ff5fdb,2037bc1f,5ff9e0ad,f2551fff,a2176bb9,757fb4f5,a578a726,53233bbe,fd34673e,4890e0b0,d2609bee,5fcae095,1fdd2711,b618954a), -S(a51395bb,6cf06cb9,b2898e7e,d39c1011,ea8e4539,cd3f5c17,4150ab6f,7b0f170f,50820591,ed76ec84,a0ea2b57,b11a10a3,d46f5b73,71a67016,f952c497,3cbdd83f), -S(c6d532c,a8745145,e005f8a0,82b57eea,a235d56c,4688d98e,5cd4a911,d0b381f8,fcd16c55,4a38f1a7,3f82ddef,a3dbfe97,7d554b37,e6b60727,4a37ca7d,28473b2), -S(c42dcb2e,169a5276,e0dd6195,3f7991d6,2d4e9459,5934dcd0,e4daa217,1f050bcf,9ea1f3bc,e274ba98,a38d76b8,1af87fb,4f760b1d,940a1ffa,fc6c8a32,59cbb197), -S(ae7ef14e,5f93dd3f,3ce400c6,c6944a2f,e14617ed,af42aa9e,dec2f269,fafa21b1,465a5540,e5a4349c,1ff0bb26,a660a935,373deb42,f16e900c,f66d638,38113dc4), -S(ffa64715,253ecee5,2ab8dd71,17100a64,936e7d19,3e8230c4,1d06c0f7,b516b91a,1bdb95d,631fa76d,1a8fe556,44c69cfa,b0997ab0,16b256c0,30a7ab5e,fb0de0fe), -S(def35473,ca162629,2f49c77c,2cba01fb,af7c94dd,8f9a21e1,9883901e,8305e3d8,68962e7a,aaceac89,1d5da447,40442b70,f2248b4a,b6b5bf03,f1e00a66,3b0378c), -S(52d2f036,925d466e,45b33be1,8d16ffd4,4b1d191e,10d0d72d,209ebc4a,3f8358c,88a7454f,260b9d74,28afdc59,1ebba74b,710c1b11,ecc755cd,ff482e0d,bd859719), -S(6ab19082,9a23767b,404d25f2,355fccb0,5625b6fe,88bfec66,409668a5,e5c0cf1d,85c26852,95550088,ac9ffd07,dfd972b,dc6f25e0,6509e9a7,92d59b2c,afe63ca3), -S(188dcd54,5c0859ae,6916c4c5,44f3ce1f,7f747007,a6a8d26f,5843f88a,8dbb6b79,9146ab39,c1ed37e4,557aa5aa,c557f874,bf47b4ed,2d2216c4,64b66572,50feffc4), -S(d6ede828,c35972b0,7105bfa,ce6396d4,12fdab87,19f93ad2,cde46a4,219b4faf,8316a8fb,2c30c3ae,88cf61fe,ab875c03,3254a2d2,e1c5eb70,24f83973,3db48b51), -S(a363f5dc,ab07afa1,bb0d93f3,df44f786,4f5f60aa,330afc5a,45368fe2,55df6097,a5839073,c4ebc180,50232a4,a6ce7e4e,b3ac6114,eebf3be5,b978e1fa,7218b660), -S(8ff6e368,f82040cb,9647c91f,7bbc75e1,7a163f0f,7c9295c3,e7901026,e4fcf2d5,fa8fc30e,8607708d,1e2fa7e2,6d4c13dc,3d560fef,c19cf1ed,5dabf5de,8ba890c8), -S(4dfb283f,fcc74939,60d239a4,d364d773,21f1426,b48f99a9,5572ee88,17ac59d2,a6561134,2c7559e8,8b180a59,a0708b97,9e9b381,a1541e0e,a7b6cfd5,b7aec1f0), -S(59c8a74b,ebcb88da,5b8cda4f,1af16c77,ce323f1b,1a9bea22,bbf8a38e,f5a8a6bb,9ec04d7b,e7d56114,f72c0fbd,b462332f,6f921765,93affd25,6a37ef5d,91eba83), -S(9b8dd571,edc71d3c,3337aafe,b3c33f8b,a1a35db9,fb071cd7,577fd5f6,f3a1d3f4,ce7249c1,e00c87db,1149e014,7c531efc,ad8bb3ff,75e51a52,318743bf,74bb84ee), -S(a410bd11,12ddb03,410eef03,ce8ea4ac,f1663660,c12c97de,bd4a2532,9ee2fced,4fa2da11,2c0f4a1f,5520ac16,7809d7e6,2faa8b9a,c442b84f,e2badf94,84368117), -S(6a78a5f8,eb495f28,dfec9329,6b026bcc,f88defff,ebdf4986,782cb546,332fc840,c90ada0f,24723e43,2a7aabc1,931954d4,cf60908d,38302255,a79231a7,93f02f86), -S(1126bde0,fdbf76fc,722bf379,43126763,a3a3fd6e,5f86e9c0,d5ed9eb3,7b9f29f0,d85252d9,ffd674ce,3d73ba20,49fb2b57,f1bb9073,daab3d2b,79bbeb,11bec42d), -S(ecd869b6,4057202,af53378f,a9e57c86,949b2b78,8034656f,912371f4,e5f122ae,cd94268e,b999b0f8,baa47cc7,d84b78c3,4817cfbf,43594655,2a138d8a,7c75b201), -S(deddc4ac,6aaf1649,b69dab89,7650fbd8,f4eda196,ec973025,7bd24cdc,7df2a94e,bd6d69b2,fb809b58,95812ad6,d1a4b029,f3861c52,4fde59f5,ab72a378,8bde28a), -S(4305fccf,95196da2,1aa49916,601b4f00,97e0b145,93e7a6ed,967768a5,836750c2,b997bcf,cc942007,c6b30a6f,a4f8ac41,52b92f52,fb9a3561,2015e846,4e4c4a8d), -S(c6235374,bcf2ad2c,6ec1e9a5,55080ab2,3765f1bb,892991fa,6df94a32,ac0ee35,e878dfc1,7a210fd2,ef572fb8,3ba9c4c7,b7d67dac,446a7066,ae0fac29,1b326401), -S(de7be4ea,50937662,a22a85ec,b2cb6f64,eff08302,13456045,e86d459c,1d36cfe7,b6beae42,d2d26eaa,20ea9941,e7ac5b88,d13e35a6,ac457f39,b80382e0,1c1fcbc1), -S(83faaa90,c129b256,736d231a,aaeb56c,851cd0b8,8a32066e,1587fe71,3d26e7c5,d5aa97c2,9eddce7b,58f9d96b,10a2fde7,4c1ec756,d30cd5d,bac03a2f,f4f5af16), -S(3ea3ac7f,976f5a3e,81cf5ea4,4325c73d,8fdfc7b2,57512f70,236abafe,925c1d94,edcbdef8,de65f541,9c5dfd7a,6b1e03ea,5b15803b,161a403c,8775e29b,7a64f3a1), -S(9a51b8a4,5bbce94d,8ce04cf5,dfe4bb76,cc8eb592,9aba8964,1ec58e,9d979461,661bbf31,86f36500,d45bc5b6,58071b27,9b3d327a,a86108ae,790f1065,dd45780d), -S(a3c3005b,5df20d43,411dbe7a,3daf352c,c43b8a87,564a9891,c237b7b6,2a485369,20603c49,2c90c32b,616fecf,286a13f5,213402a0,c0f8d64,e2a39b2b,bfa978df), -S(8685133d,3f0b48e3,fffc28f7,ece3b6f5,2789d948,68107d3a,4cd380ea,a00040f7,4b07a1a0,91f3fe2b,272d594,9336ff7f,d88d758e,d7c157eb,5e9efc65,4bc52c2), -S(f4512104,eba12a54,aa6d497f,59a256a0,ff1eac53,573c2ad,e480684a,99635bc8,538b015c,a96decb7,ba0ce9fd,b14393a6,7825205b,ff2c712,1f96d27a,3beb83ec), -S(709fd8b7,1795cc61,892ef282,10049b56,28f1b6ab,e5ba9a5f,285777f4,320d88c0,4a742056,abf637d7,e9b75e1f,938778fd,4117f87c,7699a67a,1c08e3ac,a2275622), -S(68a4a2c2,c222513d,b7aadee8,3d05a13c,9ae4c422,6d8ccffb,f6b6b88f,f59bce44,706c2374,afa7cb27,8a95d8bd,6aa98533,ea7fc003,33678c38,65153006,3589db2f), -S(38bfc02c,3430c92d,958b80fc,ba196f4d,9c4656c4,3f667cef,1ce0726f,d6be250f,a05c4f47,7b44a3ee,aa21107b,3a679db2,5aaa738,c474436a,c7dee4a2,228fd940), -S(c2e84b8e,f4380fe0,a674f5bf,3c55d3f9,3b060e08,6b207344,923f28c7,b7935fb7,bf1a2c1d,677595f2,33ae6530,d3bc151d,6b33294f,57d3ac23,78749450,6a0a189), -S(4425f7db,6cf56461,147ca518,732f101a,39c7f585,b5ff88f0,43ba3e3e,a47bb597,4ff5698b,88fa8489,b08c4094,3cda74ab,b5801911,d36232f5,9b358d12,193b3d9c), -S(98c57e63,521541b8,acbbd5c,f568b1f5,d3cd74bb,c30562c0,12518cf,96617e48,f49e42f0,8c236a61,e08d2d86,ec245822,64117ccf,6edb80df,403bf084,6e25aea9), -S(dbf6760b,351925ec,dc6976af,97a088cc,63115fa8,5fde9763,e1524c1e,ce901cc7,909d7429,73923501,e69d1bf9,ba1ad177,f99da741,560af1ab,9cd07e80,7b4f5f8a), -S(b42ef95c,79d167e0,6e29a6ce,ffb76ab5,c96f7455,21f128bd,faccb108,d7f2a609,6a3374a2,5edac6d3,744eb2d6,f39a94f5,44f852f4,779f2a98,6f1de5e3,fd729323), -S(a1034444,997dba07,20de1194,c355a1e5,ce182420,b19033c,ed68dc08,fcc2507e,b2cb95f5,d58044f2,36088bde,cf0d3af7,fe9b10d1,aef8f355,b688c68f,18829bcc), -S(47e80598,1a97f80,fd0f1a14,12d0d1e1,33d7e4fb,bda4c1b6,1dfea483,3589a59a,d33bdc2b,30d0c301,bf85e5c2,c364f1b6,f88b83c4,9e51c9a4,22229b82,10471443), -S(a355147f,281d4518,f36bc6ac,820478a1,6f0a1f50,bef72be6,aa53d420,3dff20df,627a5765,41031765,c3751c39,e9217493,f9da1927,b496eedd,8466709c,4a47a0a9), -S(b02ce0ed,6196748f,cbbc3809,7ec6e7d7,80186023,cf96239,e5a79834,4edcd3eb,f6cbeb1b,2b0b17b8,b620b799,14810a4c,8c47e404,89573b08,ccf826f8,7d8656a5), -S(87aca9d6,450aa411,8f56176b,49646304,dfd5d3dd,84f4508c,3a4617d1,92843418,82a93bd4,b6e4e426,27404ef1,7d837656,e0f876e9,1bb4b9b2,89e678d5,a430bbc6), -S(1dbe7199,bd248d19,5531ef66,260096a1,9614fb65,e90c2f5a,49ce3056,2cc60f29,ea49e29d,60082d51,7a807196,33c55ebf,f243a2d6,254ad322,8d614943,d19a5828), -S(a16909ba,d4fec20a,8b6ade2f,8ba3cfc1,d347812,f35b96b7,9b2910b9,de4e7ea0,496f1a32,3593a23d,ffb5f0c8,d9b599cc,18e101e4,215fe501,41147e07,6ce86a8c), -S(56e18008,832f45c5,30b819d4,a84416f6,db9b952f,84478dd9,243a293e,2d576867,16399c95,8ce72e9a,b2a3b2ed,becc8f5d,c220e632,60a1cc9c,57db3a4c,12e1943c), -S(d32b7ba3,d0af5b68,21d7d716,6f7d827d,f67c2f02,8510ab10,31e4ae6c,2beff031,8b1cadde,54e84e5e,5a0cfe29,a838865f,9dba3867,85016145,e9f81478,a6a20ddb), -S(55e603a3,8081a476,f37d73b7,645f3de3,9db27208,e0d1574d,99a7350e,95c76631,a9c50870,a3fe9f7b,da389eac,963e26f7,51a6f289,351025f1,b621d611,8b5872e5), -S(d8c1fd0b,a561bb0,3d44e9ca,33850198,3163f44a,5d6f3b71,118283e9,bc3c4feb,ef835785,9bee101b,dfbc2cad,7af7b10d,a777e78c,ee9277a0,ba29fba6,d9ee0568), -S(1bcec745,f89f938b,466bf429,3ccddd5c,c8566c9,2ccc25d3,a1cba363,b65bbb2f,b344f901,cd6317f,b4380012,d6fa9caf,64a5f75a,b4347f14,a227ea5d,bbbf2023), -S(8e9825f4,af70c5d8,15dbd92a,148cd259,30372bf5,f86d2a02,e700b156,812cc9ba,3290e56f,6876100f,6e20db9a,723bf99b,72a7be04,a3162d62,386abacb,ba377a80), -S(2581a86b,bd224745,a6518042,add5a63f,b640efad,191ecfa7,a582503,6c5797ad,4f08900b,e4e1abea,63c9fd36,c6939bb6,dc91f066,88ae9318,5049332c,be32e994), -S(d32004b3,48c65b67,80891f3d,7ef8c029,1cfba007,1cf03f18,c0b97cf9,bca71bfa,256a990,7442d77c,a1e3cfae,48a8230e,a03c0889,29c12275,994ab662,e9beb3d), -S(7b6724a5,a0090968,311ea2bd,d3ecb7e7,c7246bbf,b6a0793f,599a2146,faeab5ea,48a676,fe3a185b,cc6f7188,86bd7064,3ec7d20e,ff94b8a3,c1953b3e,a2f8db4a), -S(83d6737f,fee8bd73,eb4beda0,1916f875,85d9fc78,2f726243,f31a2289,456deee2,1d28e79c,c010e982,9a94adc8,35022da4,e9dc67aa,ae5751af,64c53f13,afed61e9), -S(472bd739,ece53ef4,12979f4a,89b6bb45,fad8b374,14478a14,afd13a57,3c315cf,27698c4d,861e5cca,831112cd,449980ec,1d81bef,6a396b6b,fa0da65e,ab164dcb), -S(8ea8e81b,22657ed,51bc721f,2f7956ff,fddab5b5,c703415f,ddeb524a,16123765,a301e8f8,67b1038e,56964048,2dfd39aa,9ba6cf7b,773df76e,eeb46882,2a229c7e), -S(1f931775,2da7d946,b6d9ed47,75ac74cd,6029531f,27487c1b,cfd2ab3b,faa7f6ff,37277158,e6b5c0de,5436191c,1ad8f944,7b316876,ae519306,f28a3606,ec8db8f7), -S(2a6aa0b1,106ddbf8,dceb8988,cfb33c82,4d55af5c,670d1e77,873f4a,ce74f4fc,889e4d41,b885fa99,21b66aed,83f46883,ec6cdddd,67a0ca45,dd12ed1e,ee6ad292), -S(9ff77e8,ce5259d8,58431c69,bf001dbf,fecfa5f0,bc356057,eed7543d,13486274,b8f0037c,c9c3b771,dd6b18e9,95be0ca1,23daf9ca,5bddbb35,a609811c,cd1ced95), -S(7a9b1d0b,a3f1414c,1ab3054e,f9c2fd5c,ebdc1931,ef670d1c,78db9549,6b1af514,a2407af2,ceaa367f,d6d4d733,49d77a2b,993062f3,d6ca8e0f,89d21eb,beab2b93), -S(37de2b08,4bcb4b22,e4643fb8,5f777b48,944a2351,88036c45,793d2d81,c984ee5a,c788ecf5,3900585a,a4226825,f89f9ef2,8cd25d37,565adb3c,a61e1c0c,ce4bf1ed), -S(6c3236dd,a08f2a08,9694f01,a4864dd5,d5ac105c,8c7cbc5f,7d2060fc,b4e8519b,2472d89,10106497,6ac425c0,43714ad7,d5ec4f66,fcd50af4,abcd690b,d219971c), -S(7c0038b9,2f2a96ca,115a853a,557be238,146eb196,8e7b8e88,4801a56a,fc8976d6,d68bd242,5586cc14,49fbe019,deab8a9,97a56dd5,f52b02c1,24e7b8b,141525f0), -S(24449d21,51eec6d2,49d6b613,d1b03e29,3b36185b,ecd95bf1,a52cdeed,890afc8d,3929bfa1,d9648c49,aa4144c9,584424df,895622c8,9a7a37a9,8462bddf,ecde7a2), -S(640d6b44,2c5e0388,7ea7c4ea,17ad3e5,977dfe97,907200a6,a43fb6f7,73848db9,db3d21e8,237ffa32,8d389e4,d93f33e3,cb75ab12,dea034c2,83b5a3a8,c7169b1a), -S(d2372e52,bc1d97b,8ccda950,37148f3c,1516d519,b171a9e3,6a3e87ca,619a52e2,21331dec,da625e2f,7330888,a31be425,9f69f49b,47e38e9f,85eba5b6,fdf4094b), -S(7143910b,fba2abd3,d2e7d7d8,f7c67344,581afa60,cd82827e,547de354,e5299a76,1965b472,4873bb50,c2b55cdd,dbefeb1c,e184d9cf,97ac9142,a49bbfdb,37e4669f), -S(275557d5,46e5acae,1ae98537,8d787b51,73b260a0,57e8b884,7bfbbe2,d15d5555,ca93b2ff,79544d54,8a784fcc,52fc30c0,49337a19,2b88533c,550432c2,6555e47b), -S(290231be,bf6b01e5,7904e066,5b1265d,ef4debb9,d14865b8,75341d98,de3ea5c9,acd3bcca,8ad8ca8c,b7a43edc,69fe9746,50d63593,71dc4d6b,a76e0c1b,bbf41cd), -S(93db5e11,7fe021e2,ca71621,29087cfe,93a2ecf2,560b6c0a,91044253,3dd4e351,11d18431,959d1dd4,8227844f,251a9c4a,134523a3,cc8c175c,f3f509d5,9da8d869), -S(8d346bf2,d4bae98e,ab44629d,720680bd,610f61b,32f6c109,9ef48434,6e3642cc,ab9975d6,3d4dc8e8,e90f2413,e93b2ad,e15f848e,7589451c,a7b735d9,c45f0a56), -S(6d7e8457,c1ac7255,c612d8c,99a1e850,d95d9058,113b852a,4ff0513e,e83e4f06,cade7182,8f92acab,a7d5ad5a,65fd84bc,15c57af4,499607b7,dcdd8c1b,20d75cc1), -S(23a703e2,540ba5d8,dfd5c7bd,183be8b8,a2ac028c,c51806ab,8ce1874c,5f66eaaa,5153dc37,e939eaba,35caeeee,ead1f666,ad62e15a,2f078b42,15cdc33,3372e839), -S(2ecada78,339caa89,a3baa456,15cd0040,9e7e7f4f,15fd5f02,665d5674,3ff48a7c,b2110739,2dea146c,2df5856c,aeed7577,a6bcced1,cddc56b,68462f0,f7999d5a), -S(2516768b,6d6ed0f8,9550c2a7,7167e0cd,34d10a24,7bc10f4,9c7ff55a,650bda2b,f363a634,be194643,68957ff8,2e329184,f2a6982e,51d4cc58,ec24cfbe,f0e6f95a), -S(c958904,ec9c6ddc,37f16d48,b56c74f8,64c547a1,c001e2a8,fadf0a3e,7069ea47,2dcfe201,8111bccb,29ef1f45,827d2b4a,753afd51,ed9927cc,395057df,7591bea), -S(c82c9164,9760ba4b,bed19bf6,a2323fa8,c61ca2d2,d27f70a3,b5798d10,c33eb5d2,531d2f00,be4f3c9a,1c08079b,b7aea0b,c78fd8e,30f5e2e9,27f465f,b814938a), -S(73d756a8,f79d7da7,362dd79c,5c0c3226,45e6d6f7,fe43234,1f6d7208,b9e9f5e2,2a80441e,c1b321e6,3ea1f341,838ff513,ec05a23f,e42b73e3,6dfb4a41,b96580a4), -S(78921b3b,ccd1d7b5,ac721e44,b5c6c8e8,371ae531,d36576b5,464b1fa6,6a3921d9,ade914f6,8802342d,93413c4f,8b67d343,d79252a6,d023f712,9e464e7,111e3044), -S(63ad2efc,c1e11521,139528c1,be3af253,ccbb4f8c,af95b00a,7a6467c4,d682f126,29b54282,c8718452,7ae954c0,1039c1f4,ac7953f0,5250b6be,47cc0b2f,69cbf28f), -S(448bd0fb,d7b22662,d6680a1d,57d81a21,a54256c9,d0a882d2,ed5c6f6a,e1e5cfb8,ce23a4b8,cbf12323,ccd55287,e5c68cf9,751ed0a9,1ad563fd,35688ee9,8c526d46), -S(ad41c647,5145c360,fbf6579,8a54ca90,7fbc9b70,a9323501,8ecc6a43,3ee564bb,c1830237,87a2872c,2884ebd1,f1ae7a1f,8e96ab7,99d1dcbe,eb39e68d,796a5659), -S(65b45a74,13b2e78d,20d1476f,c21ad4b3,2807b174,19eb89b3,fc799f92,7cae5a82,11aed89c,d5bfbc7a,9138885d,f64a38e4,d46a270b,ada85cc8,3a3ed7d7,65015331), -S(5e7db226,92f3d7f2,da0811a7,d0aa0d4f,6adb5651,3ac6a386,7c0cea91,ab212b01,d8250eaa,46275c9b,71f43f6e,cffb063,7b90a827,bc89f513,e769dc00,d5e28150), -S(37fb22a4,7feaec72,7db1d62e,390e7b8c,ed1d20e9,7f934137,1d5276bf,5c1110b0,9a537c0c,8da9c43a,6b7924e5,a6b29e9,17ae9e25,e8afa6fe,926ba053,f591c090), -S(4ec7c867,aff4fa7d,ade9777e,2d4a0793,fe1a1ecc,fa4765b5,aff9064d,98f16a50,433ec3e0,57138a6a,cf7ea45c,f2a91041,2e356c0c,751bb535,1856e37d,295143dd), -S(85b5685a,8e784360,dd1eb47a,9805165c,bf77dc81,56c93b68,54766ad3,87cfbcd5,b866861a,6da7efa1,fd3d5360,2b94daff,c0cbd09d,5707f3c2,b47d76e6,2f2037ec), -S(3a390af9,11caff4e,76bf870d,972465ee,f6f8da0d,c7232add,5ae9dd87,32be2269,f5052db7,7f43411f,ac6553c1,3d930945,a8833641,8af417e4,5033a8d1,a1a52c90), -S(44d40682,4608651c,4fb418ce,99391d55,6d93b631,d489f92e,fbbd56a9,c49736f2,1461465,fed84aa3,ebfc39b2,c1cbd1fd,b7472c43,5c9034e2,82d59c34,9dae7cd4), -S(9aa43d73,41ceef39,1b1bfb31,f620c39a,434e5235,2c14c28,8a50490b,9c62295,ad6272c5,19439e27,5a1c94c5,b3940b23,956d2656,d9870163,17e57d99,3d18b2), -S(1a5d114f,d0bda301,e76f3721,ff1e06ae,fb40cf85,b16c5dc8,a9bdce20,6ac8bb80,cd57ee40,1f4203f3,e1875926,199fab9d,9102a3fa,c851822b,a5bc489,6e1c7cc8), -S(711c1d24,299032bc,f2959c63,8139ae5b,b528b56f,e1a1b829,f7b8afbd,e2effc8c,98bdc11e,d2ec73b5,532332fc,478ab4ec,65626bdf,85287f8e,dbf1d8b0,5f163450), -S(3dc0955b,86e2d6d7,49bbc95f,2760978e,fda7483d,1f3b07c0,7d97ffb6,6961b0ed,f4af5628,d74d3fa1,daa5c072,9c1ad396,1b0792c1,b6fbd235,64debbf8,86d3051), -S(9cafea3,411e251a,8776e3b0,72f11229,8a23125a,5bd995a9,a4655031,9907df23,743b8ad7,ebcb4eb4,9469225a,7a2ee594,bd534c16,a8dd68d3,a58373ca,85f2b01c), -S(faddddfd,96d20fe,ec2b0c84,8ea7e6fb,f89dffa9,efadf475,6eedc815,b61a404c,ebc560c8,253927f5,a928584e,8e87b950,dfe26bd6,d37b739f,b0e9163d,c6312c8), -S(b539be0f,8ed02ba,f7787d73,df02e1bd,3210b88f,df1dfba7,a0138713,8a2d5a8d,e0271fef,2d0581fa,5ca30caa,8a101711,341d4221,b6b0a7ed,776ce399,e370561d), -S(5e3634d9,b7ff4279,3685022f,d3165c03,2ef8ed0b,c8a7d02b,685ab5ba,8557ac03,565b3913,355bb664,12225097,4e33e9ac,27cd38ed,a804824b,83985011,60f44200), -S(609ad796,d50d20e9,9cbe6ec,650eba26,ceee3c56,a6889917,44deafab,6a7a5904,54f9351d,9aa7d0db,822788be,bb1cc2eb,3300c144,1c7a4c01,230b47f3,7e67a9a8), -S(6ed020f1,fe8d7e4,73812756,3325e0c3,290b9a5e,d2723929,584f177d,4d9d429c,a1e48a25,b02ba024,eadde7e0,ea82c900,cb297d2e,b550c289,d664d4a4,b9b85edd), -S(5083663a,afe468d4,ec901e5a,14d2593c,b28c5948,1fdbca52,347d6aeb,4b7ce960,6aa5586,7467c6a5,dfc41278,c855727f,7a8b4168,98bdebd1,f9c6a918,a1d31aad), -S(e1c334c9,e355ae43,7e48335e,691a2aaa,64c3bf7a,16c77810,6bfff582,2a324df8,4603f15a,d7c85327,15502c35,cbe0ec58,e4ba8ac3,d038c4d3,ee3b4b77,74a13c07), -S(8c51fc03,ca1ed69b,4b627be3,3a7943fe,e1c15c47,ff7bc83,89961e40,6552907e,2a51ee78,7d48f8e2,53e82deb,a07083eb,b9513615,7f2a796b,c040b1d0,7582033), -S(4711e429,d9cd2b6,e539eb68,884d2a97,375c2cbf,fb30d6b4,1718eca8,9f3fa41c,ce826e2,711b6e6e,9a487a8,4ae72f80,a5308c21,1db0ecf5,706abe6,6b0565a1), -S(277440ea,ae6a1839,6f72ace2,c5cbc75a,41866c7c,c761bf3b,7bbcda07,ef5558a3,345f1584,9e4ef4b7,31964dbc,f9f899f1,def99279,ac2acbaf,3d1eeef1,bfd0685), -S(b9d1ebcb,91db7845,426accc3,578ec4d1,6df30fd2,9650b47,5c154d65,7a23bd5a,ea0ca814,399a76b9,5107501a,40ef0206,ddb1e9f,4933399e,35db6385,3dd2cb2e), -S(29c07ab6,e703dfe2,896985d,4d894d5e,5b793b6b,7ef2f5f6,dba00348,a8882fa3,7565e4e8,4b5485e1,661bb0ab,4b672cd2,5e9d58d6,48049ac6,8f2457e1,98b04a8f), -S(b9d17c46,9733963a,2f20626a,ef4f2184,6da791b,5e63194c,128432f5,58ccc682,5dcad0d8,7e08bfad,43e55633,3403f5b0,76482dae,d731e01e,3284c945,7c6eacee), -S(961e90a2,904e80f,1be65717,a0401722,6821876f,fecfa598,b216b04c,b4645c8e,5ab0efab,7112254f,722d021,a4da595c,99429a1a,5b242b1b,9243a8e2,54acd804), -S(40865cb6,f002104a,54a45d9d,da84e6a8,f98a3bd8,364275ba,4e14554e,2438f6f4,5b822fda,eb719e33,75309c75,b7c115af,351de484,98867a13,6b1fffb3,1e277d7b), -S(5efc3d76,307a2cbd,34e7d009,92263a44,c4e76e50,f1c213fe,b7fd6ed2,342f1a08,40bcc04b,cb227f3e,3cac4a7f,446bad6,6a304df5,a4128bd5,46f9f40d,a3e12f46), -S(13caf790,6a97e5ae,6f674956,c1586c67,57d3d56f,3d18d522,c4f365ed,97b54e87,156a85ca,74541ff2,9489b562,28324549,5cc42397,c54792e,2ba485b4,a86bb65b), -S(657e9dec,84a9120a,308a5235,6555c56d,6c1c98f1,cd946480,def7913,7e50f7fc,600ce754,7d74b757,c1e371c4,73401734,8fd6dbb3,72019f10,bcb4f4c0,bab1614b), -S(fec2b1d6,ab46c020,ed672687,7f2ec85c,214f36bf,149b2c1b,e75ae29c,54050071,3ec9964,20d9954e,edd8848b,c439fce5,740ddb41,c404c52b,f76865fb,26c48b8), -S(bafc595,37308fb3,c691f1e2,45908e92,776d76df,f6af7002,c581afff,320a4abd,2d8b8ef1,aab42751,27d0ba95,dedd27a0,29951664,e7ab9d54,b3a4a24c,faa3e386), -S(927cdbe3,2c1d78a1,89a4e3df,4ce6661f,149d7e16,d0cc7dbf,c287e492,891540c,e46911dd,cdcd70a9,f99f6892,18899fd,d3ff666,ae4533f6,dcfb441f,2b7da62d), -S(b443d061,1ea3a164,2e31195d,111bdb01,b6a3999b,e4377780,e19c3614,c0d7092c,e95b7ecb,e196c667,a19dbd2e,ff0115ff,9f0ce1a6,7f44d20a,a47d2990,e6b48c64), -S(e1836c7f,8b7dd235,f6af1b89,b7a13ad7,22dbad8a,78b1b37e,f6e5ff5,a6bc992a,57b02ceb,713319e6,9ebd7e6,844f374c,5871a792,e2109eae,d2cb5222,6c314e8d), -S(9f661b3b,c5829c51,2fc613a5,ad8aadb7,5c78edb9,9b84de7,683c6de9,d2a93f78,70e14e0e,558e94ac,aabb847d,3acde465,14c13177,45d45226,b6ca9911,f23ecd6d), -S(e835b453,6f13ae6e,7103137,bb695ed9,4d07507e,9fee8f9c,af661e9c,1525d3e4,192463e0,f1111a94,9f6236d3,1c0d6620,af9e0a3d,1f13f83e,7c4adaaa,76c81953), -S(a29fe97a,2ecbc4d4,f7156ae9,d6bfef6,ef601e26,4f92a115,48b5cd26,7cb26b3d,23b7d6a,15681341,6e1b8fb2,cebcbcb9,698d245f,b920f8eb,3d6b46d8,9cd25cbf), -S(396cf745,6127f3,31ca0fb4,95d98b32,7a738a69,260f7345,9eb79f0f,edc6a7b8,31b6ff3c,26879dde,6ebc9873,22a32b10,e283a256,1c1a65d1,928d3e02,de2505f8), -S(d1bd75ac,c37a3119,8f768b38,f665039,7d2f331a,32018a66,526058bc,aab440c5,5c17fcc5,b8e2500a,4edc3cef,ced52f2d,e20e7c41,bce4fead,8e12a880,aab8a185), -S(de72076,62274020,1791b51b,39fdf2e,297b7c2d,d358ac3c,375dae4a,494df54,d33d439,d4508520,6021c95b,cb1b22ba,b1595800,54056f86,82d73580,c50692e5), -S(958e9c41,4b096f8b,2d1ba41e,f5142a17,339cf57d,689d7d13,dcc22355,91418331,628b63d1,4e4cb154,a31d9752,9e50a1dc,f2684b40,47c27c39,bd54a0ff,dca06ed7), -S(38bae438,9a283e43,283d6a06,94e7ba16,b026dd59,3b505a09,6ee0f67f,eaaff536,9fb69e6c,73b27204,30968157,d5782423,cd4b7809,f09f280,93f5964e,6c06b170), -S(d620240,753af5bf,f1719165,f9d8116d,54c97a2b,5f99b7a8,97eea7c0,428dd1b5,66cd4f98,1b037f95,eeca433d,71d37fb8,b4a53f9e,853943a,ee0f5254,e42d89ec), -S(7de22847,c93ed32,6ff056f6,a002a7d7,e5d13361,e2580ef,d2cb682f,28e6ab96,c40be4d2,1273633a,e0ea9448,4bbf29e4,2b9bd775,b77802fd,31167d50,76a9b34e), -S(df0b50b6,679ed759,35883080,ac9196e9,ba5844b6,d9e541e2,bedb7693,c7af37c3,f09fe7aa,bb08fa37,aa5413f5,e17dc1e2,a07f83e7,4aaf160d,ad3ead56,1509e152), -S(578581fc,184af60f,80d648a6,97ab999d,f5ddec3e,b6046528,b9fc6233,7de81fc3,552be39,a8587bfb,d8de2f2f,6b923fde,20c7ee70,3a1c0c09,12ae85b7,56495ed4), -S(cca6a75a,131b5389,b2f8ae71,7d1a9f5,2258d3f0,4ed22b2,c836f7ce,3035def8,1787070,1bff0d8c,b74f5f95,1c6e011,f4e682f2,5d744f98,4c351b64,59669a4e), -S(6f81f602,b2054706,4a7c7b12,d5f13022,8657a77,e0bd1669,ed1541a4,b8eaf068,6ff959d0,1288bbb3,eb7a59b3,2eaa8945,8e4c6754,2a9bba0,668bf14a,ebb308ee), -S(90725203,94d2fb81,59e2ce17,5fb27da,7239f36f,61c70250,78a69c12,27fc0cd0,34a471f6,eb168b59,4a6a53ab,b93bad33,7da670e1,8bdd1eda,53b34849,94c21abf), -S(4e952fb8,b5e484b6,4ce1c1,c66e94de,3bb3a64f,26585c03,969e834b,291e597b,f7910643,47cbaa3a,e88dd796,ddac4794,c6500c76,147a26f9,c8f596b5,50da9961), -S(1985193,527e87ab,5b7dd218,718486f,1ed4b7f1,a444ee6f,21f273cb,901aa0f3,b067191e,df69ed50,b0771d24,2d99c8c7,22f1bfcc,bef31bb2,8d245f3f,b0acd3e5), -S(5dae1881,7a2bbb01,23561907,a22445,78e4dfa3,c6373f21,efe3f159,58abb5f8,7c6bd578,301ea8ab,f2b555c,66420c77,b84c6959,f96938af,eff54db5,4014d51a), -S(96a46ff6,e78bb2f0,4b299985,6d56310b,4df9702d,7306b30d,cdc7ca4e,68114e77,3f871bf5,d3a4ee91,17653bb8,5a98e599,d86ae580,17e8963b,9b18400c,979994d9), -S(31482d19,6ce07585,bc1268cc,a355df50,b9009f17,fa1e4f39,9876fe2b,51eb361d,50dfcba3,ce43896,1fc51f06,5ac4e58a,4757e75f,419a9525,5263830f,fb936e9d), -S(94c128e9,6d36f7f9,540da468,a2fd488c,ad615f6f,7920b201,27311941,db6e2405,595f29f0,f9622e32,b62e3ead,9f9ac21e,d07d7c07,7bba623,6c7e57cb,747da989), -S(a16882ec,b52def37,227e2990,3dc15e4,d4bf10ca,1b1adf31,c9cace43,348182bc,53f6d3d,6dd5603c,2f2bc7ab,677a6133,c138e26e,c030ee9e,705ce002,62e11f5c), -S(f0f5ef2f,f0f63cc6,fb7b3d99,6a5b14df,99a53a45,3a1fa425,3ff3ce71,4168cbe0,598b5ce,44e168c3,bef06c4b,c032924a,da454c75,b53d17cf,cdc2ea7d,93e3b883), -S(3aceda5f,190d83bf,f5111acc,d57d4d2c,5b7692bc,62f480b9,f5cd539a,b2ef0c1a,5b8f973a,16151dee,92930702,f3bc7f1b,93a096a5,ca4ff3e4,8a41bdcb,f78ba60c), -S(4e1eb580,b3e3bcd4,4b2905a0,d07d7334,befcca94,c7cbf639,1710948,cf2e66b3,c1d6ad62,c10bec2c,127446d5,34863682,196ce8f,4a966319,2be7764a,46e733d8), -S(322fa340,76bee9e1,697206c8,38cdbbd3,d54c3a30,82c22b3f,1ae17da9,a9047856,c4493e49,b5cb97d,eab7ccae,8f1547c5,98e286b,5e7301de,cd50656f,25dfc1ca), -S(4aaf3569,2b080f70,aafe6374,f0007570,d23fb620,cbb60a43,305f5e3f,29e9d189,1dc30c11,91f985c3,39bc8592,8390bc0a,c99d3efa,98f4bfd7,df2f86cf,7c297dca), -S(c18629a7,17d1b01e,e2f4bc72,2c86fc26,878884d9,a770b62e,d7167f83,631ff2b6,3438211e,bd80ab41,dcd4e76e,c742aa3c,1c859cb9,1fe0960f,eb0dc74e,d119a7e6), -S(239f97ee,44d77679,7a91a196,82c9064d,4552b4a5,33033377,6dd74ae2,fdef44db,dbf917e,c66d0b04,a0bd607d,6448a678,1821933d,26d51865,35d3d587,ea680a96), -S(c0fde604,387fa85e,5c5cba98,346042db,83a64e6f,103d7448,22b6298c,98bc7100,28ad14a8,30b7be30,58ce8e09,7fdbc87e,a3c60b3e,840ad9fa,a7cad01d,b83a15ac), -S(95ec759a,5526cd4e,eb9d00c6,9702dd89,3ae115fa,de3629c6,5fcf5134,2f389355,2f899643,711c5f72,8fb442aa,59139fa3,b1b0b4a8,ce75ba07,67aa958,eca943b1), -S(7da3bc4e,867885e8,febb8c6a,e5da50e4,55fa749c,adbc5800,1b70ebc6,96ee9b89,dd989b8,c4bc42e5,8b41fcac,bc1e1f17,bb77aefb,964bfe45,fbae0843,6dec8cc2), -S(120fc1d6,12db86b9,f352582c,e2761ad9,8a29444c,c438e2f3,5f523d83,e2bc3d,437828d4,5357a2cb,ffad57f,f991e91e,83466aef,584dd7b,a3b24d9,31eb6cb2), -S(50e42888,366a1fe2,83cb22d3,df324d3e,e52f58bd,26bdd4c9,67575f7a,5adc380b,2fdd99e8,427f9b30,1e132beb,3e0fbb43,8e6ffa8b,147c825b,e4453fbc,1318e015), -S(275dbcf6,ab238c94,740100b4,29356528,69de76a,9d84d7b4,9b88d526,9b8d5339,90e835b0,f20a7177,936c5717,fc18d0a0,28a31e65,53c32be2,699ae03f,6ef2807d), -S(59d174a2,bb918007,f3e044b2,7acf5e6,8264d529,cae342e3,fed00475,d95b86c8,dabbd87c,b49bd118,a663a848,2f7b1c51,9fcb0fcb,48f2f966,7a13ab2c,ab122860), -S(f8926a6d,5d824029,8f572847,6439f60f,528cded2,2849f182,e173f84c,cb75e1fc,8c641986,c4fb6a7,acea7627,e4f6872,26f86de0,a2160a63,1b2e1a26,9fa5f6b6), -S(d765faa2,b9cdc6c1,d9f070f5,4fe286c0,60351c66,c7a241bc,94d10e4c,7287e7ae,ff732ad8,fa7f0c3a,9ced3ffc,f5bec9e5,2d1600eb,4ce4d781,20481559,82c30ec4), -S(bc83f94c,7be686df,9caff340,35c6e393,1fc2a33d,7a09fe0,b5d09e64,a0610dc5,772d167,e762b3bc,df68c291,656a4259,cda67486,e430c7f5,492c66b4,b3e61fb1), -S(5a8b0422,21313e22,c5a2cb24,ec6199fc,a4e95da4,d5f59629,ca33f4e1,419d5626,2f609bb8,966ba692,84fb6854,5dff5b2d,f1463504,5bbfb145,4fbf40df,c9884fd8), -S(b106e89c,b4da505b,912da09c,44f42d11,a2de8836,28623cf5,7f27742c,a3852a97,90ed9bae,78ce94c5,5e4e971e,16013f9e,6902838a,f7f851fd,100c8e64,babdaba8), -S(c55445eb,439db24f,deaeb4a3,5a71ac1c,8915b051,350d4007,15cb9d70,2319b0da,98b517e0,32c9a963,f22e25d6,f3306f91,a4b604b9,6591729e,64b73794,55d0137c), -S(f05845b4,5f975462,e1051499,d8189cba,89bbd435,6ca3ba68,7b9994e,81dfefac,11511fa6,126f8d88,14c5de2b,dc92bd79,9a466940,3ec8a5f6,f445c59d,bcf779d7), -S(35620920,f58bace8,7dc7f750,876b59bd,980ad703,b3127c3,ba53c20d,56fb5755,759d3f68,60643a2f,d6c946ba,5bb70f61,fba28208,77dc47fa,a4d9ae14,9d6ac9ee), -S(f70c93ab,7145bcdc,2ba3a9c7,f423da0,26a39180,6dc3686c,fe32408a,f659f918,84f71fc6,818151bd,c620e79f,a2d380e0,eb37391a,4a56b919,eb14b2b,cabee697), -S(858916af,74216be7,beb2dc10,47f941b5,157d7f19,c9b60900,bc844703,79b4bd3f,77b78d3f,5fc4e872,3b7cec8d,8653ea2f,298a1057,88bb4cbc,18e4fc99,108620c), -S(4b690a4d,a3649304,96fbeef6,da701b8e,569e61c1,6456659e,4c229813,d7118d67,d64261b4,4f26a263,55e787f8,fe2fd5fa,55f44b29,5cfa9c2d,8cc90830,60ef8b69), -S(37542949,6cf4e6eb,36b733d4,ecf1533d,4ef38ed0,768ff1a5,58dd210,ef8d950,3fac2cbc,a4280d61,1e30efcd,cccd1392,374d351,ed9dc460,61041741,2d0efb97), -S(870a9ee9,e2a00f61,af0d1f0f,967971ad,c5afef39,b52a3d5b,de74802b,a39cec0,a4751ec2,989ad16f,460f3071,ebe3865f,3319bbee,7bc7c285,e8215ca7,831a81c0), -S(28c63e6e,99936241,73c0c5e5,7c74543f,dcbbb678,bc786746,809d3206,3c0bb3f3,f0c610d2,e268cc32,3dd39ec5,51723b9d,22cbb5f2,f59171b,14771bf3,a4ec7183), -S(1045176,321bf271,cf34eab,686d3ec1,26000d6c,b1e66d55,860cde39,e5b00885,2cdaf0,11879aa,10231e46,ac93baf1,7bc92067,24f97521,7e2fbde5,cd7dda17), -S(9872ed48,bfef1218,35ff27d9,168740f8,38c2628e,15dc1a17,d5c72ee8,df21aa5d,f744a757,b922361a,3976de72,7ed83300,885cfd50,5f6be5ee,2ef9bd5a,1823640), -S(12f16ba8,5a2833f7,1af7244a,36228deb,38075fe,222f4d6d,6c02744f,b5731a9d,5538557c,f3d2b832,77db6634,8119a3f2,9e272b9b,bad3dce8,df38c3f8,33dc9095), -S(96489f8b,407618ec,698cf6bb,1366664d,7f14cde2,3d3417d2,80f0a3e7,cec87c23,4e78ceda,5f034e7,8eeee63,bf263fd2,35b8d60e,93263fe2,fc2acc89,fabc7728), -S(5380517d,3a681527,cc2aa8ed,29075afe,9eb0660f,cd4d381e,803ca7fb,2bea7245,d37ef6e5,f3c824fa,75ef185a,22d6e6c8,d8ff865b,433388b1,a6e6cd7a,4bebcb1e), -S(2f33b34c,3b22eb72,5d27688f,96f94ed7,23c840f7,549063c1,386e447b,faaea56a,c86fc369,59426e76,8f005d41,5c7316be,bbf1bfb2,54add259,91ad2961,8e9f50aa), -S(cdcede30,e227f45,18d39336,204641e9,27a61c6f,801aa002,5f892be5,7b49e574,dc3b0562,5e5dc396,26c1ca3f,5f2fa1a4,dfc28dc0,18d6ca0a,b21966ba,5d1ece42), -S(a9642c56,2e284ef9,5cedc32c,94c55dc8,3768344,e7317ce7,730da1f3,c6ba501a,cb3bc00d,de25189c,b8894fa5,219eda80,934941a4,8dc8e140,9b0d467c,ffb1cd95), -S(32b67c85,f0f4219e,2ae8e63a,ac95b210,32674730,6a37317a,19a52235,73bb7641,d8bf9f41,e584dfc3,de237e70,79cc170e,96c2cc6d,62042157,ef60ee02,3d142213), -S(4d095001,ec45ad22,1c9cca7a,d588dbdf,91156878,688758ac,63514992,128e50f5,c66d7dd9,9206f339,e0b80e51,f6ee72d,619c77bc,4ef33b46,1c3b8617,7359fc62), -S(f51d320f,bd158ea2,71cdaf12,651e3eab,e7deff0b,434a8b06,b3b31f4d,f6d6547c,7233df17,a17de7d,3a87118,97006ca7,8c7cd5d4,7a86403e,24f050ef,dcf3bff4), -S(f0dfe901,237b4b5a,ba6deb8c,39c87cad,5bf4dd5f,6a5e55da,d7565ded,c4e50089,eab06c8d,6bc7801e,7aea2e6c,919db667,324f0377,ea58b070,2e87b10,7857130f), -S(2921d36c,4766c1f,775ec19,302f5690,3898a835,aa8dadad,6c8202ae,270e38bb,a79c8e4f,cb59c784,3f81b66d,57060d2f,7c7acecb,c2399191,b7f98ae6,771cf849), -S(99ad0478,e840c3ef,470a47d9,ff66a197,b62881a1,6189d9ae,13d8bea9,3c1c0994,3e9fc2f7,d37d580c,a16eda71,ff6d1995,47f18ce3,515adca9,c08ed241,d1607f82), -S(970f064d,32c1eadb,b42ca1a,8893dbcb,dad1b9c6,3b99a15,e772407b,3aa1489a,efc34e6e,38e29927,9ee73b0c,9970cefa,f471f130,9518b8c4,81e7f67f,ffd807ae), -S(8d995e26,e9ebcc56,d2f9637a,df1db60a,e1b51d12,9850edb7,ef020a2,7ace35b7,1ed723ca,17892eb0,63ee5164,ee8e7216,96a3c3ad,67a3d8a5,a0d87803,37c01176), -S(c650e8c8,f995291a,a1feb490,dd9ae957,7506f591,c308b423,6ca005d3,ced75866,505e36d9,2ab967e0,a1168424,60639c72,646b0569,d3651800,316126d8,810a9444), -S(aba9f9d5,ae231382,b3583971,c875f4fe,4c51007f,6d55e1da,79d7e369,c21964fc,e6a176c8,34fc11b1,6f270f69,f4f54f1a,fab4729a,20cf6348,9cdbd551,ae5d1fb5), -S(1068b9a4,19f849a1,5dcef7d3,9b3b55dc,2eefe04f,554f283,212b489b,79b79d69,20993e51,4344e2b7,28188465,340b28c6,5331a7f1,a6aeb6c9,7f09e9ee,701f3828), -S(598358f1,cd3aafb1,9328dbad,62b65232,4aacc23c,87b37271,e8604caf,d69fc3e7,4297b258,6c94df83,6fe6c528,fd1b8fd9,62969227,d854e09c,375f85ea,58cd78f), -S(d4a638b0,1ffac322,48dc1844,75e3d06b,3b6b9a4e,971c7153,da49fe20,f44853dc,e9e708a6,5bd3b39b,15ca6606,512933e7,97b4adba,e72cee79,c79605ed,cf601d6f), -S(38421e4e,fc54951,1560c7d0,dd947c84,652530e0,d5155ece,8795936b,83b5e115,cbd0d873,ef6c0d90,9890b820,e8c063a2,35d2071a,97cf73f5,74ef2ddf,83ddf168), -S(2cbc4bab,442eae5e,aca1cccb,4a589c6a,8822138d,c3a35885,132dbc52,7648712,174b4deb,3b28ddef,426aa586,314b7b62,4e9253c0,1fc2dd7,ee94ae0c,57d3f5a8), -S(202d232b,4244ee54,3fb77958,32c149ff,8ee9a4bd,86c02037,634f5254,9f2dedec,67d64143,1915831,bef7e85e,f057ad07,a6de2cd4,3578ba0,eeb5cc70,1d16a499), -S(4faee6e9,90601af2,3f204f8a,615506a,82288490,a14f692b,86c8585a,52b4c94d,b45c0547,98d18942,7349a87f,5abfe689,68d14f82,d5ea836f,131ad030,ad31c8a6), -S(976db42d,c73a4705,fd782bb,2a87f260,19f6d218,3da3ef97,e0e19304,87ef7b42,2e543c4c,721512f0,81c7a6ef,987776cb,11318c52,ae6e2883,7d52a160,d183c31d), -S(9dbbc369,218c5741,36a0dc48,a17055ba,2a8b1580,88932e85,9a0b8188,5cd11309,e93dccf8,4dfa1519,45f6f38,d634a21a,b431f21e,ed8fd004,e27ea99,4c9d648), -S(660a226e,48ce5825,14c0f49c,d27621b8,f52657b4,17b8c1a0,ac9ecd0b,b9e0cc16,6d2c4b6f,74432c0b,ca351ebc,27a72b6f,68ad7a1a,8c509d8,8308be90,d7f7454f), -S(2ccc9a2,5c61d492,5293f4da,cfcbd818,11bdc998,7aa58258,f161210,40773237,5abce831,b2b09a34,4d93a77f,b8bbe8e7,d6334cd3,be3fc86c,154c74be,c191e9a5), -S(dd9d0f81,6c41936c,fc90cf9,3cc8f14d,8494f853,2b3b72d5,95d94742,8a01a4b,f30ca0ba,3db463a8,2b82b1fe,3f310936,c58906e5,ca07e4bf,9f4482b8,360ce7ba), -S(1314cac1,d751b3bb,c867e592,9df56ff6,99f810dd,f76ea0d6,f68a3e7b,4d95051d,8d3631cb,226a854f,143c1d09,89dd1ce4,7d943432,43060f78,ed3af3e4,f0d8d41d), -S(b1abd6ee,fff64a72,83c26a60,be0d1cc,f5152df6,b85655d0,9495d405,f2ccffd1,549457e9,b4f2edec,63f81471,12957918,baf8deaf,7d8a4b1f,489c24a9,44f210fb), -S(5d8e23e,1212800b,56e7740a,2f20c402,6483ce0f,755e36bf,fc4ee667,3df1b32f,973cab61,da46c5a8,6d1633ee,1fa28892,6e1d814b,800762b4,e4599ec1,803c0af5), -S(ae0bfb9,b5567b95,34510cc4,ad8dde2c,50c1dc53,6c9ce5e9,ee97fc70,f8b4f562,a8d15459,7fa1a816,3eb33c40,6b78ff19,b4927a3a,fe48a8a8,1492884,46ced08f), -S(b2ed6275,b818b2d5,ccb807c5,262d5578,c83743b3,701217c1,8188ec52,bec10325,5281815a,b21491d1,62e0b3d5,1334fbca,54731fff,f5d44ac0,396f477e,ab566896), -S(5d5c034d,228aeed2,270dec13,deb5418,3205a996,509211a6,8884c2dc,42d7d7e2,316c32ad,36906509,2e0112ef,eef93269,e251f83a,9ea7781f,ad59122,ae2ad4b7), -S(3d94f70b,39605f40,23107882,b491cda5,6f1b9ffb,3fcc47,51e4309c,812c428e,b3de1921,d29a77fb,ae8c6460,c3ecf92,22b88c4c,3a96cacb,e4385416,7898d7b1), -S(5c0dc575,84732fe0,5098de0d,45926c0b,3f8075d9,2ece92eb,f910263f,3e0d6df0,34c7fbd3,171b85d6,65bdd9ae,30f671f6,688a55bc,cd68c0e5,1153348a,16b75a88), -S(15d25179,6b55cc34,5beb9bbb,f6ad1aa1,b11b60b7,5bcd80a3,2a44c180,879e3513,46632865,ce1e74e5,f3a89a58,35adfb01,eec8e0f0,34b84aad,a0d2d901,ee07fa81), -S(86e5faf9,dc091174,bad52eac,2c83f945,3bfd9f82,13505e10,323255ab,b9e8d0f5,3bf19876,8c8b5f39,ba25a9ff,5d112600,956072e2,7775af11,52bec5c9,7b2396ea), -S(308c0956,4ee3aa0f,792e8630,3ede1407,d3d3da3f,423408e8,7b0c5aa1,2d6aef57,7c39d220,975a21d6,5ce1e2ea,930bd585,203d9b45,bf5f2eba,ecc5b245,e95f0abb), -S(19f9d4ac,c7de487b,cccae45b,2515f727,196911db,d799c7f2,a68078b3,181099c6,645522a8,adeb841a,81e27714,ddc40585,81cb8b24,e7d9620f,c940590b,b14f14a4), -S(a05d82c2,4493370b,cb7f1639,16865c71,3e89d968,8c96919,ab99ad92,afe96a35,1576f727,6c65e32c,1dc1ad98,2f75749b,75589cd1,43ad60b6,2163a8e9,87cb35), -S(6453661d,303acf74,751bc7ae,e8226647,b17b5808,f3f8dd63,4c00a78,94e830b1,145993d6,ab6592bc,b6b242d4,432be395,de7d0014,479aba5c,88a48cf6,adaea7ab), -S(adb18972,9de87486,3207f954,4e3eeafe,fa255209,4a8c0170,44a952be,aac0485b,2c67657f,d6a2b08e,28463e9d,abf708f2,2c790aaf,907af16e,598f325d,f657211f), -S(8a6ea198,371f94e9,288943c0,5e387cbb,b2071935,3562fdd8,f9fbe899,ac31ce00,d5b817e2,4f5b3fb,e25212a1,fccb6e1f,1ba55211,ff2e0123,c71175b7,bb94597b), -S(9e18eaa9,621ea829,38505584,a5879eff,446303ce,9cf61bbc,eaa6c495,7f259778,3310042f,54b5ae46,1c996f45,abf27c3b,5df06779,3c931927,4689da07,46254968), -S(27ec08,dbc47af0,d3db2aa1,a3b4b22f,5cb42750,b4ad6680,9815ef21,ac44a8bd,292fd5ba,9371d8e8,d4126197,18bfb564,2ed1f537,3303754b,af6a77bd,271d660d), -S(4ab3436e,34fbe37a,aea7dfb3,70d93352,ff4a7c22,53f1ff2c,8453c5e8,cadec2c2,90221aff,faacaed6,760b1c91,50eb695c,a1117054,1ee068f3,8c684e6f,b005b406), -S(46d75d8e,b2b5ccda,2d6819f2,1338b125,61a9c872,1d8956d5,b9c73148,4d928895,8153db74,27f7c4e3,381567c6,e2629702,8db4a5ac,c8762ec8,181a5da9,b531b6aa), -S(469ff047,7ddcf32b,a0c71766,474b5730,3b687406,c22e51b8,9f5fcedb,d154e270,acf0fde8,b426233b,20ffe9d5,5d1bea51,5a19a9ca,dc642a02,6928c05a,e068f747), -S(1d0a4e9a,ff31f94a,456c974b,ccd5169d,594b7263,5e817f29,4ac1cc45,52d3c6d5,52d567e8,1316fa28,1c2dbe62,75e51bf1,32f2a573,77e0825d,eb024a1,8e637683), -S(d1f25e6f,5038f784,84ffb8cc,7b5b67ce,908b3050,371ac332,228c3f79,577e6e3f,6cc0b7b2,76a948ec,54b79662,6fe435f1,5c68abdc,9fdcf8ad,41485a7c,58291f77), -S(56e97220,8d42989e,2a0313ce,203dd87,e8bdd09e,38bcd097,6e3d047d,7b8eb385,c78f2ca5,93d563d9,6caf585b,25873cba,3f4d1f31,3e31fa32,df2e9e0b,7538cfa6), -S(61f040fc,eb4db17c,7675ce64,73721c47,785e30f2,217f03c2,5e1fd723,d40644a1,950c39d5,1994a902,e637cbba,e0afa218,50e5b191,ef5b5939,3257d67e,555a1d3e), -S(ceb5f3a4,e47483e0,a6137f38,1ea23678,81c3df5b,830f80f3,1a08a3e5,e5181f0d,6a31aeaa,7533fba6,7e79f63c,abeef7e4,f130f37e,1922f17f,af20a63b,51a1c485), -S(d9b195a2,dfb91ba5,814e54f0,3bce3f30,6b7f880f,594e8dff,684cdf8a,bcf63634,130e6034,3fba9959,898d4227,a8b4e79a,5a4055e1,a22cffa9,8b445c6,4684233)}, -{S(5e8cc841,c1b251c5,317faaa,89f6c9b2,107e793,4abe27d,adca6318,38a9ca72,9c1c881e,10e9f194,e00388e1,e2414f5,74946554,d2656ceb,392dd6c3,611eb982), -S(498fb0a5,c2a2a7fa,2e89a846,d7987897,b3e843f,8d664911,277c85cf,3ad0c128,c480af90,6f0aa1dc,8330d211,aa409649,3da0257c,8d09d5d,8b1aee13,f7e6f26d), -S(9060ce66,41a763c4,8d0948b7,670c1d71,1ac2a81a,431b979c,946eb25e,3c8ff8f2,567b9831,a2555c20,6dfc4c41,9ea75b99,d02a00fd,f3942ea7,e27c44c5,98df4d7a), -S(b528d336,1c7c3cd5,5480aba,4421c209,cdc234b,f948593f,98eb3c2,95a18396,1326dec0,490078f5,7c541200,9f131410,9fff1f92,eea82577,2fcb8834,c59f0c33), -S(5b0e61ef,8c9ca491,83508642,8cef89f6,75f49ee0,f33fc8a8,5783e6fc,3b4c59b7,bf1f0c2a,ebc45330,1d12e8f3,43b4d3fd,df0e40df,b78cf093,bff413da,923f913f), -S(22e892c2,258575c6,e6ba67f4,e0e36853,27771a2,28ff9ecf,a2efb43f,c9f1c7d9,2b20a268,bfc51047,a8b28952,795b91de,624a3487,9abe535,3cfd3a11,87a86493), -S(70bc895a,ad0c993c,25155e97,9d9276f4,8227b6b6,d7a31bb4,b64a969,8102e886,7c0be1e8,f268015e,987392b5,15f60d04,d1453e7f,fd5929b5,2176e24d,ac10da80), -S(1dd63c17,421bf994,3a85019f,777bd41c,fbea006d,d4e0b80,2effda5a,8591b87a,2fd392ce,2e25e393,9bad93d5,616c65d9,87718cd5,9b8cfe4d,e54473fa,49c86735), -S(7d3658a6,df58d88c,7ea92964,3dad19ce,12f295e7,b8b4e710,9b9297f8,ea83a088,6ce3e119,496fe842,f7e2fa75,b635c11b,bb4d00c3,843216bc,82c31cf6,46d9f715), -S(aa02cb68,5acd4d74,f2c547e9,43aa7360,6a960d80,72aac984,b44bb492,e61b1d94,1db77713,702ed407,655dc5df,55ae0329,a30aca7b,d5655ebd,91dec954,feb0e02c), -S(e015e1f2,10b7eefd,775369b7,64192078,edaf3118,9d7a5382,28a744e5,5ee7f068,dd69db3b,a82ab3a3,86e1f09,a6c3b8b1,37b48021,a560c0c0,a8c910c1,e315b721), -S(ec50fee6,402b79de,afec1f9e,25778b95,5b36273a,6974963e,3cddb748,1166bd4b,21b5136d,2a71804c,6c90a89a,70bc05f6,afa26558,ca1aab74,610cda3f,7adf0f03), -S(213d69ae,6ea3a73d,3566a2d0,10f6c42e,d0c3b60c,9f104706,153b48da,2b155415,198a8c8e,ab3c11e0,2b0d69ae,7ec09ff3,e69ebe21,8a849655,14c46aac,786954e), -S(5ace25ab,eeca3eef,3439dc5d,7313a07e,7cc94c45,5332d38f,5fd367a3,cc88b2a3,2ddb1c5a,168ebf76,6080304b,df44e644,d5b34ef2,3ac49fa6,3b19390,83fea9b), -S(fd0ab7dd,a0907d2d,7349f860,4cb4794d,db9d0a2,dab0e6e8,7fdd90e6,49a3ce19,6ab30bc8,fd9fa11c,835509f1,c4e9b0a2,faba9de0,4f2b8ba5,e3ca666e,cd1aed56), -S(a8af0736,a5e408ec,84b46f55,16e04fa3,bed5f733,f8b99e90,192bf2ec,ae1fbd4,aea37eb2,6f9b6ee7,90eac699,92a53732,91a68317,efd3e651,f27636a,878a531), -S(a4effed2,dd088a36,ad6902ba,db705a35,187f721,20e747b0,2011839d,76d68be5,5efc6581,210022b7,fd8d3dd3,f11c95ba,99a28e44,c316c8af,7510816c,256848a0), -S(290bfa2c,8971750f,90aa6762,aa1b2b9f,e9eb50b9,cff25ada,4a7239ae,3524a799,1e16aeb,1fe3c65b,395a06e6,49545ee1,95f0a6ae,9954f6f0,dfc1f528,ef7d0759), -S(25496b16,b62fbf6c,3e9c59b,de7df4f,6216256e,3b968588,e184bd6e,b9543eaf,6964be4f,d9fc2dbd,146774fb,1eb37f0f,a13a11e2,35b1c870,fde75c,ecf750d6), -S(8585f972,5efd5404,fbd73e8f,c78a4e10,8089f024,f6ddd66b,28d56031,b98f970e,4e61cd98,c9ed1efa,6dd112c,ca27383f,1614b0f4,728ce990,9251309d,13c2777b), -S(b4fabb0e,52f273b,9e5e245f,82a151a9,296d93ea,d690378a,2653eb7c,a68020a8,5a0d976f,2d34b780,34ccadd9,30371689,f1e3c5a,6ce774a0,db9da3e7,aaed0542), -S(4c902996,a5a7ddde,3bc42bf3,31fb1cb3,61ec471c,6b9d8e9c,249d9e74,693c9e8e,3d118fb8,4e8061f6,3c8c5f09,f60298ef,c7983887,d1522034,8c9aef13,9759347d), -S(8a1fb43e,3591b453,ea7353ed,f3414793,2cb2e5e4,33aa01cb,cde2a865,27954691,40982292,e5b49878,b7471564,a84606f3,6e128d08,3d542e57,ab04acfc,dc1f122b), -S(f93d9de4,43d93908,8529abc2,d27efc02,682e96f5,79133ea2,e65c44dd,4cf5e6bf,15c9e50,696af51b,64e3b7f0,19b3e27f,7dac74bb,d72a0007,18c4c3ed,10db4873), -S(8755c259,f333b12b,88917775,cd5c2536,431e77df,f80a59da,d2dd7a1a,a56c930a,d2d681f5,d6259780,8d5c4a4b,9169d9c4,181edf5a,cbf4b817,d27b4e2a,3adbe697), -S(30f44aa7,9d8a39da,3abc6085,b6d5f33d,bd96f266,e6f37382,c20e749b,efced3f0,8acdbec8,2461ef14,f4096274,cb08f3cf,149e0041,7c075595,ab24fe9c,5ec15b96), -S(691a190,7e98a004,98af8c72,3850acf,81f07e76,b70afd62,96174058,84bf4a26,df902e4d,3e7294dd,66952c08,4e562954,2e6cf93e,94cc0d9c,672d097b,38844483), -S(998d8727,55f5c048,1d738583,e3a80de7,c6abac0,249f01a4,1b890d98,2ce74471,cf9b4563,67eeb428,865a1416,ce7b7f60,ae953bab,ba7a67a8,15ca6a5a,bb4b7567), -S(21f95845,8adf4ff6,d500e082,56454d33,7893cda0,e02ee161,7368a2ff,1aa66dc5,d88c985c,3c40ad,219ad336,ced08e32,f328a0fa,f4cb8ea1,9cd17762,7b4b257f), -S(107b438f,8273931d,d14d9b3c,dc5a102d,41f24887,9342d3b4,539a9d76,a04cb362,a41365b1,4d0857fd,da9d15b3,76dee746,55d259ae,91b3e97,c61bb70b,4d0c3a87), -S(b8f40c64,3d17a3a5,5329f710,5a8c799,66ac1466,30d64264,1262824c,b276c705,81d88197,c24f85c4,88c96401,4a34bed,17067ad0,d640ecc6,8482a3df,b374647), -S(33ff357a,ebfbf690,b97644d5,af3b5766,7e564c25,5685458d,1d0dca97,f28b9cb9,59de095e,dbb83b14,1610f1d6,289c21d1,811e875b,dcaeeec9,40c6bd8,4ebed43d), -S(6f2c27e8,46c1b5e,b02c57e0,2f8b78bd,af6a6489,858ec5e8,e60c7e84,c92f8a42,a20f6853,3e180ab0,bab00ac1,d517c66b,9f81088f,f2ad751b,63fec4df,d2beb5e6), -S(510f00da,f51cbe28,7bb0eae,59abcca,f3dfd507,976b92a4,558de2bc,91761621,f268b1e0,549117a1,b2123754,ca50589f,283db3d3,95c1e081,bbe9d027,ac3a8561), -S(fcd2aa5e,5c3fd7ca,a1c9dddd,30feb5b5,c3abab65,924c1865,913ffa5e,5658d2d5,662318b7,2cc9a9e3,5fb122b1,d74cfd8d,55eeca4b,a0d6f998,aa9dd09,266bfb3f), -S(9292c47,e36ad0d9,957a90d2,8fc00580,745a52ab,f14f3d61,c9c02163,e43c41b8,80ea3a5c,16f68cb2,67837544,289d1ea4,48056da5,51b56bc3,e243d45f,51b770c), -S(30a07a32,2d6deb75,7c3fdf92,db896b78,25b4043,87e7120,eed7cc56,3fc1886b,b07239e3,68803d55,96f843ef,929529ce,96df7e47,36a2cb35,dbe30aeb,1ff5c3b), -S(4ace91fd,2db5f7c4,29e6fac3,ed7aaf6f,46217f3,e2a67ba4,74423f4f,5f2a47f8,18db8c0c,eacc55b9,fa98ad2e,da9634b9,c47aec7f,9cd8e89b,41913e20,ba2ad9cb), -S(63ed08cb,b10860a5,4b6c0428,8f345cf3,f6e0a48e,9935727d,9070bfe2,dc0ade69,f24eaabd,e3cb05e7,c74d3be6,d17bed4a,2d4257cb,e69b876b,c161f8c2,4b8ae792), -S(66e91d3d,e5f63aa4,8fd6d3d,9129f60a,c030cc88,a2ee10da,5c187832,ee309ac4,5d90f490,8f5f0269,cadec883,e4ac47d,7f0b8d2a,cdb979ba,78f1576e,7644aa74), -S(e6faaf1e,1b7eb6b,e1daa8a2,f7f3fad0,e0250e35,f59b4ad8,a80fb38,5c0ca6c,3ae02379,79d9c291,68a8f555,8469b4e0,98dba357,7ec85f01,8f4043b8,72e78ee3), -S(c1006c5f,f598f904,94edfaa6,2eab93eb,e11a44a8,5e3e1014,91218cb,13e7b497,b6d15bf4,28df9655,bf70336c,ff7b6d80,b7890d9c,82b0323f,20f45935,6635f4c3), -S(f9cf093a,f613d28c,695f146d,5790f6a6,379feb52,1a337d66,a5032f93,46a0c7a3,e017544d,56a9dba6,e9c248d7,9bdfca89,8b521ffe,b5e68a9a,26ad6f2e,46299bc5), -S(90d1d995,67f6afb,37806ce1,997c8917,e6ff7191,5b6bb4a5,cf1433b6,9ef433f1,44b0e285,e03ac5b9,5e4352e1,13775a20,66cdd3fd,fc4a90bb,9d39b6d5,a796864b), -S(5e48b3fb,eeeb724e,8442fb8d,1510770c,c0e879f,94ba1ae7,f67a853c,57a38996,20650a89,dc8e0869,5f6c2b16,d8620af6,b9de2333,e29ad5d5,56445f54,e4c19a56), -S(90ca5392,1fbc1d53,7402708b,82d3d4a9,366c39f2,4fe6bcea,8435b5c6,544a4090,ced1590c,b11bed19,8a14eec9,44f1a117,d51a26f6,df89f62d,d4c0ff2c,d38758e7), -S(7d4a162f,6d359758,9a9cc446,f111da83,4ac9540d,7dc3fde5,8fb8d3c0,fd63eb8a,445033ab,53a9ae3b,7ecd39fe,aff2b18e,8d308de8,dec4fd18,8243ec1a,caa5ce56), -S(3344eff3,c3a56453,f2d37f8,1970c94,5ee2bc68,b85f53cd,3f4baa3e,2784488c,4966989f,f6372f19,5eb32554,9642e3a0,954ffca3,b650fa01,a7246743,ffde881d), -S(dcaf9831,99beb377,18623330,197415fa,667848a7,634b4821,610bdd7e,453794af,44c24125,71252bc4,db15ade5,abe3813d,f8425f1c,8a1f3281,6d33077a,bff19bf1), -S(57fb24ce,887ef2fe,f02be42a,a09f6e24,1bcfc52f,a58c8bb7,fae08613,6431dbc8,c2044794,1200e77e,a1d18139,55f58a30,c9707f22,42529a16,c1bbab3f,dce4ca23), -S(bc4dc9f0,54afeea2,2bf06988,265d01c8,b3cd5d47,d745c75b,a234f6fd,9231b3b6,9dffd7a4,1627e744,a637017,eb54fc22,4d949bd4,1b1f868b,865765df,13508cb3), -S(299f90b3,ee45e1e4,3ee1dced,2b302caf,11094a75,9e1bb90f,6c751330,d13e1f6b,6bc5dffe,53dd7c39,51623cc6,a7f61314,7d1847e2,73d03369,836e39a1,e6da81b3), -S(5a239aed,c93efe47,3141523d,fea3af03,16aee518,8629e8c2,e279eff0,62b0717d,117ad8f4,ea8a387e,d9f01296,e00c5864,ac93a78d,1968ee4e,9c325402,63acc5c4), -S(609b6afd,77d8c8c4,3c14ea1b,e56dc2b6,beca0239,faa88f43,59f9e6e0,1ebb8839,a576ec45,1bb52bf,39e9981a,4079f3bc,8e417bda,36797411,5e95e384,74632481), -S(663283fc,3d0fcade,ef669583,180a8e1d,b297cdaf,672121b4,4c481533,1d06bc26,139c7dac,f30b9031,de97c069,76812e66,7cf59091,7f0ac6be,f606afd3,c4f30448), -S(eedf6685,d605ca2,e97b801,ebc72b5d,e135f782,df6c243f,140bf172,9b23f671,a6da00b7,3ac5edf,b83e8fc2,5d6603aa,72c2af47,62b7ba2a,4ad98aea,53c8f0a), -S(ed14e1a8,73f82d1f,4e211823,b0632e49,3ce198ff,ec6c19e2,b9467791,8164fad9,fda82b27,3517f8ac,2464cb9c,b0edf241,ef91ebc8,2bda29c6,de3f6602,736c97c1), -S(f7c21813,63a5efb5,9c57da8f,eaef4738,38b9d34,8d3b16c3,ac28bc0e,b11c773a,9bd65899,bc4d15f8,875ceaf5,936ae25e,b4e9f,ce5963a,dc6095ac,5b867c17), -S(d407ed6d,b840bfc0,75c392a1,bd446340,9fb8f35d,80d9d4ae,95ea7bda,bb35e1ed,9f2af608,93692dc8,11330ac,35e317a1,fa856984,cc635354,43846545,5a9953d2), -S(32d706e,fa5382d3,ceaf0543,8e77971a,19e0e491,275d0381,ed705326,86f52376,66f4e0e7,1529c73f,aaffd9ac,a6846e3d,e2e8386a,939d02b0,7f64baa7,1d6c0f04), -S(ebe33ee5,f6baef23,ebfda782,e9ef55a6,d1b94e84,b76e7784,6d2827a7,82484a2c,27137340,2fcf2cf2,8ed164cd,7fedb8cc,178dc3f1,f02be690,ecb64938,cd942487), -S(5359d4ad,617f0a27,70392201,a2a1dbc7,fc5479c7,93be1cce,23b905e3,2751dd8,cbffabdc,ce183e6a,acbb21ea,86cd4fd8,97dd22c2,582f49b0,9f51e846,db2e8b2a), -S(92f718f3,8d2c428d,cb9dcf3c,847375e8,7f53d165,45a89dfd,629516c7,e5efa5bd,ca140596,6d82382a,453a5a4a,98ac315c,4351a4d8,5518af2b,996a0b3c,55edb05b), -S(70ec6cac,37a78311,8394e3a7,5a0756c2,117b8eb2,bf330440,ff6cd5fd,854df5ea,a1c909da,7c0cb4d4,141334f4,2a819c39,30af0877,8b4ea63e,601e3356,5d0bd54d), -S(72a4c06d,21fc5b6e,978addb3,95c1da3d,7c6390f,98f0abf9,26770ea6,d33c24cf,e811ff7f,ccf7f961,3c16b50,f74ce397,ec1c3e4a,877dd71b,b15cda1,c3027159), -S(ca5a0a96,e40e0530,344b532c,be4fcc47,2d243192,4c19019c,c602a6a4,45148259,b3274b9e,f30bc965,eb518686,3bdea539,130657,8199d2b0,4c56558c,a1bc19a2), -S(50e52b93,574a12e5,1f8c562c,2d335c54,4aa6edd,b3a83c4f,95ae5509,80b76261,dc5c4d8e,ac4d34c2,71af7d5b,abd714b5,194441d,72fefa4e,d1b4ac42,6e44d477), -S(e5ca0666,86f060f7,7c1d869a,94f02407,962cb101,1bdbb6cd,dad786fa,15761a6e,4ee18b3,7b15138b,61618a3,a7632c68,4f31cea,4d0c59f8,a6ce82a5,2c5480fb), -S(73560753,377906d5,9ac8c104,57742dc6,2d37b454,658d90ff,a4cfcbe8,f0e311d2,35ece58c,a5c7e200,47f80080,28fcacd8,2c8254fd,99fb392,f8e3b96e,31f40e4b), -S(a419a2e1,362adc6a,6fa18354,dcdd0cdb,37a4f8f9,bd1347b6,8763276f,b7acea19,c10fd807,3afc6f05,a2775e52,5d880417,f1c684e8,6dae0e35,9e600cf,9a6fd02f), -S(64a26b02,59fdc9f8,86ce26ac,cd826316,95eaaa3e,d95f9504,93c00505,ab149aa2,b03fca02,6b90848,965de8c4,6adadb8a,ff41f633,6c4af3b8,2a064880,f455b07b), -S(a8db77bb,4528572b,1630adce,107c8cd2,a296783a,acfbd84b,8cce742b,2c519e56,fa81ec4,7565b607,39dc4769,39624240,725afb64,df8ad9e2,70291dc6,acd1b19c), -S(95d43497,c9e2f1ae,4ecf2a6e,7839ed5f,135ca565,909fae2a,9590ffd4,2137e772,7977da8c,7d6d8880,d5c6a7ac,56b1ab4a,12d101f4,a26bc594,3c1ec394,5e085b7d), -S(184ad7a,9d1f54be,ae9bacd0,30707699,16e4158f,f1c7a9a3,e7303f38,53011793,7731244,6ceed0fa,3a832731,b477db26,743ccf3c,f3d8c09c,242c3327,6c67e3e7), -S(2f0ae3fe,5aa29a17,3a2718a1,91171d8a,7d33d2ee,6cc201de,4afbb00b,62db95e2,90f37a42,efb5787,6ed382cc,3a243179,4860ffaa,848b6299,52c6ace3,7dce5f28), -S(aa487bf7,fd746413,60e46513,4dec0aee,84287354,a74600d,65d02102,8deec2e3,d5de9cff,94ba3830,ece6a020,e9bda5aa,d999e97,a0ab4a0f,27fec770,ac2231ce), -S(54551633,398a72f2,66754798,5d2cab2b,6a107d84,72f8c06f,a34ed482,3a2a133e,4c33cc27,c462a5f1,e02bde02,aabb69ea,7a6c258d,55c6ee2c,a7b573f2,a7d970bc), -S(3b28883a,7df3010c,90b8613f,1b7639f0,7d766ebf,e3c1a02d,3bb20c14,156747aa,a3b1af7b,b133f94d,d2f720d0,aae669e8,b0a1b6c6,c2e14b66,72383cad,c28dbc71), -S(b3910ffe,6c153fe7,59ac3097,fd1a3b12,181deaac,f2cc3310,c036ac54,ccaab3d7,e242b0f8,de758d5e,ffb5e824,9cda6202,3686bbfe,439bed7e,eeec0c88,5b7efada), -S(679c5fd0,ddb09e92,77bd7c4e,651c862b,4fc18991,3892a31,6d0ed64c,1b66a0bd,f3cf0bd5,7e4085ab,7dce51b1,479e4ebc,63efb364,d11902a1,5d84b89,5599eaa4), -S(978d478b,3ad85f55,4b19a2f9,22f57cde,3d235bc1,92511422,fee2ad13,82a79f9d,fe0acd64,df69cdd1,985021ee,135050ec,879ffc35,b14deaf6,ade2734f,91781de7), -S(7e683666,eefc660c,e4326801,2690fac,4b0e3812,7de197a2,ca46270b,cba20572,250becb5,eda33bbb,cfc594bd,3675a82e,d5eeb642,bf755d2a,9e137ae2,1bd218ba), -S(8b90f968,26c56532,990cc0e6,8aa007d7,4555d566,7be7f23a,306788d6,cad77664,bc021a57,8e37d617,4a8320e8,e7bf68,4841096f,e191588b,79219fc0,d2559f6b), -S(b4e60f20,b7c71a14,80710413,fe81fcc3,88e83167,2183c36b,71185522,112f854f,d12ced59,7834d01,70a69bef,fb516ae3,4c67fea9,573bbe48,b3c2cc7d,edfbf0ad), -S(47d28ba0,3be64972,b30e7cb2,d4193440,bd4efc5,17194eca,2ef59cd1,78c6429d,304390c2,7a550fe6,23c9d6d1,465241d9,5827362d,ddaff80d,26ab1bf,9e32cc43), -S(2441a57c,1b9cea4e,28076f12,7fac389a,1068247b,56a1a4d7,7a2d5c1c,5945dad5,ff976ebd,3df8763d,aae65b64,c579408d,96b51a6e,9b3a85b4,401c25d8,fc9263fb), -S(3d69b290,d22112aa,ac7e2e7a,ded5cd9d,80754cd3,20831381,6e3840ae,d986ba78,bf7a0570,53ea3a3a,f27a866a,f0920ab,47f72d5a,f9859c31,6239aebb,d8d4ebf4), -S(2ec76c7e,3d684284,902f1725,54eb3dd2,b0c4304,4807a25b,472febf6,e9e6d1b4,97112d42,6850ee23,e57ae095,2565ee23,66c04ac1,6a388a44,14264767,20e38ac4), -S(972cb83c,80859ff8,96b0a318,a3a25386,3b6c99a0,49faca99,d36d5150,36da0e60,9668359c,953d20b6,e1873041,f0aea3c4,8e5a1d43,e4abab48,c0eaa391,8f7d8e98), -S(dfa2ccc6,9cb6c27f,6c072fc8,bc875c5b,e716c701,81b451f7,a85735ba,29363243,6342e27b,f9dff0e1,48fce3b0,1f9e569f,6af4a97f,b434725f,feff488c,501a7b4c), -S(3ee11d8d,8a46cdb3,8af24cd,f5f23f6d,2f18bc60,9f89fe14,ca0326a6,2a75c4f6,41ec4c72,ae99670f,2c5a4d8e,f0b2b211,fd3ea5fd,33b9158e,383c3ac2,d5c759cc), -S(bdc7399e,a6415348,77c66ce9,c62c1a96,7dfb72ec,6ef61c,e50dc71c,cdb3df96,90bddf9d,21aa5a98,8737c202,f89213d5,dd43c352,90a5cc96,40653be2,813f3f26), -S(d170eb03,dfad39f5,2e72298b,881e7c40,df9c4ee0,94cf092,25ef7b25,4250ac25,c9b3b36,937a83dc,c0592f27,202db5ae,9868f917,e6155e55,c9e0b3dd,8daa9085), -S(7153994,4971899a,8eff44c9,f38d4dba,e9315f,abff6106,a74231d9,97d4c66d,a95c07cc,e5d41397,7bdec5d3,bcbeb106,9dd90aea,ec57b911,3c6e3a69,baba78b6), -S(516ebb6c,f30e37d3,25bd8a77,f99e32eb,f2a84716,45bdc04b,a39b514d,268e9927,72504ee6,53710799,f5295c69,c022854f,b6ea6ff1,576c667,ab936d66,e651d103), -S(9de88063,6bcab6db,c7967dca,ce14949b,75529de1,73b46fc0,37a8c450,d5686d29,399f8480,c0f68bde,64ccd187,f247e09,30cc258,69e4779b,868d0af6,1e2dd1d5), -S(3a59c31f,dfae0e1b,a9b83db5,6f1fc0f6,51a0f9ca,8dc49c15,6e8d4ba4,a3ecd58b,a0513e83,600b57ce,3f87c762,6c0092d8,f88e0b4d,4b45a291,61abcd83,d2e93bc), -S(f533472b,fed40d17,566587fe,6f9e3c7e,3a657962,acb80e5b,319003c8,9b0b16f2,2fcf2b72,102dcb28,b36d8014,ee850bf5,9700d4d4,ae07769a,61bc0730,6a92304), -S(31b9170a,cefb23e2,330495da,dcc8729e,ce63a807,7406c4f4,de3d118d,1b759abc,111324ec,fdd8522c,64c0ba5b,a73cb848,9f1e77e8,d19c9731,dcfc59d2,26a88f41), -S(17ea4c86,6e3293d6,6cb535f2,db4ec265,331a4881,a9eb9941,2064ee60,38c3f8fe,a88536de,8cbec45,3d6fdcf4,3e3b5771,25ab4791,e2f318f2,c7572b19,7f3f02de), -S(f7a2f7a4,9462978,6f82557a,ec27a021,21995935,d5ac4adf,804b28bb,36ae5086,8a7ed1fa,60125463,96e3a50a,5616c515,3c5b6676,92bae5ea,f418bb57,8c4f42cc), -S(4a6b83ac,11a8d30f,c2bc4ccb,71b312ac,9ce05d77,3ca4a971,2f45f16c,c4a36099,c198732c,fbdaf72b,2c0471ab,5b4e2ac1,16d62e15,c5cf3bdd,c7fc2377,1db156ef), -S(d61e0f2b,757b2147,36f69e8,80f7882,26796f21,34c8ac39,7f023f60,9a222df6,dc369e3b,a99264d8,1041e2f5,decb93d8,7f3ddc5d,ebdad99a,1993e432,f92326ab), -S(ffc48a38,3faa0772,995f2074,4329141,1ded8a68,69f54f9a,53e14426,8d2d7788,edf446f2,660f6fe9,95129656,fafb76f,c1ef96fb,7227c4ac,8660cf16,867aec57), -S(986f203c,c3400685,610c83b4,fcf7a0da,636d92c4,f6f0bdb9,99b01321,ba47b952,7e152eec,4ea0a4d4,8f594801,40e5bfed,6539ddff,60646b86,ab463f9c,1c1cd72a), -S(e078d96e,97b33ea7,bf1a118d,8e45104b,18da1b7a,f799b5c2,2fc95db0,869a4b56,500aea63,487620e2,1c89ac2e,187eb32b,5567f715,2a090d9e,8e493190,c0b904c4), -S(a0b76ce8,3dfbfa5b,9ffbed50,736a676a,8e3e58df,aa3684b,68943ba3,f89d0ee5,5087ed66,33d4eafa,d7f962ee,11844da6,6e152831,8d780d83,5a9e7341,77c2551), -S(e6137a2e,1c22146a,81b622c8,947ebd54,5ee49505,e7343d6b,434ae440,f74deccf,b9598911,43813abd,14323cf8,fd880dbc,bb4ac611,e961c461,94d0f78a,1118b35), -S(bc966ce,8e2d896d,454cf19f,8126bd2,fd21f912,9e0c5b56,3afc6483,d5a8de1a,d7391926,bbf51367,c0d84d14,9fda784d,4f5e4db1,a4a71868,e8dc9968,ad27cd7a), -S(4fed3ecb,7303d658,48260222,6bb94148,b56a753b,902c3655,47db1db9,9b355624,87d3c83b,c4336625,4ddddcc1,a380b9a6,a7796f7e,6da00426,5c067f85,7c446b5f), -S(53151e3e,793f7ef9,a75180c4,ec3106ab,af3452f5,1a8c5301,1607ef98,3fb208b2,ba84da4a,dd761991,f375cfe5,146ba47e,d79e8983,8ab1e71b,737ea419,7aad93c), -S(f1ea6a7a,1595f99f,187287e1,2ca4cebd,8268da53,17c9deda,31c9c828,c91ba210,77d27512,38290ab7,4a75d9e1,63238537,555b51be,c0644f11,9409c1c1,7895c2ca), -S(4ce24395,80fa27b7,3a3bbed7,379b19d9,4c59e23b,1d482237,3de48d84,1e7650e8,258ae955,11a0890e,5912f651,f7705920,1971d6,82ea9abc,92d34888,f134aede), -S(20f5aca6,c33e91e5,97b66f07,30a7eaa9,4badf23a,b6f7653a,69f7a638,8ca20808,58642a87,964fd398,259037fc,c0c3e028,392eb7ff,15646480,1656cad8,7b6165f3), -S(5a84a300,9a7cb6a9,e86447b3,9d449bd8,3ce4e8a3,88395cc8,b851d961,df2bdca4,a724823c,bfa39a73,c02e8509,78d661d9,fc8dc8a1,e3a98c21,45448b2d,2c0d8d26), -S(4cc4b57,2e4cf18f,212315c4,65ed2464,b7850846,d64872ae,7b98d316,73853a6b,72594713,74be90df,fdccec2f,3a84b30f,74d6cbbf,fe966fd8,77de5b51,f9eeb409), -S(84aa8352,80aff2fc,b747f2d8,6e6d3f7b,5828ee7b,c0024d9,9b9a4998,fb809d48,a33e80be,b6131f8a,6ede3e5e,2bd265e8,5773a903,5912ac45,83cebc02,e0f70585), -S(4354311,ff6b6381,92ffa63f,a7a52fc6,cadcdd05,9adaafcb,7695686b,478dccdc,fa6b68e5,9d7f3aea,8d90d21a,ff26041b,68f68660,745bfee4,179d9e3a,2683f06e), -S(5be8ea1c,c7412e23,fe4a505f,aa15006c,ed823cb6,1853dde8,2e7af0a0,f06cc196,a2c76a9c,959b6b5e,d71dc83b,7a81e43c,a22a019b,8ecc54b0,eddfce5e,af9cbb45), -S(a69f7034,b680b802,189c6e8c,9cccd352,ce9ce14b,a50f9d41,a5991af3,e1822a07,df0cb8d6,86a38785,77235cd0,edf76b1c,9e902d2a,aac44b99,c916c3b5,848755b1), -S(f278be9f,11ce9c4d,2fc94317,98f3f552,b3f73bca,7da23757,93ea99ab,8aa0418d,8ec2cd50,6f3cadfe,2eea65a8,7cd8be99,a29d57c6,69482737,44e48289,d5eb283f), -S(28cf2333,17cd2dad,a4c83715,d0af39c2,cbdf7d98,7c90e1df,8709bdb8,929caf1e,a7905953,6c19b52a,459803cd,3a2ffb3d,d5597e5b,656c05bd,86d8e3ed,a9b7dc51), -S(45071195,99d6f85d,1e585fb8,2d4bf807,1b8ba01a,5487ef8a,b80d0508,2edc7b45,4951b428,1340ae42,1586824a,24933dcd,31a954,880d3c0,cc49864,72b6bfd0), -S(6df50945,4355e918,36a945ff,fdd68626,1b20f362,b1a7f601,9041506a,7cbade3f,38301bfc,e21d32db,83951120,954e9d56,179bf6d2,7fa3d5ab,7c37ef40,5245a031), -S(4db57458,b29c47ff,6f8b8ee5,12d897d6,36226380,4be13a48,6837f8e7,ebe147c5,e51039eb,7f9c8b93,3ad3c932,1b254cc9,f6221e35,13cba26b,a7c3e6ea,44f93ae6), -S(ad0ab782,d9a93270,b7083a32,b1913b7e,b0fb1947,9c8d8be5,ea74d0b,2590e087,50ecbadb,d801fdb6,5d40e84b,1511522b,3e603d06,5bf3a6a4,2b864558,c72c3fa4), -S(acab606b,aa8bc48,c452487c,700ddbc,daa04799,e9f57811,c47587c3,18d3900b,5be0eb5f,3f78292f,c248b704,f6cb2df1,891a05c7,822d9b47,35efd687,35b2e6c0), -S(16168437,b019abc,49fcab11,f7c0f2cd,14c2f784,dbfaeb40,f3790404,c4348d51,c68bc496,f40d5e97,4fdbaa51,dcf54ea,fb50abd,5ecb9f87,99bb3533,262ce86d), -S(5f03f4,a6cc9ad2,475d0f90,2090888c,31ae6eca,b08f7e4f,da8db504,876c8915,c918b3fa,1104d382,1d862299,17e0c5d5,cfbbf924,f69c24c9,d97b7091,157d7ed), -S(6da6938d,ef8b701,fcb228a3,c9066555,b4f7f0a3,297de3af,39d42897,5f0a27d0,f3ca7083,79910a1a,cdb94e7,9a7c8eab,e2c1b779,b749ad6a,fb4579b8,a3c56b6), -S(6b25cffd,587c71a9,3a736f8f,f5daeea0,26734350,fd158415,727fe6fc,6d309f86,dbf00735,d0c10049,27d582d3,8e61257a,770067fd,f9418dc6,73cf132a,c33f7b74), -S(7c48e557,27b1bed3,604cc3f6,7e47e24,b6f9b8a,7cd56cb9,f531ea5d,ef793f12,4d251353,73636962,126782f2,170cec17,e08483b,5b651f78,f0723da0,d6d4369f), -S(6769e622,cfbfe289,337de46f,4b6e1843,97fdc046,4560255d,9fc74c06,b00fc7a,523669ca,56e3e24f,b2490db3,6ea0bc33,6851041,d9146dac,1aace8c7,3a55e92b), -S(f83e990d,87486667,11214f8b,6a4643e1,901251c6,118d4d2b,a9087678,5313984b,b9decf7f,44c2cb00,d3d8858a,164a1,7ccbb6f9,5bbfa72d,6792ced0,4786a12a), -S(f3034416,5db59472,d7753efc,b55203b4,44b3a5f0,88825c4b,145d982b,38d369f3,3b765eb4,fae61edf,4a4c3b11,c71c5359,d8920eb,5cca2896,226e85ba,5932458c), -S(b2051f1c,5e6b22e7,d565ce94,bdd27c14,885322d0,e7bd3db9,eb13cdde,b26fd66a,b3245d05,2e93fc5,362d7e0a,4a4eebd9,ef8fd1d6,15c8a343,e308ef26,b9e331b6), -S(443958e8,fc9271a2,5215abbc,ad1bbcd1,887286ff,53d0d6e3,7803df80,f26094c7,3ae3f492,f51f287e,3f881bae,b16f4ca5,60583593,108053c9,352a48aa,95ceb545), -S(e8c5c31d,8e814515,b992ef4f,28bed3e3,ba6b2ffb,373a62d1,45976712,da8f5ad2,9d9e9d26,83c6b623,3d867d0e,727d00d7,fb5b7312,74d58bc3,b036b74f,8c22f676), -S(8b997cb4,8291df62,82ab7ac8,f6a917ec,330e76ee,4d21147e,ac15d3,2a9900ef,ba8e7e28,9bd40fc2,ee71f32e,48b1ab1f,1daf8c1e,6147cca2,a11befd7,e93b6920), -S(18ce6b3,126fd15d,29377619,4ad888c1,9355c739,7099d851,60111cd8,55199865,2f4ec4ea,4d215ec1,e102f7c9,ba9137da,5e75e00c,52b4d740,57bd37fa,61bcf038), -S(5b28c60f,a6c84a2b,dad6febd,f7cfc5c8,9fcf0e8f,d5cc8882,9540330b,8eaccc7,4d1c0d1,bb90266a,219592ae,ee619a4f,7b07c3a5,430ae20d,945f2121,2a652cdc), -S(5d4bf89d,fc3e8ac6,50f7c29f,6d878ce9,a1ba9cd9,d5970a58,ba7975ee,16496844,ee920d1d,8d7ee256,7f556433,90d0cf8,48458f75,f81b9f36,5c48dcdf,d60a96ab), -S(1fc5cd84,8a5680cd,76deb83c,f8ec6d99,db0e2fa3,7d7ac5bf,feb07fc0,ce0f0d9f,239f7252,18017a1c,d8419aa7,229eee96,37251ba3,a4a1eff4,9e42a29e,4f61eeb5), -S(e5a33510,603428c9,10cb5bd7,1da8bbca,3b50e97,46475a49,9d69b7df,badf601a,ee53e84a,a7e18842,a6879ba,ab59998f,62b6eac5,499230de,55a5c681,5d287a65), -S(c5ff6446,39c1772b,efe07d3,aad6dad0,5ba3074d,588d362a,6b5de6db,9d26707b,f11fe8bc,7f449e9,ecb22301,f131c6e9,7f4cbc52,af8fa880,6272705e,527a8e5f), -S(8246573e,b3ebc64a,c2118bce,9a275eef,6df0a34,61057e4c,a8836187,620041d0,fbe4a4c9,3bf019d3,2c2beaaa,ace3e4af,6c924195,8af4e387,d4ab3ef1,5146491c), -S(e9e9fd34,83b18055,cbbc8e33,cc6f3fc4,c507bb8a,84a09254,4822b44b,3d6a2910,45a4b02e,18da3327,80ab1f5c,37545bef,551c9a1,98616099,14bad711,1b4efd0d), -S(c3e53eb3,7d3a9fdb,bc2ab9c4,83656ff8,375bf18b,34aac991,ab5a6584,19d5f2a5,f95cb1ef,a793934a,2c1b0dc2,a0746974,75a29040,7f4413e7,449cb71a,af96225), -S(f54901b,fceceb3e,5beab5de,e9a93344,f354d956,5a989fd2,21cc8442,51944dab,57c0cb7d,8a79b236,608d7971,c1590672,8b5039ac,32db50f4,f50ca4fa,eabf3014), -S(d5cad259,e0716691,b5a1f8c5,970b4bf6,c7329aae,e4ab647f,daed2388,85b4fc55,4d944544,63cdfbd2,d769628e,bc60f501,ebf1d1ba,a1e4d68e,4a50e57,7afd7fa0), -S(fdfe1cc6,51fda605,d30582ae,d6d3e74e,855c278f,4151145,312f22e,ac142bbd,42f5dcb9,5772bf4d,4451614f,854f5ac5,e753533b,4d16e8a7,ee2a1adb,64df9029), -S(4db28db1,f69d04e3,27a438f6,199a5f98,292a6380,5e8b7edd,b36d341d,28d2e790,fafccf3c,394ad72d,40e938e2,5eb64079,f8617499,313241a4,99a840f8,733786dd), -S(1dffedf6,a430c31c,9875ea06,227583b,5e5160d0,b2d975b3,452a99ec,dea4d3d7,67bc0a31,ec97cb9b,fe191614,ded30a63,f77025cb,5cd7acc1,2e3d84fe,24b590b6), -S(41239a63,857928c3,e4d51a41,f77129a4,d60c7d44,9b6028d5,3b183efc,2452403a,8ac22f58,288c4a53,b6703f49,cff08a9e,39c16516,126b2803,9a0759f8,776ac785), -S(f2ecdfa9,adab5e32,eb7740b2,4eeb0fa2,649baced,1a69b03f,d47434a7,3d0c28e0,133952e0,ec187463,6d5f15f8,d2ab385d,aa58bade,36b9984c,ab94a591,70f2beb4), -S(7e74762d,c7c312a2,2fb7a48a,b9b393bb,7f540f7c,279eff83,c2170f2f,27132da3,9c7e6962,f6fd9cfb,a83a7b7a,85062f9d,add8a558,cc4cba51,d6079072,b7775daa), -S(613df89e,dc48052a,b497e0f9,571703f5,78e0ffcf,b116c162,277319b6,df774ffd,9cfa93b4,61200eef,c2e7855d,898a4198,52921aab,a30412f6,218095c9,4827d672), -S(caa6c1f6,c176e31c,a2baaf8f,39a1b5e0,c1c28443,ac8503d6,f4a55759,8e8180e,556a1519,73ece75,8e68d10b,151039a3,ed0521ca,c19281e0,255ec99b,10c21a26), -S(267f26da,2393ffe2,18f5c574,ad4fb6de,634ee94d,ee5ff952,10dd72b,1c550f5f,234fdc5,fd8e9412,650512c7,a510dd4d,f5ae9c88,83ecb1c2,edd2a3ec,d4bc3824), -S(8a26bd9a,b45c1aa0,772d794e,b088a941,2414b48c,82e2a118,23e869e8,3dea895,68ec5163,a955ab1,7c338a15,d2b66d36,5734f015,4e21e750,1387e978,452d9902), -S(29593a26,f0b9a728,c0248f06,4471e56e,4fc8d38,9823f7da,aff9e46d,81b9eae,710860e0,a9c98dd4,b1086e7d,2364be88,8741253c,9b8a7772,7b4ac275,53cf9b72), -S(5676cbf9,a0a41fb7,cbe1f3c0,a202bf7c,4458e938,964d903a,65325526,27454bd2,96cf5b8,1aa71fbf,f1f60e7a,2e4d28ee,ef7d0288,1b63d8fa,da9a10e7,8fdf7723), -S(6db9282,fe0ff035,b279a832,6f1c4f63,839a6c67,788e2e5,af7a4492,ecbcd9bc,4788671b,aae2f709,a2377b86,2c30af5c,49c721ee,fb2e3f91,20d49eac,821bbede), -S(db46b01b,c6047a92,e9e5c8b6,24f6aeab,16b213e7,91fdaade,8f045c55,d8de4275,9bd83ff8,31737782,21f161ef,ea079ea5,1e459023,445d8255,8e5f318e,949b52bb), -S(fa91fa0c,c71a2f21,38c61aeb,f451b435,1ae6a432,53a242e9,249727c,7c649ada,7c518caa,bf9fc9e2,c88a9ddb,712f32c,d8d04d7f,54dae53e,7dcc154d,e8826b33), -S(9752d6d9,e7dcc767,8bbce21a,5a7a3ea7,66d70518,fb59f435,eb6cd1a3,40f84dd8,9d1c48aa,2965ccfd,c03f5bfe,41a073b3,da6948b8,457e6e0d,c8a13de0,149a00f1), -S(ac9c0ed2,2e66bb0c,83ccb76f,62ee840b,5f2d6f5,568697e9,b0223009,63cf3c2e,37532994,58f79d71,df7d1b04,91523c98,9d30578b,706e3665,6c897fb1,1746c948), -S(71a9d71f,1f44b087,e02f7f28,5c47c947,f143d9d5,95e59dc9,64233226,d51c15f3,998119d9,7ad626e5,28e971bf,6ce85176,e3b9a095,1426f6d5,6ce8eaa2,81d6401d), -S(fbb85fdd,c4c25602,13ec981c,a40e69d5,6f3c6132,d1ffa38a,87b25c1e,87e40ecf,85882651,1c142a57,6bcf5f9b,1fbb0786,38511629,4c1c82a7,21e24bbd,16551bfb), -S(ad1fbec6,59b15b66,d34190c0,cc9165de,e48221d,eb1666e9,4d18042c,26db21e5,b579467e,d7d83215,c260dd2c,f089b2ce,513aa5ca,c9ac705e,e5841a65,8a583e18), -S(2af71297,ce1d4633,4ab66dee,42d005eb,845b927a,e6ae91ca,2fc8d414,58ceeb68,7477917c,5a456710,266815f4,39135116,69654290,36968cf8,e6983ee4,c508e605), -S(c0ae4daa,d71b2fce,d9c9b40,76be40e,a0cae11a,3d86ebe2,282f52d5,b86f39ec,61343833,f5d4ebf7,4445c133,37fef065,13fa3e0f,66cc7937,698b0cb6,9225fc9c), -S(93178803,9a374b99,df4135a3,50e1be5a,efd2e73,fa9c050a,d0b48812,a654c529,1bc01acf,3bf8b64f,6ac15664,c163ebfa,4a1a6ce1,4f9d3a9f,6e5ccd45,beaba2ce), -S(25458ec3,e24ae756,51f84ef1,a2bf49f,c19e86c7,99022de6,b7b58933,82a0050b,eeb2e93a,e357cf8a,9afbb9b7,fc0e97de,d80876cd,f08ee79b,ac07324b,cd41463c), -S(136e031b,1ab7a45e,6b8c3b53,7a615fc3,9e89d81d,a822e60f,aca2a496,e651e974,4cf2e215,8bc5c677,60e7d9bd,e9a476d5,d44a1c98,804e2697,a28dd17b,d4f5fa10), -S(5fefc4b1,2a3caf6f,3d025f3c,3510085e,ecc1ed97,46ccc265,1167cb0f,7fcd1af2,5cf8288,30eb25ff,1ad53354,acc72f49,5eb558f4,776b219d,bdec8ae9,24b1f125), -S(807a0f68,dd6026b7,2116e606,90a39596,e8558ce1,d11ffc9b,dbf2c574,40b82c38,12a2f38d,c84c41e8,2526fe56,2b877aae,10f575de,7edfb5ce,25f6a93b,158535e7), -S(8579c776,ad8f4fa3,65bd4efe,cf0b66be,3cf33cd2,61efc2cb,387c9a13,13947c34,7d888de6,9403e15d,3489748f,5d85bf7e,fd8213b0,673403fc,28a3d7e5,c3559198), -S(7374f757,46d03189,46386205,bc5d222e,243034a,3e0d4566,48777a3e,9239dce0,396af260,b295933d,2b6ae205,6fe53231,7ffec745,c4c95621,c1588d68,c3fd3f75), -S(a076997a,d9c613d4,adad3eee,9cb00a08,dd747840,4fe33fa7,34dcf3b7,58e8670f,8eef221,804526da,bc1b88eb,4320ea86,8d36ba82,775d059a,dcc4017b,6356f60e), -S(88494285,1a2626c7,f52abe1f,b31f124d,6fe0563d,c962c35b,ac690b96,27fbc604,e0a56299,86cb2c2d,a790688b,c63542ab,7362969d,d40d9ce8,5ec09e87,672cfe35), -S(682bb535,2da425c,87a541b1,35925e63,a161a84c,30beff50,b1c34193,fce7a6d,cea25359,481132c9,e9792a9c,4beedca3,4d16c3f9,f46349b4,e9d6cda3,e55f9b6d), -S(f80aa12,f4fd2631,26e01c2a,2cb0f86e,4293d3b8,87fc954d,daeab57,cbbe18fd,f6a2f24e,458214d4,c07d9191,23f8b6e0,af62d656,6657ff2d,c9894fc6,11917100), -S(f077e470,ca971bfa,9c762c61,132f5dd5,53eba38c,9629a8a4,9fae5b00,a23334ba,8bebf838,df798f83,88200f99,cdbcac9,8495681a,e4debeec,3f5ea4a2,b07bd87c), -S(1cffbe02,6cd70d89,f27a9db5,284a94ce,c9705d06,72b64bda,89b3a23f,c8b4a098,ea668c0d,61b0307a,15a303c9,cdab0ace,2ce5f1ef,8772dfdc,85d936e2,57bfe49), -S(7694c9e6,c10ece3c,f7ca1bc5,aac059a8,32f541df,da8342b3,ae31ea66,35d3c5e2,98054fd,39bf818,91b0d50a,ebf214a1,23010078,e75b20dc,c6c6c768,493899ff), -S(54f25d1e,1de2c437,39bcd34c,8a7e7d9e,d322a6ef,bc025143,de17b95f,e5cbae3b,a0a13012,cdff3d30,6bd3e863,9b1156d1,17c1f74f,8be3d8c6,a3d7a77d,e20c3d30), -S(ec3ab50,419649d4,78592017,c539f924,122d8aa5,4104309f,fc213499,8b608cd3,9f147580,8523383c,83f75c37,4b802589,fb1b0f60,99f20cc6,3497979c,4e558b4d), -S(21db4eeb,7f414ad,d9d951f2,ea33b9dc,8ac6f752,5549c982,174a4742,7dc99145,b4cb3a0e,a408bb1d,31e946b1,f0a99344,b0f2fae0,183088a9,543bef43,61950b22), -S(9e76ef4d,aa872a56,514bf43b,767a4bec,59dd96ad,9c436e39,807a4e5b,ff7b96a,7245b4cc,a609a698,bb3c6ab3,78d5236d,aaa3d8a4,c8502f5f,83432d62,b46685b8), -S(ef1c1a18,9fff9518,b1b40bf8,1edf4505,6a46bd92,1bd93c3b,1291597c,1d50bf29,ccfa479e,cb5e2217,ee9d2af4,42cd873f,953ff640,4127f760,2cd465d1,6590f309), -S(2fc501dc,d994ee04,81f1603,78a056b4,44b211cc,85e23459,f9969f57,626b05f6,29385f01,6b4180a6,93533c57,63e33818,ffc4f63e,72f78174,91532bf6,89d3b847), -S(52fc0f14,ce831d5,85e242e0,8421d021,cb58ec34,1d3d718a,34764966,48017b80,ee55bc21,120709fa,67251940,2531b231,e9713263,b28f52c9,a294b32a,cd7b2a07), -S(86932072,532e1a89,80b5ea8d,896deb75,6ceb8a11,87affd5f,c5eac0a,8ab374e6,efa4d9fe,3cb01ae9,b685e938,1a7ed4ae,b673d6cf,3fd8b47a,d55b2b22,cfe771c0), -S(d5001bc,4888eb3a,28ff21c5,52fdcfb9,f64be472,d677500c,2c6ad71c,854731cd,20a40358,579069a6,b246ea31,3e58b5ec,6569ae72,ddc20a0a,5ad7bc14,70aac129), -S(197d8ed,db431380,ac8419bc,a9a415d0,c19ff38e,84145635,a50eb5f4,fc026731,137d9984,ec510a78,130587a,59a3091a,24581fe8,40f49bb4,aebbfa3,9367ccb6), -S(f0efe141,83441eb,acd172a9,5496b85b,648deef6,9dcbb653,be2993fc,ab70eae0,1df1c523,4433bc9,7050c858,f477652d,636edbe9,8b3f51ef,b1a2ec17,6a0ad6b7), -S(7657e05b,c0659f26,2f2e86c7,73dd6dde,1e650064,5fad0165,4b52803d,c1c06599,26407f2f,a1c5c820,b729b9be,4a3c7c6e,b5c0ca46,f9c07d52,654bbd67,2a2d5f35), -S(6d037db3,bd776672,ab096fd6,e048768b,3acb7e5b,14cb4a77,ad8fa2cf,b67f7605,81d83989,87d95d38,5412e93d,43cd82e1,1060bfac,72d689c6,4d0572,7356db5), -S(16243eb9,d4eeb5ad,a68617e9,1dd8fd82,87db58ba,f7b65a40,db756936,54653ea5,fb3d260d,abd9a44d,e8795df0,cf9959d6,b94bbe4e,caf9c715,c4612c2a,4cea9615), -S(a59b5c4c,f732c9ef,f10b7ce,6e918562,d6082906,8509eef2,17c539a7,7601a48d,ae27b1d7,77021234,d703c423,cc7052b5,7f23388f,371d2a07,e0188630,ddbe4cb4), -S(33da8d1b,ba39bbc9,fdf39d17,1b8256f8,853da773,184d62e1,6d0d6ead,198b3cf,50bb1787,a917a656,622be1c6,1948adcb,1992153e,9b7725df,b93007db,7865719a), -S(4e5b40ec,c1dec23e,ffd4d2ed,4b3be8c1,b2a37ae9,e7d17d02,a00c046d,6173c48e,a68713c,3cefb9aa,559caa17,ff33b2e,476cee33,27dd5026,157ae77d,98bced0b), -S(86c5fb99,352060fd,2125290f,cc4625ca,2aabeda9,5470c14d,91afbe64,36511ae2,aa638940,d79a2237,c1cbc174,14ccee68,aa6dee00,c411dc3c,caf3b4e6,a24d5a24), -S(f3082a0,934921a7,6dc3d0fe,45d4badf,c0bb26d2,8b597a4b,bc7bb719,e43c5e7d,2f7a82ad,fd0099ee,3afbe9ca,a279ebbc,55841101,e1d2361c,1b7b4e81,98d78a90), -S(9eed2803,f83079db,90d50731,3fd889db,adf10be7,625a6455,709690fe,318df86d,1eba34d9,e0eb25b0,2494e3d4,14bbb963,69b6b6b0,f1ac8936,58170039,4ae254bb), -S(5045129,bafa3288,6d6678f8,eb0fa73,c182dc1c,ea039839,9e7eaf01,13d10432,f9290714,bb6972df,99d58a5a,50bab590,8c274310,1455d479,db9851a9,242c658b), -S(5083cdc1,1249ae24,4d1891a9,d74ee53b,90bb57e9,25fe26ac,32c364ee,99544031,ad385238,f304b7ec,6726ce24,9477326,15ec400c,c60069ef,cba2ffd1,c33ae39b), -S(6c1f547f,41bd9771,aa16cc9a,e19e5787,52e06b06,3d1aa740,dd219bd4,b8413ded,4e42a565,5169be0f,a65a471c,fd3fedac,58dea3aa,7cfc31b0,39902c6f,9938341), -S(bd455ad6,2c32f8e1,98f92a6e,ad5f8d1d,4ce6ab3b,57de4c76,d4a2557c,9d0cc2ca,ee672a2f,e514b76c,ad8af99e,20840aa0,231c423d,450451c2,66130160,a51db589), -S(3ef7949a,2f73d9eb,29390e2f,621cc651,54a31770,d49664bf,6602f8a5,3107df1d,faacb2a3,7050f0e7,d3d5e0be,edf3f658,ba30da79,df8fbc81,167bfee9,aece4f69), -S(8f45c59e,dbdd7f48,cdbb0fad,c2058ca1,b7007ba7,4ed1a121,4c6b562,7bcf6acf,357a629d,1e9800d5,c1f83981,81a39afd,56b1fdc8,9eec847d,a72fdb26,8d7fbcad), -S(3f7d488d,82c85663,b618af77,30a1b987,f662238d,9ce02ed7,f5160677,99ded34,c61323a6,bd1d8c43,506e24b7,e0635d72,e8eff076,db783b56,5f9424c6,8a1b53b4), -S(3700e5de,478887df,4f0819f0,86a2199a,a12d5925,f8e5c32b,c40738d2,edb329f8,8218c49a,3f40c04f,2a9ebf98,cdbb2d5e,1e9f2b51,5dbecc94,76f6e54f,26711232), -S(47ac5d4e,e3147cce,3d3e0c66,fb0c3a8e,a1d9c0fc,92dde919,7153ef9a,b4de1642,37b484b,4f0b4016,341a8b02,8136228b,6744ad3a,a871971c,6fb07a93,d16dbef5), -S(40cd13b1,6b0d24c6,d730c135,6ee2ba56,cfe6bcaa,d38ada27,230441ec,b50d5f81,31ed93d9,a98b6945,58c0130,b57c8c27,5caf386e,690cb1c,96b530ff,7a3ca4e2), -S(d491b581,10b6e137,57d20933,b356a977,51d3d03b,327354e9,aa1aee11,c8dfa15,85bcff81,4b5601dd,2eb27e1c,ff7d1489,93a98cea,9ec0553b,d14f108c,beabad07), -S(eabf656c,8b8e7de,a4a4ad70,d9a17911,d56891ef,7f6c32a,22078713,84f0b3f2,2ff10143,49e265ff,16619e7b,c7528fb9,9b3dbfce,e0c1e6b1,c30ec1be,47cf4e5b), -S(ed8abca4,ac4d7946,1ab4e3a5,5c05cea3,834381c,c7ec940e,c1b390c8,cce350d0,6b54dc69,86bc76fd,fef49c22,4b536795,2961b8f6,5ac6f552,73c4052b,dc8285da), -S(150968f6,3a67fde4,b4b404eb,866fd66b,50b822e,43f4e684,230cd720,e2e8e6d0,93e824ec,28bc5a84,f21b7717,d08ce64f,f5ede647,81538f4,a6f84332,4704c6e0), -S(83cab683,9ce8d260,7398446b,9c8f63d2,e4e1471a,f183f482,b22dc360,c59403f2,8f570cf4,391133d0,e31c363,84cf5195,f160ceea,b96e44,ba79893c,ddfaaa0d), -S(b3f062b0,189836e0,e9cc7acd,5c3c7810,bd287bdb,c0d64b4a,27202ea,f3a05b41,730f1110,ad1e7dc7,f6e1b84e,9a332c86,2003ec5c,f9e75835,97c07530,dcf9feb1), -S(7c226926,b567438e,cacc7662,2fa3f806,2888db46,f3e41649,d2bd5142,1a90f83e,563b94de,fa1719a2,b7f09c8e,5b31476d,8b8ee80e,9dfae6f6,aa0f6a6,45ecc33d), -S(b9416bdc,9862a2c2,cf1a50ce,132d07d2,8862f6dc,19e36f03,ad3100c9,659fcb99,5ee3e16a,5be0ad7,9c908fc5,f61c7024,678d2c93,47dd1c95,45734edf,e52fc618), -S(ece2cc3d,10edaa0d,4fe86a0f,b2d682c,aaf4d50,2913d942,8d704590,c2b3147e,5e79ac71,109cdd4d,12ff674e,b512cde,3a8004df,f2746165,e55233b6,2ea6fa07), -S(1dd18b36,369ddbc6,5a8d84a4,69262341,e6dc55dc,6362e7c3,5be5d5e6,ae72c0d5,4f7679d,e9ef807e,be2c1d39,163b7b17,1cfd22e2,6e4fb466,d8af03b7,1539ec98), -S(beefd37,fa712452,695bc66b,4fee98af,bd772c13,e63d0ca5,d62a7b0c,a8a2a3bc,caafe844,5be9307a,e872d297,991a9e42,7364ab4c,257168e5,660c5297,8a623aba), -S(d7f42137,7048d65e,39bb5032,ca991d91,184a98f5,4c35b3a3,73c118cc,d276d3cb,64e78d01,8e179101,41685830,dce8ab9,3285ebd3,ceb9817d,76edf7bc,524716d), -S(737fee9,6a6e5ae1,98bab025,2554e3f6,12517cf9,2614a503,4ab7b882,d97555bc,ac29b0c1,fb66bdac,a3ca5f19,3ac71997,87573d85,8353b9ac,c30ab147,bdf379bb), -S(784f4c1d,6a815b8c,6e429596,183e6e17,e846a50a,c65f0c0b,abd1d943,e115a307,ac5124ea,29517daf,782c5698,e5318d0a,fa0a05ca,d7a9d395,bd17c3c7,9c3a9972), -S(982794d0,a4430900,e6254f33,40924116,ec055a4c,8c0715f6,72af4cdd,e1bfeae0,90b9959c,3ad2170e,9bb70c1c,676ab6d2,584b97c3,855d9ec6,93307407,e57a3c7d), -S(7532737,c45039c,768b4cfb,71aed614,c8c8f977,70c94bb,1c8d5bd3,cd092d2a,b495750c,b0e5fd38,7f7f08cf,b5d2cf40,5f5c9a07,8184fdaa,5af78135,895be55d), -S(2900819a,badaa25b,5e79c9d5,7d35a079,4e587f3d,f75ca042,736969e6,a4db24ce,e7489b71,d1e8492d,66a1c6b0,dd23a453,12095649,b902f68,9789eac8,eec97435), -S(7c615aa5,b7134559,82fccde3,8c90d0ba,2d3a09f4,6bdbab02,4dd7b6a5,cc9fc205,4189a5c,d5830638,53569ebd,77855a63,f70229bc,f9322b2,2546df2e,e687cf50), -S(13749da6,79887b0a,d7e4f461,ae125385,c5126eb3,63d88327,6f0a4773,ee00193c,c2ee7f13,49def3cc,5d7963d9,2bee09d2,c36128ce,a5a0fbb6,964a0c14,a7644e92), -S(4ed1478a,b92b688e,aa491c7e,e3134ca9,7cc71cbc,3cb32ed4,a69c5b13,4e73b526,16f25a92,fb8e8042,ce2105de,e9133b82,3be2277e,66dfaa9b,368a2c5b,6b980a28), -S(f1efd577,6955489b,57759ad6,3c5cd042,383c1cf4,a1ea3719,8b1ad624,8d2649ed,909afd94,20027b64,aaeea435,25c77989,674411c9,14bcfbfb,7edc1055,e0b0ba6), -S(eec2b3d1,446835e2,ed2b9c32,80f320d5,296fae6a,fee19e4a,e38da171,6d0e35c7,a9f0beef,738d4ff8,f56bcb57,8bb509ba,8ef9e07e,3abe009a,9f0e1a7f,9d1609e7), -S(1d45c89f,fddd05a5,5043c44d,b8d0211a,f49f3aba,31e3ac62,5687413,4ecaa89,ab2abf54,db899f51,6c19848d,f0fb6e8e,9b43de72,3c74c33,9ac74611,7a64592c), -S(61531e01,5b2f0ca3,e36a20e6,b6d7f2ba,e2a1e245,340afb7,f134c3c8,799374ae,fae6274c,1e646987,2aa0b680,8a7fda0b,f3d495a1,24e859c0,2ac50be2,72dd4596), -S(a1b129b7,c1803643,6136bc8e,f7b99895,c5551ae4,71b2c0cc,ee48c266,bcdf2808,b9f97676,9623c4b0,bf10a738,6081cb23,f68693cd,626abaa6,b3874be2,5af886c8), -S(27e38dcd,d63bab65,c77eedfa,7e1f4b46,203ff350,20c86fb0,4ce2ffb8,af8d7056,81f30a56,7340be31,52ce5c6b,877f2c67,a7db7acc,7f24e13b,bf836660,9d61f04e), -S(64919bfc,50072a00,8769f559,3ad0e5b7,72ed6575,81ecf37c,8c759a3d,51149fc4,5759727c,20ae86e,b38aa3f,5e53b848,8ecd2b,477dca0a,ffb83903,65e70900), -S(d392e5cf,3c2d4a0a,20779b28,f4957800,ec7148aa,63b2bcb2,348afe9b,d28ad57d,54062719,a0ee0869,b1a99d9a,e4716487,70386747,9ead4774,66df29e1,78c87c6b), -S(6b9fe223,333b0802,34fb49d4,85218d11,9123c430,94e4ffba,38f33bb2,dbe7d9e2,5ea16bea,b5101109,4d34ec62,e6a63a71,c78de1f1,fcb7ce23,4ba2f51e,e4eb2ef1), -S(b1a505c,eb85f130,ef6e4a49,e429b0c5,51a87831,f850ed83,6bc8649d,6097ce12,a887e16a,805c0708,45589bff,2b22fc6f,4187cc06,cecef137,9130becb,5d5d149f), -S(8bd25993,c653b1e3,6f477988,61743aba,a5ffdaf,fd0890c3,caeb2963,736cbb44,341aef51,13b0d08d,90e90ffa,56570d57,5777260f,e85a15c2,2b5b3139,4f0a8c20), -S(2da121de,147507bd,b8836321,40394006,afc65465,7c6d4399,97cf6c88,ce0c4016,3ec87a24,eb19c502,848ff433,7ac3f48b,9a56ca56,3d0bffe8,eaa98e97,49f04aaa), -S(147541,9e9e9ff8,5b93f56,2832e74f,6c8c311a,676a759e,7dc62c63,5faa0b07,40fb95e4,810607ce,7ed10d9d,61404078,10ddbc55,261badc0,5e07bd1a,579ca271), -S(7c48371b,7eb5655f,b9d95bc3,5660d783,b1884573,d2934346,c5a5342b,a0949cb0,8b8cfb2,4cab96fa,1ee1e5d7,7dade5bd,23fa7868,445d9ad4,723529db,38110dae), -S(6ac2912f,d959d41c,19ff8ac4,bc136e85,91944b79,470d633f,b9fe65f0,f72541f4,63351f35,d4a7787a,31ef0bd6,f28aedd7,864ec5ab,7d841f11,9163e351,e070fcba), -S(db08e4fd,63e16bf6,abc05d78,be6bccc7,c9b8e15e,334ad697,9205a2e9,c2100e15,eeb0ba62,e1a5ee98,c2e2cc5a,8d9cbf11,d265019c,9eea8f50,4aa1e50,a422d4e), -S(4160dad,5255da89,12f69754,77b445a7,26fb7b8f,6ae8e2bb,d6276ae7,2a31afb8,ab0817bc,7a9b6907,9f6db9f3,c9a77718,23a1d79d,9f2739b2,cbeca18f,e5b8fbf8), -S(3794fc72,f432c983,2f9ba8dd,b46b1c64,d979e899,78b3c14f,2f903ec4,75af091e,a898cdf,7cdaf6c0,3715e38a,4bea1081,fda150b3,7faa4a11,ddbdc350,c7e0bb05), -S(244b87a4,fcecef37,76c16c5c,24c7785,be3b3c13,46595363,b8c066ec,45bfe561,9642f5fd,e0ec25ed,bd2129ca,6c023ec1,a2eadac7,f6ec5b7d,2b7fe894,41e5aa11), -S(9de52b81,157165cc,aef44485,4c2b3535,a599a79,80d024de,5334b385,ecbb2e91,74fca165,26fe2f87,a41ce510,4dd5634,5cf98c11,803c0392,3eb4b8b7,60240c02)} +const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = { +#if 0 +#elif (COMB_BLOCKS == 11) && (COMB_TEETH == 6) +{S(629bee58,a391595f,eb20c534,4933937a,cdb2eba1,86d49f8b,845c1b5f,4ca87182,8dae4162,73c6c068,2e2aede4,76efa86b,7612c07e,f72070d0,dc4486f1,47e95085), +S(6fd5e13c,a94b874b,28cd574b,726efdbf,143ab108,1089b846,7b5b2ebe,6c6a3c8f,4a4db306,52c9772a,868b2859,57c5a005,d83f6afa,6e65d87c,700da998,ce651396), +S(609b6576,191514f4,83f5b428,500cfbaf,96871b8b,3348fe5c,1a131768,bb266b6f,90abb9c1,1bf184d2,8dbc424a,bbf74eb8,de4e0582,2ea5dd93,7d1e8b30,e5f695e7), +S(b5ec0263,27cfd922,23a46abf,a755e6fc,547806ea,333666cf,a43865a3,f4ae647,143353c,cc733d02,617f7764,7dc29c65,67a2e245,aed27120,e5fc11b3,95ffb9c9), +S(ac1fff6,cd869ed5,ca920544,1ceb990c,ce304998,10e27587,6536dcd8,1d4cd15,67a7a012,3e5ea292,85dedf0a,9f138b80,58a1d23c,2a233c5d,783bec39,b6482126), +S(c1807552,644130a3,f9b8aea0,29fdccdd,59e03e27,ff2cb1f9,9d13cf0d,42da7b13,85e99587,f77a25b0,bc64b882,bd279fa3,5be0262e,c2f5253c,70a43261,bd1fe361), +S(42919187,2b3c6877,c3b91266,79266e49,9fa37a8d,74d094a8,8c4a3638,89c2717c,1e4bd2df,a9757d42,285cca1d,856b49b0,ad481ad,828d826e,8921f744,7e04d6ad), +S(d4b10124,283afe03,4b278e5a,91daf61b,be608417,fc845e1f,9b9f52a5,43659f2,fd070859,75e2bad6,b34e0396,47b81a87,cab9fb,fdba802f,6ae3cc8b,67cc98cb), +S(ec4c2c4c,722a54ae,edc37acd,cb6ac490,3077bdf6,3f2c145c,7eb25e74,87c046aa,327bfe37,d745283b,a385dfd0,8e30b61e,2b4e5499,4432be41,fd3f0d31,c00e9ed7), +S(559e40a7,e151eeeb,46442b86,aaf4922c,12030adf,7279bb2,2bca24c6,67566a05,5483756f,60d26b97,82033592,cec21681,c5b5496a,c47f600,2013e5e5,f2ea82df), +S(c1d2e92,19c0138a,9f0a34fd,acc92f4,eafe13cf,1c004b6a,3175133d,6cc7bf12,8fa653f2,a20c1262,be59c7db,20f12579,b2adb1ff,54d84ebc,e5ad4116,3d2ebc23), +S(1becc6c0,e4861825,576624e4,fa622c01,139d9cb0,50c12062,9b87ae6b,9622245,d8516472,656ea10f,5b23839d,43f64e,85fc727b,faafcb6c,fc9c6e89,bf9c038d), +S(c483c2b3,8ceefd35,a9fa9e7a,da242c,d618cd6c,8b3bcb62,e39d68e,c1effab2,71964aca,9101863a,d7c865f2,41e814ef,3c20face,f46246b6,4a742026,471b2495), +S(3487162e,40c7efa6,92bc827f,9af9121e,af5ac549,b4ab6585,6353d699,a94a3783,f5b29042,28833bd6,e3ce0deb,dc0396ca,42701752,f930f437,d042cab2,8f135c1a), +S(eb3b21fa,f733f15a,b94ee0e4,3378e9b6,47571aff,d69292ad,a1b107c8,ad511d5f,cd95b4ad,b8768858,cb750cbb,4fa64523,6b6fde59,ceb71dd4,73a7fe48,9e5a2304), +S(21c8dd7c,34d3f333,758d1d1b,72748fe0,8695af46,3d0bd9ad,e4a6498d,1d01e9df,634d8671,7b885f36,a54b6691,35c3c026,667f3cb6,f2577701,beb0d3bb,84f07940), +S(608e33b8,14998177,5d78e286,d5c6436f,99623417,4e887da0,a95274a0,d120b57d,5d094ca1,181f8dca,87d1e043,f798bfaa,f1004edf,a470fce0,7ff8b124,328397a5), +S(f77710b4,dbc5f7fb,ac6b015e,956ed26a,6bbfb540,6a931a30,d4215aed,de610c7,7508a762,a7333ca8,ac244d6,47e47647,c62c82d,387d8df6,175fb563,1de83d54), +S(f37040aa,b0347fe,976d5980,cbd83db5,4d8cb90e,7f2d2118,85159911,af769d61,df228dd7,67fa0d5c,d44c3f6d,b09e662b,99faa5c6,688b088d,949ddab1,6f11e42), +S(7bf929f3,25374a1b,a0cbaa50,db47fea2,a5d1e3f9,3c34bddc,ea5c2250,d8252071,8fe2d2bf,b23a6755,50f16760,a6511ae8,4e4d316c,45d7cd62,4411ad3f,c72805c), +S(261bc0f3,a69d636a,b82248,6132bf91,2ab7ca95,e9a4925,b3f68bb4,745ee63a,68f52f7,df1ec349,77856c74,7b280907,cb3d456f,988ff7a7,225c4ace,8457a804), +S(60ef138d,e7086d09,711defff,68dad211,88d7f878,d616efb6,dbd3d498,5b730243,ca7c3297,3c56b178,b0cfb8a,da98748a,c3d06cc0,7fe050d7,3a6a9695,52500f8e), +S(8bfef3d6,4be90cac,8b83bf20,906b4277,75a6d982,23d5141f,b74e3851,50bc5eec,ea8b6b4c,c7c8d9ba,809ca811,3621c72c,b82006d7,81ff5f25,32010fc9,57858324), +S(9ca85f3d,4ba47ab0,e9fc0a28,74cd10a4,a8ba9aeb,ff319405,6140fea9,6e395ff3,41182ce8,96554f45,93768fc3,a656981e,69719f05,5469f9e4,ba79de22,bcfe8a8e), +S(38cd0c79,437b1299,9567999a,f54d4f8e,82a6354c,8a93a5ef,56ca2ff5,8a1ce180,c96f5ed,d78de5,9f560716,82b60b13,f06de5f9,49206258,80544bfc,73dfa76a), +S(be37e05b,9369b159,6b390290,3eb8fa0f,f221f599,1270c5f0,47edf62e,a1d0e6e2,4fc860a7,1fa69a27,fbefd8c0,906fc68f,4713fa2a,b37aaa2a,7edd3c8c,d100963c), +S(aa640e99,b091512f,85faed73,a3ac8ede,ee120513,b661f812,9a046a74,d624aaaf,dfb48ad1,a01fd508,e5652406,b681cc9e,13d0d600,68411dae,72d68061,6f6b94ff), +S(d08bb931,f008a1a7,38a16200,9fbf1ab3,d3d455dd,47f45cd6,617e81,8b8e0245,18d92218,21c9a2ed,bcaa5d26,2b7aba18,1f7f1e,7f2007a9,ec6f7d18,f038d723), +S(4e6ed1f6,c39c894f,eaa53e1c,e115fda,75fecf8a,55794628,d9a2202a,9dd5c719,1bb97d73,2e0e137c,e9c94d4c,763f9a6d,e1496548,904460d,df1c3a2f,73b66c1e), +S(867e83ae,610a24bf,401119d,8e1af6dd,414a7161,52b2ffdc,50f71f77,2fa8409c,d5d21ad5,ef365994,b3ad0533,92df82a5,6f677cb3,8500781b,a769dd50,1f6d235), +S(6031361c,6dffc505,dc7e1887,bc75c1d9,5a9db023,8b7240e4,c254f855,b35686fa,b9a9a979,c6b8c576,11eeb783,8b4ac2ae,66506bb0,a203fdf6,3efa9b59,98c7643d), +S(8502d0f,34684503,68784822,f4510c5c,562ad30f,be29a792,f0667e83,b6f95773,cd0e6511,763674b5,57fac9f1,bb62f9e2,3163a0a4,cf08cd52,a6d10064,d8b02ade)}, +{S(840e41bf,13203a96,f41ea041,1ec034fd,db0dac3d,53b6bbc9,4f8a3a78,d0371235,71b51550,a79af319,56c9b3de,fcb167d0,c3e318eb,a852eedc,78490dc5,fdaaca85), +S(5678a034,a24a1607,d78036b2,23eaa3c3,845c9f9e,7293f656,7390354,2f714d5f,57f624be,ff5d1774,c6962dd4,d14cc565,acae170c,7aaf8c6d,b0552daf,e3bdf48c), +S(722012a5,57ed9c9f,9d737a87,39954469,ca12ab29,9dedbaca,507c1259,7a27c6f1,6c28881e,a0e62453,80d73a7f,499f05a4,d9a9c04f,c2ba11e6,9fdd0b6,7c5d5ee4), +S(70c638d9,3eeab892,8bccf1e4,82368eac,a03ca8f1,b30f7b2d,34258539,8c95c014,f8635082,3dc2a200,67dfb293,891929cf,18a810f2,5c85c169,159a4b44,b190a029), +S(2ce4a530,b5f6c77d,c0c4d891,6e89b24b,c25c04c2,723842d4,29300f82,5e260458,6f306154,4d1195ea,98b972e,91a962e2,95a2a4eb,9be03949,a789b01c,f61dd705), +S(89e71182,851bb441,c0af4e31,cad89dc7,3947369b,fef12eb6,b1dfa71a,72498c51,20b7ffd5,878718c2,2b5bfdc,ac422794,63aac0da,4bcdec2a,8f3b538e,3a9f574d), +S(f01f06b8,da0ba34c,e1045e83,adb95fbe,b76f134b,35235539,6b07f8de,9dd25869,afa0fb5b,45ad1f24,73460f17,5ff4bfd8,f162262,65c423fd,ebd92bc1,72f3aa7b), +S(f0c217c8,1dda2201,1f46648a,e096906d,71fba006,1b4dfdb9,85dfe59c,9d8f1894,d5ddd6b7,bdf2a6f6,cba166ae,4c01c60,b012c9ee,ad954a46,6f631f9f,928b3fc), +S(bd9acff2,87cc2a2b,396aef61,b0937a49,c43a2366,a2c3c461,c1283987,a7b6f53,828de0ad,b9067b2d,8f8fefe6,ce3a5c94,e7d63ea1,7c891d2c,5f266e8c,a5fac116), +S(ee314d97,2b9c10a4,fec9f8d,ccab0015,d4923e52,d915eae8,b319911c,7a8fe379,82057aef,ff05c496,ba8b4753,c4e57832,aba9a724,adf70a9f,1b3765ef,952ab52), +S(d39fa7b,9b87ee2a,aa32454a,13470406,c8024c39,cf387143,3364de62,cb94c103,5cf1309,530f9e09,c9b38ad9,3a778ec5,533f60f6,4a42e31,1cd97c2f,c984b9cc), +S(5ab1a07e,5f6aff68,16780e5a,23c9faff,b29cd7d7,5bfb8984,4834fb6b,c6b34a14,deac47fd,6567023e,b5ec7a94,a0133bbf,158c0425,c0a6d288,23558986,314d54bd), +S(b1a4ecc6,94bb5212,98e80464,cffacd32,331ebc7c,4d545141,a129b522,a4818830,9772044f,3722ec57,d76a049b,2afce2b6,319f0bbc,b17c7f06,175a288f,3ce3534d), +S(56015e42,81aed744,a0859e29,eb913a7c,b44ebd39,2ed8c0b7,1eb42f9c,9c93c8ba,8f973650,45f7d8a9,24a276ac,20056895,fb2b0aaa,4b35468a,a51f41f,722b9d33), +S(7d99a5c5,21543229,c8f9c7b,50dbaa64,b200bf86,47c71b35,a0105dde,2b3a8e0c,eae09ef,3ffdec8b,9a30291c,244c0a72,6466c26d,fe2c8d30,174f57fd,ec6aba60), +S(ab7d21f9,1e7dac68,afd6e4e4,794551d5,55a9f42,59825109,5b25652e,946ebdae,8805a806,710ed7b0,fb99ff30,130c074c,6a0be3d2,abe6e155,f9c07496,f8b92454), +S(b31a5f85,d65e5200,8f5261cd,fd6d36f6,4b2a1f3a,6f08d7b8,defc7e84,21d0f7db,2e6d46c3,3733b3b5,597a133f,7459ee2b,570ba333,4d1e7648,1980dda,1aa8d2d3), +S(30af789e,850c8ef8,9eeb226b,27786679,442a9a0c,35cb7337,98345400,29220fc5,f6651170,c83e24e1,eb6e8da,ffa0b0bb,a6c53676,72558d44,c5b77176,3d9b5d7f), +S(8d87f808,98fb8007,ffd5093a,bc6bad2d,23e09e90,e6967031,48d5418,4c60e0ae,3d14332c,21df527f,a2e98243,d3ed4bd0,6634d799,9f62efd,e8d6c919,8ed716a3), +S(a961c219,eb9ea127,205af30d,909ef732,8cc599a,b2080966,f615796e,1126dd98,3e235ae0,37b10074,32e5cee5,56778856,1d552e3e,bf40bb82,5b527cac,8e1e5b9c), +S(b9c2de21,40cea728,2aec5293,bb77dc7b,550a72c8,84389c05,310651bc,7570f2ea,74171cd9,4a5683b7,5bc7c5d9,b4c8fc10,1fecc3b1,b7349ce,840b6ca4,877fed21), +S(cd041ff2,e8191946,8fd7ef0,c33021d2,9533cd75,64772252,c686f718,7e33166b,3f54a9af,e8597bb,faccbbd2,9280e60,93d31bc5,b366aff2,2c95e21b,fbca6041), +S(adfce0b5,8a9cef85,e690b84a,c7ccc6,8f5aa4de,ada5e265,3720412b,e1f19ae,8ae2dcdb,c6ce83be,825593d6,87f9afbe,a88af079,564c60d5,c9b88898,897515ea), +S(833a50c2,cb5507c6,60bd450e,cde341c9,64f2809a,e400215,c52dfaa0,9825df96,de85e216,493cdb4c,4541f720,201f4c67,1472b6a,d61cf8ea,3cf54ccd,a4584b77), +S(3475027a,628ea423,2d689d70,d45e975d,39d62303,282b16b,1f94a427,3d7ea746,97c3052d,9270df78,6efbd2e7,beaa58cd,f864e28,905e3ab5,507cb9aa,e3c69160), +S(cbda2707,e61d9e40,124668ef,7ed83973,dd293dfd,221396a8,d27e7aa1,392edcb3,fd5023a8,af8eff08,f0e3c8b9,b6a22a99,b3ec3aeb,7e0104dc,1f8409cc,d83d8a02), +S(963722ec,aced2105,2bf447fe,619a8532,dc78816e,2e17a111,3ffc601d,9bec0381,f31feba,259f7d0e,3c326c69,53aae60c,1e0479da,5ca839ea,77c6f1a4,9419172c), +S(fc531e1d,49d2a984,83c861b2,b299b8fd,b26831e0,3bced6da,5c4449b0,18363be7,9f9cc9b0,8d72ced1,998c6329,a17695d9,c94cfc76,ba9f6943,1c5dab83,60f2942), +S(dab255f5,b47d96d8,ec5272b,5cde4ca4,33070920,84aa4866,d53b674a,330aea2,feeda13b,a544f090,b790514a,42064cea,509bb3f3,9dbd4567,6bd75414,37579d7c), +S(ac5b161c,fcc42998,71b49d1f,8cf35bd4,dd6bf98e,5f84f2f6,420bc363,b9cac257,4511d4d3,1fa26d7f,e56f671d,7467bbd0,41358b36,b60775f8,65f7d491,3d17b685), +S(b62fbfcc,2aca0706,b0fe67f4,ed5d96b,4a65b048,f73e8f4c,9782e1ee,36189e31,6549e8c2,f77bc824,4e1a90b4,e42ca64a,5ade1768,a0996d69,8d7b047,7bfbf862), +S(56938443,5e509000,5cf3dd18,ea629078,e15097e9,da7bb5c5,737cfa0a,a40e8818,f86a1815,4f379054,11016994,9b2eba6b,477c32b8,b68091a4,4b14990a,5e8eaf92)}, +{S(7c028bd1,75367939,74871a6b,cc957d95,3813331c,87ae606c,17aecbdf,a704ebb4,4fea040b,a0ef0319,91ff9b8b,7829c0c3,93895439,d506c5c3,1a1a3fd9,e32e7e59), +S(24e966d0,bf1227ca,11eb8fd7,8dc5369d,2bb9b681,927990b6,dd02b948,fc18a169,72b7fa7c,f929a6b1,c556a372,4149a279,8d57f504,4b50a1a7,922cfddc,17308ca7), +S(a2b7db3a,265b30aa,94823577,6d5ea839,c4fe564b,97a5e3da,313f7fc4,5de617c5,5e895546,a2778162,4a91ea4e,c104c911,85f3e954,f8378fc2,bea41a3,f1cc9e15), +S(e365c695,449c9976,cb67ede3,325d9229,ee526349,e6b255f7,f4e72184,6722580b,eff99cdf,a0920505,ac37e46,b812d47b,31a29113,e491208,a19e3edb,557ac2e), +S(c3d90905,297c3a65,2c6c3d5d,915cd9c2,d741f472,4a47c8cf,35e5cf3,cac9dd11,8e9ebbd,34a7dd02,24fa6e33,193cdd72,4906dc81,a5aa41ee,4a34d3d0,4b2ee5b3), +S(6e4e23cd,ee4388d6,e8b61f8a,af7678d1,a62b3e1a,3385d278,895a02a,de4c9f00,f69b843b,ae39cf41,11fe9b99,a0287057,5695421e,e1ea690e,2e76d937,e7e32c01), +S(92eb38a6,3743088a,39b58cad,4eb4a27e,a8b08c27,444d704,6d2aa5f4,89713217,22af8d6c,d3567a6d,cf7403ef,e0afea02,48ea4266,1577005a,9afb5f2a,19611864), +S(b3c84323,e2d022fd,d2a80d07,203f4a26,f5d32dae,62842072,9663a994,3a829d08,9a899de,82329d94,83b88e1e,1bce53ed,8714cad4,c68cd491,1b71bc0a,e3839821), +S(daae5199,57a6002,8958b22e,6dbbee20,c4bbd8e1,7ed589e,b8528f35,7a4dbb40,afec8a03,321586ec,ac38e941,7fa8e342,f0542193,59decf5e,56479a39,c32f92af), +S(7afb9a56,89fd1344,cdbc5c72,62dff7b,718c2e47,a6e19ec,665af795,86ed0161,d1c2c9cb,60a191a9,a3db7e20,2ebc2eff,444bbaa8,d81ba086,6f8825f3,8c765f53), +S(8d0c4a2a,e72b54c6,236d997d,61a2a24f,ddbd39c7,ee16f1e7,d7c45b22,b4bfdac8,15a58f4f,fdad9e3f,b4d33c7e,170747cc,6a5abfdd,bfbe5814,ef0c3611,6a0a9e91), +S(24d8c0ca,53400126,347e67f3,72f19298,595b6d33,76ba2f19,2fba6dd1,7b57bda1,7c01404f,bd316814,f10734a1,559049ca,d6f20e90,d6b13ed5,f9542630,db77f9ec), +S(4c2b7a58,87a49df4,f98cfc72,22fdd832,362b8cc4,c5f4fff4,d0a20674,c9749bde,c2a1cfcd,e8636288,31a5c450,fb5cf552,c76e581f,9274e5d9,888a3a68,c37ca349), +S(2028e381,f42cc2f7,a8829308,bb72881e,94e5b54e,3331d848,898ccabc,bf971cb,16debea0,203f0709,d9b55b0d,2b8651b5,cb085d8c,8f56708d,c1fe4d33,a616dfab), +S(d11e0753,f72b7c4e,641ed50f,84dfa24d,a0baea77,98fcf062,8b2696ba,a7ec2529,55af37fe,88324646,777387e5,a9b18059,ace20e9,becd7488,5e43fee5,fa6809e2), +S(72309865,b8a1a6f3,9d6d561f,43ddf5b7,f2d022ed,95df130b,2563eaff,9008a95,f3fca0be,3ce7d9eb,e1648964,58eba87e,934d000b,a535f223,868dae11,dd5230e), +S(adca4785,cbf38a0f,28de7b36,daccc761,89b8b918,f3fafa7b,abbbd9b1,4ed5485f,880d76a6,fbcce864,657edb9b,349f124d,1b22c7af,2b0ff833,40d7a0c4,84b49de0), +S(bb43e0c0,93d58c6f,3946e58e,4727d7e2,d223c84d,513c4e2,222406bc,aafb03c2,c00f7dc8,fcbd55b3,6a95f2f4,a3a07b7f,9599736f,af099a69,e2fc2630,a2aef1d5), +S(179eb588,d1c7aa5a,24e51f5e,6d86e4ed,2e6f0f98,bf956b71,ec1caca1,b7f775cf,42f461c8,a784f643,d5a8682a,6ec9b470,455f0ab9,f269140,b1ad2376,95f64afd), +S(9144fc75,b00f8608,714f027,16b30575,be19dc01,d3689e8d,2665d967,6a077d11,b168c324,7dc6c31e,8302b6df,a2e7c053,dd849538,f9d45b87,14d889ec,cc789704), +S(d6cd2a7a,b7253b86,34231eb3,2793f062,bdf103b2,4fade912,6206e745,a3b429a7,9903e507,dc5e3a61,d73fc83c,5c4ba476,6ae92655,9b208369,bee55948,4bfe444a), +S(264845ed,623bd3f3,808ca51e,517def45,1fbc237b,e47e3ded,70c3769b,391a9f83,cb5022fe,3d535f4d,192e73d8,5d9ede23,78e0824c,e560a97,d53aabdd,f8717377), +S(2df9621c,cf3e67da,54c47ddf,81e3ba7e,7b50e713,cc7d08ac,d64f47e9,85c4f334,8058f6e8,139d8e87,cce4a389,c470e3d8,45da3537,ccead4f3,abbccf42,a5fcc49f), +S(ccfd6c4,c5966144,32d2efc4,1ccfa0eb,3e0b44ed,a4558128,c3e4d68d,949a5cac,bc77b87b,5f50d3a9,6b28d5cf,fb371b4a,36cc1360,15c548b3,f98d661a,beda8acf), +S(4e2e6052,cd35d585,6531fcf1,73bf124d,3c569bf6,6cc54ed6,9a520d42,cb836296,6381d100,e5d9ae50,f1821122,b8e91a5e,f365edee,556fee1c,2fdb6d17,3fd29c65), +S(6603d715,ed0f8725,7d9c3f29,cf86ad4c,aa0500ca,fa16a708,3168e265,b87d0255,9d2eda4a,6195e2c4,a4576e4d,5d02383,a3a01b2c,f94ab8fd,fef2f338,15807d31), +S(f09ef30d,fade81df,2fcafe31,387ed34,5a8029cb,e93fec3b,eaaeb8ac,8adc9803,f9f3039e,5b73c7cc,cf841eb8,1c15203f,ba192e,9eb39aeb,36f56c29,44b286bb), +S(ebf4611f,cb3a44a9,f9d5b00a,c559dbb5,394840c8,41a06496,bbd2011a,2508cc34,1e183324,9a610584,5d62ef4b,685152e5,c75c7525,c703f81,51bdd87c,6fda0d43), +S(31fc3226,c19aea7b,4845ff2a,ddeca6a9,36505a49,92102cb3,499d66f8,a6e1a3b5,49babd41,b1e8a6c,a728f971,d8d8cb76,47cdb94b,89767a67,fd975ac6,93f144d1), +S(be1e37d9,dadc4b4b,7a5ba74d,fb7eb55c,2b0a4fdd,81564f8d,51038afe,f716e3d2,de6f0c3d,b6efc974,975a7d6d,3c6e9d44,a712879e,4e95c612,164273bc,5de1f4b), +S(f8034e14,2425cdce,31e82b49,cde33ba8,3630d1ae,283b8b47,73960539,c67f1652,a302e3b1,860252a5,e7114568,748746ad,1e02c2e4,280bc913,dd4b4d2f,92a561af), +S(21e709bf,369cdb2d,b7f51b10,f0ff56c1,2c1938d6,18419d00,34e57d94,7b83d5e2,d7e09ab1,2e7d04f5,aab3a75f,8cf75876,ddc3cf0d,cb4b9526,ea7f755a,dfe1e495)}, +{S(638b6618,c1498946,75a1a943,8755a68,30d7dd3c,9d8a9f20,d65a7161,9c8b477f,e4e66035,e947c73a,c34a48b,b43a3762,d1038e6,893dee23,cf658a12,190d2a56), +S(4b6ce93a,acd4954e,cf0febd1,fc9a965e,ae7fbc1e,e24a12d3,a4b86573,62eb255d,8cea4838,1bdf4e5d,79e25ed0,1aab94b3,5f00267b,3ec7eeb6,63833507,583407b3), +S(e2a42110,3e8e2a80,a6451f71,b348434d,7d508023,beeed16a,d87417b8,5c7b7913,5fc15b62,124014e7,fa8f95cf,78ce8415,d46a1f97,d88be55a,76431786,8de3d605), +S(6949956,91582c2c,2e14576f,5ec0dd37,65133237,a4e43369,633edf69,933d1f75,5ca8c2a6,329882f5,2daf48e2,e291c48d,febbbd29,9ccc9ff,3ad54ed,33ccef43), +S(55d836af,2dd4b8a5,7f20eb57,6886790e,a3ccfcf9,2a2940b3,646f263d,685f62cd,7cc1ffe6,37781c72,d3cc26dd,9d4147c2,183c8e0a,95b87742,52ac47ac,19db266), +S(442a3090,46bbf3ef,503a138,b60ddfa0,ea4a5901,ae801003,f3f18ad9,9703a44e,129d9913,eff78c49,16e67c4c,cb658784,fa47da35,92ea1c98,4054b371,a275639b), +S(76981efa,29944c2d,9463fc94,67a92e1f,9403c287,dd595292,4860aee4,b78626ca,c87cb5c9,ce93ff3c,23189404,cabf8e09,996c4cde,e67935d5,874c705d,6a7f95ae), +S(42ad08fc,2a1eafc3,d793f04e,304831e,c1bae89,c7d00b24,7785d870,904bef5c,c3913fd3,6b8c08c2,553b9c48,5b90221e,ecdc8d02,6d558bc2,5fdd6ba3,df78ed63), +S(4d70ffbe,efc6254d,cee74a89,70244bd3,384b3af5,8510ca61,258fcbf8,f0c82575,ba3e19d,b022a75b,c75cbaea,84ff912b,867124d,a20e0d28,a007fb74,9a9d1c7b), +S(4ec8dca8,7079487c,adfd516,da2df139,5477b524,df4aa6d6,4db5e206,cfb14b9f,e88e5bad,c8654d60,fe1f8f6a,73328209,63bb10cd,31aae381,ea1b4d9c,eaf9cb27), +S(2e5a47c9,a47cbbb5,ef701784,34798a6c,48244df9,dab1e5d8,83c7f732,b89c7d79,7c8202dd,cf7fb6ec,471856d5,830d59e6,99c04377,c553d835,f64cb333,cc405c35), +S(3ca98150,bc5f116a,e7034a07,628d698f,67cbb8d3,74869ab1,534464f5,5e8ed24f,fad702ec,c6b738de,5b653f78,f51c98d2,1e4bad57,4db97730,58324d1e,12b89f9), +S(f414495d,9093ad22,11e001f8,b07b38bd,f5430a11,72899bcc,2c553b55,a9d4a225,bc130e93,998db229,6aef128a,5b8e5b9,9cf67eb7,713aa7d9,9fc4c902,af660f4b), +S(44e794c9,5a28ee80,f9b64193,9c626a78,4a851a4f,84f28887,9eaec508,1b60e508,b219e000,1b07a275,f63dfb3b,e977a40a,f505be1e,d3eb8194,b919b9ea,70d7198a), +S(35024622,bc17bec1,9c352280,297ddf7f,41654c08,61c3744b,13c74ed5,6673b98,64aece4c,3ec0b19c,cdbc06b7,4eb15704,50ff689e,6c5bafb7,6ae99396,12f4cca0), +S(45c4f36c,ac4c4738,ab216363,e12b2475,50b8ef09,7a986ce1,60b0462f,f8725a58,fb944806,dee59834,7d256885,3761e3a,9ae666b,9b0ee095,fea33ec7,bbce9a5f), +S(20a0b4f7,cfb58bd8,d09d008d,70e7f807,b4fa61ff,65f2e15,f00bddeb,55df1124,7961d1de,e98ca40f,4d09e5fc,52ae4916,cafdd6e,2bdb9f9d,2776239c,a3480157), +S(fa10af8c,eb2de4c9,3c0c2cb0,95f95911,755b19d9,90f17e33,69930d6,6002fcd3,68a3bfb4,533bb5f0,54fbf91c,b771b08e,e388a61a,9727bb7f,a3a1f67e,60b2eba7), +S(d417d7dd,30ebe9f1,7d52edd6,c82d91f9,25d5987f,a6f53b0e,d769a34f,e557c11e,ea89c810,619e32f2,369258ae,8ad8a456,cc36d87e,b45a42d3,83956039,62e437c8), +S(349b002d,ecee0e4,1788a3c0,cabb9ff7,c17848e2,78ef8905,63924c55,52d59853,47583a2e,7ff61b9,6fa168b5,1191b363,efa3e0a1,ce825a3c,5bb04e5b,e403b4b0), +S(4b8efc8d,7eeb3554,b5128e8d,ce20c29,697f79cb,29f61b4e,a2f7ac28,57910bb,e3cef657,7b5c0d2f,dee52c96,b6353073,b099fc9c,65688969,24cd744b,981c5ff0), +S(f356e8cf,5785b05e,e99a2b4,d202b64,2b1e98c2,57741e60,7241fb9f,d3f5ea2f,9079fd65,59d5a93f,91370d16,20ba487a,a8c6ad3d,e67f2c83,a1c335,fb5398a2), +S(bfb74aa2,15e5ce36,97cb6156,c2666ef7,1b579a50,56ff60ba,d3d5e10a,7eb2d31f,3def8a80,ddc3f407,e30d11fb,232f0e31,191bba1,d51a7eaf,b86d7f97,45d78dce), +S(658748bc,bbc75ba,30c969fa,371fc1d7,76c32a5c,7e632201,264deb36,b296ad2a,c173fe4b,14ead07c,2c6574c,8887500b,53f6c02e,dbd4048b,e69aab41,9267ef9f), +S(f51a5ca6,fd6dde25,447fa46f,c0984d26,66004c02,8d402624,8886d0d4,604f6ad8,fd4290e1,7b2928aa,f2e03b98,97252b82,d481c4c5,ad4edda6,16dc1cd8,e7ee83b2), +S(20ef1ab3,491b8d0d,a1565e2,8dd92dff,efcb88f,e88c6c2f,6b100b30,b58249b6,6814d32,7b5b94c4,12fb770e,2fc4077f,fa9a336c,9e7db2a4,bc7dffa4,286eee0), +S(d98785a,82dfe5de,343bea0,d91cd8c4,93344b86,7fffe1e6,efd7758a,90cdd899,37ad7f7c,5783d262,5204bac3,4405c207,972b7fb4,cccc3585,ee152f0a,48ee16c4), +S(3885e910,18a66e64,2d3f0c76,bca6dc82,a6916cb,1e46a858,7aff5ea2,d9390689,20765590,83ba89c2,14be9178,46e40553,ea195c49,de203c9,d175296e,a4430819), +S(c88cf650,3b50f5eb,7bac15fe,2097ff76,9c57b983,1b5d05c9,fbd8dc58,d4a9a746,b6443b76,64984192,e7056478,e9f372cb,21a0c7c0,cfcb0e84,850443a0,25ff42b6), +S(2831fddb,2ba2d301,2dedd58,a3f47434,3450985e,80e4e4c1,646745cb,1abc69d4,1b04e1b7,db84b6c4,882f264c,7bba91d5,2256dc97,fdd22e58,483dec32,5020a257), +S(5e492bf,c9d19dcb,c3bcb9a8,b7bec84c,23c359de,a78aa0a1,e0522232,df037abc,614fe5b7,cffedd76,35d371b5,2d89baf0,55af687d,e6c12d80,b221d0b3,9d03d0ac), +S(bbc64d06,681957e9,685c9864,c5f9bfda,34b4dd02,6b749399,a12bd8de,87f311e7,3c525096,dd6b7d11,26c6ca50,5064da63,f7f6a203,87594f4f,e4ae0403,fb4d66b6)}, +{S(2b00c7db,16887372,753ab219,17092563,8c603992,f501b07c,9d8442b3,721addf9,8e7c5f66,4c2493ec,77cc74ef,d9221235,f26bd3bd,6f505347,39f0fe19,c41b9fad), +S(56b9a3eb,d9360224,56267f52,21ade9f9,674863ee,4bacb7c9,ef0155ca,b36b336e,2e2b1a4d,f6c150c8,6dcfe9d2,e2836579,f82ac4d4,2f8fa4d5,d814b952,e92da69e), +S(ff52bbc2,83bd15ad,523e6d08,873a8896,9449a1c1,c5ec8570,ed532000,5a92aa3f,dd9c534b,e59d3845,a1943435,1a20513d,1a829424,e65ed8ad,60342b38,6578b21), +S(84f79356,86b0d45a,13a1ce22,7e7c925e,d80be5d9,9fd7e671,270c4c35,7254e9ce,3dfe2058,1e91dc25,12c16951,c667fbe6,83192bf3,3fc0bdec,c760dff6,730f82be), +S(db14da0a,86bcd275,71cb9348,36268bb,85c306c8,9ee1b78b,83c247a1,71c7355d,66ba535e,81e877b4,71b0b75a,6545970d,6e33cbe0,ff011e3f,d653d026,f4fff395), +S(28bfbd9e,44554371,74a4c24a,cc65ef45,5fd4d39e,b466e94,358cef4b,b0eeaa5,5f5ce6de,2925acc9,e503d731,d46601aa,7e668001,669819cf,fa54b3e3,dbb98f32), +S(a7b21a3f,a07b4049,7f9f5087,c763b431,d5f04cd0,e7b7e0dc,f9c6c664,df7c6ac7,daf23f35,b903ecc,af4f50cf,459deac9,85d0d008,3b5afa73,7131a61d,8591bf9c), +S(12fac42a,40935aa,e881894d,245b9691,cd1f6ad0,e0481e1f,444e0ccb,6ee88781,c519e0b9,e3c19fc8,f67c07e4,f357f43d,589ec23c,7714f7a0,4347be96,4ca572fb), +S(5c2e28bc,94f8639e,50133dba,9b6c8a35,348eefdd,2fdbc18f,2abb792,eb8807dd,c546b3c2,5f2809e2,7977a8e2,3a1c3ddf,36229f31,434c90e9,1386ee84,b64e8fdb), +S(e8e73382,fbe8b94e,58bef90b,aeb28305,d27ea48d,9c5f6e08,ef47e4dd,5fad6b78,d3529a2e,86240f06,a63ba03b,ce419c05,24d22622,fab9107d,aaf3016c,6ff7fe3e), +S(26b93629,ebe68d1e,878e94b7,5babd663,6fe1f6f8,659b155a,e10801eb,c2cc51d9,f4630056,b3e532f7,32238911,555c0ffd,f4951c9a,b2f45119,cb12e774,aaa2666), +S(57b3b642,431f793f,24862328,dbd271ae,19d343eb,c3b0ca7c,affe4fcb,319d8d94,1d7ed35a,5abc7e39,1858a9fd,b90f907e,6a065648,c00f94a7,75f06d2b,1cacef1a), +S(c2123794,d98f0311,c1327522,1767236a,6f45cb14,8fcd65d7,e0be8d13,2a650953,d5a382f,fcc2ffba,3917763d,ebe0549d,66f358b,d727c281,288551f8,4ecd193b), +S(16789662,9208b510,7528efd1,36036980,994d6c3e,5b34c69f,ef3b86a4,3db9e8f2,217105f8,39b0ae0e,932b5207,e8e7c190,3ea463c5,40c043aa,e4f8b106,97ccc84b), +S(3a0b8ffc,83a1702e,214adfc3,79bec5a9,753274ef,9e3271ca,8ec5b067,a5f3b6cf,2c3de01b,f27dd574,4496c2a4,75a07e60,71ee60ef,7eaf1c94,c257418b,744d1338), +S(482e5ac2,6477feb7,6c848d58,40173d87,1687c5b7,3b2970ec,b8dd69e9,3393f923,dfb3995a,ca5b54a3,b48e1dc,107023d4,dbd7a918,6adf2af0,61f92160,76e7f78c), +S(3869373d,638a30cb,63177204,bfb194f0,2c6ff503,3cb4ef1f,b146741a,f3b495ed,f2ac9f3a,ca159c7,c2ce9f48,e895c543,d3f19066,74f335b9,efdc4b47,4ccc23c3), +S(98c16ec8,54b34ea2,f08aa4fd,3ce1877d,4a36f2a6,4e673191,17f74e5d,86e57f4e,3448646f,c9aaab0f,4d9ec298,8f7c07ef,448888e7,6318e0ac,552d7cc,b59820a3), +S(1b3a4ebc,8ad1c200,2847e182,de7c9eba,f0f7a408,e2aa172d,484bb9d3,ab897b73,b93decef,69cf2da4,5c3a2373,ac2abd77,311fc1f9,21e7df8,5f5b3504,a5ecbdb4), +S(57b5b2d2,87bec103,e4aa7b96,16129718,64780441,fb5ef847,19f16d,a1c909fe,2c2d983c,d8c37a7d,653716e6,15756121,9e5ad5ab,25664967,67a0fbd8,e8180c71), +S(cd7e277b,ae1498a1,8e7bc00c,2c299a49,69f6862b,bf96e6d9,f5143db8,7b582115,f9548ddf,c27108bb,38f80025,6ffdc25e,28621c17,c370a40e,5009b968,d40660bc), +S(80615f12,82ed7a8f,bdd70890,77c24f18,c03fa395,3cbea7bd,32a26c7c,260102e7,8d54a3a2,83383d6c,a633d17d,e2f4f756,3bcc3826,10cc1012,3f2f192b,e654c2cb), +S(9b16f5dd,c8c8c8d,53786b49,e2d025a6,838f6322,700fe105,7de6d78e,92281a9e,a36aa3c2,f2034285,76f5c570,63bb1bd7,e6e0410,2e1cd2dd,f100a54e,431ca08f), +S(f1d04075,35ffd40f,2a0b59f9,14ecf368,67700c5,b33e15c5,153fa9b1,c724d36c,22a8b48e,4db1d3d1,28cc735f,99db74d9,ba7457cc,67b8fb39,7b38fcbb,153f7c0a), +S(c252ae6b,cb711704,659c37a6,f425b215,1ac8a4c6,63420eba,899127e8,1d8df3b7,8e9a75ab,c5a2cd8c,d44331ea,b07e5d97,a30c6619,8e382261,642c0e10,8f6d46b3), +S(59f6fadb,4a8a3389,999b93d4,cdf1f8f0,4735b397,9fa5397e,64df420b,85876ed5,c6e8baae,fdeb7019,23a68b71,9c88596f,60742a38,db04d7e5,76bd1b8d,1ae25a6b), +S(3c2e03c9,3f610ffd,db519c7,80c201ce,b58ffed8,ee10e21f,d1610e99,33fd08c7,d339d979,38e1c5de,7492e7d2,d64fe34d,ed889d48,54670345,1c51432f,ec6c829), +S(59d16070,f9147ce5,5bac599e,aaace0ef,24c02ea6,85249cc6,ccfbeecb,a4bba83f,8105bf41,47f22f7b,18c73941,3a85ef06,40bf6805,51c68a10,e16be920,193977f), +S(3aca1182,3f31b2b,a12e628b,604b1010,62c45fce,22e15dd0,8b9b5ef9,a53dc02,bdca8ab2,d2dcab6e,3a98e7f8,7e192c19,cae60952,fc6f54bb,d46acb49,60d51c0a), +S(261e9b93,3648c7d8,d5255219,fd0634eb,112e1dd3,fcce0a04,135b2784,e67b5e32,e0eb5ec4,30b1f9ef,2bd10916,b21f4fe1,4cfc80c,2bc179e0,fceb8678,ff933068), +S(75918e0c,a0f03b34,40cd6239,c108bb72,f293a881,a1f2e9a,73c604b8,8c451c39,7f02a925,80e50aa2,5b786d10,422f1d80,2c42cb37,27f09ff1,1f5e0dd9,bf6a6c1c), +S(42025e76,3c05c64c,311a275d,d6f1fb3f,2da2108a,39ed24be,3de83123,b1c1d1e9,dba2eec,7405b67c,a1915b13,45702062,7bfeebb8,6b90dbd4,87849e5a,756921c6)}, +{S(ef2c5fa8,b23285e3,50d7f05d,bd8c96bc,6e662824,5b10e1cb,4b659bc5,ded5836f,1b37679e,1177b653,8975790a,4d5d2abe,3626d636,1d863e0e,1db5881e,8e0c54a8), +S(a1d5a92c,93df3c75,a06f9c2b,a604789d,fd487513,62d957be,68c033e8,3e202fe7,64c1c00a,3964fd5,b35fb52,b423b285,77c8d269,bb1ffd16,325c5e0f,7be08bdb), +S(ef13ec66,d46813ce,68038fcd,541e5e8,bdbc970d,337d7b5b,9099d0e4,3fa4288,7ad7f4f0,c8345229,96341248,b1455ebb,89aaeb6e,1ae9db25,1b86930c,9f779fd9), +S(aea7cf4c,afc1079e,e61396b6,2df9bac3,bf334745,54af4678,8621e337,4c7486c7,c0538605,5911c893,459b98b0,4be449f1,2e9f98cf,ef4cc292,9975d42a,f460d65), +S(8f082b3b,6476b4e9,ffb317e6,1fec0cbe,8e389041,1fdc87d6,8d4d26f5,44c2e6e3,eafc2bd0,d6570a7a,cf8bb5d1,6cdc1020,456473c9,e7fec1b7,fc6217cd,89d0a2a1), +S(e0d6310d,e5e664b3,164faddf,39c93676,4ddd3f0d,f5e007ef,5293ee35,980ae0cc,de093cfa,ca1033bf,47e88723,4978758a,74b93cc5,2cef48a3,daf4dda9,adc79ccb), +S(2518110d,5d064422,5ead0e2a,5ac8b8b6,b1fb7fe1,55e351c5,1d39673d,dab0f6a7,84f0d6e4,b497043a,95b6af9d,e72cd502,a7b6a68d,ecaa01b0,9e0d8ff9,9d8a16c9), +S(6dc820b8,5db42353,c97453eb,d7d768cc,af9732d7,c261bc6f,8399caab,34cf5b93,30b168c0,2509e2f7,2035f60,8be8b89d,577b6e72,540f521,934fe980,7412459c), +S(bddc1c75,5bca9911,3c9ae05d,c14441e,2c707fe5,8a329f8d,feaa36ff,12771376,8c0087ca,b7688dcf,5a3cf1a3,3c27c7b9,cee36007,3aeb9b9f,d7088623,af20f62a), +S(b6e5ef5a,a84c6d2c,a209d50e,8fa8e1d7,93c61ed9,bfbc22d5,2ecf293c,9489ac13,f76e3adc,a89cb983,b6b670f9,5a7e774a,c015de5,1ba56417,40ac1f68,e3df377a), +S(26699dfe,93788eb8,d91cb601,cae628e5,75e8468e,73f6cefe,588755b8,c396071c,e5f9e00f,bcf6f1cc,cd39ab13,41cd06b0,ef2e789a,17d761f6,6a7a83b1,c036791f), +S(72f7e16f,77f0a4f7,92db2cd0,354382af,34282dc0,7b8cb290,a89a5d60,894e8090,54d32ecc,2cd022c6,c03f1379,657450b0,db9f08e9,6e2be5ab,5233dd84,62733cf), +S(f84ae7f8,a03b60,af9cc359,36f0ae78,96935b2c,534f852,8ad159bb,6c0b44e7,68f4dfc6,20a354d9,d6904bae,67792622,337e3180,ab340828,80bf04fd,f47cc23b), +S(5dea33b1,b5207880,6debbcbf,83ca17db,4617488c,ac5c6997,ad4092a9,8a7bff7b,99976fe5,ae88d36f,597e16bc,6dbbd4b4,547f4dcd,7e85786c,d10af30e,1d81bbaa), +S(31be76bd,4f946e41,7de73037,ceaa0dd7,c6eccedd,74399e14,2ae6fb2f,d2b59def,54ad8748,ef129085,dc3172aa,904cc376,e203fa69,38783007,2af33889,52cc6549), +S(b6124d0b,f603a00a,22662897,8dd0da87,fcaca5c4,fb04ebaa,81a7d13b,39f2e307,34ce08c7,4463b06c,afb03c02,583288eb,7bfa6f2d,3eedfed4,91e31781,dcff10da), +S(6aa4bd60,90bee70a,295c451c,c8af72bd,3665680f,545f46c0,bf5af990,aab5f43d,9c2364d8,25406b76,94ec9db,a0ea2f9d,bb36fb2c,5bda62a2,bec941c6,874e68f7), +S(f72faef0,e268a7b0,a9b00a57,3674d846,c1f0dcab,c9a586da,be318b1c,d2874d8b,16b3cfda,65db0f3d,1b5274cd,20b1329e,61ea0404,1f702e71,cd98708e,28c9307), +S(1d26df15,98a6b9a8,7c0a6171,767539e1,86d51d1d,cef130da,1001226f,87872c5c,f227cd82,becf5493,e2fc7635,6a37bb48,3e681a19,ab4d9dc7,92edb114,3a7b072e), +S(28690cb1,db697840,13e9eec4,d9388723,4c28451c,cf9dd51a,746d1274,b13b4610,d9bc39ef,19228981,a1ead1f8,94deb254,162fed5d,cbb58a76,6d361e04,3d8f62ea), +S(4b0b5258,22dbc31b,1966b004,4d39c5de,f2e16d5,1e032045,f9973b1e,fe83ca12,2db33ff4,3631fdc3,b3608b40,7dd494f6,ae730212,9619ae35,f6ea08eb,51aded12), +S(a5b4e205,462ae419,8fffc1e7,393d366f,c5a9eea4,e98c67ee,1684d63f,cc09aa64,d3c11017,de4ad175,17cd076f,cf6c0ce0,4d3108ed,60eabdf0,935499f9,4226078b), +S(d4f1af69,2a3e9fee,1f92d892,b14eef6a,a0ec1f4e,d4d455f3,c70bcb19,52fa9837,115c7ee,73b90adf,f142191b,eca0be01,7d5a651f,93e2e90,5a36646e,21790294), +S(c275c715,9d6e9757,d2adef47,2ee53856,dcf067db,bd4f380e,892c9832,708d46b6,70da1cdd,853a0dc8,a6a9043,3c319371,25590c9,5807284c,ae168f65,62e4465e), +S(d2e38b27,83156e2a,a8e4eac0,149bf2bd,bc2918af,1cfa2a23,d1c7136e,15dca7b,738a0fe,751ecfa3,459e005f,72b7461f,a4b5e1ed,736420d2,22c5428e,2ec1348c), +S(f8f5b3d,b3659174,e0149fc6,fa747c22,9607c434,8f9eab60,900bfe92,b23f9a4d,d89eff33,94a093fb,549fece1,4e11028a,614cdce2,21d5ac26,1bc25f32,dca3919c), +S(5e266403,e49fb860,e6ed0928,45bc0811,a214a0e,dcd6174b,290ecca9,3539d862,ab300acf,5d8b8a14,2fc9e93f,ea995d2c,d7a2bdb8,6a146f65,2b8bd49c,4e8dac1e), +S(8ff869a7,60230ba6,aa5adf91,1ba61702,17cbfdc,5ffa4018,b8a09b9e,4088d634,db5a5aae,bdb946db,80e4c207,22ce38c9,4921bf41,47eea510,70e5aac5,c592f32a), +S(f3d39b65,95bd5ab9,aeedc43f,f49bdb20,73a211f4,5ec2c1b7,72226a97,a31c059b,ea41abf,9322d733,bb5971ac,194da6a0,a6d41c6c,a0d0acaf,a53e17bd,dabcdc68), +S(18ba0c34,10169914,7f7589f9,179b94f9,daed92c9,287f3468,d283bdcc,d71cc637,b3512d25,c199d2a4,c115bd11,eb53d6a1,6ef16c3d,97be6291,5ff76b76,890ba675), +S(2cf3354d,7f96c58f,3c6336a0,6fa30c83,8da767af,48f89fc5,5ced5b40,e0b86cee,403ac306,f6c3ad55,be1ee5bc,29cdd46e,2e3d83ac,71050909,5f117d21,7ef015cf), +S(5d31d140,f754d6c,5943deb7,6aa4d867,cac81abd,9911618b,82327795,da8d085f,c25f99d0,5bc5d583,a3a72b41,4e5eac5f,c14ced01,98247ded,79ba482c,882bec49)}, +{S(e0ad91c6,6ca95326,d440f44,df91c1cd,cd3ec344,e906d0ef,51fd4a48,31ce293d,3559f3c,e349f7b3,cf66c17b,2c3fe7e6,8ba3804e,438c0816,b68ecfe2,30da18d), +S(d8b8c50c,ae9f285f,d6d9282c,373607d8,5fda59dc,71ba0066,148b378b,37440076,ef83dd08,ddc115cc,24948009,f9eb4afe,dcd65c64,b6ef2194,bb4ddd0f,ece180e6), +S(881fbbf1,a9627bd,369abbc2,edda8026,a61b10f,4161e442,530a5e36,447a0290,6a63cb8f,7e5094d3,c8beba5a,2a1d7b54,bc33005c,efdd5a1b,20d51f74,d00c2fcc), +S(36bc0df,fd1441be,1a4efd6a,43ab9d83,243d44bc,a6e108dc,fa9a79fe,23106f0e,eeec58b7,dc37eedb,4432dcff,4de7f88b,2a0e0721,da2c0a72,eadac4dd,71037ed9), +S(7652c155,c2ca8a23,7680f015,a62c7c31,31682752,a99c4329,77ccfb9d,cb58b03e,5339a51b,36ad4548,197d3018,4bde4428,b38ed983,d624bd18,a5f8c4e7,21871c5), +S(904774bb,fb8b0c12,e2b3f91a,e5a2a0c1,a92971f9,86e29fda,9edc609e,e85b222d,ee843f1,8039e251,9c7b23b3,725ca099,114b4f0,26970111,35ded92b,94445e2d), +S(1c7c82cb,fc14b9b2,cdb3c12c,32df33b6,a08e7af9,df62f310,79fa0710,f28f5f95,93471b5a,17c84eea,a45948df,80c0f56,d8684f35,1aa2ce73,ab84b3c,1b8250a4), +S(bb060f5d,971ce062,427a5630,8f114532,40ec54fe,6479d5e7,9ce81444,27f07927,fcbeaa69,8278eff3,d4dad904,836c0233,40a866b2,d8f66774,70d1159e,201501dd), +S(287c5b8b,8dc168ea,197200ea,97c4f63d,db0b620c,7f30d623,7934f856,a558438a,260630e6,ce310eb0,366acd78,bb58f4ef,27fe4836,edc8ff0f,5d5ff987,b659bd20), +S(7d4c5c6a,d6bb0f0a,47b45a35,1264f4e6,a81ee0b1,65a7e665,4b226c95,feb59dbb,e89691f3,ceb4c57f,5aabc1b7,4acd9aef,41531851,b41ec1c6,608f16a2,2243ab5e), +S(ff806f2b,9eaea4f6,47d85077,d8aa5052,9d4b96d2,1e0b31e0,7c86b14b,73b7ab4f,9acc2f77,a994997c,7a2b1aa0,79c0b5d4,c84f6715,e4a50e33,628b871f,8885ef9), +S(3ce795ba,1d91a9bc,b0260654,3450ced8,c94184dc,8a41ac5,e1b84856,e88927de,3492e696,cd1ab2dd,587d4707,ae34fd67,3ab7902c,d0c0972f,ef419795,1ad88a1), +S(299ad528,afa3f36b,c80a757f,f081a8d,c4a6ddc2,d2b57fbe,1e3d361b,ee5a5d8c,9fe823da,74eda2f,266a8e9b,331d511b,623dcd32,ef9ab7a7,f1d1cb4a,7e6fa65c), +S(bc4b0549,16177aa9,b52b29b7,cb91673c,9ffce4c,7d0066b,e4249383,4467e3b9,55bc6436,7db68687,e699cf6c,f2db9dd8,c2b9a438,8202fef5,11acdce0,ab06f969), +S(a8e8b02c,ff5de02a,9e6652cc,6fbe41cf,6e87ae0a,abb14ac5,a178b3d9,e697d0a1,285d4af9,405b03da,c57c993e,4b40df8e,82c6979,f8de57ce,4543b7ef,3381e0a8), +S(e50aa8b6,d7dcc055,4f406959,b056dac5,21a7842c,ffaf09a1,ac24a3d9,8aef5228,46656395,ee84d061,a9f5788a,cb05975d,5ffa5fae,edced564,1f81b5cd,2491c23f), +S(cb516899,98a214c3,c31e4f2,692cd7d,fad6f1aa,eb8afd1f,b29c23ce,429c224b,2292b8a4,5a89eb80,167238ef,2027f975,98a2aea9,a4460c5,3646d088,82403c63), +S(ded04c06,74c6eb16,557b5bed,4b6703d2,cc37c6aa,bae466e,ee7b5665,6693c3c9,4f3ea70f,8e75b02b,76934cc3,645d2af,eee8e9d0,8d100117,40e8a16c,dbf01113), +S(f3d0a253,edb74436,897e6cc6,621c74e1,30457b41,e0690b6f,7b2a203e,8ccf8ac8,89cb07e0,97495bdf,403490fa,d58eefe3,e79ffa33,1deb5cfd,2c548ec0,8771be67), +S(d4c66267,aa73ed55,bd68fee3,2a166a4a,4ec660fc,4cb13e18,fb6ab0fb,19a5f330,7c2efa2e,4509b221,97589483,40b6c74a,8ee2b5b6,5fbb794,7f838c47,ee03e2f0), +S(dbe9a638,f262f9a4,b3a8955f,22293feb,50ef4b32,20df0184,f363a373,d7110981,4c563e83,5e957756,5e6a8996,97510c67,9561972e,5601c1cb,2f2f789a,c1e0b5dc), +S(70c7c07,1b1e6fd0,a97b55cc,5ee34297,166f4d02,417a796b,eadcfd43,96e1b338,b5c49a6e,2ab03e55,f4755f37,e5211d4b,e23339d9,d464fd28,6781bb29,56db23bb), +S(aabc501c,6d52961a,a613fe66,96f0bacf,fad74fcf,8386cbf8,b18704bc,a1392ffc,cb72ba86,70bc3f7c,85a00d3d,76b11596,6cfa0fc7,44b31e01,9129da9,a5b04b77), +S(47f72ec6,e7820788,f0f7814f,aefd6e2e,af5d90f3,f877677d,ae72569f,c6a2e8f5,6709731b,ef2dd880,4696a6,a0661d13,fe579704,5e0a9bc0,e5fdc0af,789c5830), +S(20026251,d9413e42,47a5884c,209b144c,98e36f7d,8ef3f56a,68efd475,8a2ba8c6,9c5531b6,94ba0d24,a943d0c0,94bb623,75c798ca,c9716181,a9d659af,2acb978c), +S(8dfc6293,9b300c9b,fb617d23,6885f652,424b4f12,d04f8bf1,151d1ccf,935e445d,9a519433,18e94107,5472aa9d,6ec3390,59bd3bcb,bbbf6937,c9290e48,9da25f8f), +S(afef3520,3b558495,6fde0eff,5cfab48d,8fb08806,3c1d7cbe,d7e352c2,9d49176f,a764e6e7,bd0c8fa0,8a6f7f30,aa38d7de,fe71773,fb7ea484,68b3fd9a,8adfd650), +S(354c0a98,1628dfff,8be8ede,ed809db4,bc39c686,39a26828,ff28dd47,90801c46,8ff40299,d607036b,acd7c0ab,66a102ab,38f8d3a8,a271e2a5,20b43cbb,687cce6e), +S(da2e7eb1,1a1e66d9,5001ec4,f7b66c1e,d9f7d0ba,ea3bb326,672b9069,5cf4bebb,cbc1c7da,b9bf7e0c,dea9297c,5f45ad0b,9c4fb093,318b55f6,1e4a8951,726c4021), +S(6f780994,d0662667,8fa74156,4232bafb,b3a7f54b,a5b66507,9df32545,c192c3fb,5f11f0f3,af1a763e,4c9fdcb1,1e5e57a5,6dfe0d0f,f27535b4,4343a312,90e375e3), +S(8e28948c,729c1438,5bd09316,31ed3eb8,7acfc5f4,2a9eb4f8,afa50362,33591cec,2c09fa1c,bf0044eb,a78ae81f,bdbd4271,2a89ffdc,f7d476af,881d29fa,2627f250), +S(4011cf05,a85ef14f,1875cf3f,4f78a51,a52a89bd,a8930a4b,8e13802d,b85f319f,35045b10,45c4f71c,c762fa78,5b8d4daf,aa2a1c07,ba37d82d,ee0592ae,ad807810)}, +{S(9089bcb7,1c1559bf,e17f6c0b,91fc098,c63785fa,18a42d69,798b063f,a0930175,de229175,5e4ebf17,1047f79a,37d81b9f,9004a7cf,df747589,7365e174,ae367969), +S(4d1caeb3,41f25459,3b06f715,9e9418df,e29ee076,76c26e6a,51d8add2,5c70a5d1,bf773e4e,4151d17,650aa7ed,1d6a5505,2d622264,75c50f31,3261aea2,cf68dc37), +S(b0760330,517c0d66,2571cfae,830da7fc,a7e0d86c,1ca7f75f,5150f625,db50ad2,d8d10ef3,9c84bc13,32c2cc01,4d4df0fb,45e5c546,1849fb1b,81b7fdd0,7484d35b), +S(3db731e4,273e5b20,2de984c9,74b4112a,d0feebe3,7bb0d2c7,db38c7a,21bd8c67,b425c1d3,46b6a61f,2893a3aa,a243d60f,5563cba2,40018cca,3f80925f,71f4f1b1), +S(3a74a50d,cfbf2ff2,5c99c4d0,1a13a917,9f510c2d,eca1d5a,7ac8fb69,7eb9795,d2b468b6,714681f4,57bc586f,40585c01,e1dc14a1,a42ce887,9ce044d9,ddb92d82), +S(b9139ad5,4f44fed8,4917ad55,c49c23c7,8d62aadc,e83c9ebd,9efde865,cb1eb298,18068856,c80abc3e,2a02a441,bb7a7609,aae8d2d7,8abf4e2e,378fa3d0,a27aa900), +S(bcf5cf94,5887f183,e58a0128,4ed9a4f9,fcf918dd,4e68d70c,5a54eeff,166cb44c,8235f63b,bb06a1a6,d9ad2ae8,47aeb2b3,4838c962,9608943a,93294c6d,e21a3ab9), +S(4b598ce3,a77680c4,c5f66e90,1b76627a,27f35301,9641520f,53ea3894,dcbbd187,357af043,f77cb9fe,c04ce1f4,dd9b610f,9151d15b,3b7383e4,ecc5384a,8ff7c5cd), +S(b588aec9,2dc045e9,a95abd7e,da929837,28b5a7dc,d637001,ce7f0917,1283b16e,e682f53b,5e94fd84,914b7bed,5afc28a,30ae6f53,e12d948b,3c0d88fd,adc5d0e6), +S(eb8f5080,218ac5c3,cd792042,b59e80ed,e3857a75,a81d67e0,7c2221de,d3b7a677,c5f272cc,3734e0f4,6a5cf40,626973ae,1aa76839,1953f211,eb52693d,254a7fc3), +S(87d119ee,65a60dd9,aac3e784,22049cfb,4123d262,ac9e7473,4c9cc418,fb7ce4f0,5185ac,7bcaee8f,f1334eeb,cdf2c39e,83b8b665,1ef9d8f5,48a029c6,464242da), +S(cfd0438b,186d0f5,c64b5f38,a190baf7,35b67512,a439f486,fb79d501,90294683,985edeea,243e9c6b,d9c57cb5,c7372202,7492156f,e10bd2e5,67edd14,8603daf6), +S(52abfb67,5fa8b12f,1b0cf0d,8e85f402,47696662,64c7252f,69562590,839ce4f8,8483ab43,2d4851d7,4f432c0a,8e3863b9,783cff58,3d4c390a,9865d7f7,d1aed67f), +S(52926df,cf12eebd,3008459d,3c91dc1,73532f1d,ce3c5d0a,874ea4c,67331787,18b48fe6,1bd74ac6,4b34f2d0,e7de8920,2c875625,bcad84bd,cb3c81dc,cc86dd87), +S(695e09db,8c4479cf,4c305005,b5737ca0,63f89d02,aced2010,5600d65f,58e26401,32123a91,8bb23fd8,79715cc7,488184b7,53e0eb00,6dbbc95a,ef9d815f,3833c08d), +S(97c35716,e5aac70c,45dcdd45,a5ca0155,5962f09a,cc22c16b,c79ec272,ce1c12d3,93869464,6470f8e3,c0db18b6,2e4378e6,5caa7203,c4d6a079,a10c8182,b8eaec3a), +S(35197cbb,8da9188a,fc60faf9,71cf08fe,73372e15,f857b93b,6afd77e6,bf4db7ed,4e0efeb5,2db601dc,a539c777,14f4aede,c5ff121d,77dbdeee,7f16fb0c,4cfc19af), +S(afb2f842,e0818237,46c294b5,9ae8afd2,279e834f,100f7d1a,58a9551a,98408d49,5bf5ac43,a3609b4f,f058d6dc,6ae09fec,19a19864,6d12096b,6bd3e06d,95d15ae8), +S(a37f6113,882459,b1dc6335,26253a8d,287c9285,b7862721,f9bee74a,d2c4c09b,9ed3252a,303c6d,e01c9985,c5b3edce,1074d478,db56b961,d91fdaf5,1b1d07cd), +S(4579a503,cb12a345,182b28f6,9a3fb98c,4a80579b,2ff592d1,ab18b32d,212098d8,8c61c503,df79dcf2,6083f15b,c3ee1f99,9e1e0960,8bf6af9f,b3175699,cb0e32d5), +S(545031f7,883a2c8e,bd56a405,52719096,4aa1d40d,b22a1730,242f3064,530ce326,ecb024e8,e762b456,f62072e,5f471180,bbc817e7,54e830ee,7757ed7b,df5c9300), +S(b127fb32,bb3e193c,99d232e,d50dcad0,3b45c072,e0d521dd,de72daa9,e20e97b4,b198428,12a344b9,2e8a8d26,f7964c66,82cb3652,66ab3e28,2ba56197,a159f1a), +S(28cb3582,d312cfcc,75ab637d,66c646f7,5157dc74,7a464e9b,933c0820,2326b6cd,a87042b8,510ef9b3,ecf918d,916128e5,f946f43,6f18fd5f,ad62c46c,5882a23c), +S(8a46cb3,27efbeb6,850e3861,c4845ab1,21414f12,9fb27387,4560826d,c9116886,ab09eda1,9156f1f7,194b7b17,fce15268,ba041c96,24765ce,fd964ede,d1f05b3e), +S(b73af914,10ad56f7,d490dc37,1a2584bb,633de0f5,3f00cd0f,6b8a6019,53c7ef16,3dbf4e52,753e5d33,3fd23cc1,c839f278,38eacb3d,5980cba5,bf1be426,b27641a4), +S(b38c1896,427a0108,3f24a917,2a64314c,d9dc1759,60971135,1b2db6f7,d66ab745,d3a71a74,f80d6919,b65629f9,80c7757a,cc49c2aa,78dc67d3,d6f76d06,91a90d85), +S(6f6ac108,aa819a27,6dae862e,276b3ebd,8ed5a3ad,9b0296e0,4f8b65a7,f6a5ac1a,e3048583,7aa2140e,de381363,788d6d95,25a7ee33,9e3a3ed1,2518619b,30d9f71), +S(72f5809c,7c282ab3,4dd81851,33070d85,53999a6f,14fd753f,2ed8deec,ed7adc5b,112bf5fc,8cfd71e1,84ca1967,d05da765,801f12b4,c852768f,60afa7f1,e9576534), +S(4c348833,10f7dd6f,b385ce25,e2d6eef9,8556a59b,5e79a084,ec83425b,37150085,9c4c97e1,be47b073,5209ecf1,5f05cd8a,58ece74c,1b35a92d,96a70287,11d95add), +S(f16e4513,2291b577,ab360b42,c1babcdd,ac61e623,da85819,e9c4c73d,463204b2,5556d7d3,a2d45955,28781d15,16b59aad,941ea356,1b5c88ec,94d09314,555ea64b), +S(3580d3f7,896fb70e,d48d40f8,1b31a72b,51405574,2c2b4369,e3e7dcb,aca4ca22,e38da3af,f409e459,82098305,87aa0eb3,b2339959,75af2e33,501115ce,648360ee), +S(407e63d2,c0cd6d37,84c27734,f7e517fb,4bdf7847,296dc7c,a8714fab,16199828,2dbe5da7,4b29bcc,fe9adabb,69157830,987ac51f,389c6001,2577f298,710025f1)}, +{S(f61f644b,e2414c07,66c6caf7,5d32683d,efafb133,cb4d341d,7eb565e8,9f6e4158,2848548f,15a6e7d7,2b2eefc1,1b76e318,15ebb4b2,1e3bb938,e0c2e9d4,5ad4f7d1), +S(5b891f8,ec902550,429a5ea8,33fc29c0,bfdddf6b,a6f62c19,87a14050,a9689a9e,77901539,1ef92985,6d3e3b35,4e4ba2db,3bad967c,dedf331a,c0bff08e,f25f2e99), +S(d8c5a617,62655ffa,c943ba35,3b595b46,88012282,af068e52,d918bbec,46bec87b,9263db7f,6f74aa,df0dbdaa,7e7ccd76,cb3a498b,44de2bd5,f9b23029,2ebc6009), +S(2e940645,cd189edd,2d6cc2f4,f9b49e4d,305cfe8a,46f2a596,fbb55200,89fa5b21,4c197028,e89ef8a5,b5b6cbb1,3733e90,408877fe,7425d58,1f4bd063,ce286fb2), +S(396c3bd0,9c6af07d,123a8441,c9f79ab3,a783b8f3,fdd69dba,ba61c7ec,f65e3098,534c8657,aeb8cdc6,ea34b372,68f1c70,70881797,46b8e335,477c8525,cd17aa8b), +S(c34e6be,b079f3e8,d1355754,4246d2b7,a82d551b,740b4b59,b9220bbb,768796fe,57806a7,653ff7f9,3d7cb6,b3acf68e,aed049c5,75988fa5,f03b1ab5,1103aee8), +S(5d2d6aa5,252fc9b2,55d89773,e920891e,7021f233,5f7d0ff8,c6bde5eb,b65c5149,1fdbd2c5,6b8bd095,2d16c304,8d9c588b,2a26379a,17f748d,f1345695,1c5959c4), +S(dec812f5,745fcbed,fc36c635,76874bc5,96dde8ef,68a8724c,201b6af3,be7c6e2c,1715328a,f75f9661,d58c667e,5c5514d4,c99dc881,8cfbe702,e0c3c8cf,662e6906), +S(32499061,83487250,f65684b9,9434489d,3a83ec93,61531dfe,48086b2e,b2bd18fa,53217af1,2a25fc6f,45555d93,98fe46df,4247d38d,7b162e34,945f8928,bfe148ba), +S(d3e9381d,83f31116,ee161490,c9b5d1e5,7e086c6c,1552160,2c913315,af033ddb,97ae863d,34271b26,a4d6577a,32028c12,f092a54,8a18ae1b,a83de384,3b8fb84), +S(1347dca6,d097faa5,7c6583c1,c292c6b3,ed87b31e,9f7afe8f,d0d151ee,50ebdeb0,570a9be,e4806ee3,e30696c9,71b5d905,65d09ee6,8b4fa8e2,8acc54c0,7fabb492), +S(691f9995,af2bccbb,f556f624,b28a1da0,67854c15,4f014e92,a56a8cdd,9a43c25c,81babe0,ae44984c,bfdfa958,4dc5c677,881d1b0f,63993075,a3fc462d,e986866a), +S(cbfb62c0,b91cedb2,5a9d4b3,ada43cac,7839dd18,33174711,24688ca5,5f162cb,77c12161,e8199410,b040dd57,4d90c39c,2f1b499e,6b7c17c7,fb21438d,aff4e674), +S(53627516,8de62d6,2c792f64,f87996af,3ed8ec88,653532a8,ad60942e,cae4a339,d8449a0c,c6ae32ff,45a11652,97b3d3a0,57e67c64,42d3bdb1,ea2cbcbc,cf0655cc), +S(2a81679,7505601c,763e6f6d,f7ed5c0c,14ee7fbf,d75b8755,7bd57f3b,e2d3c7c,99f26af2,10540397,b8423da2,c4809942,63734d99,f0d642d8,96b5f216,767b759e), +S(54b2c03b,7a7ea964,220a255b,bb688767,99ff1b83,f0934e4f,fd03c2bb,51490e22,b3cc56a9,ada9240a,a3730828,26733090,ace3d7e3,91200d08,2cbfacfc,bcdb9c08), +S(aac88c8b,7c96e629,6f023e5e,8f260324,9f4e645,bd701705,8f38e9f3,a034eb57,da03ca87,b98ab6fb,e4869756,7c2db04b,7f9948d9,ea65d93f,d222d52f,6d48c552), +S(bfdd8394,fb49f93d,630f6b8d,469da38b,105529d6,70b9a1ab,e3196816,d2a13978,39a97919,4249f78e,c336b00e,475722e8,7ca734d4,3d1e97d4,d2aed074,abfacbe9), +S(5b5dc3d8,66ba3647,d2aab2ac,3338abbe,4d1ca08c,6cc6fb26,4335f40d,4dfb2331,3432ba31,46a0f15a,beca45e4,1ded8729,e6a0a49e,70315745,bfcb3388,4e1b9e64), +S(77057b28,a1d139a1,91e05ad,a8d72f3a,c7bbd198,7647070a,b6a21355,7bc0c73c,46f32321,4519afd2,f830cf7d,567aacc9,47ae6b8f,8c841adf,988e39ad,e7b9757b), +S(f6c8d1da,e28a3d23,2a388998,1b638b23,f381618f,18dc81ed,67bfa696,4cf1626f,2ad8c92d,43378941,8d298dc8,2cbf288e,86d21467,ac73c0e3,383ef3e0,a03142fe), +S(b75b5cc3,77a55310,a3b97067,34f1929,fc0db732,3265e6da,71405f37,729d5a90,be077940,4dc94ea3,3cff505c,e1aef457,bc120359,521eae05,1de1963d,b1948053), +S(a66d54d4,4b4d06ea,f141307e,27e1c225,41274eef,5c0b1743,e6398b22,fbaa4068,51b6b8a8,48e1c27f,107f82cd,d0554643,b9e16611,fa93b789,a2199b3e,3bdce296), +S(56b2f9,ab707dde,3479d0ea,baeb62a7,6cb9bf03,66278eed,559e027e,a1ea6b3b,27c47e9d,646684dd,2a54db0f,c245fcdd,721416f7,22ed568b,736e3e1b,f195b379), +S(a9642a49,83b19c3f,f5f63ea2,9e76afbf,a25dd0c0,221b32b7,6e67373,36e7f5db,8ada3766,9207c6b6,a6b6006b,5240a4d6,cdb8b807,c0c16a56,91289b7d,62b3a051), +S(18eef8d,f9e64c1c,548db40,ad77d92b,11f3ac43,60c63792,5f7d598d,7d8d5155,806db24,eefc3a64,c84da338,937811e1,20c6d0e6,9cde79ee,9957a4fe,c53d0e12), +S(d11359fe,61861a36,8b3809cc,c727320e,42905036,774d0e83,98453ac0,68d404b9,d4182ce7,2500637c,8e14b977,34fcad09,f061838d,57c555fa,420fbd50,9abf6b81), +S(7ea072e8,f60ff273,9cad1d8f,c560f208,b54149a2,5748900b,50830e3f,738b2db2,af09e54b,d44feb44,b39956af,fdca6894,91c7c6fd,f029e71b,e780f8f6,77a48a0f), +S(f53406ab,9fb1317,b038dc28,f0165abc,115b37fa,77d23bc9,e51993a7,8a15ba00,a293f429,f7fb281,9cb60b53,b2e6f07,afb6537a,39a18be,a5ad4cfa,55aea13a), +S(b1674e5f,9f194a16,94fd12d1,4b64ac8,bba69432,241aefd9,9a1c49d,23287635,83cb0060,1f5c33be,9436d946,22c3b3ce,68d20733,ee1e2392,8c3d6c14,a7cde085), +S(22b72e08,66b96344,ee53b898,ea725f7a,b5832c12,7c0881ce,862ea945,5eafee85,b886e8e9,cba29b15,be5c22d6,ada99b02,1098be69,d1c500fe,6fd2ef8b,f1ecae25), +S(9b7151af,698a85d,2246c88e,8ffb14a0,c762c2e2,64ab70b7,e30e2434,9b8370b7,fd9c3d89,46ee9d90,e7fb6d26,796062eb,4cb6c160,76df4834,eecd2748,c8a7bb4b)}, +{S(5ba26c2d,53b04b63,d260c6cf,392786d9,41a1a7c,b88331c1,149cd3b9,9c207f5c,9c7f6303,bd72850e,d4da618,3427e7f3,eee078,6f67cf9,85d483ef,79c2eab7), +S(f7d26944,6d29f81e,39a44a88,49f12184,b9f42eef,16c5d88f,60c96a28,cf0c3e48,e7ec965e,d0a966a7,45087e09,a058421b,852c8a7c,3790a3ef,7abc6ccc,e17c6084), +S(98590b7d,36bd2ef9,37ce788b,22cab951,d921724b,87c3ad83,8263416f,b5a67dc9,b711c21e,5af72a36,5cc1b220,7ed09ebe,be918555,55e9239a,e9b03d75,c0261d5c), +S(92e1cc4e,5f57514e,9ed13535,5f3e2cda,b0b22f8,8f56a972,a657dba4,7263463d,14d296bd,452f2faa,7d6f42e1,550fe35b,3c47eb2e,fe7636c6,2eef90b2,e7822da8), +S(33de9b1b,e153bdd6,efaf9d1a,30aa9b3d,faf26a32,4486b6aa,ecb1f958,f11c4673,7ef29223,4d3a565b,c0f0e295,deffa3c9,a86a6bf1,933a084f,9334b790,51eb0270), +S(f9fad0b7,e1dfd4b2,47cd2cbe,bd863e1,95b3be25,6cf7a707,5d422b9b,f5631ca6,fd5262f9,e6ca0cee,e1c7e531,83d9f3c0,7ac518b,c024681b,56c06a1d,1826f5ef), +S(455ec5ea,f34c02c6,961469ed,27bc7883,c07c9a18,663e22ca,83830a66,569b2b36,4dbf1b57,a7de2fdd,7c0380c2,b38fa5d3,697a5995,8ca0c0f7,6405244d,bff4c9), +S(940fa05,d96fb400,bac8fa39,e696c536,71a490d7,c98b3851,ef76ed35,c62bac19,b6de17b4,1a045978,5755497f,1c2a953f,17554b4,20f2ccaa,9fcfedf3,5afb9b46), +S(16012402,4ded6478,72374af4,6daf9c2d,a9000841,9a7d4672,98b627c2,420981b,7c2607e0,a4b86f7a,d5df7371,60987d21,35d2ce2d,bc422ab9,b643d080,26f84323), +S(caf887e3,339046ff,42c629ff,c954873,2c629ecf,319c44be,6701a9f7,c81bf842,d253a688,3b3d51c5,a914ffb7,46e7ab68,70c2b1ab,5b7e46c1,7a5119e8,4ab6c878), +S(41a5b720,595bfc66,18406547,d59ec09b,4efba0ec,5bbd3191,9e9256ce,f40a7afb,87ee1be5,2233ba8c,82dc06a3,6fd0a1b,4ee8d7d3,ce89cb56,1dc96c19,dad79613), +S(8bdcbe80,fe8533a,174045a8,3cf9d89a,ca438ef0,8f6393cf,6e24d923,edb02586,8d21379f,c053e8dc,c628f0cb,83a7782c,b4e946e3,ca88d467,36232762,fc6f8fdf), +S(409a4482,6b6f0ff6,36178d65,aedd64cd,2d28b39f,3e9cd93d,a0afe712,b75fcd19,25a3bec4,74216dae,d686825b,bee6aac,487a6d07,606e5aed,7c3032df,f4911eba), +S(b7f414a8,4c0af927,64ed5b52,e96dad38,6995771c,2cd90af1,1986bdc3,cbeb61c0,702b0a68,4e93f0a6,26b807d8,8049db6a,3e65001a,d75a476c,e4be230,89574e8e), +S(58b0cdd7,bed4f327,bcecd493,d835c0f0,e45f6fa4,3687d1d2,f19de285,5bcb5c11,21b0a478,2c1d14db,9c67817d,7b23db21,a96e456e,62a85c3f,2a02c76d,78dcad10), +S(c75cbf00,893447ba,5b3f8462,9d6897ff,64be841a,9a6bb714,54adb849,8df03900,15f68903,ae20ae4b,9b3fc7c4,f8135936,c09de15,18317dde,bcf66190,2db79f72), +S(e6258fd4,b63be23f,38361a16,cf3f81cf,f2d7343e,515b2d0c,ea0bfe38,6d4400a9,aedca212,9b73e49b,9757cd7d,a39a1e92,f885b267,a188521b,32089ae7,6d351eb0), +S(7c61b66d,d76f759f,be92708,8b075147,2ba10db2,eee4f0a4,2eac1ad0,d2dac3a6,c2b79de,70372e1a,6c9449af,2612e34a,8e101cc2,81ef378b,97cd77aa,bff004af), +S(29c71194,bbe41f4e,b2f58bf5,799616c3,7b247283,c993bce4,630929d7,55f7c8c4,c0fb083f,d68f63d3,599c2da,9d0c1f03,b6903545,a47581ff,3caecbf4,359e0235), +S(f1cd983,5bd3eb61,f8207495,48da075b,ff4191ff,d5b1521a,a1f4413f,2173a68e,beac8102,13b643a9,4658cdbc,71713894,39b72abc,f8644697,2fe6310b,4ff0233f), +S(94f2137a,ae170855,3af3dd45,8f8fc9d3,c1bf07e4,35a62798,25d5b93a,37380144,e952d6af,b27f9b2b,80ccbe89,59fb8b15,5fe1b2db,f3ffbf14,cf9c1fe9,b8e8209d), +S(f4f0cd2,e28cb8a1,9b469b18,90033912,4a40a39e,67ae1642,a3a677b9,fa1a9a3c,75412f04,5c41770d,73d7cd77,bce0da96,1e6fc69,cfc6cb9,8f691d43,dce1e548), +S(15ba2fd,b652ea98,f2b326ee,e5e1629b,ec8f8e7a,36078d7,cb8a80c8,c943e98a,db416844,cf757376,cfcd5a9a,9a318b51,184f8c89,fcda3d97,e735c120,43d47c35), +S(5754903c,ffa8cb6a,3ffe3488,e484c498,69163b77,7c07183e,8d2da037,78b8da34,508312e,6c2fd008,fac12bd,afdf8e50,1940a81b,d05efd38,5277a85c,ccf125da), +S(3bc76f6b,8abc155a,dbba76a1,9c0fef85,373bb1bc,9775f431,1b3ccb12,9c7fb29c,48036702,aea467ec,daa8b809,97c41c07,9e38c414,f798bdc3,a531b08b,fb4ae303), +S(2992c410,306d3d40,313ef69c,a2e3383,88f592d4,a9c2bd36,ebd9f51e,883aa33,cdecc5df,41cd193a,ecb26700,baa42486,a0506372,d56de3e2,2fa09156,7b525519), +S(baa7d83d,6d70a528,e6392adb,b2af797c,72772b92,ace96a25,90d65c37,b0ff1bc,9943b555,4e44b480,28815d8b,e50189d3,6617e9b6,c8f07393,8309e04c,9978fad7), +S(935488ea,4c88c2e3,cda6c0ab,5b42d519,e7fabe09,fdd3e36a,7c78c9bd,730612fe,705c8f8b,228be0c5,539eae13,1f4f4bdc,2fecf6ce,6cc567c4,dc692af9,7c1d506d), +S(8edeb68d,e63c35e2,5e36bc8,61445a63,8b0637ab,d14557bc,f0b0648b,db43f86a,d20bd0ec,14ef4f35,68954130,6577ef85,baeeeed1,c1004130,80687a5a,94a9e9a3), +S(9a39617a,27c2ff2d,9869acff,b22fad1e,a7d04271,be154547,43234f54,7f21924b,917bf9f3,fe0563a9,8daacf90,dfdcd8eb,e657f023,3fb15711,79bc5ce6,e6f5dd56), +S(41dcb02d,21137ea3,a179b469,199f9ed7,9b831923,68719a4e,5c727ce0,d42e95d,4669d53,82147266,8327cd6b,31c21b80,d3394bf7,fa29a43c,2ed7441,d866f5e1), +S(d4e3e3cc,387e0364,6688a62d,9390d585,a69ff43e,1060811,431dea8,d868355e,3309af2c,b3d7ca6,55334f2e,c53de6aa,debf5d57,1618ecc2,9dc9830f,ec46144a)}, +{S(90edfd0,61871350,b7f1f029,c4114190,b050065b,2030a400,9a8a7a6f,4b92aae8,872d4f07,5f60ae2d,dcec2f12,98a22da2,53d54de4,fde85560,690dde89,1628db56), +S(27e3ce53,b4258f97,a499f408,ecab24f0,60aabae1,dafe992e,5a34952d,5e6e486,d393fad2,9be684f4,7ecec306,332ad969,75b79d29,b5863d98,5f959c4c,b8ffb442), +S(420f1078,27c75c95,d5bc657b,a46cbe2b,415a7d42,ad62cdf1,6c84ee89,22215379,8b257a28,e0b15fcc,ae0b555a,cdadf4a,be93bbb3,a208ee45,77710a9e,d58da7fa), +S(28859abc,b60a95e6,b26c0996,566bf798,60c1a194,2d3342f7,9655f286,32f9d5df,2a770426,5eeca5d8,87840cab,3923d868,aa7b7b18,f9d19941,738ca006,54ccba6b), +S(c33c317b,490e2266,2649a021,e87f6596,3897633c,90be208a,193f1d52,28614059,af850be0,d18708bf,d0e1f523,c1a4fda8,9a6c156a,55f82518,2bd99bb9,b999a358), +S(2333793d,b961d3d6,740fc725,6cf9d833,81b5dc92,85b6d83c,5c343aa8,5baea83b,accc199a,ced3012f,b6db99c4,7a36c30a,f88e7eee,b62c2ed4,1352b488,ba0167bd), +S(4834aa89,caa9c25,a99ee4da,e4a64c15,25a5d74f,9ce573ab,ff44b63f,c3a578aa,fb189539,448a265b,eb87a268,b71a18db,f12fe8ac,e502720,c83ca156,c1cc7a39), +S(432cc05f,c78b0d56,e605391f,e4708bda,a1ff3edc,96a729ca,aad3cb0,300c4d4d,6675d8ee,ece8c078,e1bad373,247ce383,d4c65519,4a6aed20,a7ca5eca,34a89c30), +S(874fda6c,b284ca2d,a216bbda,28249388,88da3968,7f615ab,52c8e61f,b72a1fd,2d7199e2,b0b88f45,18e6eeb1,240b2ffd,a9bfcee4,6f754a4a,3db7959,dfe857e6), +S(7fe21a0f,3ef67d60,1de05f67,2b163285,a5577948,ee78274b,19fc35cf,2d2f6801,62fb2ade,5e2fffe1,28542038,91a6ea73,aabfa35b,1f7fb000,95190adc,de6663f6), +S(cd0540e9,efe497b6,2beb2227,a2da819,a1ac3bed,8eae24c2,6e2991c0,a707dd69,446c3218,7d0c9229,d65dad2,1392e4a1,66445386,4a5c1620,bf768fad,20a45c06), +S(a533c295,74e78024,52218573,66c30001,6159d772,f5bedcff,28d7f7cc,3051457,b61a106e,e0166d54,5e1b945a,f3e4e285,31a34cb8,56a34dd0,cd21184a,9555eeee), +S(5e144f44,ed88845a,c089331c,eb58811e,4c164e02,5d1758ee,51a7a522,c66deb30,ff95cab7,597cf62f,e1aa8df8,a2cd3844,d71ab4dd,4eb02a9e,6175077d,261e2540), +S(97487a40,9562ee2,7620fc2b,c5bd55ac,6509d487,8ab41257,53884b97,7c5a84be,e52a282,1430c540,5f1143d0,62b69faa,16592f02,cb9b8602,d52c9fc3,70769091), +S(906f9ac1,d3db4690,d74771b7,f1940679,b0de7731,a68d7d35,89caae34,c3760eea,6f2be7,2275dd5,1e77a066,b8d3c303,f565cb97,b8fb0dd3,14445d18,876665a6), +S(4c355a31,d17617f3,5d4066c7,a125b2bf,1d6f77e6,27b585ba,2d271a29,a88c81b1,6a686e69,237b75a1,a1ecb86f,b715e858,35aa0686,e2ef10bb,38b762ca,5646e9db), +S(15aac1a8,9b6b7629,57375d4e,aad87c9d,e1fc2617,89e57d29,731fe96c,1380140c,2968c0b2,2c3dd83f,3286d37a,639bcc14,3d89e75f,cac1da56,7e07799a,62af1008), +S(4642f29b,37b87118,65767998,d00b41b9,fca6718d,bfc55785,1c459efc,2ea15037,a1ded31c,be33cc1,425df851,998ddd11,1518ed13,f84756c1,c7cc46cf,3f5e9a72), +S(9554abe,9e092bd2,c4ff46a0,abd0b7c7,fb73d85f,1c01fd96,83146559,306ea727,89e2c07d,db1fe6b0,9872ce91,66ce9ca8,1124986c,c7e48e09,f80aa3cd,70987711), +S(1c0977a,a773c56,2e36dd15,58b95fff,d35b4dea,ac464011,ad7b79cd,26227238,e04ce4c5,b0b165e9,87dfef97,d32094ea,3e86e6dc,33a4c96f,c9470336,34b0db68), +S(71d44171,60361c39,6295e5cf,b1540ef2,1ca046b5,98645a23,e8c9772,ac21be4f,7122d5b,32a654a0,1476a47f,d3317a25,ed51536,4a21253,f4068dc8,14660c55), +S(d906f59b,4d56bc12,f26d60e6,6fc31733,e5450707,89025ea3,8a6193c8,520ddbc7,cd7f414b,c6cc79aa,4c65b943,ff914234,a9d85cf1,9853be59,2a71fe1d,dbb20163), +S(11b7dfb3,17dd5c23,6b8084d4,f3cc157f,c25c0e70,8248b472,240963dd,9a3fbca7,dd2c8caa,2a2d14d7,fbec267c,9fe87ab2,8b1ddd92,dd100449,f75ef1da,97d4e5e), +S(3ef8274a,fca8fbb3,1894d7a2,d1ad59a9,4951b21,328b1e84,ecaa6df9,cc1ef473,2e4f0c04,f5da671d,4a2b641,46ae749,27bc35b5,98a54190,3883469b,3e7874de), +S(a861fc27,f5e6300d,ec0fbf6c,3315d053,98f90b84,2422992,bdfba11b,1c1c7e34,75a7458,5d98bca4,e3517897,afef848,8e524168,a586d8da,18834171,4b51846b), +S(9537019f,57d7869,2a358758,47e885bd,1594a426,4412c595,62eea9ba,4ab34de8,21bfd84e,a66650dd,79cc8c13,7217a351,57b9c046,938f20b7,246362c8,6637d5f4), +S(71c80c38,b1889d4f,507132a1,87af0c91,79994b84,1b816c8a,6d130a,df1b500f,8de1f76c,100e75b5,1572da6,d08c76b2,10cdc447,cf903e0e,2b00e002,5dee0ce2), +S(2fa9ce2f,59865d10,17880d74,d31cd446,5c28ff56,50f29e6b,d74a810,977ef9ec,6c5a2073,55c0dd3a,b994778a,6bd02b87,80ba8e1a,899330ee,cd8781b7,6e15cddc), +S(96ca6bb4,bf74c748,75703386,ae02dc29,13329d9e,a5395892,df1c6f57,4a84fa4a,fcb510b6,dcfe8da5,690f8fc9,4dea8ac0,e42af209,35c33347,b088cc79,52e98b1d), +S(36a066ae,694f2645,25cba884,956ebd46,ae568acf,11664965,63cee00d,a32f2199,5d1e975a,856ebd1a,cb1fe254,101e89ab,ea089e8a,b38bbd0f,1100e914,709fd965), +S(4922879f,800234c9,63f4b572,d236843,4c4da5c8,ff741982,c3d1e341,841d1309,9b259470,24b5f4cb,97c68d18,f7f8dfca,1e57f7de,63208765,2ce15770,98f35494), +S(ee27e2b,acf95f6d,dbb5ebae,bbf181bb,43322a3d,6db87e78,14e57a3d,41b581e0,3d6a18a,daf69ae4,88ecc9d8,7d6b1bf2,c8d65544,3f4b45b4,c5a0ac51,7b1dc3ca)} +#else +# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build. #endif }; #undef S diff --git a/src/precomputed_ecmult_gen.h b/src/precomputed_ecmult_gen.h index 7256ad2e..283738a5 100644 --- a/src/precomputed_ecmult_gen.h +++ b/src/precomputed_ecmult_gen.h @@ -14,9 +14,9 @@ extern "C" { #include "group.h" #include "ecmult_gen.h" #ifdef EXHAUSTIVE_TEST_ORDER -static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)]; +static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; #else -extern const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)]; +extern const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ #ifdef __cplusplus diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 1a8be57d..a17d32de 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -389,7 +389,7 @@ int main(int argc, char** argv) { } /* Recreate the ecmult{,_gen} tables using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */ - secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, ECMULT_GEN_PREC_BITS); + secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, COMB_BLOCKS, COMB_TEETH); secp256k1_ecmult_compute_two_tables(secp256k1_pre_g, secp256k1_pre_g_128, WINDOW_G, &secp256k1_ge_const_g); while (count--) { From 5f7be9f6a53a99f4a7d00e79c1dfe37eebe6edf8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 29 Dec 2021 14:37:38 -0500 Subject: [PATCH 020/383] Always generate tables for current (blocks,teeth) config --- src/precompute_ecmult_gen.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index 11ab8ba0..ec54d2b1 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -53,6 +53,7 @@ int main(int argc, char **argv) { const char outfile[] = "src/precomputed_ecmult_gen.c"; FILE* fp; size_t config; + int did_current_config = 0; (void)argc; (void)argv; @@ -77,6 +78,12 @@ int main(int argc, char **argv) { fprintf(fp, "#if 0\n"); for (config = 0; config < sizeof(CONFIGS) / sizeof(*CONFIGS); ++config) { print_table(fp, CONFIGS[config][0], CONFIGS[config][1]); + if (CONFIGS[config][0] == COMB_BLOCKS && CONFIGS[config][1] == COMB_TEETH) { + did_current_config = 1; + } + } + if (!did_current_config) { + print_table(fp, COMB_BLOCKS, COMB_TEETH); } fprintf(fp, "#else\n"); fprintf(fp, "# error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build.\n"); From ed2a056f3da9c3d75a1604832b4cd53e1871e784 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 29 Dec 2021 15:09:52 -0500 Subject: [PATCH 021/383] Provide 3 configurations accessible through ./configure --- .cirrus.yml | 2 +- .github/workflows/ci.yml | 18 +- CMakeLists.txt | 23 +- ci/ci.sh | 4 +- configure.ac | 35 +- src/precompute_ecmult_gen.c | 6 +- src/precomputed_ecmult_gen.c | 1410 ++++++++++++++++++++++++++++++++++ 7 files changed, 1462 insertions(+), 36 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 04aa8f24..6e77403b 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -11,7 +11,7 @@ env: BUILD: check ### secp256k1 config ECMULTWINDOW: auto - ECMULTGENPRECISION: auto + ECMULTGENKB: auto ASM: no WIDEMUL: auto WITH_VALGRIND: yes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ad905af..d2466820 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ env: BUILD: 'check' ### secp256k1 config ECMULTWINDOW: 'auto' - ECMULTGENPRECISION: 'auto' + ECMULTGENKB: 'auto' ASM: 'no' WIDEMUL: 'auto' WITH_VALGRIND: 'yes' @@ -83,8 +83,8 @@ jobs: - env_vars: { CPPFLAGS: '-DDETERMINISTIC' } - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' } - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - env_vars: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - - env_vars: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } + - env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 } + - env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 } cc: - 'gcc' - 'clang' @@ -377,8 +377,8 @@ jobs: configuration: - env_vars: { CC: 'clang', ASM: 'auto' } - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } - - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } + - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } env: # The `--error-exitcode` is required to make the test fail if valgrind found errors, @@ -431,8 +431,8 @@ jobs: configuration: - env_vars: { CC: 'clang', ASM: 'auto' } - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } - - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } + - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } + - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } env: ECDH: 'yes' @@ -487,7 +487,7 @@ jobs: - env_vars: CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g' - env_vars: - ECMULTGENPRECISION: 2 + ECMULTGENKB: 2 ECMULTWINDOW: 2 CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3' @@ -600,7 +600,7 @@ jobs: matrix: env_vars: - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } + - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ef7defe..a70f2edd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,13 +101,22 @@ if(SECP256K1_ECMULT_WINDOW_SIZE STREQUAL "AUTO") endif() add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE}) -set(SECP256K1_ECMULT_GEN_PREC_BITS "AUTO" CACHE STRING "Precision bits to tune the precomputed table size for signing, specified as integer 2, 4 or 8. \"AUTO\" is a reasonable setting for desktop machines (currently 4). [default=AUTO]") -set_property(CACHE SECP256K1_ECMULT_GEN_PREC_BITS PROPERTY STRINGS "AUTO" 2 4 8) -check_string_option_value(SECP256K1_ECMULT_GEN_PREC_BITS) -if(SECP256K1_ECMULT_GEN_PREC_BITS STREQUAL "AUTO") - set(SECP256K1_ECMULT_GEN_PREC_BITS 4) +set(SECP256K1_ECMULT_GEN_KB "AUTO" CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. \"AUTO\" is a reasonable setting for desktop machines (currently 22). [default=AUTO]") +set_property(CACHE SECP256K1_ECMULT_GEN_KB PROPERTY STRINGS "AUTO" 2 22 86) +check_string_option_value(SECP256K1_ECMULT_GEN_KB) +if(SECP256K1_ECMULT_GEN_KB STREQUAL "AUTO") + set(SECP256K1_ECMULT_GEN_KB 22) +endif() +if(SECP256K1_ECMULT_GEN_KB EQUAL 2) + add_compile_definitions(COMB_BLOCKS=2) + add_compile_definitions(COMB_TEETH=5) +elseif(SECP256K1_ECMULT_GEN_KB EQUAL 22) + add_compile_definitions(COMB_BLOCKS=11) + add_compile_definitions(COMB_TEETH=6) +elseif(SECP256K1_ECMULT_GEN_KB EQUAL 86) + add_compile_definitions(COMB_BLOCKS=43) + add_compile_definitions(COMB_TEETH=6) endif() -add_compile_definitions(ECMULT_GEN_PREC_BITS=${SECP256K1_ECMULT_GEN_PREC_BITS}) set(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY "OFF" CACHE STRING "Test-only override of the (autodetected by the C code) \"widemul\" setting. Legal values are: \"OFF\", \"int128_struct\", \"int128\" or \"int64\". [default=OFF]") set_property(CACHE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY PROPERTY STRINGS "OFF" "int128_struct" "int128" "int64") @@ -294,7 +303,7 @@ message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNO message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") message("Parameters:") message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") -message(" ecmult gen precision bits ........... ${SECP256K1_ECMULT_GEN_PREC_BITS}") +message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB") message("Optional features:") message(" assembly ............................ ${SECP256K1_ASM}") message(" external callbacks .................. ${SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS}") diff --git a/ci/ci.sh b/ci/ci.sh index 3999af4f..c7d2e9e4 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -12,7 +12,7 @@ print_environment() { # There are many ways to print variable names and their content. This one # does not rely on bash. for var in WERROR_CFLAGS MAKEFLAGS BUILD \ - ECMULTWINDOW ECMULTGENPRECISION ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ + ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ EXPERIMENTAL ECDH RECOVERY SCHNORRSIG ELLSWIFT \ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ EXAMPLES \ @@ -74,7 +74,7 @@ esac --enable-experimental="$EXPERIMENTAL" \ --with-test-override-wide-multiply="$WIDEMUL" --with-asm="$ASM" \ --with-ecmult-window="$ECMULTWINDOW" \ - --with-ecmult-gen-precision="$ECMULTGENPRECISION" \ + --with-ecmult-gen-kb="$ECMULTGENKB" \ --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ --enable-module-ellswift="$ELLSWIFT" \ --enable-module-schnorrsig="$SCHNORRSIG" \ diff --git a/configure.ac b/configure.ac index 158ed5d7..68eae5ad 100644 --- a/configure.ac +++ b/configure.ac @@ -213,13 +213,12 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto], )], [req_ecmult_window=$withval], [req_ecmult_window=auto]) -AC_ARG_WITH([ecmult-gen-precision], [AS_HELP_STRING([--with-ecmult-gen-precision=2|4|8|auto], -[Precision bits to tune the precomputed table size for signing.] -[The size of the table is 32kB for 2 bits, 64kB for 4 bits, 512kB for 8 bits of precision.] -[A larger table size usually results in possible faster signing.] -["auto" is a reasonable setting for desktop machines (currently 4). [default=auto]] +AC_ARG_WITH([ecmult-gen-kb], [AS_HELP_STRING([--with-ecmult-gen-kb=2|22|86|auto], +[The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms).] +[Larger values result in possibly better signing/keygeneration performance at the cost of a larger table.] +["auto" is a reasonable setting for desktop machines (currently 22). [default=auto]] )], -[req_ecmult_gen_precision=$withval], [req_ecmult_gen_precision=auto]) +[req_ecmult_gen_kb=$withval], [req_ecmult_gen_kb=auto]) AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind=yes|no|auto], [Build with extra checks for running inside Valgrind [default=auto]] @@ -358,19 +357,25 @@ case $set_ecmult_window in ;; esac -# Set ecmult gen precision -if test x"$req_ecmult_gen_precision" = x"auto"; then - set_ecmult_gen_precision=4 +# Set ecmult gen kb +if test x"$req_ecmult_gen_kb" = x"auto"; then + set_ecmult_gen_kb=22 else - set_ecmult_gen_precision=$req_ecmult_gen_precision + set_ecmult_gen_kb=$req_ecmult_gen_kb fi -case $set_ecmult_gen_precision in -2|4|8) - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DECMULT_GEN_PREC_BITS=$set_ecmult_gen_precision" +case $set_ecmult_gen_kb in +2) + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=2 -DCOMB_TEETH=5" + ;; +22) + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=11 -DCOMB_TEETH=6" + ;; +86) + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=43 -DCOMB_TEETH=6" ;; *) - AC_MSG_ERROR(['ecmult gen precision not 2, 4, 8 or "auto"']) + AC_MSG_ERROR(['ecmult gen table size not 2, 22, 86 or "auto"']) ;; esac @@ -475,7 +480,7 @@ echo " module ellswift = $enable_module_ellswift" echo echo " asm = $set_asm" echo " ecmult window size = $set_ecmult_window" -echo " ecmult gen prec. bits = $set_ecmult_gen_precision" +echo " ecmult gen table size = $set_ecmult_gen_kb KiB" # Hide test-only options unless they're used. if test x"$set_widemul" != xauto; then echo " wide multiplication = $set_widemul" diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index ec54d2b1..25ab445b 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -17,8 +17,10 @@ #include "ecmult_gen.h" #include "ecmult_gen_compute_table_impl.h" -static const int CONFIGS[1][2] = { - {11, 6} +static const int CONFIGS[][2] = { + {2, 5}, + {11, 6}, + {43, 6} }; static void print_table(FILE* fp, int blocks, int teeth) { diff --git a/src/precomputed_ecmult_gen.c b/src/precomputed_ecmult_gen.c index 25519d31..95c18bcb 100644 --- a/src/precomputed_ecmult_gen.c +++ b/src/precomputed_ecmult_gen.c @@ -9,6 +9,39 @@ #define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = { #if 0 +#elif (COMB_BLOCKS == 2) && (COMB_TEETH == 5) +{S(7081b567,8cb87d01,99c9c76e,d1e0a5e0,1d784be9,27f6b135,161e0fd0,3f39b473,ad5222ac,f062cb39,21b234a7,15b626ae,f780b307,9b5122d1,53210f42,d9369242), +S(228af17e,df90d1cc,a40173e9,478fa445,9780dacd,c3f15b90,fda5d00e,1faa1b51,8ff47c4d,a4ba636a,f656da9,12a81f79,6252496d,1e519886,b2c2b073,25be2b4a), +S(b515ebe0,f48fb34e,9e01824c,d90553af,db116579,96667847,5ebaa700,242fd722,4cf08191,510fbf0,51f9e19a,198f11f6,ea31268c,2a6d384c,60557250,f0553c50), +S(c37581f1,35446ff3,e80cde04,ec987f08,5af3af9f,71d87494,99b03ba,dcb8f78c,9e46324a,8d8754fe,fbda7c34,2446cf72,b7472708,25cfb92f,a22a4e73,4f1e9bc7), +S(768392e3,b2ccbbc,21792f2d,6f43c63d,efcc249,bcd549cb,96abd8ef,4ae59e90,5d061a40,ac3f93d1,82f0f7a9,914fff5d,90bbacb9,1965882c,591e89bf,c49da994), +S(a9db5de9,2d96c715,8ce5ee00,3d186cf1,976f6a76,f1be0714,726594fb,6c1ba564,743df2a8,ee73fb4a,47b3d0f,2f2b8cab,5af5227,f232946a,82676e4e,8bb70c8b), +S(58921d8d,3712f640,657e762a,737ccd0a,cece1459,a2ba8323,20b43903,d4953f93,78c26959,7e422c02,c01fcbef,484a9d44,9f635c82,849bc2a3,2a9bf6ef,3e6f1e7e), +S(bae41760,ade541bb,60028015,f6906b78,aa41515a,d995dc40,afa091da,77ae8b9a,716ff74d,ad6dc24c,77ebe31f,abe19792,41d18b0f,43ff7598,c6ea04c6,6899219f), +S(e836ff6c,6f9e02e2,4e6f6bcc,2f2460b4,9de88730,6d69241f,b22fa574,7e100f80,77c41df1,4d87b6d3,de74deca,ad426635,f85daca0,ab966a4,5a26a972,32105c5), +S(c7f17d19,fbbf28e2,543fceb2,4268ff6f,1b85e189,79b09991,7457fca0,9ba1b5a4,23a6d4aa,83ee15bf,f1655575,3e4162c5,8acedadb,4c4abfc2,54b7018,f477514b), +S(79c337ad,8835046e,572eea35,df76276b,84e99172,7bbc68a6,8c0b743,28619a,af6cf2b3,9c6b51c9,f1f92e42,6598dcbe,39da6196,2abae0da,d5fc8d0a,aa16a875), +S(1e77739b,12d20887,2bfe200b,d202972a,544804f5,2b0969c5,c22fbe1c,b8b23837,880c7490,c0455322,a0f1e67d,34b3fd1e,33c1e7da,83b9b047,5aef7bc1,332ccee5), +S(b1d314c1,74d493f6,c36a893a,830d90b,f1e86d0c,6deceee0,edb77ff4,31e9607f,8a4ba010,ec3e47cb,29d8f056,e056eb73,3b6b35f6,4c742d06,9ab832f4,68bcd3be), +S(2498aea6,471f748a,f14e50e6,bc17e0a3,ee09514d,fccbd174,f8a21d02,dd0fae48,55a3949f,2e4188e2,b3d344ce,6f0276b5,99b121bc,358e8fe6,bc4f03f5,a8219d08), +S(42d0778e,27e87710,dd19285e,d531af1e,7064386d,11b1b3c9,fb788bf2,b0c112dc,37888909,d943825a,9610e37a,362549f,547b7c7d,ae64a27e,c34290f0,b4fc5fcc), +S(af09a9f8,3a21b2fd,69ce14c5,495c680e,df18e426,c1ca5a1c,af56246f,d6ea5bbd,8eae43ca,8e591017,62c4cb02,9e5cacd2,58f0fdb1,ddbef7e2,c5765208,107c96af)}, +{S(4a7f72ed,ebd8df1f,13db15be,3ab296a8,d67edee4,37965f03,eb501205,3518ddea,1f8c4dc1,2d0e59e7,7d30a326,fd4ecbf8,aacd5fb6,7dc7169,898a9708,ac46b972), +S(c4d4f8d4,949d1ff6,559925db,f4d34972,af16062b,d59493b8,b1e0d546,c2870874,cd7f93e6,c0ee3fdc,4267625a,a6620540,4f6d80c3,d0f7210a,ce6b52e,c350706e), +S(773627f7,dcc56184,7eabafa3,42fffade,325b8ee2,a96f2f77,cbe675a6,2942277d,fb0ad731,9bff4c9c,270d93d1,89a4c380,218ec9df,1f564228,641ab35c,46526bd6), +S(ff443101,befd0bd9,e1914864,3eceea06,b9cf711b,1405e3d5,3883a29f,906063ed,aa1b7d9f,59cbddf7,bc1ad03c,44c4295e,efb406ca,7960c683,eca508d1,b2a9a2dd), +S(cbfb6813,a6874b65,9234e866,c2875f70,e45f9f76,3d634752,3f86040c,880a2e56,ed85d1a,6620c1a4,85ba3038,d2ee6590,4e27206b,eaa531ec,1eb5b886,8232cbca), +S(4e85c77b,27788563,aaeba139,975f7125,f3c933b4,8d67ba6a,2e964243,bdd7bb51,200a9d9b,3400c87b,1fb98422,3200aeb8,e6a5af1d,58c061f0,d059c0b8,d431c08a), +S(d58178ed,f0ce32e3,39a524f7,ad389f7d,8817f41f,ed782612,45218816,2a67d4f0,4840df81,5dab9596,93f9284c,54bdee72,f4861d39,3944c648,ecd76ec5,6dd3225e), +S(670f8f7,9b66496d,13692558,d56d4cd7,a1eeb0d6,9e5133ab,4f0a064b,7152fce4,1a72206,6f530586,927c2e39,370d11f3,e251bd9e,eee10303,406b7592,716333d6), +S(10b41abd,ed4de2fe,b7a40050,e61e5982,89a8cf3,6eaa608c,f2a82c63,5788f1d0,532d168d,680e9c74,4d5111da,6aab902a,9a0f5283,7836b9d9,585dbc8b,1a407de4), +S(76abd21b,103aea9a,f04b4040,297894ce,a501474d,9d38d30,8ed02cc7,137bc7c9,b5a432ad,9e92935f,7040897e,3b04152f,693c5f2,cc1e1d53,2c33f70d,185318e1), +S(4335e10d,5e4f02e6,f1b58a0d,ffb473ec,15f735a3,bf96c140,50bae78c,37061db2,1301143b,1f29f122,afcd0230,d46b6b38,b154e589,92b7eeb4,16088968,a7d57485), +S(2b3966f0,7e37e771,ac4c68ad,b8eef3c0,977cb895,2f47676b,e658aa86,76057f67,5382a6c5,bcdd1a01,6d79d817,80faf650,c0a486bc,ea8fb592,1cd3492c,42c91c3e), +S(f7738800,b7fdf237,dc7f03fc,43724011,8b53aea4,4d7953d4,276f3b4d,bf5c0ff8,c1de7924,ef8dfeed,c4fb409,f1a15d4c,5e8ab42c,90ea9c92,867b5b5c,f2921605), +S(5cb07874,ac4ffb86,2da619be,4c8fa38b,e8b261ec,3ec73a12,cd4cf8fc,4f8d5dae,549d1896,4931dabf,ba4553a2,461f2660,87733454,ea8eec6b,f671e3de,60c70340), +S(5cc85d41,7b2ae9ac,dedb1b44,ce78d8a7,8f56b878,1a4b3af6,635a55c1,fead3be7,66a48c79,301e57d4,54cc8644,d2e778a8,45d85762,2c10eb98,d77eb873,e58bbeca), +S(f27211c9,a067b01c,7fe7fbf7,7b5d9b0,eb0f2475,9d541457,6eb24ba4,19fd3db8,e26d28eb,89f7b518,e9ae0b88,fadbfb9b,641d3a44,c59c6f93,ec28a541,486e041e)} #elif (COMB_BLOCKS == 11) && (COMB_TEETH == 6) {S(629bee58,a391595f,eb20c534,4933937a,cdb2eba1,86d49f8b,845c1b5f,4ca87182,8dae4162,73c6c068,2e2aede4,76efa86b,7612c07e,f72070d0,dc4486f1,47e95085), S(6fd5e13c,a94b874b,28cd574b,726efdbf,143ab108,1089b846,7b5b2ebe,6c6a3c8f,4a4db306,52c9772a,868b2859,57c5a005,d83f6afa,6e65d87c,700da998,ce651396), @@ -362,6 +395,1383 @@ S(96ca6bb4,bf74c748,75703386,ae02dc29,13329d9e,a5395892,df1c6f57,4a84fa4a,fcb510 S(36a066ae,694f2645,25cba884,956ebd46,ae568acf,11664965,63cee00d,a32f2199,5d1e975a,856ebd1a,cb1fe254,101e89ab,ea089e8a,b38bbd0f,1100e914,709fd965), S(4922879f,800234c9,63f4b572,d236843,4c4da5c8,ff741982,c3d1e341,841d1309,9b259470,24b5f4cb,97c68d18,f7f8dfca,1e57f7de,63208765,2ce15770,98f35494), S(ee27e2b,acf95f6d,dbb5ebae,bbf181bb,43322a3d,6db87e78,14e57a3d,41b581e0,3d6a18a,daf69ae4,88ecc9d8,7d6b1bf2,c8d65544,3f4b45b4,c5a0ac51,7b1dc3ca)} +#elif (COMB_BLOCKS == 43) && (COMB_TEETH == 6) +{S(e3adcb1a,fe947e6e,7cc4f5a2,df78310a,b235e2c3,bcd75eba,1904de80,c8814c50,e0b27ead,c4bbb9d2,37dad580,6e366674,4a9f9c3d,e024f2bd,1edb11d2,fafc0a22), +S(612c2ec6,f0e9c4ec,c2200d23,ddca77eb,d003be35,61e52b1,890bf846,3bb53ea5,9e944d7b,dfc7a952,c1c5ee15,485d7199,dda19551,2d729628,c215a9e0,285f656a), +S(42053dc0,9f90a7f7,86feca60,d68a5c3c,789e44d2,3479aa13,2d1a427c,621373a3,b338f891,f3930ec7,738669bb,3a29ae2d,637be08a,954f2a8c,acb661af,a660bd22), +S(4d227ea1,5194ed57,10f8ea4d,a639be04,fa68ecb4,f3d2d9c9,43ec32f2,80f74051,28a94075,bda4c195,40c20493,b5391df7,166b1264,b957fef9,683cfbec,4c6e6875), +S(8ec4abf4,d4db3b0,2b0712dc,ef54a405,54b6cac9,3f88fa9d,d8cad4c0,9b94eb1e,4e37e159,517346ee,17e948c4,a17912b0,b29c303e,497cfb38,16796752,99aaf9e8), +S(ab186398,117fb83d,db8b9392,cc888fe2,50d2f604,5a0c3f89,92d8a82c,382175c0,79437224,b3b1604c,fae64902,e3030448,51ef17b8,9af02d7c,54a92c34,7fa2abda), +S(2bd09ae7,1e8d85a2,ba550bf2,9c1787a2,3d2c8985,e2ed07bd,1d39e7b9,8ef8135,ddaebb19,195bfd6c,a44ce82f,b7f3c65a,8af935ae,52e2d2fb,33cc231d,c4b16082), +S(e6da6560,c8265e7c,8f62edca,78dc739b,74bd6543,44a939cd,bac0f489,12b920af,147f5ce4,a98377cb,981dfaf0,1a1e4740,238f1c5d,ee69cfff,a54f3aeb,e53980eb), +S(7df5abfa,d6b46a37,30bd5892,69edb6fa,b70a0d31,936c0787,407d5d6,96506263,bc5cbafd,1f5fee67,1aa449ff,bacefc67,cf7c529f,86100d7c,a8160e4c,376c76d4), +S(ad672823,cfe3ac01,50038d30,81a1a109,d8629b4a,a4e26779,373ee0db,44a466d9,c288397c,f91157e6,770c401e,dc84b328,87b22534,d11e11c,c8415a4b,743fef9b), +S(72032cac,3177c280,ceb3076d,7f510405,2413706c,956ecf38,acf410ad,a12473a6,8bbaf50b,95797824,2994e6d0,a4bf6d07,149792bf,f2a74847,1095f845,bb332036), +S(36a1f78c,3bebf8c7,1fae5e29,cf08485d,d9debdae,348a20,ad84ba5d,4308fec9,842f57e2,e900d07b,eefda7e5,9dc40139,c5deefcf,11c07c42,4629c59d,593e01af), +S(5f418454,72e80d51,1c1b8bc2,b6b89224,9119ed43,5b915809,f7b26d01,8427f579,dfc29fdc,f3c65221,a6615262,cebd9a14,acba91ba,cca22ec5,d84303cc,1fe0085e), +S(5577ced2,f6bf41f9,503aa4a7,c0060fae,6d33cda6,e3c8ec55,1eaec315,bb91fedb,858ded64,6c3d6231,87c0967a,84ee5253,2b21c4e5,b329bdbb,76f6a6d4,93cdcb4b), +S(bc74b56a,c94ef36f,2b356bc5,dfd11d2e,7a371087,653ad607,dbfcfeb8,27abc502,d57d74e7,39e758ee,96a422e2,f1fa61f7,4f6308f5,71e6dca6,3b0b0103,e83cf1f3), +S(727ed91f,be4c5086,50a0d365,b28ae4aa,c9434c0,735fce3c,7b3ebb42,f4be911a,8c595547,5e627c22,6bfa855a,22ebbc56,d3d0b331,9120d8e9,13bed868,7d3bf331), +S(6286bb90,71f8887b,c4fbb3f0,a9ecb19e,fcdd2cf1,5e286da7,1bb60c9b,5ff5e644,73731ec5,ea3e537c,c6060ac5,dde716b7,2aef4117,ba747b12,1c26fc9,eddbda74), +S(3905682b,72282a78,2b8d8dba,72cf147a,de0025dc,a21521e1,ea989040,c248852b,5da3bf52,dceaa14a,a3534068,c05bb015,2cf9c722,cc80c56,cf828ace,d96fc390), +S(561a2ccd,ca12b67f,dad28ee2,c3cee78a,cf811766,9e4a2543,c81b1ca6,eb4bd16e,3b386a9d,553c2746,893477f5,17a05e99,bbc8ddf0,896249e3,85e406d6,a57b9ed9), +S(75bdfa06,6a1a42a7,50f283e8,3ec91cc0,a5b68829,6e6aa24a,28a61e33,65f378e5,c73224ec,797d6736,c1a541ab,34523d91,e1ec3754,fe7fed44,474f9cba,29f305e5), +S(e881a840,847aa2e2,2417cd3d,3e798c56,1e630290,5dff6bf7,754d9419,98d401e3,8816d775,f1555452,f624e45,710a240e,90fc5e23,7536d217,cf555349,b5e31bac), +S(1fb527e9,4e9c70e8,657de745,8b81ef9e,e3c2b4e0,128a675b,f7e28980,e18b201e,bab00a09,1145407e,693d5353,7818bd30,49e1f364,757d228,58b8aac5,416e3e78), +S(1c2bd878,b94169da,722a9de0,c4e317ce,a8802aa9,60458301,11a89d1d,9de4270c,95b7d99,bc3df31e,f0dbf17a,a09ef148,71ae6c5d,870ebe75,1f52aaad,a48dfcc5), +S(41f7fa0a,9a59513a,e221e3b8,4b91995f,c9d40eb5,d120a6d8,e663452a,d92099c8,813dbbe,92ec4b62,25d1cc5e,5820ebb7,dbdc2964,d5dd1ab3,deabceb9,5e793d32), +S(e5cbd627,89c6a843,25a24407,89b88dbb,1dc55afb,9e8296e6,bb8af7de,57a50e60,2cf01cea,ae4f4fed,46c4efd7,86ca5e4d,ef5af524,e9393d74,e9dd224c,604b9408), +S(eb3bc68c,623b1f46,ab905412,c7f2d588,fa25abb7,7a7bd782,ba9bb3aa,c05a70ae,df9f46e0,5dc1d126,2f72ef3e,8db01fbc,11915af6,4aee0c51,da1cfa,b4d15ef0), +S(5702fb8a,2602f41f,52699f68,8d4b005a,128762e1,1dfd13fd,22ea751c,cbedb2ef,a77105b3,7af534e6,46f58c3,b02543fd,9e0666c1,58051952,a61f8389,73f5847), +S(66954eca,5434263,4036fc7,fc0fe33,81f5195e,88433bc3,2c5a8a60,341e2859,d8b1b14,40e9f123,f39c8658,f9d64e7d,fe4071f0,ada879ea,42eebad6,4d37f4fc), +S(592152c3,98d6c719,636a03a6,dad64246,a5a6814a,a62c156b,ce5332f,6759b031,8d22d1e2,d93dcccc,889f3b6e,dd5e2098,2f5586d4,bac06842,d689a37b,4b845c12), +S(5699b93f,c6e1bd29,e09a328d,657a607b,4155b61a,6b5fcbed,d7c12df7,c67df8f5,c147ee87,14325497,6b2e534c,e6902748,2a5c33dc,867732a5,8338f05,73368388), +S(c62c910e,502cb615,a27c5851,2b6cc2c9,4f5742f7,6cb3d12e,c993400a,3695d413,e80c2522,898d8a22,2c4dc0b9,8dc9ce88,740fe252,5144656a,c30f978d,dba83c1f), +S(0,0,3b,78ce563f,89a0ed94,14f5aa28,ad0d96d6,795f9c63,3f3979bf,72ae8202,983dc989,aec7f2ff,2ed91bdd,69ce02fc,700ca10,e59ddf3)}, +{S(efbbec14,ff6d7e18,a8015d68,ba3ceb19,d4cbfbb8,a1bbc09c,ce755a23,e9d4b3f4,a76faa08,2b02b8a4,405573c9,5ac067f3,ab936127,24bfc14e,a27f923d,3adf0133), +S(f02f6744,a0ee7b0c,7bf0abb3,c7ec0a5a,3275d109,92be2893,7e9ef649,23fa932d,955f3630,c5621787,13e6d8f,39efee26,d91a0947,8da36db9,4ab4a89f,aaf9019a), +S(1c6f9f0f,d6ecbca1,fbcfbe9d,1f3d2476,dbd3b6ca,ac8e18a5,949b993d,8c0063e5,e3e3770e,33081dc9,5125d69d,c631450e,5494d21b,2ddf48f1,fbc3169f,3cc1eb91), +S(2062725b,739b793d,c9798397,dfc7b1a7,24ebe8f7,5e5654df,536adff1,25970841,22f3e3e5,c0201265,5e6d8e58,b8ba633d,9a9216b5,445a7f78,a2605688,4a5b6092), +S(57ffda66,e0c29448,7a1570f7,e2f5dc58,ecf9b906,5f374046,5bd1734,841785df,22ae8728,a8800436,1264c380,3beddb65,a9dee575,6f0cfa97,c01dc047,3c806def), +S(4b49fa7d,463cbb43,b14928c6,7b3a85a6,8132ad9c,427d3cc3,bba76d1a,7c9a69dc,7e7e3133,3782b30,5c7c3bd6,94e3c306,b3f9829f,86f76f08,d44b1a76,a207f2c5), +S(411a3b18,c9b638fa,38a0e811,ee370f34,5c9476db,61df1843,863d6d7f,4e803ccf,bb306f97,e97e492d,e74afcd0,a771570a,8210b51,9e61df78,4e6e97e0,ac23e109), +S(c8227510,49de1572,37afdf55,d175196d,5d315001,3670b478,a0255a4c,ebe95075,16be5950,a3f12be9,5905fb52,8d5bd93,23eb5908,211d2e8c,26204b32,556c5c45), +S(e46bdb74,8692d0fa,e6fc9f50,6685487,31d61f8a,5717fb88,4e1f7a41,70e4997e,35398e06,48bea42,cc48fa4f,2805efbe,6bead663,c054eb08,2c15ad46,c0611052), +S(d18293cb,d0902dab,e4c014e1,22969601,84aedbbf,a01526a8,6978e144,88ca794f,3a5b423e,32c1d2f4,bf754f42,9da3c9b6,84bb798c,ea73f637,1777ba77,1aae6086), +S(7b9cbbfa,a53923fd,e9f50845,3130101,3b17548a,8097433,79d3a526,d1c90c31,3fd7b71,5b6801cf,30fe22a9,8b7895d8,1b483f6e,9fdefe7e,6c59fec8,fb9786b4), +S(ab6e185c,be9ee393,5ad6278c,167396fa,aa4d936,80524d16,27ca8e93,48fce67c,7154007d,3f96ce60,d09499a5,1262c7bc,3ab5e9aa,929e0594,994a9671,8f912987), +S(56ffb418,8b9c9c13,4a110c03,8df8636a,71141ff9,8448cb79,eb6dece8,a28b65b4,1d728ed5,23ab821,ac0c40e2,b9348e27,191536c6,79a73835,8bd9b3c,b43dcafe), +S(bdba1eff,bf6af786,dca1da26,cc226102,1f95d56f,245298c0,b87a40e1,fa9a0cbc,fa18673b,41f765b8,25d13f2d,7963f1c6,b3308a14,b033fecd,e1d0d597,583440b2), +S(d9a4a7f5,5b3af93b,1c49ffa7,4f8154e8,23aa1477,16b16441,39fbc86b,2d9346ef,19ca90e7,538ac3d8,a28e1aad,5d8b1dcc,756f8a84,240e5769,a0f561d,f53289b), +S(ee5c17b2,74c78b87,9eda9341,256b1506,25582835,60a0bdcc,c8eba320,32d58638,d7d02f4a,b81215b1,7843e3c6,abb63755,c7e05d20,6c61a4f6,bb08d1b0,256409ee), +S(6953ae81,7ec599fa,5f739bef,dc4cd8b,4670eac6,912bd03a,a3fbe91a,5122ba0b,61bca3fe,36245ced,31cae918,fab6d463,50856947,f64a3be,d0eb62d6,f9f16059), +S(3bd721f7,59f7c3a9,93474472,4ffd3e34,503cbe45,fa7fa5ef,40a5a173,b8bebcea,bd7cbfbb,797034c2,d293aa64,1bf175dc,74a44dba,84b8d99b,8182d2be,6512ef2), +S(ab6e36ae,f5b7ff2f,fd2f42f5,8c408b7f,3ac84253,e1d8a43a,55cac222,678dd38e,ff0dc59e,51e504b2,9a0ba824,3ef26eb1,2446f628,78293da2,d924028c,21f57342), +S(bf1a1f6d,7f73b09d,3efbd73,eb9ea2c6,23e17911,9063489b,42fb1303,7b53fce4,236566ae,5371fc97,b5449b9c,2db32175,90e02412,b44539d3,bda7a814,3cd4a634), +S(fa0c6aa3,4c4825de,304cfece,37a20bbb,f72044e3,94cad202,c9e1edc3,b288ed57,df8e64ba,5f5e8381,4b6891b6,14dd4753,fed5f566,956a6dd,95540bdd,25c73995), +S(d2ea634d,ab56961f,52e39ba8,ebc5c150,ba9eeb1c,6178aef9,64fa97d5,e80581c6,2928f71e,a09a35b9,6fc1976c,f6cd3c1c,7d1fcea0,2142eb80,9666917d,c9a0621b), +S(827d6a36,697cb2f1,cf19e27a,ac30c06d,20d818c9,fe869309,6435f1f2,171c9b75,53237d41,3781a1df,d0d977c2,9690d488,b051dc2a,841ba226,c552cc28,12ae7caf), +S(59dafec5,4df05695,e123004d,38d9aa12,6a06c399,e5215245,5392e5e3,f1a47dd6,ff7d173d,ceda39ec,ca8d2c95,ab1658a8,6ad99618,e3fdb7cb,b07b03c5,2f96a86b), +S(5c4f5b9,2acb30ee,8c7ec4b0,ec577f41,a9502af9,a5a384dd,3386f230,3e62a830,8aea5f7,145de3a3,679c86ce,72e8b36,f3d6ac81,bb1d2043,9d719c32,ca2f8b30), +S(38add3d6,209080c8,efb65551,3d9420aa,457f06ac,d3ec84e8,db84e208,a0664ba9,ad95a891,c60f01a1,5fcddf2c,923790e2,d5596334,4d83a21c,dfe5f6bc,4c2b32b3), +S(9038876f,21c3bc14,111d5f6a,4749d07,34e40a53,7d398c68,809355f,764cf1ba,da030216,5e661aff,53367578,4a4d3447,707f14af,cf0d771a,53e8e687,b9dc29e5), +S(b07d3e8,dbbe686e,5e163725,8402cac3,e1e4f29,fdf154f7,bf008c5f,9969da10,c8b668e0,56bf8173,2d9778e2,eaa069d0,cdfbf826,47f615c3,6d0b311a,b2e14922), +S(8bc89c2,f919ed15,8885c356,844d49,890905c7,9b357322,609c4570,6ce6b514,2cec0c32,283233e9,21889013,c4a76d3e,e8d2cfa9,eed8890f,909c0b30,5736aad8), +S(308913a2,7a52d922,2bc77683,8f73f576,a4d04712,2a9b184b,5ec32ad,51b03f6c,b5a4f6a,bc0141a0,6e1cace0,993fc8a2,57ccc015,7d42e0ed,9f54a102,1701afc8), +S(3f0e80e5,74456d8f,8fa64e04,4b2eb72e,a22eb53f,e1efe3a4,43933aca,7f8cb0e3,34992828,d693436e,16f463f7,b7a2fe4c,6afedac5,59a4ac5b,34fd761c,15a0bbe0), +S(d30199d7,4fb5a22d,47b6e054,e2f378ce,dacffcb8,9904a61d,75d0dbd4,7143e65,6afc7262,f51c2a3c,4c292136,167c7f9a,e089f33c,9b127e69,fa4c00df,dbef9176)}, +{S(983e1ca0,5dd64afe,8d39e15e,43c1cf9f,6badf550,12cdea89,5fd85021,b49f173b,18200e81,d75a745,c1ecfe5a,3ead988e,4327693b,7e3c0e04,329b0c80,3d9934ba), +S(4e1200fe,d3e5048f,f6c9fe53,cdff8ef7,5d78e601,4df471fe,369f3d1e,80e46674,a62aca58,4ecf32bd,cc297b38,c1951c71,a66966f,b9ceb2ad,de411da7,d175df94), +S(82f5f27b,83d49042,63e69f48,b676c9a9,2446955,cbc18ec7,fd4346fe,37e0b0a1,e523d039,d0b8ccae,737bfc11,9b83dfd3,d6878403,862618bd,40ddfc89,9a688557), +S(a8c0fd4e,ab1f0e3a,cab37da6,58fbab3d,949ad9a4,31d6461,b2648308,35762d19,950200a9,63c3dc2e,6d2771e2,eff401d1,f9ce037e,75782943,3fd3c560,a169713a), +S(25c1b464,33068900,bff89a4,ee973937,b03c11a,5b33d16c,4f672fd4,bfaa11f9,471f1f8c,df18e73a,e12cae35,43506cf2,c57894a8,f633ad4c,e1c5330f,eae42b43), +S(497e56ce,8793bfec,4dc6f972,dbaf4a72,aa5d8412,3bcac5d4,2aa9baf8,ccfd6723,1d3d028e,b70105b6,eae66785,5dfe7e0b,7c0a6b3a,b069a475,bd913aa9,c29cf426), +S(68a285b0,d30c2dbb,b543e480,f66824b1,69aa339f,7e2282c1,5dc60f50,8e3f2fa6,87529a0e,1d53588d,21064447,99a8fee8,ffc791a7,cacc9e26,f7a7d94b,25e74cdf), +S(721c92ae,931712f6,15f4d7c,498dda23,e1029dbc,944cea16,9442b22e,d755a100,7ef052e6,a0d2646c,a5dff39f,3b2a1019,de43e3b2,5e51913f,d636281d,cee74a85), +S(aae8418f,1b124d79,ad15f773,1bdcea1b,453493ad,4cb0cd6b,ee5c9a8e,34335ba3,c2558bb1,4a7addab,62d1f308,1a9e6fd5,92a06976,3be877d2,af9ae1e8,b510d98c), +S(b6a06052,b492d74,c68640de,8bd3251d,fbaaeb0,ce1eb997,f2127ead,4bd0b81,7bb4269c,4a9ece8b,e8ea2f0f,d663a193,2a571249,2814eb73,4ae1493a,6a97b39a), +S(42fbe048,38761203,11e43178,6af555ed,d7bea551,d4d5aa18,afaa4c05,2c6d0c19,9ba562c0,a4cdc664,87caf55c,291d8246,65c29f32,2a56360e,90138b06,f109d83b), +S(9d6dcb88,b378e7bd,233464e0,25e97bf9,97768e29,6e4aac31,301fa1c8,bfbcc27b,f434ea54,3f7269cb,1ae1279d,4178dd25,bbc337ad,2f0d5141,610dc061,80daa8c0), +S(fa6fa5c8,1e6713d8,90cd6f29,cc8b7d03,c5f8f2d5,88963652,7c199f6e,8f98e060,726194a,2a5da1b5,85eba1a5,5e06ce36,5aebb89d,ba5f7971,db3c1571,c848c5f9), +S(809167d6,85e432c7,372dc111,8573e620,d9ce7e9b,c3ebc15b,ea7e866a,3a8addf4,bf0cb694,f00fd1b4,b62119b3,9dd6c88a,22ef1fed,a94ac0a0,9cf33225,9298b968), +S(99d28ee0,962c1bd2,fa63109d,f5485653,964059df,bd514206,24117eb4,e582ad46,8cbdbb66,4ee209b3,419c0b80,36affa24,85cdfbc6,e6644429,33908490,f6f6353e), +S(559d0617,e0860cd1,87f1c68,e9a9951b,fef7dba,3a67594a,eade6e25,e2df593f,194595af,721e3b26,786fc25a,cf5b2d77,1fe00649,b0cc4938,7168a9ea,1fd2947e), +S(ab9a7228,f0d533a3,4a95af3a,51021b55,bb324229,8d101a66,eb362c97,eac48b02,80a6d111,e451eb09,cbebdd5,a3ce4fdb,42b3665,f8974df8,912221b0,fc7db6af), +S(42c6680d,18b0f528,274c2eb5,422e4731,560ea862,adcc4419,68bb5f3a,5bbfcf16,c8961934,e5bd6e7d,d64d4b1d,f7867c7b,978d182e,48315ae4,3fe2e082,a9455792), +S(e8bc0f9a,c3687bb,69627de1,df71fb34,21e0252a,e33d15da,3039a200,43ec3374,15de9e9e,2ac74839,5116ef76,1267300d,78c2e583,9286e6b6,366c8a6a,540036cf), +S(604ee928,4ea1c8a9,a0a75bf7,be3a5c02,8f52d71,b5fb6340,53401e8d,8f5d3d6,43bc16af,5875b25d,8e2427b3,3913f6e0,bda886a7,52a3b812,f8f191cf,f7bee54b), +S(7f589067,5b771ce,ac754412,a9984352,4f2a4a6b,a5cecae8,5106bb81,f7e4d9dd,a74f2eee,584696c6,88157a3f,fc27085c,6445c7eb,e363c6ed,7a1f5902,63de2024), +S(80aa63b3,1fdd0d2d,ef602bab,dd88a15,71abd052,270988a4,63abe269,fc489fcb,9a145d0f,6dcf0edb,a4873287,a2f221dc,4be613df,f70f7755,f28879a,6e7d9978), +S(ca9793bd,796ae0c1,d778f3,6445bb8b,aa50d859,4be28fe0,ea1e2d16,30972503,7304af4,4c56106e,f0064436,c09b411b,926c4c56,cd82577f,f8c01ab9,9f7c4c6), +S(4cca305c,baf6615e,8cdc8a58,f3a9e52e,97ee20f3,ef080793,ce105a03,a1f1d3d2,637ea84c,9578321b,b5dcc239,7f6206bd,abdfff2a,128d3645,47d474f4,8a8ae493), +S(cb7813b1,a7227a24,cc53b458,1985592a,a9077113,28fb2a05,1d4972a2,3127a913,208b7263,f8f8193b,76dbfb1a,6c4f9264,dd12f63f,e852aa8f,8375fd00,eef83482), +S(d61676be,a11dd1a5,79164cfb,b2488e54,555d7d55,23ddc8a5,454c49e,4a86d8ea,1875b5d5,6db950bc,60b1eeb8,17a94af6,5a19f690,d48aacb0,e483ad52,61995cd9), +S(7142872,6f59c2c8,b398b22f,2ab5c3ca,e803a34c,ab580947,9b7b4d83,1f8e8c0d,3702510e,324c0911,b3154c61,e064ba23,68eff5fe,6f05353a,34980ec1,87ab9ad), +S(72a73d15,9cf7f79b,950971b7,1c66f362,54d13783,c5ef67b8,4da61dcd,4cf432aa,77d711e5,c1793c36,eabf9b86,bf3a692d,234f02db,e4d5854f,5deef926,b9818d2f), +S(ab3b2de,c0a8f23a,a7d3b9d2,88870969,2e45ef47,37a792a5,d65af92b,e58f6347,ac4e4ac9,1bbb57cc,1437e612,e4d4ce37,3d4f0286,5905b621,56826d80,895cb48f), +S(fe5efdb4,32715fed,f9bbb16f,d65ddf6,4ce9bb13,14a491c3,3bfedeba,cb4704ef,e5dc36f5,5fac6974,eaf9d8e4,232a22c3,8aacc6b9,1225a97c,2e695940,ec795c21), +S(5f94851c,a4149e75,e44a0d8,17e81c75,132eb242,c96ae41f,53f30ab9,c8c828a,d9473c47,505e0117,1a0f8682,777d0ca1,7399208a,b03974fb,4014f5bf,c8cbaeaf), +S(5d1bdb4e,a172fa79,fce4cc29,83d8f8d9,fc318b85,f423de0d,edcb6306,9b920471,d7bc7d98,86c861d1,86b4466b,c75dd9a9,8614e166,693a9184,8fccf998,847cb2c)}, +{S(8cf1437b,d87e7faf,550fcbe8,81b0741c,ae0b48e6,e0b3c3d9,9b1b1924,2a925a26,17b40146,c313b1c5,3bdf52e0,efebda45,80d86783,910996fb,8b2d0acf,9bd253a8), +S(fedc65f0,d622743c,53fa6172,e68d983c,2c9b8fbc,58943f48,ad06a852,c98403e1,ca5dcf28,1a2f20d1,5fed06db,89dfd290,8c9d32a,cf40fe6,817e861f,7f168ea9), +S(846c6a48,e771b90,4ae1e8d9,d3daf1ff,d1cb4c88,bbd1de98,454bc817,954654f0,5a4947a5,8a0ab994,3cd0a90,6c1d1f0c,3fb73d2a,49b9c0d1,a9bd35b2,99475dd7), +S(4998795e,a7d80937,e4abee13,6c14585b,40b2dbbb,3fd3c80f,c8c61b45,cd1d59e8,8c817eab,e210398b,59b31660,267c099,baf29e4c,894e09d9,a50894b4,ebbe97f6), +S(76c29921,eb3f3d12,5c11b906,3d1ac276,a205804b,b3e7484b,72ae0483,e4b3c517,48d8a8a5,fe658e1a,4d736bd1,8f07b5ad,28cbb775,d9388e7c,4fecd837,c8eb964e), +S(78de8fb2,b15ff39a,487135a2,636bdcea,57bb3a14,efc329f5,a06bcefa,7ffeaf09,a55c9e98,5e1f529b,ba7ccb6d,3a5c00ce,28cb14f3,e9012d5f,9f66d8cd,5e45113d), +S(71fb3464,b0600c08,7fe70906,2792a676,27830e50,a0bfb473,ec909530,30799282,fe036726,cb928a8a,8affed30,38977377,2a016e7b,1dbde8f3,6db810d7,cd423f36), +S(f1f23de6,bf779cfc,d864dbc7,b46009cd,d2306b1d,cd0de2c3,65f3006e,565d9e21,84f5a011,74ff8e7c,c9a98f52,3f2980eb,4b013695,f6239016,9cc5a1d2,acd8193), +S(f18909a5,a5db0daa,ece22ac7,12ae04ee,53484793,6fd8355f,9ff5ffcc,ab6ca78d,6306f08d,13ce2b0c,b60b3b8a,b0bd5f46,b3ef2a83,7edce51f,2cb5ce41,79f46344), +S(7598d96b,189f476c,bcb1992d,9a38adcf,9d1b6ce9,6c87058e,24584514,a0df4770,7f288be1,b82da02c,a37f655b,d23643ba,bf3d5cff,3b6c2726,9ece7409,ed78bcd6), +S(1e44193e,8223b57d,8fc68641,924cded8,3a04d806,cf9dc18b,7af06010,4e6216eb,45ea3ada,fd726fbe,2b1d6fd1,858ccc2d,57b237bb,bc2965ca,ebcd1b63,53c2f2e1), +S(80954b78,4872286,8fe38891,2d76dfba,d676b4e7,7901e559,dd5983e4,e908f13b,6fe564cd,a0966639,e0237f29,46e92d29,4aee124f,cb33da53,974e8882,b0acf22f), +S(6dd8a9a9,ad7196c1,3c36464a,5cb9fb41,aad8b0cc,423b99fa,a281c5d5,a6ce6ead,79a51469,8767adcf,ed287aa4,914eedc5,8382af71,5485c2aa,c3a77c4,efe2aafe), +S(1895cc13,f99534a1,187a3d65,d1480669,f0d0c0bf,b42b2a9f,1a6392d8,7e1d2c6e,b7905afa,c0eb9b66,51de3583,2cfb9ac7,ae8d2355,1e334d59,32909de9,ed400a0c), +S(f1efcb8a,86f94997,65b38fa5,8edced68,7737b8e9,49dc05f2,190b359d,9ed2c0a9,79b2c874,22de216b,904572b7,a39f320d,f53e392,8dd8e533,a1a28d93,fdd4945e), +S(2944af80,c207d107,ce89fb90,ea6daa2a,c65c1360,503c36c5,ad798333,90432ce4,44b53d27,fd6730f2,33b8c29,f1256136,c637740,86e001a7,60bc1ff0,f8b6211a), +S(938a1dff,117540c8,f6ee7df6,2d3c2cf3,31b38593,131527c3,9804c6d9,874752fb,4683d049,f096bc21,2e0dc20,a8600b8a,a02133d5,d0ae8d6c,b26e4694,ed6f2aa9), +S(b1b3b2c9,54d1fb6e,98fcf939,efc18803,2f693989,81f19c32,f5e55b30,1f59eb16,423a6754,1a29bb01,95adfe15,c1df1c9d,81394e96,2bd1926c,cc789f5b,eef9ec29), +S(52e23f2b,19048d43,b1725695,e3bdfc7a,f4ebd2bf,594f013b,b80d6d0c,ec10632f,258a6236,67090b8a,73881e39,746906f8,eabb6683,4bc3473e,1c6fa8b6,54641cdc), +S(5799a463,cc817bfa,26bcc543,efe0e00b,ca9d2320,1989e854,620fc9b1,ffc14afe,645238d1,8c69338f,9c9395fa,5ef7c9b0,f62b7dc9,c4c6b9e,c545c850,95b6b7ad), +S(1c493b52,3f5a4467,6268220a,58246228,608a603d,f6edb1c9,1a90b060,70b16069,8d311a45,5af92640,e9fe08f0,2981db57,3b22bf4,8fd5e76f,31c175be,23e24fd4), +S(84f5a9c9,cda291c0,71aa9f8d,d7af5a8b,f2ee0dda,fb9139ed,fee08f0f,3f9cec2,df381327,16527be1,d86991a9,bc28966a,c3c6c081,4fc0def8,85e5d160,f59f4458), +S(712c18a0,ae87e7e,87856c8b,ff6e3f6d,996ae157,970e754f,bba80bee,421fcde7,b2788ba,e69d34ba,eb5dfd62,830396df,3b8934a9,551c6070,ae8203c,ccc50ac9), +S(a5104184,ee996a34,7122a460,cd2eba5a,11d04aaa,a47d2ede,25ea13fa,41ee01f4,f4b5f2b3,f7ec9061,7ab5f3cb,763233d0,afc8d4bf,fc535076,5dc5fd41,cc547ffc), +S(79383075,a46a8eb,559ac95e,7dbeb9ee,51b6e906,27e55b9b,922473fd,5f2eb63a,243f56e9,84fd2673,58754a67,2bac56a7,9ae71a5d,68150740,8eaf8c2d,b55ef1a0), +S(2b22635f,b83ab0d4,9b82edfa,a54d6234,8d3bee6f,edbe3315,9470b18a,96f97821,41d9f3a9,52f17182,ccf02725,b58ebd7a,1f37235,1fbb8f2c,15403890,e8b25b82), +S(272fdefe,148ef7e6,957fb8a1,4a07f0ad,b17c27ea,49532547,5114c1f4,76170a0,789b8eb,5846e50b,d489bf66,cebd873f,7cf05619,3674e7d7,147ea691,6a9b8451), +S(2c2da4c0,8a6e73c0,2efd6e7d,13006135,f09990a1,4c0a0eac,1f286108,f4a2a0e0,8011a521,d7fa0ab2,75765bcf,50dba163,9e89c9,300e8a25,31942cc3,fdade63d), +S(19a9e5f,1c4cae30,797a98db,a24051a4,38ea755c,7b062094,a34ed6e8,8a8ff2cf,e199e398,157a50a1,56f9d6d,afed48cf,f3181411,77b792ca,c5881898,24f1b8dd), +S(f7a4be3d,fc6579fb,43c5a960,890893a,f4026165,ed9e3ab2,e6929378,b63968b6,29221093,17dc39ea,de2d6fcf,c735ad2d,668fd047,2eefefa1,b6b225cc,2f3cb3ad), +S(e5380fe8,575f26ad,b7924ae0,d58138d2,68112776,b11bd34b,3eb5e196,33f0e9aa,4680278c,6f784be2,a496ec9c,6db371fe,9046b1a2,b97ce71,3b45bec8,bf7d8a20), +S(4c1b9866,ed9a7e9b,553973c6,c93b02bf,b62fb01,2edfb59d,d2712a5c,af92c541,3e086d2c,df4175f0,804348ac,31a91963,39ad1528,1bc14e52,8d3b0c01,39701c0f)}, +{S(5a13b9b2,5aa6944,1b0b5fb7,f7665dda,95aff48,e3250b4e,34cf8e28,87406c1c,245f250d,78fd66ef,24745e09,f067f16d,d400c387,66d2a1a9,af51e84f,733d0ba2), +S(617b41c6,8534072f,2302290a,4956171e,902634bb,4356bd27,ab83a377,13d8ef6,c867779b,97383817,dfd0971f,64c09c71,7c468a5d,e1bb8ed0,feb98f5a,305d8e6a), +S(ac118ae,ed46b08b,488202f6,96d9469a,e9af3cc7,ddc8eb71,44903a3c,ee43c654,f992fcea,8268ca6b,79f5ce69,c87dcfa8,42ea0345,d7c85a5e,a1b89f1c,9d0217aa), +S(741dc47d,2e0d1424,3f2bd96d,9033d8c2,9008c1e3,66bfb5a1,1434f1cb,3d85310f,c3135d44,e86f574c,266f97d0,f0279dc7,52aee0ab,8e3ed78b,ee0fc646,c133000e), +S(2e973138,f6cea9c0,5adfbb5f,49a7b928,5ae0c15d,120a8b1f,2d0c76ea,1fdcc7e,a05bc93e,68bc82da,7a7c7e38,95a647d8,7f724f20,c5b312b,738c6dee,90de771a), +S(9d938d6a,cf56104b,5522351a,3c424e01,e4d21c33,771ca94c,f55357fc,fe51f91e,881d05fd,4658b08b,edf87396,be3fbb95,ec9f371d,79ff4586,6ddc803b,65ae763f), +S(37a8ed2b,4085961b,84645ad9,8f2c901d,fe9a9a8b,4de8fc89,2cfbca5,c8909835,b1bdacde,94fdc3a8,78cd0eac,f8865d64,77e2cff5,efef834,97b93835,5b7b401a), +S(da1ba954,899cb05,dae6fea2,dc8ddd7c,5ef9e91c,3455838c,a49d2858,ec217d66,14051c3a,12332d70,f8ad8ffa,567765fb,def69640,4291b81e,d3978bf4,51f788a0), +S(92d2ef44,5a10dbc6,73f8c1e6,af093596,13bd1e3,c1b24705,bad2b3de,e8f11b81,adfed916,800d3e94,91a42c59,dd72e3ea,57d47081,b9afe668,f853cec2,c72cbab7), +S(e62208bd,52620df8,91b3ddbf,e6cf0641,6059ce50,be3b00ce,14e7a53,6d1acb07,1fb71455,53b2f4c,431fd86f,c72d51af,5e2edb41,dd3f69a1,9a971371,d9679dc5), +S(191fec47,a48ee268,35ed37ff,6758a80a,532f7011,ab099048,b024efbf,cde1d0ab,47b6389,b3f5534d,a632924d,5b65918d,f65c9c2a,2904ee95,4f24aeb8,c6a02557), +S(60c822fe,a74d52b7,d5203720,b2c2a361,b7628aea,d2a683bd,80655636,bed15714,5d9a9c0,120211b2,e8285b77,8f8d4bc0,b06240d9,22944248,e1cfce73,826bb67d), +S(f602da1c,788ea65b,cc339a38,c353bc08,1c43c2f2,6e05ea6d,ab52648f,890c9101,21468929,89348f8c,67cfdeda,31ef3429,23b5a450,9fbe9a49,f011d42e,57f998e6), +S(756240c0,5274101b,3059d23c,76d9ecdf,33e1312b,7a36af,ea21e6a6,c52cdbb5,ab24e853,900c7ff1,3e4f813d,a2acdd5f,53ce1710,b785ffbd,e74494ab,43e583ee), +S(8e815b45,7adf482e,e30e475a,4949e5ae,c7ff494a,a918f07f,c39441e2,360d112c,a966f04,2dd9edb9,436b0005,7473aa66,dd19b4d2,cbb3bd95,932ba98e,f1a1f406), +S(216d5970,36c661f2,cf6122c0,a136cc33,9660306f,1c190ee5,5f3bf438,e7189261,5bd23797,c6753eee,6fb934bf,dc897ec1,25b31c9b,9e797ef1,56d8cdda,2ec1d128), +S(a30ed06e,ce34d29,a92fdeef,6954b5ed,4065d592,3af09be4,f0ad4a73,e7c24346,f6aea418,6b38c188,b84fb6f4,2b6559be,f52dc13e,b7ddeccb,6e85a76a,8d4efeaa), +S(aa42d20d,8acf7c47,fe40ac15,3fcaf1ac,6c4ecc37,dfa39c39,fe5c7657,c78444d5,bc3becdf,464ce930,e42a05b2,c52d3589,fd45ff37,c7d1767e,f8462811,89634059), +S(7585f8cb,4812e306,de02393c,c06e9871,1953133c,bcb67ec5,c6a79228,69124ff5,c242853d,1a2c1c9,a1cd1b5b,364888fd,28bb23c1,2b0e169,67961b3,e7c8b95b), +S(b096a1aa,fb969483,185ba1fb,a5fa3f3a,d1da87dc,a10344a4,d74ef471,45cc45ce,edbc9490,23801861,44ee39a5,7bdec0a,230df57a,72649e04,c4c99883,a147f0f), +S(7034d8cf,df226df1,6b310628,35dc02c9,f3e3f91a,635ad93c,46be292d,56c0ec2d,f783b6e8,29447cf2,32769a13,7ff33f82,f9fb166a,aec8c3ad,1679c48,c1a913a0), +S(9f88b01b,b936defd,f61156a,b55ca290,cf282a2f,3718b0cc,2d32dd3c,49248b4f,c24ebc35,27052f77,41087cb0,e772ce12,1035042e,603f1301,e19cee0d,30029230), +S(14443190,51f05d23,343367e9,6add133d,fcb63209,2f218847,59ad81ba,c65e7445,745216d2,d11f2556,7e3b224b,6dce478c,bb988b96,a1240093,964e4ba6,f3b15554), +S(54aa2e02,3038fd83,f17a633f,d9ab441f,e039dd0c,57f9368,3da013f1,751c6813,f4d163ac,a9af3e08,c009b44c,b358ebaf,31aacc5e,e0bdb917,d1b4df5,420d2d34), +S(fd44e742,b04ca4df,693e3109,3ec52ad6,1f67264e,100618e5,88d638d6,d96efa41,7ac09cb1,2134a246,b17ce054,b38f3bb7,7d794f9b,2fca3786,a0ba665d,3eb0f14e), +S(f662f214,10cf6e6b,7f79fca8,7ea3925,6760d83,17478419,ff4671f0,2bd2ab6c,be4ad0b7,a56c87a4,8fbc166b,da8473ba,6518385d,bd004b5d,c85126bf,7b9309bb), +S(520e2755,1cd804d2,67f9b4ca,b3986952,612bb099,cbd3f3be,a54f505e,bba4db64,e3c75cd2,c831c539,b095ac18,3bb13a72,ba7cb152,5b9c214c,288509a3,98a9cc3b), +S(4d16fa3,2d74de13,111b3f22,c4133ea5,377921ba,e54af1d,666d6e9f,b01e117d,a63bdf75,78d73f03,75aed657,fbb8675,67230c3f,868f2cf7,b7275ec8,b02ac46f), +S(ab928c61,ad1c2f68,905b9e95,3c2629ad,9bb7c8cf,ad9f5a4b,35b35fad,69a92568,bf39ec2f,6c1ae222,ff383375,6bd83882,c05be6ae,692539a4,5124b972,e72159ee), +S(8731aaa4,93580732,66b96577,7bc24a46,17fb8363,51c5ad8f,c8bc053e,802dd07d,36957f16,1020430f,69a3b1c3,1a6df993,d9ca8e2a,8f487b7f,b2ccd44c,7f528ce9), +S(3514d41e,8b9388e4,33d1155c,c777c398,22ab36c6,3c2aaad7,ce674831,21231d11,7657cdaf,e9fe8147,10bb2ee1,a97c6100,6c7b0ce2,f5086141,ac2904be,1c7a9e3a), +S(9bb8a13,2dcad2f2,c8731a0b,37cbcafd,b3b2dd82,4f23cd3e,7f64eae,9ad1b1f7,6ba44d4d,50111c46,490622d7,b079c17a,f0ab57bf,b8ad2ac,9becf9d7,3c7edfaf)}, +{S(e60e88f1,dc24f079,f835b687,778307af,83446e,71809086,e6dac0db,9f191de4,25a0b86e,ff05c849,d79a176,1a634d82,29d2a759,fbd003c,b6ca4147,85726362), +S(55a5e6cd,c9e11103,749d469,dae84a88,9e744dd5,d9309762,15050a83,fef66fe,31278ace,a971a41,e2f9fb16,8e80ec03,37009cd5,b0a49938,c28c902c,a7c71fd2), +S(5f25326d,e99a7c5a,d81bf2ea,61a9195d,48832bfa,8caa9777,53e483f2,b5a62580,40b69a1b,baa2d0d1,5cb78a3d,3d184c08,5b4c16d2,90751ec9,bf3eb3c1,d3ec2ab5), +S(1a32cc7a,f88976b6,cbc89865,89e685ac,49381a29,1579bd2a,13f9488,c0333d19,4667a3e2,2048f781,11f009ae,5d7b1b97,850a3a5b,86f77880,b128c8c6,a9720acc), +S(1d78e74c,66247be9,352c9797,5fbc1299,743f9c74,68c64d1,f2d8affd,1b098769,37adf553,fa2a11e2,6913ab02,e59c4f2a,48133fe7,d9aa3c24,a76e9af9,48a29d8f), +S(8bb6f83f,6be5c2e2,b2bb265a,9bb3c931,bd5cce6a,48efccdf,daa040da,535dbc86,eb96a982,23278b81,6284fee7,b5b8a121,7350cdba,d56b6078,89602bba,bc003481), +S(a9f19ca8,1d2ebafc,4bb5d881,76bce19a,d2d2564e,185f905b,8f9eeca5,d6b12d6b,ab23a468,3279a9f8,e2e8f880,e0accbba,844bd4e9,4d3e4b43,74db2b55,d998771e), +S(19680305,c887467a,c3bfe44a,dbe65431,7323d8e5,62271e25,1a794b78,618befcc,48e9303a,3d6371f7,cf0a904c,cf16f606,b0007583,87ae0952,c6119521,dde25532), +S(18b3bd03,ed4696c4,7c3f896e,5df7481d,6f19a5ef,53d62ff8,2948f1b2,154175c,85fb04fd,6573a19f,2c136753,a1ca2585,d39dd64e,6e6e3fa5,fba362b4,ae9dad36), +S(38e3bee1,3cc3e18,a57aef97,4ffee58a,a392c311,14ac8baa,1376b56d,f8ac017e,8596c7f9,8abf3e44,4ab5491b,fe659619,f6defb58,f48e2b7b,57842193,cd48fb5c), +S(dba5da08,8cd17c33,3e892bcc,46261694,d2ff3a22,2a26f92c,17c5e1e2,797b235f,ebc15bfc,5729e986,85a19afb,d7f9a219,e60d2784,e9b283cd,3697f782,630fe222), +S(60456426,caea7fc4,48970eea,fab9c632,3e66fcee,50f92630,7b130937,25b85ee8,dd22df89,c5dae339,49459593,1433f2f6,5f719379,68e56f92,a38d1290,17881924), +S(f1ceac82,15670212,279f36e,f0c8ce28,3a192f66,460e4875,d90b2f51,a38f5712,ec11f026,c76c271e,fabd7d55,c8488d99,3298f6ff,c05ad4a1,26be9447,7d878b9e), +S(2c2fb5de,5dea249a,7bf6b196,8bdec8d6,1838da2c,12147045,18d6494,f09e50e,6c0d020a,d6bfd730,5ee73634,e939ac89,ca2b7d4f,dcbe760c,2d14ade2,659a5b8c), +S(2858ea8c,d40ce264,3c9a305,c0e2c758,af5b0b4d,5c57ed21,60cf7ec4,154ffdc2,33586bf,a61a3cde,4f402bea,123c69e2,2410c0e,590a71d8,9a1e8130,85cbb579), +S(2749a250,4e7cefa3,a3647088,6bec22fa,339fec0d,ec63c02,19e6af39,7fdec3e0,d3415104,a9070af8,b61acdf0,77954d37,57fcf742,a006129a,5c0d3529,3aa95407), +S(8edf3ad8,39e661b5,f7f16a85,dce3caf5,d571acf4,d0c6195c,53b618e,5311ac65,fca0efba,35a14d3a,9944367e,db4ac982,7dcb7aa0,12438c5b,aa5627c4,c4a15ed1), +S(dbb92358,8b083294,5d6d3b62,9cced57d,7085d3e2,d0890bde,95d80400,98c22745,42816661,5515429a,aa023737,5fb77804,624546f2,1f0a34ac,1ed4e4ee,dceddccd), +S(aaca9896,6196ce2,e13df3c7,d058a5e5,10566df0,5fefc04e,51f9dd,85a4349d,be389d02,789548e0,aaf67c57,3b91b389,c7e6ed80,ca3e637a,2a147262,80cd5620), +S(104804ab,e621b098,61fc540f,f4d6be9a,750e3cfb,706170db,e34c06ed,e0a431ea,14b700ed,a465915a,eff84ab9,fa568535,f63e4f44,1387ab4b,d841072d,97739071), +S(b2215070,a8ea71f9,b71f1a73,d6ce366,c322b8ac,4d135b3d,ccea68e5,a51f1c0f,9e415cce,3bcc4e62,6f3c8caf,fd632eea,862a046e,bb45e8bc,84fc05a7,a4b87e00), +S(600c6e28,be5ebd28,d83e6c86,bbbd9b0b,aca22006,42234634,6124133f,3348e6f7,822b1816,79e253db,a47ddd76,c0023991,5c0c0206,8f422415,94ac38b8,ff7994fc), +S(f8b9b45f,c6298dc7,13355bf1,3ee33ca9,c4c1aace,c09776e2,56b3746d,ccae0dc,bf4b7f96,1844aa2c,6ed8c8a5,6626386d,174e77fb,98c0c23e,e2b6de90,3f1f79cd), +S(63987b18,67fe5a17,333eef28,5385a0a6,576163e,2c74cd00,ba87b6fc,96a57faa,23ce6655,51d48ca3,c702a5be,87a05d98,b5aa1097,dd5877e8,11e32d76,4873e6cc), +S(2eb06c4f,5ea9ad2b,124a1202,cb13c1ae,aec4394f,4af7c96,d6a9ecba,540ee04d,b96173dc,77b46ef0,6f4141ec,96ce8d1,4adfcfde,f0bd7ea2,479ba6d7,522d037f), +S(5db39904,153002b3,1498bb01,16efd0b5,838e3495,62d9428c,912987f1,3aae5ae,2115b896,479d0d0f,75ffcb54,ff9e3f73,d1356ff1,4b14292c,6bfe8d54,e9e08861), +S(c0f14110,7f324ffc,f3d3e6c,78d5a628,6000d57d,7e85bc7c,fda15f75,79cef3ed,6eb03650,c8142b12,b330b96b,81214a4d,d01b068a,74827611,53d2c52e,e1315ce5), +S(7e3d1510,ed767345,bbb3515b,6f9819bf,33ed9dea,fab35d01,a7284cc2,371b0e66,4c6b3aca,5159023b,d43ec0b2,57e77e87,e5a6b745,178bb017,9960c89,361fd97), +S(f98b5dbc,3e54c227,b002f458,94850ff4,3b15b2d6,1607851c,50d1e4d1,8b20907d,1d2af742,b0b5ec05,bd6c648f,94563361,be03261f,da56f1ca,7caece63,a336d580), +S(188ef3bf,ab103784,37e1859a,7d53e899,6124c395,ca422c05,d6b21b3c,efc76ac1,19036685,fad04566,2ffa04e7,30c671c7,1b299217,c389c78a,cae9fcd4,ad70fb73), +S(b89070ae,96ead4dc,49be16f6,a1a30bc2,41b4e98b,c18d0227,4c9d9d87,dcbf00eb,90db373d,375d2770,b8dd6b1b,3e3b5899,34f274f9,49469598,e480e431,e4f195e1), +S(381c4ad7,a7a97bfd,a61c6031,c118495f,c4ea4bc0,8f6766d6,76bee908,47d297fd,6c950ac4,dc71111b,70c1a058,f66ea133,fbaefcd,246c63ff,6c531ce6,82b6bc6a)}, +{S(704a26e5,19071bb0,24eb2a16,48b66a6e,157b07a5,52fc4258,381f7d02,e8fd9b9e,d169ea55,8650aa3b,ce52c645,278422a3,69326e74,46039381,920f5857,fa3492fa), +S(705063f5,e481735,60afe9dd,5b2beeda,d6e46391,75ad7fb6,f73350df,51edf53c,32290956,61cacec9,472dd014,bda52364,3399d7cd,9ce2bb31,a5b23590,22c6ee5c), +S(972e7585,f8b1725f,4a7d18e7,77939aa6,3600a7b,a07c4d94,5da9511e,889473f5,aae4382a,49b4c97a,bc3edb7d,26ba7bad,16752047,dc99b434,f306c673,2851310b), +S(260530bb,e338f4a9,71930b12,4f18c82d,e33f22d7,32de9375,81e2b0d5,15e59d97,77c66c36,d6b09205,8ade9c0c,a311b60,a705c8c8,73fd2d4,8e6327cb,71eefd4a), +S(15464351,d21d2513,f792ee32,aca3eca7,a52cdaaf,9862172a,e7224a03,804581dd,d9ee19f4,502f1c44,f656ad4e,add6adbb,d8a04f5e,5344b554,894721eb,8e3e2285), +S(4fcc68a3,caf3ff91,dcce9770,11ad5157,6c844132,321791ca,a652593f,6cafcd04,e8db3aea,a35371bf,9700a9bf,b85e90b3,93cc088,9cd655e3,fb18635b,49fb59eb), +S(301c65ad,567952dc,6b39134e,c361030b,3f5203ed,da89784b,225548ec,45c75eee,95e2c0bc,7b4a7cde,8ce3dace,a691bafb,f78fb03f,3170b347,ee807f42,6b947560), +S(96ca5edd,8047ec6f,b5f8c37c,a734533d,13f0e6e7,f55d28,b8b10b5,121f4abe,1a21f1ba,f6a2e336,247f6ee0,88cca9ff,816b0667,3badc241,d9ed00fc,d2070f1f), +S(c94633f5,783c4e68,12143fc4,6e670978,8e8a526,819afea9,404dfa00,df1bd839,874f8760,33dba9,de463f86,b597219a,c1ea37f3,970bdadf,97c96c48,feec4ec5), +S(963146d4,5bdaa05a,b5115ac2,3ee862a0,2305ba9c,75003f4e,ab838f7,e9adcdfa,d75766de,299e5cf3,c8796234,5db9866c,cf011c5c,f108a794,5642a6b9,dd33eb0f), +S(dde8c870,ec4e9890,2a820a7b,c5784034,19ac261e,de5afd0b,82b8c5a0,7c2863df,e7833936,50d4af7,427158e4,6c753ac1,a5143c9b,c09de97b,3b27065,6f622b82), +S(546c6b00,c5e34a8c,4cc7255c,2edea33,d9f77e7a,c67ee629,bbdf1879,4622265e,5ae149da,f65aba8d,e214fa63,be9bbf11,3dd3c220,12d206bd,d56026e7,4a019897), +S(4340c850,d91b63fd,bdaf41bc,f8d8c010,d3f30eb5,79eeefc9,e67c127a,33324071,dd66033e,eb5ae8b3,3c47a940,2482bcdd,4db5c8e,dda3b422,35627434,dc3bad1f), +S(f796431f,679d9cb5,77bce62d,236d1fe9,b5042a83,fdd1cf94,1a2e00c0,5a261d11,718fffe7,68aa2591,d3fb1fd6,1a00537,3b529f9d,f9c27f79,31ad0df9,9aa74859), +S(f3d17ae9,d5b4cf41,27423894,916318bc,adfb5a9a,6c2ca219,1b918e43,eb5ed129,9da6d033,49c64d79,7ad09a33,bf71cf87,8e0ae6a7,9fa7bc3f,1451126,18415960), +S(23899a73,a4b52d27,29ab52a8,370ceef8,4c7684c,cd535f4a,ec360eab,cfa5a787,f1bcde3c,5c4740c7,37b066b3,8a1a88fa,c43357f7,f3fa23a7,b00815a3,85336320), +S(5805914f,5418971b,106305cf,c397dc12,f63a3b2d,8b451e5d,c1b60c2e,3d9e9208,616e2764,67a5f1b6,46279ee9,6e8645f3,76a80192,31e17a5,c92e26ec,1b76e62b), +S(85ffc326,1991848b,5e918c4a,53f291a8,31796b52,d56a5c38,8bebe625,d78cd07e,95fd6f12,7b155e6f,806c089f,3f5abe95,344e9014,e2c72fdb,e720bb8a,93d864a6), +S(6f1a57d0,6566bf81,f4b16329,19f477ef,aab4f829,e29dda4b,27627b96,1cbfe3eb,de1e8359,7ff20c63,3d28b909,caef273a,a57898f1,a797fd91,e00e2e7,da1872f4), +S(3d28eba0,4d0ae2f6,208adc71,cd6af3b0,e208860c,722903ab,e106feb0,af3185e9,cf8bad18,40d3d2b4,abfb5b28,b50702dc,512527d9,5bcd403d,9713ec7b,ef1dda13), +S(46511979,2b845113,1b32663e,baa14c4,20a5408c,1f53afb2,43cd496e,c4b18118,40bd602b,d740096e,842b40fd,8304ee73,842b074e,415d5ac,c5e2243,28b241f9), +S(393a8bb8,7ffe4265,51678524,8ac940c6,4aa70e71,512ebbc2,3485596c,a6d9da5,25773032,d2c1f80b,3954715a,6e4132a1,74b4468e,658f6cc,4d5f5d63,d458980b), +S(aeb37eed,35274696,2b85a21c,86b9fe34,60433606,9ae4ce6e,3a8235a5,e43c48ad,d94165e1,5372330a,7b5507f0,377a966a,541b6fcb,949398c8,dd6d6f52,2411d86d), +S(b0bbb4d3,100ce417,dec58f46,95ed8b30,4306f21f,ee11f899,585fb37e,a9905c59,89141fcc,9344e617,7742e31c,42c565d0,45c7ccb8,6f88df7c,5c36d23e,45e51d75), +S(49694de7,330b4c3,1431d452,f3e9e562,eddfe029,1cce58c,73b69cdc,b89e0f49,4715ea3,b6fdccf8,e224b93a,ffdfd1ac,ad8baf44,c5bce735,e7c9b4ef,3faa2656), +S(9a7720b3,ff0363dd,7263e1ad,83c32526,67b67d3b,72c2c14c,95f0804a,dd20f7a8,815a769c,494824a,a819ea,54b560ed,e1df9bca,d7df2d63,aae69c4,a02f9f20), +S(b89c399f,cdb3aacf,99796fd0,95c17cc9,786d79b4,9a1a255d,5c9ee510,38d3620e,ee3c4936,d4f9d1f9,d2642043,d25b21a1,aa32fa3e,ef44f409,73db47a,96965cdc), +S(add68bac,d7180ac1,4e9bbc5d,1e0c3911,f2202d90,1f9ba649,46b06507,b86ed5e9,fcffc13e,a9be67be,8d090a77,9fd9107b,f62bc785,3f98e97a,c0358b3b,7719944d), +S(9bf62cdc,cdabe928,c1ab44ce,38cd0611,135971ed,81ce6c6f,dfc5eb5b,d9c3996f,885b2381,e0e785d3,cc3f78c7,f9fd54b,ecdd9d9f,c2979e23,f97e9bd2,a4f10d3c), +S(bb223cee,f11450d5,c5e0b75d,20eb44be,9d44dcff,28574117,12fc5875,3b839339,8bb29985,87eb6f5c,c8cb615,285d9e69,71db8e31,8d81fd5d,6318909b,8311a00b), +S(9ed73f09,2263e84c,d022388e,da82361b,445f573d,b646cc62,fa0bf5c5,1d33fd27,49ce7698,144e1115,118a4b0c,bdb98dab,6b57dc1a,4d1bb6cb,a68d4d20,d8e937d7), +S(e747333f,d75d5175,5a0cc9f0,a7287084,65a02c58,7737a7b8,b8fa1b8b,4bb2629a,d5001fe,baf8f3ee,b33bc9fc,7fb3da7e,377c8955,91e56965,607269e4,96b90559)}, +{S(516ea742,3f956765,a15f856,182f1e7c,18d3e548,b9fdca94,ea46024a,1a8fcbc0,cfddd98f,be500604,28beb901,92c01282,aaf9ed93,76f0e26b,e912ac42,a378d542), +S(8ed072cb,13eb90c9,e5c107f6,ba576a87,ac75a431,53025e6a,86addb95,bba7862f,eece8a5a,f28d356b,f1a84c14,2549ae7f,894f7c07,305194f3,18e30e0c,873fb5b0), +S(3e0e488b,1c8acc24,f81bfa1a,f6761afd,b4fa5f5e,6317ba72,bfba2f07,6c2ff593,2c4ec39b,2f37b948,fdbc9e3b,a3fa82c0,dcfde2e2,57830a04,4c178759,ef5bbc8b), +S(f6b3f19f,cd7eac5a,13630ad1,bbf331b9,5608b7a0,ceaa67e2,4a1e830b,5eed9825,a2a64078,19ba0f7e,7a890df9,523c6736,50ad08d5,c2557cd1,53c6ee65,ef493ce5), +S(e2de599a,879285ad,398b1031,8e1a8387,21a5c4f7,1105469e,affc8e37,189548a,dd977e62,3dc05cd6,3155a71d,d87d91d1,d74d6e31,5f73434b,679b605d,9db264df), +S(bc52359,683840a8,59fc2c8e,22d72ec5,da2493a4,bb5073a7,f658517a,de83f867,76a13651,712ff42e,a0c10f09,45c4ce41,2cc8c4f2,ac3ae446,7cb383c8,656d3186), +S(d87e2b08,154e38c0,13847a5a,2f84c276,dc088b6f,c19a9bf3,90a8a433,fa937fda,d91447f,7c9042e4,6f64a9c6,40a5c294,1a6f08f5,d3eed464,b09b2a1,1c402c0c), +S(4359ac5c,5dd70bf1,d4f24f00,1301b9f6,17d9c69b,63350dad,9a8cd192,655ea801,c9e14f94,d8ec39aa,46092657,5d770426,350794a4,b1ef2410,a9b0118c,ac5d55c1), +S(3ab3f503,29e22bf6,8fe9882b,3b4dc989,36dfd840,be6af588,ab6d61de,48094b9e,4a40c435,9f4dd21b,11664095,4b55e6b9,f0308786,eec32fca,6bcdd5d5,8d055ac6), +S(a0f1ac27,d046d987,b9a98bf3,f770205,931fce93,59b75944,6494d221,dc2752b2,bf1bfdc6,47a15997,97b5b6cf,2d8a2a44,e9c36b9a,20b53abe,58ce9e0a,395fab70), +S(a9aa63ed,3b0260d2,b35b030c,7a5511c8,679b6170,b8a4f386,fae0bfa8,92735905,2f654620,4dba9b31,99bd648c,cb1605f7,62f312d1,67123d98,ed66f02e,4d794e90), +S(e51da157,5e566ef3,bad3fa66,e55432e1,29be6c36,32e390c0,f4d76719,bae34b7b,55930b79,2ffc91de,674820b1,eec290d7,74ecd79d,1ca07d6f,5ea2f817,4759984e), +S(8b69a891,b417ea65,7ba52bae,58920eb7,f101bb92,e150dc1b,c961c37e,73cd18b7,5b824edb,f4a68988,39de0d70,ec16ee1c,a01a4692,f29263e1,1069aec8,6b149214), +S(ee5c1186,77462649,6d37fba,e48e797,dc69f31c,d6ad22cc,937c7224,ef7ce8db,13f7987c,f2cc4551,e058d410,3d5c24d5,13c2d602,ddccadae,fddcab82,d14d5310), +S(b961cb45,5de8b5b6,c4c5c2d5,75303c81,35b5d278,503a15d2,371b0551,5b236b,3ed18486,5ca969ba,31c734a,19055129,1cd664be,576925a3,2a142769,4fc40df2), +S(83effa4,c127b5ad,7a0c53df,5be5596b,d4a42987,2eafd8f1,5498a6d2,47b87314,efa99759,c9360b14,7643de2d,64ad07ea,39cfabe0,2bc94e00,dc9b2e70,c2e2c217), +S(f253fc52,4fb0254e,e772f50e,5d6c16d8,48692455,c855d4be,15ea9f9e,9a5411dc,59bd1f8,2cece609,8a63fa1d,48e4166a,d79174ec,5f8216c3,16c48c1f,e5c9a0d7), +S(6b61024e,e6451d97,1446b55,1476c3ec,eb6b19ec,16155acd,317bc2be,11086411,8de5c6e,37b562da,ca5a203e,ea028b76,e6befaff,e54b49d2,6605f169,592242cd), +S(1691a90b,9cf72621,3680a72d,af59ef24,985448ff,5f35372a,ab6e2aef,df8b33e5,83d2032b,6ca761d1,286c1348,31250054,5a230558,cba391e6,f0db9c9f,97c2d618), +S(42a078dd,cf749f25,aec7a1f2,8e976f79,e268c36,a7b5b0cd,6aaee3e0,925746ea,c60f1846,6f025987,e0ea6ca0,3eb98df6,99389753,b57abbf4,f5739509,bfd09d1e), +S(21bfc1a7,16b09543,5142c31e,5038d4ea,4643d9c3,2fd4728d,1374dba8,1ca1f07a,a991d491,2601ca23,8e289e71,e9d743da,4385aed6,c732f808,6dc21406,74540acb), +S(e75223e8,fe247a98,5220cbfe,52151978,c98d1460,746f8de2,8696d235,71f3336b,dbbb8075,ab489582,52472982,c7b0c3bb,d82a0762,36c07c05,44417ff3,883f6f18), +S(7a756a,72fee88c,7a2758a5,3294da85,6b06129c,1978e217,2bc7952c,92b05265,c4ad3a0d,be72fd27,bfa475d0,fbd16a92,5e939362,bc0748c,c39ba9f0,3ad84133), +S(2bc697fa,d947fd62,63bb2841,1a274520,f5d582f6,7f039114,293438fc,9aad7c82,543109b9,82097efc,cb44d854,11fc5230,6c7a219f,2f58b37e,3dd354a8,2ffb28ad), +S(3862db95,1ed8994b,a8cc0178,f6dc97ef,db6e1380,c18719ab,cd24a88c,87039744,af1e8ac9,2b195d3,6fe1b1be,a68e9215,a453e638,67e65d88,64a8baf3,ff5c1267), +S(7b648cfa,40ce7274,59a6fae2,2836ea1d,b18ada4,9b18a61d,748127f7,7ceee771,f2a30c56,42887135,30124a69,da2c0355,8688bac3,dae6d95f,a252855,a85a9b4f), +S(f803d7c6,1820f980,ebe0b297,87aa688c,ddadefca,229b99b3,a6bde5e9,922f94d2,a5f8b450,34dc7de1,461dfb74,e7ed9c49,80407bf0,4b0d9159,af703a9e,1e0f9c61), +S(2247f630,9be2f3aa,e30c5907,c29095d4,b9198d25,1a17bb34,7cf5cb35,a2ecb1f1,82685964,20d87b07,1c5a4044,b79b069f,7fa6ecf2,cfc0f839,b2161475,5728c2f1), +S(1d770ace,ceb2183,fea7c924,a8fba197,579df37a,908992be,d42c8e80,8bd98ee1,d87077fa,b910a21,8769cfc7,49aad579,c809e35b,f1c2a813,6047e85,e2c6fc65), +S(5d134e5c,5da47f7b,a495f216,b4994d90,4a79057a,3d0076be,34f09013,99f1f366,fc4e10b2,c1f7bafb,d241d5b5,1c57d48c,30fd29e9,df5774c6,1d4f2c15,3b66ed03), +S(a49ed10e,aaab9323,3a5f485d,4bd18c06,28ab2629,f0b8c3db,4d05956d,6c953fa9,338d476b,99f0ac67,1fcb893f,5f202204,a5178acb,6971e7e4,984d42dc,b904afbd), +S(4d000b62,1adb87e1,c53261af,9db2e179,141ecae0,b331a187,aa4040a,ee752b08,95f2a470,e71f2daa,34927daa,7d268d33,34820a0e,e638d6c5,c18d7adf,b7cfcf45)}, +{S(44d42980,eb92b3e3,b16816f5,56858355,e031b88c,99117385,def6599e,f274e56f,6e3de5ba,4f693fdc,747caacd,b2cf0107,f29fa7c,9c6a1a09,a527cd16,4c2c1484), +S(9812d508,d6da303,6f08fa7b,54cae319,232f925d,6af91d71,fe6c2fb3,bc86be5,735081a0,35fc17f6,7547b9b8,f0f91ac7,f0ddb965,19f6f398,dea745a9,81441e2c), +S(5a022ba,a90ddc87,42246783,4f692ecf,dd2c2dcf,b054308f,4afeb17a,7ff6ddcf,6fc2a9a5,4c7a130d,fd26ca48,82406fb9,f67db0ab,7e6a6d95,1675fef,2e2d4256), +S(c181ffeb,a8ea7d69,c524cd42,18af3030,1cac8e97,69eaf6f6,ba73027d,30fb7bd6,e88959e5,b07b7d3e,693756a,f94590bf,997763b,afa7d850,a80dd9fb,88e6e904), +S(e29375b8,21c056c,30954b81,4f9ce795,c1493dfb,ebf06f6f,f32c92c8,c74839f1,a9040ad0,95c9d45b,1527c624,bac86841,a1f28b7,ccf8dd37,b7e950b4,858e6e18), +S(69445948,ebec5ae3,9fcb505d,7efb7902,6bc1e8fd,5d3024ac,2b772439,72142d80,5b6c2694,abac3938,db899396,62635c21,e64fe2aa,40d18678,9c246e9,fe3f4be6), +S(a86f3aad,85d0bbb3,8270956f,58c2fd65,f5425428,27d7a658,da1b111f,64c02c36,dec740b0,ee35208c,dbec5b7f,69bb94f0,7fccd075,7868a37,6ecec7b6,dcbe20e0), +S(ba2bf65f,aac92da5,6c252b50,8dd74e3e,99ace1bc,42b9d2db,9d0ead3d,b6820306,37bcd01a,75027b42,eb0d7b85,564bedf9,67153930,6fc97106,ab6623e9,90b031ba), +S(78419e61,4e8b5eb9,d09e0c09,79ce4eaa,26271696,fcc68269,4cddf1d9,6a4c7fa,a32dbb3b,46f9b6b4,9adf4dde,f1986af9,72662a6,2ed6b6a2,f8b920b6,82b32363), +S(71163271,204207c8,a84b5993,88beb505,640898ab,b24c4c10,42195dd8,15d77985,aab43609,9370f246,7035ddc2,e71d73f3,c0f1aa13,148303bd,840459da,ae307e8d), +S(473f52a1,fb7c3920,f09ba6e0,a3c891c3,3f4a13cd,9dbf51f0,f3d39ef2,d6bc07d0,b2c403d2,4aef71eb,1b834df2,8bc08b67,5130897f,a6d9855a,eb21ccf2,780444cc), +S(581e93b2,99b8c50e,e6338c0f,f426502a,d8699563,f17935dd,abe08a73,6932b71f,46e7c7c5,1e076fd8,9b8aa98c,f0b3933b,8ca82cc4,d21783a4,d74ae1b6,ca9896e6), +S(e65d9e24,e7340122,875a9d86,d6071a48,691ed5e5,a94b315c,76f169f7,f3d69c48,73575103,a70b7a59,90d9b880,8698b651,271c8c0c,ac93122a,66873bf1,fa3c6fab), +S(cceab216,41d0597,f9c7ab64,7f99154c,b22d4827,70395d6f,ddd6db5a,dc752825,4084c57d,5aafc328,e7a250d0,a7c3c0a9,627ddd70,c77c2be7,e5a1af34,359b9b86), +S(4222ee66,5baff421,17f47df5,c1c1df5a,dbafb790,d5c75bb7,2646cf85,7ae85923,43088d6c,a029903f,f5a789f8,16730345,5a5cd0af,cab57e15,12781396,fcc9b6da), +S(391c5d0b,17a8c11,3440cd30,83434841,969b0833,71758b30,27e38a25,e778da6a,69f3d295,be55f859,4bbb2fb4,116de5d0,b24b5a80,ed62c1e2,8fca9b8,3f6d7439), +S(803b7149,f87e86c0,13599898,b0c9050c,d4a6e030,e07e8d7c,a49c46a3,8a6ea6a1,6b367fcc,6d5916e,72f670a6,5ada9c39,54800e90,a8830fad,c9ea17c0,494cd9aa), +S(f7aa1c64,f8f92f20,1319f316,353d89bb,eaa4d65a,e148b01f,ab66aff6,c9deb179,e9b407d9,4c2b385a,74f22eba,93dc35e9,bebca7d5,17401b7b,576b7d2b,e13ff0c0), +S(f1c34d52,2b7493ec,cefd49da,99732e00,85ace2c9,fd14e9b0,69b67dcd,5acd5e23,29460fc7,dd77494e,a5a7764c,7ca6db5d,5d7a5e3f,65e865b9,e5f85d58,e77713e9), +S(db19a1f6,38ef7034,5340e3df,8d384944,7500640d,cdbc3be4,df3b191c,edb9db87,baac873,a76e0b91,c4847770,9dbe88e9,6195e9c4,ac4d7749,71ca204d,4a5e748b), +S(4ad12e00,f384c7f6,ea669c71,3649da6,55e0abec,67551a58,224b9f9d,de6bdaf9,2e0314a,8e3f32da,33a22ecf,ccac4965,1f1f6f5,20baeddf,39a02bd8,423cd40c), +S(c9130b88,cd451d4f,6eafffc8,357ba391,ae920c27,69e7c48b,49881070,fd088ad5,aac7c2f,4f2f8b90,bea9267,897e0079,7d6515e1,937fa4fb,1043111,6b5e1de), +S(88260ca,df81b391,be79bde7,b54f8a98,428aeacf,970cd843,d683e6e9,50686db9,3b9b187a,b998a22b,56b2933c,fcd09333,9c23889d,1180e365,10dc086,9869cf2c), +S(3984fce2,ab73c70f,a5538206,c2a61e60,2f160b1d,2eb61980,fe174cbe,fe464dac,b7e65c1a,46b50c72,621e3fc8,4f4c7cf3,6860567f,abf00743,5fd1b13f,7400326a), +S(e6b48495,c8277598,23b73f35,762c55fd,8cd20420,fe5be6ad,f27f12b0,68bdd63c,ccbb7124,3b0300fd,993dc9d3,4b55534a,12515243,e07ab78a,8d8fd528,46e5a69b), +S(6af5144f,342f492f,3f506ee7,fc515d3d,d3c93d02,27ba841d,74bc6548,97d4830e,b195d9e0,8113eeaf,fab92a2,81ddeaa0,95356053,a51cf84a,b5d60fec,5368f98), +S(14439b7f,e40ca407,374da12e,217edd9a,86c84397,e2fcf6fc,965023,ba984a1f,112ad656,47c47c30,f19ae62,e0c06b35,effd49bf,d5e604d,6d621471,9f088fee), +S(d4a7e4b3,863fece9,660baefc,ee57d09f,6f60cd25,f4aa178c,cb6f8a17,5fda9d4f,4985a973,ab0e8627,f6de7ef4,470de4c7,1adecaf9,f3766197,a86f4e40,14ea474c), +S(facc2a9b,9d3ad0e8,9fa479e0,ba777a0c,90a0c229,59d4b719,a9304df5,f1e96ff0,6e12c914,70c78733,3e5a65b9,8c01d342,827810aa,be3e4e33,cba0b7bf,eb283b91), +S(3d1b3f54,2809a7d7,79ca2416,a7b7d007,4a728599,e4f30cc9,14bbbba8,3daa091f,dccd0d01,e56c7e6b,90829ec1,f0fc733c,8f1cbcb8,79916982,3b466448,cc21674e), +S(a8c1ec56,3cf9596,d761e41a,bd6bc960,562eeaf5,b54eb83e,3d7e7259,f69671d5,a03c9fae,e160ba53,8aaf38cd,96ebe3a6,db59a04c,ce7074e7,dc3757f1,ccc244e9), +S(219b4f9c,ef6c6000,7659c79c,45b0533b,3cc9d916,ce29dbff,133b40ca,a2e96db8,db2639fa,26a61015,a5bbe7f,3fc8d591,c6b0753a,c16fa89a,d820fe57,72c49068)}, +{S(b445babc,55be50ee,bedb8c27,dfc6c37b,492649ef,8a65de02,111b9f74,29b8c3af,6f74c5b9,f9a022b1,8d3a706c,5c608b31,9f7ce25d,8424d893,4cbd2f90,84b78bcb), +S(dbed76fb,7e46e1d4,1b507edd,8994fefc,f94bd651,a9720d9f,8d62dc3e,9f329104,c047fc1a,41689ba6,9855f063,c563bfe8,49bd8b5d,37b3836b,d8bc57ca,fd02ef64), +S(844426e0,860ff2db,f012ed29,ad2919d6,f46eb102,68073862,c1792e99,f1b2b33c,243512c9,c6ca739f,fb181482,a901ecc6,a41893f1,371d6b12,31d5427b,fb486394), +S(1df697b5,9a2f9c91,b2c5d4a7,8035ea2a,351dc000,4e1c3bd5,5973020c,24836aa1,e89f949c,f6af652e,d7e79758,74a994ff,46475df5,4f7b17f2,a5c29cd9,7f722831), +S(cf4ffa86,87d9a39,7b4727ba,a033cd02,7d8a5377,46903db3,34c35f1d,855999a1,d1316b65,e027ed02,b4be11bc,4c21c1a8,585bb247,45cdfa67,5fb9cccc,faf0c546), +S(e3eed1d6,1813e3ec,d1b9fcfe,3e8bd700,bf3412ff,78a0a9b9,724d4dde,ddfd98b,dcb09803,b70d4c34,ee2bd7ae,6444724e,9ab27c20,5c3c736b,172af37f,cc673105), +S(3a202c1d,94a94eef,18fa396e,5cb8a867,8c3ae45a,e4ee64b0,822d207e,6c814fe7,147992e5,ab565bc2,ad1b1355,60f37dc6,b5cbee74,fef8e5ca,4e4f418f,811a0482), +S(6ce8f558,a853dacf,205db4a5,80c4cbab,8ef477a6,47bca6cc,9e676cb6,5f3f696a,e88e3934,b2857ec,6edb911f,acd132fa,f0078971,2805aa59,9afb3d80,942dc23c), +S(7fef9aa5,b2df37ac,99ca488a,ba598b4d,eb222149,55e1cb4d,c3ef1e7e,7bd38945,d4b7cb4a,8f9edfd2,3a0efd1,9882baf,98312b6f,7b5775ca,65e9dbf1,f2c32870), +S(6ec1ce91,d1eff7ed,9beba2b8,2f4a526f,736e717d,6442dd29,b55ae2e5,3371e0a2,28240ee,12e2b1ed,b40698e,ba6f087a,145eb772,caece880,b3e94b97,700dbd58), +S(645b9fba,2cb739ee,9b148b29,8fbe9884,f284893d,968c21d9,50696d2f,efbbf0bd,b06977a1,2d19836f,add50b7,b73399bc,698729fb,fd182026,d918a267,eab4b7c6), +S(7b930561,3a4a7cc5,ce1e7f5f,29314e1b,40bc8b93,40604f81,76578c18,69abf6c5,55a7e3e3,3f19805e,b5056d15,deaaa4f7,aea07a46,f9dc6a09,6ce15392,e146fb3c), +S(bbcc74ca,3697ef46,e7415ec6,b31a0808,1e6ade01,c7e2264c,f9d4d94d,d849ccaf,27bf64e,e1005f13,989639a0,8772c42c,b4249ba6,9d90cae,3f542ee1,78929f26), +S(4a45fd82,af96af67,9e640bbf,561cb385,2585a8e6,1b57df7a,e028ed33,a017c680,4ba76ea1,19a0267a,f019b3b9,89cde9ce,7b1c0b6e,da3c773d,ca31e44,61e048ed), +S(c3efb1ce,ddc6a749,a5db9daf,48032a6f,3f1a848b,aef9e44c,ebd76127,a9c90d0e,3de258cf,e593b489,8f92e8ac,50be894c,3636019b,a9f31f70,28468eac,687b8f89), +S(ec71a2a4,6f24acb2,8fda6bbd,ab9326e9,6590a96f,b9b9a4ef,405949a5,e3d2858d,31a91fa1,71207da3,1b0acc25,cace1e7c,5126ca2b,4c8d9733,4c50a7f5,29bc61d2), +S(65dc268e,cfd191fa,f07421f0,dcb16701,f979ad24,81ac5ddb,1f77d3ab,41a773e0,f8c9ac90,255d6460,15ddd1d3,57b92522,53bb55c7,e2f5d843,d7d9a025,2766d2c0), +S(62152eaf,df564900,4379891,4b53ddd7,3b91fb60,f16f2d18,941caa96,18d8ffd3,3a185ef0,a8d8a35d,112f678a,6a04a654,df565a8f,87e99abd,95fb4977,1b278ce1), +S(f68e6fcd,b2c49661,ae59bff1,f24e97e6,fffe7cfd,f185d0b8,133d58e3,bec1c89b,223dee27,5e9cc518,af12be21,ee7ef3a9,ab39c7d4,4f950fdd,9ce5c78e,b50514a2), +S(5d02e9c4,108860e8,2b1ae04a,4afbe1e2,9e0a8444,89876776,7e5b60d9,3fe5c753,25fdcc35,5f1970c1,43dae96c,a1ef0a7c,f95853e4,102548f3,d869d3d5,8bcf962d), +S(f6217e4d,4e6d06d1,27668a01,8225f88f,a1e0fcd8,e8654fd,ab26c8a5,4c6d4751,65a6acbc,19bb2835,13eea5d2,5fae521d,aeed63ca,50f9aed8,edb74dd9,c43d066b), +S(c18bb768,bae77077,35b4d3d0,e82cac24,fe3d7ee8,dcba20b6,a320ba6b,4695a406,b7a7ded3,a589153f,8ee504cf,fb5b45eb,b2d8e121,40f2f475,186153df,1fcf84d6), +S(36fc443c,1350b40b,881e41c4,d3c15952,31f8da9f,cdcac4be,f1d0c5da,ceb9844b,9843bb7b,fd0ebca1,762785cd,55669233,16c36aa2,d2c37b3f,2b196f78,bfa5830a), +S(ba7b8c09,d5293e6b,a2548e6f,ff3c939b,80d2ac54,34903039,dfb8b661,29e19cfc,54fe2a,9353fc1d,a0d34e07,b6d34d1f,f3a1f67d,f4aafa7e,57919142,95c2a5e3), +S(50a8ddf1,17a91c92,37a48fe8,f1a00e72,a5dff682,7398a4c5,d2f78b4d,d49ee339,f91d9b20,da28e51b,99fa102f,13f5e451,ab22e139,80052384,6b9c66bf,b7da1578), +S(642ece53,832d1859,c6543147,56b618f9,520a5888,2549277f,6b27f16,e08e3d1f,d9963beb,2c6da204,339a49c5,f253498c,48cc3e99,b715ea8f,a5eb00cb,1d6cffbb), +S(a68c0d3c,13d764d0,7b513390,5842c9,a7171e4f,755a9737,609db06e,1a44e5e0,a2c3fdd7,b7938a87,86f3756d,dbc66b29,72469e79,839a1448,b367db5a,2bc52c15), +S(5b33d730,288fde53,b123fdee,177758b1,ec113adf,74e79eac,513eadd4,cef377ac,1bbc10e,9d45cb00,db58fceb,bc4bcf4,a0e2bcd2,a7d3ec12,7d87beb7,a134a20b), +S(aa6dc4d3,ce531af3,e68590fc,acbe7816,c8293af0,d77914a3,c7119e23,e50ce56e,14386670,5dbe1ad6,91e09123,a19a199c,3ee67b25,708ef57,4620c5ca,821224f6), +S(180a4ece,d74ceaab,e0f7db3b,b038034e,5e659c61,3c66a534,8d962d14,efa32402,b675b2a8,b845281d,524403d0,db01417a,59fd3a6c,80232e74,cdfc87f1,3b76b0e1), +S(3a55690d,abb5e00d,c2d0d8a4,96d16c44,76ee767c,a9d0d1d3,694c856e,e5b7ad0d,3c1d71e6,8a5f9a84,4de0453,6810660c,fe353475,353cede7,2936786e,4d173828), +S(33b35baa,195e729d,c350f319,996950df,3bc15b8d,3d0389e7,77d2808b,f13f0351,5a75fe7a,9bf54078,6b9bfc9,db72ad43,559a9f10,4377648f,d43afc32,34728817)}, +{S(52f79560,fdfadd45,6165a204,6bf61bbb,726cd726,3a3ed2d2,45f07631,5b0b6ae8,e6c46e55,5b4a0410,bf38965e,5a7ba381,fd259482,2280482f,877a7ec5,84d14012), +S(29eeb07c,7b27f82a,1b031881,11d324a9,4df77713,a8cadb36,2ce4012f,52cafb19,b7538574,28faf258,f240d4a9,f464797c,dffd0a68,f9f978fc,476f9bf0,1a0a2df5), +S(2191ebbd,a95c29f8,e7062f21,a70cb368,ac67ed59,dc44b167,66e52120,cfe8e742,2812f1fe,557496f8,f21b1f11,2df7bd19,db6aad90,59494ad4,eaed4d77,49f66a4c), +S(3c29d849,e25364d7,576779ec,78755ff1,8aa64e2a,65140a2,bbcf22e3,da33a4f3,3658d9ff,e2e283c,f8973cc0,ede5af6b,69ac4970,3c6b1370,f6a2ba4a,78a28a97), +S(37230e16,e11db299,f54ca0f9,f5423ac6,5f05840a,e166175a,ff0732be,c72ba88d,2a26ac2c,e8f9ebdd,20f1f5f0,f628d3d,d0e02745,6132cbf8,78b614b4,51db28f2), +S(8fbb3be7,98e16bfd,b738a512,ceeea92c,1be8eeb8,5374702b,e927c614,ab1f1baa,8280f387,64a48061,26392be0,c95f0c58,3607343f,d0b24b98,afe3605b,8f7e79f4), +S(fb639ee6,29dd1f03,8e12330c,bf40ec7e,129d7da7,655c1c21,86452fe4,9589c89e,171adbae,2efe213c,8d01e273,ed9c5d47,c4e85503,de3849b4,d909823a,bb1da898), +S(2399064b,876b7584,8c977bf8,e35d6b32,2e45d1a0,c4243fe1,2a31a581,d1d5d826,79c1ef29,c1af9497,f3b3db13,17432d42,86fa014e,17e5d780,a0d39df,b61369c1), +S(dd5663da,63acee49,eb7fde29,6ac1215a,772512ee,6a080f3b,1266c7ef,51da5dd2,d19c7348,3754112e,9cb3a4ce,8986f748,3eba26ab,c415abdc,5effc956,27efb7dc), +S(30862c58,43b161ba,c127bea6,7b23d3cc,46b6c42f,8faaa281,6ae47092,8ae47993,44ea1101,26a7c448,dfed4995,46a0fc8a,3658e540,d7d0c2b4,18f8cba0,accf9537), +S(df7ebbdd,4e416e4d,6b1e67aa,34915da2,cc15bf8f,f6d79ebf,273b63a8,32d6610a,d05fddd7,e9618753,21f473b1,bfb5ff48,65b3c4f7,5cf4ae26,549989a9,e13056d8), +S(13adba8d,2485bda5,1ac7994b,c45a7e4a,1b21aa9e,8188e631,59b217a,29d4237c,6256a795,3f24b25a,c1f59384,aac3eabb,4458e504,af3b99c1,99ae614f,8def4ff4), +S(c160f7ac,9a453a1f,8811d031,9849be43,22d8bbe4,89cad7a9,cb815927,d4b54720,7958b41c,751ef3a1,fb985ea9,c7cc85f6,c16282a4,c374fed,5999d8d6,3227b720), +S(c66af931,82a7a9d6,588e9c7b,3eda3b49,40fdcb99,346aa55e,e6549d4f,f9382228,ffe4d0df,43f00af4,fe885b10,92ae38fb,97d21a8d,26aa5f69,9751d52c,a9ccea4b), +S(d3a4f4d7,d208b43e,c4c2fd00,798d882d,922f302d,a199b707,76a70f36,5ff404aa,8df220d9,63faa827,1c4ee360,67a536ab,25813239,82252483,311616d0,1458e1b), +S(47bdd428,d57ed451,cd8754ea,817c5f5f,9658274c,ef6757b8,70527b4e,96f372f9,fbcf0ee,9fb14de6,3c288dbd,b1888fcf,72f0265d,3fe2209e,12c85841,2c375b53), +S(6e6deb95,7f2eea30,5d625288,3cb311c7,f0365a42,480fb807,36315c4c,62495438,ba0fdd63,9b8678f2,ab0fe3e9,a16512e,ffd9ec23,e691cd4f,86146969,534978aa), +S(dcd2775,7cd691e8,28e21987,d6eb6b54,e8def24d,27238cd5,dfb36a3d,d0f05caf,40bf37e7,bd776a62,ab420209,c71df7df,74d185c,f0d6b038,dea9c8e0,c1dad163), +S(eda569f9,9bccdc21,580da94f,92d89312,cef87d13,f08d8ad5,f1574e12,30a64ce6,4e1da1ac,dd274e3,f9d7def7,746f0652,678e549,ad5476d1,410adbbf,aa3c1e42), +S(5d3d4a29,734fb7ad,2846ae12,4c803364,ea3d57bf,e8d77d9e,6a3b3f8c,9cff26b6,d3e598a7,1a469323,a357df08,319dcd1a,d7337a32,c9894b80,6a30c575,b19756b0), +S(10161fa4,61e87595,f269da7a,ae3ccf01,40e910fa,891276c2,df1bd91a,95e4d046,b36eb5f4,b8291a01,18691f1e,50235d8b,f66e14a7,f0641dd6,18ad7ddd,ea150196), +S(7ba1b276,3df207f3,cfd1d58d,5190eb91,99cf82f4,9d2d0927,f5f260f7,2ea0f178,cb9fcac,4be96ef5,3134f513,5509c178,99af24c6,4eabd650,afc599d8,3927969d), +S(4bd6edd3,aaa1802a,b0f46e05,418ada37,e75728e8,6ea4b293,6619c92f,57674dc3,c9e962d3,de71eafc,7fc9a329,3bfd721f,305e876e,a2a4755a,f9567dca,21aa3c0b), +S(95fa0b32,40b24ba,29a484d7,f8f022eb,b3f30349,9d8abc1,9a69b690,3e885b68,dfe6b88e,56d7b923,dcf8bac6,2241d663,3ac2ae55,c3a01fcb,9f966d62,8f3acadd), +S(d0fd4d10,18c37114,2d5f8a86,617c250e,b6c3d5,210ca465,6ec84e87,d0ae42b3,4e3bf443,290404a9,3af38e72,a54fa06c,3b2d6a81,161fc8de,554edd9b,f3399587), +S(992e1183,d4e7afde,166c45e1,37c71c88,d4039709,4262163,b4ae38e,538293f1,c29534fb,55e47a08,ecee311c,8f0ba4c0,39096edf,b2d7ed63,21a2810,32e85900), +S(9c124ecd,4e6ce167,f60dcf38,25976f33,64cc30ff,61f7dde,966f8c23,4c13a4d9,7ad73bdb,e0afe3c2,c89d9135,d445ba4c,796066eb,1909349,9e6ec14a,f74f664c), +S(b09cdc9b,d102f89f,bcca0ed5,888519b,7c5c02b1,64ccbfa0,3d0fe42,b1b113e4,f409865f,6ab4371d,f52790eb,88df67d,84b3b74,f17edbc1,29b802cb,d5e49a59), +S(6b4f628e,beb6d619,1d616e87,3233ae37,ca4cc3f2,ac881e59,9c2c8e3d,295ccdc0,1140b988,60f4ac7b,659eb012,6fdfb796,c0baa652,2202cce0,bf54b3a4,865f171b), +S(a728c830,10169439,3af3f780,b1ceae3a,6ca08ea,4bdc7554,2ae84564,f542c28b,7b68fde9,8c97db32,eb3cdbd7,15816e51,9aa58458,259dc74f,5d722dc,f48f1933), +S(21ce4401,4ce959de,f16b3912,e88ff48b,d44ef79f,5fed2d35,bdd2dc78,de8f7605,cdc598fd,c5d30508,a2690299,e0e25b91,b1ccb69,97b99fd3,eca1baed,76aae6d0), +S(89912259,11b9132d,28f5c6bc,763ceab7,d18c3706,e8bd1d7,ed44db75,60788c1e,2574b267,83365364,d84789ca,a64ec905,c969637b,21061ee,9ca3bddc,7170ed3e)}, +{S(5914f66e,28c1a0a3,47f461d8,1d7f2c55,845e35eb,3dc39945,584b5efa,8d71a215,cd2ac885,3f681e4d,884e308e,ed3ca185,b47e2d63,3fdfff6e,efb6dc67,4d7de056), +S(519834c0,d16c807a,7867b8fe,c99dc93c,3b9ed218,87a9ca17,9343729d,3ba9e294,b867d57e,fe2dd7c7,8586303,152f02fd,f67b5648,78a7727a,190d304e,64f97203), +S(959eda70,cbabcb05,fa8fae96,7227b6be,876db942,ae38bfea,a9c3d359,977e1c52,86373396,9338053b,b00d206c,5d67abd,f95d35e6,992ad69d,8d8a3322,7370fdc), +S(a40279c8,48dc042b,a3ee929c,2910e326,eded6051,9d9eb1a4,98fdd7e1,fc88a6bd,f2c962a9,f2950d2c,acbfcf29,35bad39e,2709c0e7,36378968,fa04d957,1dadc4ee), +S(650b8181,edcfe46c,eea03ec9,f8ee5af2,c288e618,7d634961,6c95554e,25957334,ce140ddc,c2e2b07,a57e5627,62da3eb5,ca1acba5,463e97,fff7eae3,55b954c0), +S(eb04688d,5f4c8d2e,4ccd509a,3d003b30,8c5539b2,dd160a45,cbe71efe,36fd9005,37d80690,2062bde0,b96fc8ba,7a7f751f,9461f774,a1d6f3e8,8999c676,a2ae76b), +S(f79206b6,7813cd64,9f946313,3bac4aca,3762975e,954e0ef5,a876b78e,4b5a5d24,6033d4ee,936e956a,af117dca,6086eb1f,6466ab18,d503503d,4b011315,365242d8), +S(539c99d7,728cf662,13e024c0,9f1226f5,ca5d09cf,67bac12d,47814b2b,b1e7d611,87efd14e,e58fbff,5491bf85,aafd48ae,6680f37,e0d928f0,13fb6cec,6f417f76), +S(2308281d,e761f602,66fb8228,45eec88b,e32f8fdd,4a06b8b9,3dfad9c3,75d64a8e,933f4071,e4f2a9ae,95f4a299,f4267098,94b661de,c96443c5,f03f6cb,f3be87ed), +S(a93d05ae,fa31c0c1,54c02f68,9184c1ff,344c670b,e13eb304,2de517f2,1f6124ed,b7549c5,4651fa60,61f4103e,27d316a5,db531e3e,d7396a46,e360341e,f53ed274), +S(35717dcb,4feada90,b039aa79,10cf064a,c8c998b5,fcbb037c,22bf9e92,eba560d8,b6ff9371,d98bf532,f82d7fdb,24fffa69,2afeb0e6,59ba30da,602b3399,2bbe5a5), +S(941d37ef,1671d5f5,675be9d0,d5cb1f0a,ab6dffdd,2bd342c5,c5b62be9,88d5a0aa,4834d5ee,a8f9ae8e,ba5cc8b,2fb52260,33e35767,d55b6aa6,d204e0e1,a38b42ed), +S(c22cecb,aff78c61,f6e34c9d,9367c4f4,1acc9c35,29e9d894,7989a874,1d70bccf,38a37fb0,5fd9036e,762e2f0c,fef8fcbd,c04a92a5,4cb72ee2,ba08213c,4b58f1e1), +S(7863ac2f,1704fd,5015f0ed,30edf5d4,33c5ea2c,e150833b,a15c1db8,a5e4d2f4,7468fa15,eeab5653,c9f982b4,ad9e4c99,2f44083f,a7a93e9a,25ff70e5,b8742b4d), +S(f702cfa6,f0cfd275,a2c7af50,b53d0c94,bb965063,c433f4f2,cfd13d99,800da48d,3da4a4e1,bc5f2c6d,2f8daec4,599a9704,7c1b930a,b37d6b2c,f8a586cd,ef7dce1), +S(c3a1da3c,6e6b8f2c,2a8eb81a,1875f2b9,1e9cd286,414862d6,57626b47,a413d7dd,983d0892,5983d42e,bdbce2d8,df116bc2,f5cf8c87,aeb833da,e5e7e9ca,f9699798), +S(df0a4106,d61fc3c6,b2a14ecf,ebea3dcf,7e38069b,8faac576,a0b8a1b,7c8e7b5e,dd97a06b,840d64db,1798cee4,9334b033,e8d3f4a,79da565d,c6130da,f0bea75b), +S(ee9901fd,9312a21c,879d4e1b,24d5a299,b8200a15,6e65e147,4a2055c8,a2363423,1bb2933c,8b10f8e8,ab93ecee,16f861ff,a86781ea,59b891b7,740fdc2d,f6c206d), +S(52890b99,c8dc48c4,b6b1e4ae,5b823fca,ad9495b9,8217fa4a,b4f8e960,77cdaf9,6ca2ba73,72606e82,9c3395fb,dd2e4b74,8c771231,e86fade,5e2d728f,e5e7391e), +S(a372b545,bf56b58,b7c4628d,aca9bc14,e8bc634d,d79d139d,8eb7a2d4,13465c3e,afde23df,fad41c68,df94abdf,90a642b,31d62f84,c6254c4b,4cad2934,376372f2), +S(89d02f41,f88b1f7c,90b01078,d7599a70,a1eb9c23,1059e856,4237b0a3,2c18010a,7e8e810b,b063d75b,c224f41,a842972d,6fe065c2,aa6b16e5,7bf224fe,e44b2275), +S(7ef367d7,23fedacf,86425861,f67c5ba2,2deaf04,69e31988,7a3a3a12,2f39576a,4b81e743,e00bfbc,1d98cbc2,5c98c516,55e574,fc7fa1f5,86f15d9b,1b5b7ac1), +S(2eec37a1,5fdd1caf,b4c0855f,e86c5534,1a78cdc,b3944798,311b1cf4,7df768ac,1c18cf5c,1a98fe9,70d1e635,ab133668,4e0d964b,4df0b16d,7c51ea01,c9a63), +S(72208b8c,fd9840d,76dfa6e0,f36cf57e,502f285b,422f0ba1,9b119500,6b2ddd11,fa09196e,a89ce6a,888415ec,a8eb92f4,149bb39a,50174a85,8a29bf63,65b4e577), +S(9f46479a,69411d57,c3c7ea6a,dfa833f9,1fb2109a,fd30c790,2ce323ae,4b14be0c,6cd6d7e0,8494cb95,9e67c258,1be426f6,4eee4514,83e9a9a1,278b073d,758487c3), +S(a9aaf56b,5016db58,5b8116dd,cbad1169,4b16de8d,9db5ea5a,279ccf4d,91b1d7a,218fed41,389a4abc,44fb2a83,7016eb50,99c40e86,bb419265,7f57714e,194a5900), +S(5f950f20,b610c06b,76949dab,52fc6149,97d254be,a1330a0,493f1ea2,1d608864,d9098481,823b3ff9,d1c0b7d0,bce90856,186b45ec,6f20da26,9b158283,8a4c96df), +S(ed621f77,98add722,b0dc5e52,9c6fec6b,dff60827,b0b12c85,18d798dc,761f1075,a8973e79,a9caf1fc,e3165145,df08b7db,6b7187a5,28b12712,6c62bb5d,4f0c46d7), +S(15b8390d,652d7338,e18ee091,97e0e176,74f8c4ba,fa2e7b85,8f5badc9,9c89240f,87930df3,710172f7,c5422833,385a6066,4cfc9854,a3e5ccca,d1d06106,1cd90be5), +S(ac2acb9b,21999a70,540708ab,68338266,aef650ee,d81c5b30,da1e87d8,a8a923b7,897bbd7a,ee3e8db2,e36505f2,ec2614c,9f4f2f40,ed2d85b0,5d23edb4,2832db89), +S(17c072d5,6bdd1382,a782481b,8aa4d223,2db79438,5870bcad,c3063330,a5cd5379,26fe420b,d7c25f9b,1883edb8,50e2fcb0,76a65389,d9a452f2,8351fad,4ef72f0a), +S(8d262002,50cebdae,120ef31b,4c80cd5,d4cddc8,eadbcf29,fc696d32,c0ade462,1412c44b,8ea40bc8,2ce090d2,3c11c945,e2b504b1,8d9874c5,271f5745,f0d9b523)}, +{S(ad9144f1,bdcc3673,26d51685,a047ea9c,3c4feb3c,da4b9b83,80e1ada6,300ba487,68003744,ab5b2c8a,cca5bcfd,e1c4262e,88ffbc0f,b0ad4206,2d57dcf8,62c93c47), +S(f3b90a0d,7a8cbf1d,9b994b19,7ce215f9,b8ed861d,d526228,59fe1811,68727bab,95f48e8b,c05a7bf1,e47fdc86,87513ae,5a56472a,44f384f6,1153a954,2db68b81), +S(24af6d7a,99122466,45b07a1d,29b4bb1,a68b5b0e,f9422065,b5bb0050,61d43cdb,f9dc7725,f628cc4e,d4e5554e,f0166b22,566d59e0,4d55c28,a4d0e975,8306c31a), +S(f704aa4c,2bf19c9b,128311c7,1bab5f8a,f2a3865b,728f4838,b8ccc7d7,82574cdf,ae7c46ce,c44d54a7,2e3f758a,e855710,dee6b189,1223d120,9e059620,38d12453), +S(f701adf5,a1bd988d,d7e1fadd,9903c453,e6798760,252579c8,b90cdce2,a046d9a7,db39a987,48aa20d0,5d8b8538,fc4b7d77,95e2810b,160198c7,ad98305,96407c31), +S(bfe36081,c492ed7e,3b91059d,bb1af376,47dca509,69be6665,50f94903,d948ca7c,a1fc9468,2c3dc954,764ee858,822b8c1a,5d0184e0,93f12bbe,21e9931,18911f03), +S(e707057a,297a3d7d,904a615d,ac1b8e81,78f52481,32fa166e,afb621e3,af3f4f34,9161a930,bfd583c0,bfd3b121,acf574a3,6eb534ab,5198aa84,ef38253d,9ca19bc1), +S(27a6c7a7,970a9e3a,7cd42b6b,4478be62,31f53ff8,481791c,4394e78a,968fdddb,e4bf1b16,6bd56269,9e2c341b,b1a51c8a,c2ac7d28,807899e1,3ab1f726,90f44108), +S(e65f799a,8fb3b6c,ad088351,614db5c3,d64660ef,8c977ec1,2bbe58fa,a53314d6,5897f680,253a948e,fc260fa2,8ac39377,4e6a445d,d2bde00e,4e01ff03,b4398e2), +S(8406a84c,e9e63204,761dd406,9651f20d,6fc3efe3,f98951d0,d0a2db9b,cf86e0a4,ef81aeb3,eac17e5,676f4455,b4372ccc,e405b786,f11a871b,d781e54c,6307d1f2), +S(c012cad9,4742fd49,8daaedfe,5b847f34,7a45c792,53c8a645,2192e905,e256c7a1,c4866f98,48f31660,8a81da9f,da112a71,34232f9c,75e388,7ff987b6,8404cd42), +S(73795313,e9de1efe,3d91ae5,15c620c4,4f9c6bb3,a21e3097,c8794710,b2032683,548ce754,93817f22,cb96c674,5d67708d,c7b9b133,c71cba5f,fede1316,c55245f7), +S(352b89f4,78a47e86,b5575fbe,ee1373bc,e93ca316,1f594564,9efaf048,a60bfebe,d784e6cd,88d7862a,d82747d9,b23340cd,b50235c7,65f30be2,ab5d313b,edb0624d), +S(8a0b3d0a,80d41abc,4b8a028c,6c523923,7b040445,525dc345,d2d8a319,c4708316,7b7a427a,f0e1f902,dd1b9bb4,65b6b376,ee68b9a3,f495cffa,c52fcb9c,705443e9), +S(b4bf6756,61462829,53f9a44a,ee3b5427,2485b45,951013a2,8d59346d,62f65894,85d0c26d,2987dbd9,e26c9673,71ca86af,3b8cfb4f,cbf97404,c99ef900,5379a1c6), +S(bff69744,3ac23a6e,574bd1ac,d0fea305,2f05ea65,14814f1c,65e86e9d,5b46a2a5,36961462,5b998565,9324f5f,c8714d9d,57ff314b,5d5c2cc6,99a4ab39,69add4f4), +S(ecb09f5d,122adf91,e68e98ea,d39e5790,27e7c4ca,405bcaf2,e086d4a3,e68242ed,aa214cca,8a601fa0,a92633cd,a353ca02,7a7dee71,cf335af8,fc75de56,a3405f60), +S(310d957f,10fb34ef,ca3a2a0b,35c901f5,35c0862c,68310134,10982d7d,e74af8ae,289cda3f,29a489a8,86121f4b,4e75a90d,2bc4ff20,e95aa103,4044ea80,cff56378), +S(3a5f1ad7,c59ee6cf,e090f210,7040b419,4ca15fa7,dc8e9f69,20825fc4,e012ac2e,8ac8986b,48d7bd1f,5ae99535,2505b0ad,78f855e,d8411b03,15725571,dc99c920), +S(725f136d,1b426894,c24f8782,43fdc1d3,79636a23,d682f389,dbaf71de,d4672067,db0ffaac,ec5ffadd,f32396be,3f01fe2f,45bb0cbe,eb0d98bc,2390f3ca,c3dfec84), +S(b28e523e,6fc68192,445180d9,5da3e411,2fe0db1a,5b3bd5e8,e00a1090,39c69d53,7c172a4b,31339fb3,47db74a6,beedf59d,c24e6aea,c71e2a0c,434714b4,d61a2f70), +S(b808db0c,e34b5607,8166b308,1dd4b2ca,cf9d2d51,3079648f,fc3c617b,8e45ba09,d69c4ab2,fc7e490f,6887f2c2,49e0b71a,746e3e2b,97a7415f,34475bd6,f6dee79), +S(5e0b091f,3144d7bd,c7e40dbc,98c716cf,d7e64eda,ee9c1fa4,6838bcd9,e0c6878f,1586cf7c,da66b005,8b2d0d49,f588d444,65eecf42,1d94c004,a078dbd,47e0bd20), +S(1c3e88b3,ba46410d,8e08f9fd,5db8b53f,8dff33c6,4f5314f5,e005442d,10cef1f8,ba365020,5f85aa9f,71a42c0,392345b7,4a17a5ab,9ff91109,4d81252c,d8c8f72f), +S(b4926018,fb0e9c,e80c5614,37c3f22c,cc223412,384321e3,6f408e4c,ec0d81ac,55544f6e,cea3575d,e81649b8,4950f225,8a94e78f,13325ffb,16debe1a,8387173d), +S(f4bfac1c,b0834e1a,e332b7b7,1ab84500,b1c8460d,c8c2efad,6a5efbb8,ae78cd1d,5faab691,59ce9d3f,6bdb1818,676684b1,cc2309af,1401b5d5,137e1c61,5fbe287), +S(220ed3d1,fe028d87,b96e8ad9,37ede03e,ed8f262,ce877c0a,42718ab9,cb2ddfb6,5ee2d60d,f96a1b8b,e11c9139,7abf9b4f,a0671966,34bf37a2,8d26864,31933fb6), +S(dca5fad2,d045526,b6a4c309,de1d95b5,23f9a7db,e669b558,edd75ca9,40c85878,f350337e,877c9c61,98fc912b,5d53876c,78ea94cb,bbf3744b,62a52fa5,f5ae4399), +S(486ba509,3272eb1d,16ece443,861eae7b,2d8604f3,37014bc5,11267485,9872642,688d4585,9fa732c4,f582d65c,45930567,8c27dc6e,5525d47c,3908daff,f0a534fe), +S(96bc1bd3,b4840354,14aa92eb,6db81f5,403e2858,c0552d5a,6b21d33e,c468f31a,83027873,f4066b5e,ba6f413d,6a7d4d18,d57f4a62,25cc9289,b514f153,91ede3b9), +S(9f131ffa,b53e20b4,e9cd9e33,793f4614,922c03df,7d11222c,7fffec33,42fddec6,c4deffeb,3f4cd90b,102cb6b,3f713728,2c5cdcab,bc6e7153,91ea890d,76207bdd), +S(c15c8c23,d90c8e35,c1a214dd,e2d4383c,735ae45,bef61f10,aa1a1c25,5984cf74,d456ab27,d7adddca,372390ba,1da02845,b84088d2,af4fea5d,3b5b7326,c6334c2f)}, +{S(e24b71ae,8fdea24b,2d42a2c6,5cb022a8,2aa9e03a,3067a889,e778caf8,34903fa,f87d5757,cae83263,1233b840,296d6066,52cd1ddc,e8334629,25c992db,7e0ee14a), +S(886a7626,6203c559,807acbf6,7e1631ae,1f6bcacf,3fde277b,ddcd795b,292c38f6,b1f590a1,52d3ecc3,2b699c23,a89b2601,de78be2d,fa11b20a,1ef1235d,93ed9e99), +S(3079f709,3d5270f2,95fee75e,a6c5cd3a,5638ee37,aef535b6,523604d2,eed0d57e,492dd2cf,d76705d7,42187f38,f38982d1,85efa30a,fd1639cb,984a8772,3e912a91), +S(7773469e,c557e3e9,4097bd55,33a87583,a79e3eb4,2e421cd6,592363c2,76641966,f827b0dd,46f4b5fb,4a656731,d827cf21,df1ec610,f36dc2d1,215f33fa,20a08020), +S(ebeec367,eb032a6f,7c421ae6,f8fb56f9,3fcdaa68,f6741e46,1992d019,7567336d,6e78af43,e10c742c,35467149,3323f8c4,a6cff91e,7b1f1c2c,65b21fa1,e63f3a6f), +S(b41658a,3683b512,c751d817,f5d92f8e,5d158632,1f2eb836,b446aebf,d276030,9396ba60,ca61b35e,4e52e879,a457ce5b,fee9121a,b2673c19,15e78236,483e069a), +S(2e2ed965,a926700a,1428af7b,68b7dbf7,61d1bf53,6eb9f75e,d56afa0b,63852cd6,8d77656e,d5f11224,3a94e462,3dcfbbdc,61749930,dfcca6cd,c4303cc4,617e9133), +S(4b54bd22,e5604384,9ff2268e,88c695d6,4766e0c8,4f598f5b,634e1dac,d03063ba,176c68e4,a1f25683,37c14fee,dcf9a64b,17cba4f7,283428c,1514990c,98d29d71), +S(b6cf7c38,2d4c63cf,78557116,55b5de99,1fd32da6,8b8d2dd4,cfcd6f5c,59c45251,c4c190ac,2870142f,2a13d7bd,5d6768b8,fb5ccdfa,b99d0e3f,6bda805f,7741ff52), +S(857b6db4,79177eca,82a6c801,bd763647,c1a49021,e5b4f405,ad02e6ec,7ccc3629,586cde8e,cbf7907f,704a6610,f7a8a910,16599e9a,93bc6a6b,1b70d59e,39c0db4b), +S(a18a23b7,6643d92a,9e1bd2c7,7bfee61d,c5171b33,12f64d7f,821fbe05,6a771ee2,321f460b,b9525303,c159fe3a,6762dd97,60432307,919a2f1d,6120c946,47cd8568), +S(19b91028,cc2e5434,b162cee8,c77351d9,d38d9eb6,8ff9b09b,f26cb25f,4b88510e,cbcf2e52,3335ee5c,56ee2a06,7c565627,a5c60f16,808ea8e9,94250c15,e427c883), +S(657e2f30,b1e0241,82c0e57d,996cccf4,7bdf8eec,5a4da875,1638b3f4,9bcdbd2e,8e0a3117,12da36b2,2d0cd048,a9a99b26,5faadec2,14162083,5210f1bc,bb79fe3), +S(576879e4,f4a8e697,45014bee,36ba4267,cf72038a,f5997d38,cf512f08,f0ccf6b0,3f313f,388c011c,18ba0938,51b0e7e,84627277,2e9da999,b839b58,92ede5c0), +S(ed72d681,6516c2f2,7a9e97c7,1a7c99f2,faeb8e31,a5f29260,faa0bbf8,6475117f,331fb25b,e71c24fe,f4d2133b,f1591f3f,e5f8830b,15615134,36fc47fc,522ad4b), +S(e4ed422d,9152f00b,96bce64b,bc3ddaee,6089e1a4,1ffbb58a,109c688e,ba44699f,6dae6420,2dc6cec2,e4a49203,6b16c9f5,9c517436,bf3b9d9b,7e8f458f,7fcba8e9), +S(fc3b8afc,fe39404c,29622db5,b06c989a,8d7a0c4d,85018796,d006bd5e,43dec087,7b77feef,2211c1a5,724af5e9,a841e09c,d7940bc5,43d70c7e,51676689,7682ef15), +S(9c2421ee,e2e7e66b,decbd152,a8839f1e,4cf03808,649399bd,ba55cfbd,9dda6360,8d9477c1,c66a532b,967895ae,66c7585e,608e9653,4f870bd2,c97d7398,74a84700), +S(22040517,334bb5cd,2252d1b9,8a9da91f,a0bd32b5,562c8218,4d991e01,d94e8f13,167d3dd5,738a467e,f8e03064,d6482c2d,64503892,b4f5b9d3,c4b04684,fe2f15c0), +S(b648a617,3c728243,f3c0c7ec,2aadcb13,dfab92fd,77da9aca,1602d47a,80022dd4,7199a3cf,89c596e0,d607d05e,de95c8db,ad763ac0,76fa7ee8,ba7ae6e1,4c14308a), +S(a7d7ab3,6722b9d7,940b2a15,c94bb9fb,41a139d4,26215286,bfff84ec,57386dae,25ea853a,c3e772b6,f400d850,a7cf5760,ed568add,a145ea75,6f20b77a,c32d9f28), +S(9787a21d,ea3dab74,366214b4,933a702c,7a07c4ab,696eddb7,3a84cb5f,80f2ba41,8663b959,2214a018,e373e360,a9e035be,f68d9e01,f6fff1ab,f8ad9b8d,3f6f324), +S(1d2ebbd0,65bd4f50,8dd697db,9c8bafff,b548edef,856fa4e,39f893cd,349ff205,85d0716b,109ab208,a96367e3,bd0a2314,ad2c8586,169096ef,9521d780,61df01a4), +S(d0a506ce,14e88414,46c08a61,98ea0aaf,75b9dfc2,c4d2cc58,1238a597,154981b4,dc8c863c,7c4611a1,85744975,34c8c02d,7cb7504b,dffa91f5,96765a25,98d1f506), +S(b6c4d103,a57d0af,27e93627,f55a34b7,75b2ef48,47d7612a,5fac0748,b41afee9,dc9440a1,596cbfd9,ff87fade,8b426091,4799dad1,ce0f7b60,d032e94b,bbaf53f9), +S(5b5d965c,f2f37462,86f088e8,b58887ab,2182f874,484686dd,43a245e3,dcbc55c7,6718ba28,cf43ba30,eeba6e49,a7234ec8,7f01762,e915ff12,41fb461b,6d87a875), +S(bc85aec9,55e6e99a,c5fa7738,c7972354,57b3935b,bb69e8e1,ddc69d01,d34a47f5,59dd49e8,cb3100a0,9c48ceaa,20cbde82,5072e13a,7af0a44e,601044a,361dd971), +S(66b7ffeb,a34d8cbc,e00b4d1b,a0558741,5123d8b2,89ebdba0,47587d66,b260bc99,43bafb96,c88a5917,c6333dd9,b4a546b5,1c37ab48,3f3873a3,6932ab97,efd79712), +S(3cf9208a,b230b73d,68470411,bf3d4899,e0f19675,f829e32f,cd148d,3c07d7c8,21fc39b3,ea5079a2,ae131935,9a3e98df,62b97b37,2a473a63,f3b56e24,25b30e27), +S(66e3fcef,b7b24cf7,af0f8de2,8e53c2df,2bd1dfb2,c0289b10,31239da0,948e129e,df4074b0,488f3f09,a674a40c,b3207f34,a0282661,2e5ac4ae,8d443c9e,d1184045), +S(28df781d,4ec05680,590f4658,713c8a91,fef23763,87ddb6dd,674a35c8,b0e74459,eb66159,95ecf0e8,34f24e87,6f0dd86b,5c86a45a,fe5190f5,721f833e,10a196c0), +S(85d8da47,48ad1a73,dec8409b,e84f1a13,16e65c51,96aad27e,766746f,3d477c2d,a76b74ac,99a3996f,a794ac9a,ce103843,6b4f5fdf,cc3b2a59,df867e8f,382e1ebf)}, +{S(39ca1e6b,9fd848fb,ac24c444,5a9f398b,8639fa6f,c0c2f2b0,8058d84e,6c0caf1a,8797227c,f956ba7e,5228a452,91cdd51f,8958ab7f,43f6c8b5,e06176b0,dc9048e4), +S(4c87e538,c9eac9ba,d5a2a81e,43a6f1e5,f8403c01,68ad5020,4adef77d,5e3aecde,6ee8b74d,dd0b9bb7,c8b7ed7a,728dd99d,a9fab941,f0132d0e,998e65b9,ffbcb9a), +S(1226617,9f5dabe4,6d963b7,e96247e1,e29f2440,f831c8be,578d628a,78561987,2d3552bf,ddb5ec6e,a7758830,9badce7b,41d71926,857962d3,c3bb28cd,5d68ce7f), +S(866c0a90,893b6b3d,807a96fe,3c67b928,67c1d95,e05146fb,40038476,26981201,8d8f3188,da86e510,b7a7642a,97778201,3926dae6,4ce80663,335bc448,d204413d), +S(8eeb2e94,9a66824,26a6f474,9e7578d3,1b356aa8,d1b42049,5fb83e5f,5d08f723,e439d710,c45063c6,d23aad9e,ac0cae8e,36552ab,ca6f2c02,6eeb03ff,6162a052), +S(ffc93fcd,85fd9502,78369b3d,291f1ffd,5da44964,888d5eba,3c3f60c,95082bfa,9aa66635,a4b0defc,b2514e97,515aa0ec,3f65ce8,6f6962f7,72eaca41,d5ea7983), +S(605ccd66,4f18c83d,edf36f62,e5089f14,4ed23f4,f88635fa,ab161567,fd20c8d5,cfccf020,363a805c,1d614aa5,b9a912ec,99cfea61,5c088789,275ef531,dddf2418), +S(d1e4f37e,7d3902aa,dfdd7254,fc727a44,98eb9303,a12fe71b,4d193be4,8dba6913,bdd29d53,4881cbc6,c2e301fb,7d757bc9,9224f12f,4296e834,9badb88f,84fcc289), +S(f30b6d53,f330e6b6,b23d21df,7b4350a0,c42ad202,4a92751a,5dfed94c,47bbe60f,b5ca6c03,b31d06cb,183b0b18,4432a06d,8143d511,8af4bc01,c364f024,b46e0c38), +S(540944cd,42101851,c2cdb0ad,61264e18,cbf948cf,2090df68,54482628,74271ecf,cd16820b,4ccf9131,476b8778,ba3e83,f5970507,7110686c,653be572,2e99db3f), +S(846e5478,5d9cad5b,5109c7e4,6fd62b04,f686c723,1fc3c0af,66bea20a,d9d60dd0,4b1a28c1,78bd097f,aeee951f,fd4f46a9,4658a76c,268ee7b7,9aea4bcd,e75fc8ff), +S(16e732f4,43b4c616,24a495d5,4497a23c,c95612d0,58df9f81,11d1340c,4b2b8b5f,61ee476f,30ac2be7,e3ff09f3,ebf0b3e,2d76177a,30573465,101f4cc4,ec0585be), +S(4f30ef37,2c730ba,a6a40ff1,94b6b58f,436111d6,848b4e60,10be9b9f,abef17b7,b579a133,7f3247f2,8c6afc05,644778f2,3668e73a,a7c6d14b,649bf948,ef126142), +S(595a0d2f,1668c0b4,9ba0994f,3b681c42,6e3a67be,e957bf52,47acd9c4,7cb7d009,fb10684b,3ef1b0ee,37684ba7,53858b3,3586b837,aba6d82a,958eb947,2eca319e), +S(85dfb59e,d7ef6e0e,355e0ce1,304fe5dc,8bc6a3ad,74de3352,2089f224,8894e0c4,7a9b9ad1,10099903,d0d84a33,6838d422,5f98abde,32d82ab1,a383969c,1fb98bb2), +S(c8e13980,cf58416d,8719bc94,96e21774,c29f2e1c,5a36e760,2ce7783e,2c810fd5,5bdcded7,bb484d46,48bc40e3,ee6a3761,cf995e36,2af21f0,10048a91,6fbd4717), +S(80b98fb8,e48f44e,db69fd8b,18eec95,2404fb59,45c8a35c,bf3616e8,c746aecd,d44010a7,20622d14,6af5319e,155fe4ff,591bb829,f5086c7b,1fc1ed6a,32ccbaa5), +S(17629b1,cf015e58,eccdc7a,de049215,fca806e7,805e0e35,951df2ed,5cb87d38,afd56698,44f6aefb,528dcea4,29438e0c,d10c4b21,23f02444,a950834,97a61f17), +S(592677f8,695479dc,b215af2d,bbc90621,e7f3cba8,650563fe,1b2a8765,6c44107b,3741e4e1,b39b0e2a,58373166,854a1d31,ed062a25,c4e3e1fe,bc82e941,eeaaf50d), +S(98d5f85a,a93c9d87,e34e3bb3,597d9380,f0a7e5c5,b03ec219,4025c89e,42126453,dbe42a83,66753aec,61f7f01d,e5dfde1e,b4b989cf,95bd36bc,a66ddc0e,ffeea196), +S(9187b546,70d2b9a6,b711c88d,353bee60,72a1f5d9,ce75288d,4e6c9111,80dd4126,80e73529,d211ea24,d4bccff2,b9de3e31,c6307ee2,3cd9267e,b2d372ef,78f8d2c0), +S(e38c81ad,8ddfd8ca,4e01f380,78eafecb,f8edba6,8e33e565,309a3ad9,f0abe0eb,9f0ace1,f05f0a85,a1488644,88cce81a,2cf55eb3,a91fc10a,e6b82f47,60dbe618), +S(7ee9955f,99e218e7,dadfed94,dad7054e,3e0b97ba,932338db,69ed056b,6f8adf55,5244e198,524a105e,2b5de11,81d7bfe9,ad56aa0,128a3d87,8cbcc5c0,25b41ca), +S(eb9e5ae8,cdf64b28,76349aab,c3f75c9c,9d95a335,3214d0cd,d43123c,265b08d,858611ee,f67a32b9,7b8a9090,6639e998,a05d9bbf,8ccb7c1b,9e5eb711,4216b877), +S(2aa74ebd,7e8b6b2d,952effaf,e5545eb9,e99b9678,a2515698,975247ac,c83ff081,1ec12cbe,6877aafc,f353f641,1a5edf9f,e4bcc09f,31422df,d076932d,8f0defbf), +S(1b7b8fee,a3ed4af1,cf9b07fe,b435ef76,1d081b1d,f1007697,f78fe5d9,89076aec,b4aa0d8a,efbc71d9,d338e998,197054f0,20c5a2df,7a9504b1,ca7cb603,6641f85d), +S(3f293b75,9f152a4c,b92e319d,e5d02b82,f5dcfbc,2ee7a53d,fdf7ef6c,e2595c32,b67babb8,d1d1963,fd742c22,5ad5bbe4,27e57d6e,b9e17bbb,f91d2c1e,a455c1d0), +S(3eb9968a,c9b01fd0,882ec65a,8f9f5a5a,b0fbec2d,e2dcbf88,cc9a70b7,887ca59a,1a4de130,4a46fcc7,6719c254,dad5e88e,9d6a0839,9a9a28ac,7f171aa5,9624ee2d), +S(a559381a,f41b944f,e2bab9d9,62ec7c53,efb25ce4,1ff1a456,54a99f46,d97ce20c,ebc6f66f,75ad7322,4c1319c6,4268c997,4142,11ca65b4,58c5f79a,be0ba0cd), +S(a8bc942f,c60ff2e1,140f9a97,3d7e0b8b,77698254,57098005,f9186e97,9e430593,2a82070f,25480267,c4fca773,3173b354,fcd5cc1b,ae497af8,58b7d451,8f048c73), +S(2f456ca2,c4f8806b,ce4caf12,32446b07,3405dcab,7b3cdcc0,247dd079,adc7a626,7308e58,5b9bafab,b2dee049,9bbf60ac,fdb37242,3e915156,15314ffe,5ad866fd), +S(b56f4e9f,9e4fd1fc,7d8edde0,98f935f8,4c750d70,5f0c132b,d8c465b6,6a540f17,cd171acb,d63357a9,2c23ee52,fa7d2e2,de2bd69c,343357ab,b95d0350,fdffec02)}, +{S(ec474055,43c52e68,5c9e6c75,97616fbe,edb70df4,fe3c375d,d7d24729,2b120851,22c1c1a7,30066375,5ef8c2fc,86452667,90347223,f11a32d7,9f1c0169,a467530c), +S(3f50e502,c45fd922,94fcc46c,b3118a86,43af00d1,634bd694,dfc0eeb8,be2dd4d5,7cb992e0,f29fbc5f,2887161e,6d1e266d,f11fb723,3b6c020f,26eee393,fe96b526), +S(443007f2,43c3f6f9,76914031,c41e0d49,61337340,9bd4a681,f20e4c79,934fc2de,df67adec,c9ce5f6a,e6c8312,699e0353,68ee87e3,1e96790f,f0bd3408,94af74e2), +S(1e15b9e9,c28f77df,75837a0,cc9504ab,a3a49aef,26a88d99,543fa7d2,a875620b,2a081093,6afbc025,3808ba31,f5597287,e32898ac,77fd0021,9e6fc298,26b0370c), +S(cfff0258,ff6c0d97,99823447,775b75b9,1881e06e,bbd72ba4,28f8248c,5cf2144e,61e63569,5c4a8fb4,f68f974,219bbf4e,e0c277dd,4b74b843,88f99041,f97809e8), +S(2824f4b,f72f9229,2aa04058,7a0c5395,4c87e7dd,bc5dd199,af6918e,6db62f1e,16ab1473,3bf8382c,521af6fd,27f8b2b3,b421dbdd,bcf06c62,3bcd86b6,4bf33274), +S(5dc7571e,27d6b955,6c789b4a,80d49fd3,17416fa4,e04a7eb2,3cdbb88c,9c253a44,b7261e2e,39327d68,a5456abc,9d4600c7,fb6d6e51,a732c7f6,c64cbd0d,56de4a17), +S(e93f3aaa,5d9edc53,6029d332,9ac0bffe,af27d4dd,40f550e5,3df879a2,a5c1d993,25b442d7,f2e2e03e,c7f1588,16a1af43,b5d2870f,e0cdf429,babb19e8,951c0982), +S(8f91f5a5,7aa40d62,ba407d8,6ea5678b,65c84ea8,f241e2aa,dd6df242,52635a86,e9333d7b,d6c319be,3ff4f5b6,f286a8eb,27d5a1bd,29646cdf,77441c40,f716a6f0), +S(77d398e0,228add30,e9e120ea,b16436be,30c254ae,65016672,8bea1198,de1fb17f,749a20c8,ad6f4312,fb6e6fa,c390a4a8,209704be,3355362f,31db9b45,f3876963), +S(96976a85,b6dfc4b6,13dde357,c21c3518,a5f55c7b,a2d22976,592d7632,3b5a8546,96dc660f,8ef3b0b6,adbe77b5,69024fb5,dd713566,617cfc51,c8013f2,5b424e9a), +S(49093c4d,26194278,623c2ff9,6c8e2f11,f9edf3b,13c33099,57b57f1,9db451c6,5d53ff56,50b82edc,9dee9f43,ed6db93b,f6a26233,2dbcd699,130aa9ce,5130384f), +S(49187f03,d5f5f628,b9210b88,8ac4f1b5,2f754015,541e9f38,162e969d,6a99f4f8,276aacaf,d38d0bbb,416bcd0b,8ea590d9,7735a3f2,8de72aaa,76bed0d,6644bd80), +S(7d64e446,65c03917,87fe0b14,16ab1048,3a6025af,b20e8c19,3bbba444,2864c587,2c0da181,6507f8b6,4c9e5684,a4d53d98,d6b88215,772def9f,fa5a7a1b,f2b2ccee), +S(2223484b,9ee12b26,2a21a18d,2682ab01,c291ee1c,fe3b4b9e,2e93fb67,aa08535d,4cd26418,bf0d62fd,b266a768,5f7aaffe,d7bc95e1,be41c6bc,7a0c9076,1ace3974), +S(aac92330,7d6a55d8,552ce6f3,9c531d5e,afdd5313,f801242c,21df07b3,a656c618,93d9be6c,590901a9,1413cc23,94cb426e,e6a61593,93511c,e67e1ffe,68b8f3c4), +S(6ec1a0c7,fe40c40a,f3515ff6,60f0b53b,8fb6be3d,d912f8b2,c7a473d2,3e49d201,b10f000c,191e9423,60fe6b5b,2b6b7b85,73c0c2ee,384dedd6,e3dc04a9,7834f93b), +S(bd982a5d,a4d0291c,38568fae,ebc76df3,f2b0e5b9,1cd0d3b6,d2f32077,6c35c43,48566068,d5142f6a,90b13105,e7841d32,38d869d4,fcc7319,3e3cc9ea,76739c5b), +S(25d54513,b9084ddc,a3f20e18,94382290,115ad5f2,dc72c267,ba845b3c,6ade39f9,e908508,7fc5efab,a6f62c41,ea8fe856,226c8e2f,95dc31fd,2b49a7c3,6aa53b39), +S(29ab6cd5,add595d0,cb64ead9,c3d275a6,ce383f15,9340faf5,118ec2d2,9bb9a62d,54584613,dc27c249,d5d1210e,9e121aa4,7d606fad,1c4621e1,67f67b90,d8f3434c), +S(4cfd960,86f86d5,bd805667,55979c32,d5419dbc,946d63a3,40dcc6f,6d6dcd48,f032b7b5,9d85d0a9,fdc290bd,a1fc703,55b5404c,f70d45c,d15fa9e1,33ee9319), +S(9c786066,b6642e11,139aa303,800314b0,6afd4d97,e8314a1,de9d7002,5b7bbbf4,463a2ded,e2185c8d,944f29f0,140f6b66,9ad6e3aa,8ab6e292,a2af551e,685e58ca), +S(4e98485,f15c506d,6cd29d7c,3f9a59ea,4bfab065,78d86b63,f25e74e3,e7aea96,2baf3fb1,c26f2b0b,1a0725b1,5d1ceeaa,7ccece9,a1dd8f2,7f80d825,d8cf1d71), +S(8412c389,bc88e9bc,b157d835,85af0dfd,48689532,e38044b9,117b8acd,ce3b62cb,17eaa404,ffc1f62a,38f7ce99,6216b1f,40bb62e9,6d1f7a5,8bca370,c0d30b44), +S(31b9b8dd,7d37b38e,892e94c7,a5e817c8,ffaa1c1c,f56979ff,7f25815b,758b6d09,cdb680a,ae795ef1,f94e7e87,50ad9077,7a55eec6,c6f0795a,ef951e3c,ab45d186), +S(2be45d05,e89c58b1,8212890b,b6eaf935,6f03e37a,fd957291,4ab71a97,7af8350d,c3b05f04,c9f7a1db,b6689fe0,6ecf7a80,3ecaa147,8d09a1ec,9a7d71dd,a75406da), +S(5185cfa5,fe6302c,b5573594,61f375dd,c483a66b,c615b5f9,30abbd4a,5c7ae0c,83cc447e,53c91e07,6f44d265,389bef06,549b8d78,9776000b,5c35ce36,5fcff98d), +S(cd42328d,e4a16323,c51ef888,b7e67ba,f9ee1c53,82161b90,65e1db15,bddcffd9,caed06b1,7e86b470,b665de93,74725fdc,94792c57,5509ebfd,f012133e,122302f3), +S(7a1ffea,8fe5114b,8a638306,3b7811c3,25a40c19,42451557,679e75e2,b304ab91,1ef3fbde,4f0283ab,96efbc83,bcbb5a6a,d781a215,e6ff6262,ca50b9c3,986816db), +S(cf0bdf47,a3f15b24,5c7136c2,3a3e38f2,661fa8a9,4df29fbd,8b41ef22,c291dc6e,c73d1fe3,919e0aee,5b3adc4b,1a86e709,4b039302,d44a0d56,638c3eba,24857a99), +S(3a571630,935c1f02,d6fd8744,2c082060,cd5e792a,1c6f92bd,c4eed01,686df50d,7a1ec78c,4a660cd0,ae90c00d,1a8f5f22,1f5507e1,4487e5ee,2dea74d6,17a69494), +S(1c5e5481,32b49a7f,66ae9fed,8323480e,d1ab974,622e7cf0,8993895e,ec87fac,b00309f0,7c80b970,d446a605,e2b3d52c,5c215314,d901cdb3,aaa284c1,a03d2740)}, +{S(2b081f0,268d6ff4,1090561d,79144bb9,554b1f3f,1f0f2cfb,c9344e2,b692157a,597920fb,c528543c,26499af1,8b5e7d7b,5ebf5ada,5df4a46c,edef52f2,1e2fda5e), +S(2ce45dc7,d84d3143,884d6696,73738e55,e30f6045,8bac95cc,c30e86f8,71779827,deb79108,80a1b675,a628fb09,725c9307,d1629b07,8027f566,29f8560c,2ea80458), +S(9dfa0cb6,2a63244a,35ce3a0c,f102e7c7,93a4530e,21c6c03f,15a4fb91,e116c480,b01c1aff,902f0831,bc8cd268,663f0ce3,6d8e22be,86026460,a8950636,ce44626b), +S(61a32d1d,cbd7e887,def51ffc,9c1dfd55,d06d72f6,a73ee2df,f83cfa0f,52d47bb4,69a3b17c,fa91e3d6,faf28d83,2695aa66,c87b14ee,7b2d987c,80242fc,ce2cc42e), +S(8cbbac63,5414c0ac,b6d7f659,5c6eca39,886c3ceb,82549f72,d07a4019,e3076eb8,c838dc49,fd5af1b5,e503a430,71901bcc,90e1ea38,9f735e31,236491ec,43e7b621), +S(d3f77c5f,663c6efa,670b46bf,dfa96af4,fc4720d8,e1df6e8c,1ffc5696,f37cb55,aeea0c3e,50eee6a9,16462a13,90ce5d47,c060efff,1fd3108,1db77513,34300332), +S(6f774118,4a0210a0,79695d20,f93f861b,658137c,3a072076,7d80e5fb,8b1ebdff,c12aecc9,b55bff04,bd6b6e73,870deadc,666973b8,ec498bfd,bcc4c33d,23f5d674), +S(fecfabd4,897a948e,5fab7200,969f9955,9eb1c9dd,2a31325f,34dc4f80,13da72c9,ba70c9bc,c8048aee,6fdaf5f1,8ef638ba,ce739c0c,76ec4c13,fd4dd6c1,1663d02d), +S(d1a1a1d4,24fb5ab1,3e985c86,9bd7c02f,f81b4633,dcd22e96,c3f33489,2e80d543,cd5b79ae,af62769f,dce99530,8b921b5e,39a60fd6,f989dd7e,1d0d7219,e9ee8865), +S(7099682a,c3c083a8,80467746,fb924d4a,56f23d16,a3b57f10,1a824b9e,653d45,6a9c296b,cdd72c93,df840003,24ce78b9,1f9df6b2,bfa33922,ef32733,fe49cb31), +S(1035866a,4e9ff0fe,6b0066c6,3f0a2392,c0b8cd61,36e13ada,21f6dae9,f22c39eb,6390f9ae,ec1989de,2146cd00,a5eee99e,76ea4536,423e9bf2,c778ff29,85538fa8), +S(e18351cf,163e4df7,d31851c0,409b5705,a5ffd472,dbda5dd3,bf05e66b,fae50fec,264c1d26,41f185e2,72b908d4,77222484,c651e8e1,9a9e1fb0,1ec5ed4a,8a4b6c08), +S(dfbee778,ae4bc89,24f32c18,bc0a740f,d01922b1,28e1a595,283bfb4a,fd8f2f76,d11f9b3c,25ae3619,99ec2c9c,2f1a5903,d80eae59,e096c5d,c5e37201,81756acb), +S(842cdb54,414fa977,58ae3fb1,9316ef32,af9c4f0d,649f0abd,cb94267a,124b59fe,a016f899,288f4caf,dcc6edcc,3cbcb561,fdb4047a,f789e1a8,51ad21b3,be62f5c8), +S(3deb5d22,a81540ef,cff29ac5,585a056a,204e4d67,2fb858f3,5c23e939,790c744f,20d73911,5b24b1a0,a4b31302,73321dc5,d8b74398,d6516439,4e1423f8,b4022d6f), +S(3108e61a,1e0f079,f76e3ab0,d69cf068,779674e6,49768aab,718a09b0,640251bc,245a9f2d,141f390c,f1a17bcc,a06c5a66,5cf3a87c,1096f5e9,b04c4fd6,737d9a56), +S(63b9eaa,ce6b32cb,e4cf4a69,6599f8fb,3797bff5,9103ba0,c1351e78,b16cb0fa,938ac414,ef911df6,bda32b5f,1f69cd7a,87a25d82,177763de,568ca95,e846fa5a), +S(f37a5a41,cc96a04c,c882c27e,e362d054,7d6267f1,c91c5403,2daa5c12,1700abda,108bd6ad,27aa72de,48406693,758a74df,53a3ff98,d490e303,54c45ffa,c64638bc), +S(52afb7fd,6a16dc6b,98f9d7d9,555068d2,c2317035,b7492e8a,fbf28aea,3b1fcaf3,548d8ca1,2cf7a11a,b0100455,c7240290,6cb2e92b,101d1e2e,32ab263a,3f3de413), +S(f644fce7,874e9154,8f3fb284,b7d1ba17,fad6eb6e,c581f57d,5aa11804,86de9889,b2acbd8f,5bed4270,ec131ea,1891c99d,ddb46648,60acaf39,d68d2a54,a58b92bc), +S(863cdfdc,66065a4,50c2b7c3,1d694c58,e63ccc09,fccfacdb,4fdf0b1a,b150e937,14d168dc,c84d859b,55a3d5af,9d17ce4e,83bd90ed,55e099f2,50932dad,b5d2693a), +S(9f5569e0,50a26288,5d91f82e,9cacdf9e,f4487676,730f4da1,46ce8769,3d8807ba,cba008af,547e01f,6a9c6c45,8f9d71e1,8ad062c4,4b305b52,3f3a6655,3979a2b9), +S(a0f14b6b,99f0bd74,cf9864bb,17b1c43d,51ade513,6cd72a15,89312dee,706d50c1,e2bd2d82,c549b4da,cebfb888,c1a7c5d2,f0757fe8,53e07fb4,747eb7a1,542137cc), +S(9e7bd727,fbab45a9,db36d17d,5e5437eb,f028a10b,392ea470,d5cff0d3,2e9bb0fc,fb52eb32,e43133db,28125280,e3cc55a6,76877c58,b4051f70,9c031f84,24f12d9f), +S(7d8b1a30,4c0c8931,2d5d712d,ab396efc,7a117483,7f62bb38,62a81a3,660b1068,472a2dbf,ee99c398,94d14c1e,ce87cf17,c8aee10a,4720357c,c5ce79a6,19aafe2b), +S(d5eb073c,a5afa126,70602de8,417fe50d,bd8f0768,d615ef2f,565e421b,4e7842f9,52571e4c,e4f0c424,fd288f3e,8b6c54b7,7481c3a,43230fc7,4c6f48b,d4041089), +S(3c41cd8a,77728b07,ea592254,5ac45462,2c7927fb,6a7aeefd,61635cc4,217acc90,eab0f00e,84099fcc,c2f4d339,77ff7d68,4c035b3f,34c6c4e6,aa812c9f,43af366c), +S(1eeeca5e,cadfae31,188218ae,7beda45,57f85c25,5c99dd64,1d00d8ce,2e6f7809,d7e5c2ff,4ddf421f,cf09b655,113b8cf1,a4c25e90,d02b871,91dbac55,d6606ef1), +S(54c13737,454414e1,76bfaf1e,b4402bf8,678daab1,555412d0,c6d3fd44,653510ae,753f6a,f382d0be,f1dab47c,1b9368f9,57d586c4,acef0d19,dc241ce,f008ea3a), +S(4d608c37,1fd6f635,9ffc57c1,9f1aa5b3,5b0f5702,55851cec,34278d2f,465fc8f4,12d1592d,c2cbccc3,7e5c9fae,4b864e9a,ca6967e,9d4852e,9adc9e31,1000670f), +S(71157d64,8c0a1a33,19b713af,f806cf9b,c91a446e,2ba48ca2,fdd1ed4e,8c43da59,c2ac2aeb,a298fcfa,c0d5eefc,6eae54ec,330f5c0,5b34952a,9821ded3,9b72d383), +S(327f876c,93652555,fa80a054,968b4712,930dc930,12ee6b8d,c10263ed,3b89a762,4d2bfb15,4cadbfd9,4f6696da,a1e66846,8aacaf8f,1428201,636026a5,46dfc92e)}, +{S(4d3b98d0,b5926a8b,3e5622d6,10b30e88,caa6e7ba,eb10bc3c,38aec3c9,c1267578,e84056d8,4726291d,e6880a2f,2d3b0b01,371dfa27,5b8c9cff,4805d18e,a5bdc788), +S(6e463689,111d1a5d,d10b09e1,5d0f438b,1cebdb67,7a6cd230,bf6349c3,70667db9,de10eb3f,5d2f4320,7265952f,b33fc23f,154972fd,d3394cc0,21b66276,1b51db3), +S(48235e7b,76c94c32,b0d21bf1,7fc215ed,df036366,a9ef494,19723485,78db8943,4f5ac8ce,36c77403,b2fa83ba,1fd0e88a,3da4c8cd,3c10ddb,aafe2d0,5da40a2d), +S(668af7c1,4063dfba,1a4187f3,f69cb457,cae4edbf,a3bf9669,4080b6de,bc3e2f0e,ec95f37c,7bac26a0,df23275a,283828a8,5a102d8,f33eef1e,87cb56c1,850740cf), +S(d4426fcd,cbdfd904,725fb501,656b9f2e,2a9f9ee3,c6522064,f078165f,61c31d97,e73f2a38,c56838a7,174ee704,948d28fa,5b5fdc34,7774df9f,72f27834,a85eb4d), +S(d0f49ec3,42076b68,4cd91172,f15584fc,ea38aaf0,a3201063,f854ff1d,f68d4600,28d95ef2,82dd7d6d,72be7854,e8858b1d,a142002b,ad7b7b4d,bd1e582e,94341e16), +S(8a36f3c3,50bc0f1a,1b1687ed,4ff83a68,1578d74c,c28fa875,f6969e52,4887bbb1,15ab9e05,c3ff823d,ba090e21,1033c34c,fa713d39,feec4346,88e3ecba,4b431e10), +S(4d1ef23b,b316e821,7d2cc409,a1baa273,cc06f79,8fdd4d16,5d5b6805,3718e238,fc37e62b,db18154a,2add98b0,ec221e8b,bd1a2096,ac2dd1fb,cf8e2e64,821301fe), +S(eec1f8e5,76e87803,bac48bb4,65ed923a,a68b2965,64365d45,bd1c24c4,cf7041b0,2c6985e4,7cccbc38,3b85be66,ab34a166,c98a8000,aad08f73,616e4d2,2a15a009), +S(9fbc20e4,de372a38,90443786,bd7cfc40,c6195b29,4cf51874,6ccd9ecb,cee223e9,f734bfc8,a6973209,903edaf8,52f63bca,b23fc1a4,879906b9,1c5df169,9d24683a), +S(7984c8ec,a2b02dd4,e8b9c69c,6f803418,48f108fc,b63d7038,de58e567,e64a894,49adeb11,13c705a0,9eb01e50,dea5be48,86e5d424,689282ba,6d64f745,74f45e8c), +S(29a7400b,16f5712a,2324becc,29fc4b98,57fbb926,f8741dcb,324c26d9,6cd178a3,90770be5,5c0a94a8,16bcfa38,aeab11aa,5ec3b7d9,eb4e7d29,1bee1c02,69e87267), +S(8299d2fc,84770bff,a4e630b9,8f2e6744,99b1c7f5,719e907a,d70515f5,140a00c0,c790968f,a3c3d4ee,3e25a1ee,8e1d4923,3c22f034,ba7c172,b5d7d91c,99eabfa8), +S(5cfbd498,5b608db3,5d1a2872,b9cd03fd,d775e498,4629f41,61a2bde4,fb2582f1,8288fa89,81056333,acd1720b,bde757b4,e83d0a49,9c5f2220,521a0bc8,dbe827f8), +S(281f1fb8,e144e39d,9ec2104a,96bf0f1d,494eaff3,57fe084,63825228,ecd286e1,ae40e075,d19ee5f1,1dd7e22b,f1c277ed,9a02abe9,975609c,a7c811f9,7c54e493), +S(51698bc6,73d3289d,6b4882b0,cab14e67,97d31221,e5bc6e53,af061aa1,9f546daf,7b850099,fe977f6c,f50abe00,bb3a0b68,90f47c45,24e9ae02,94304b6b,20bd986c), +S(db701e92,9b696c86,d7fb459c,97af90df,ef847bf5,1d235337,2a2a4792,5fa8ae53,edc7e98f,1a108bc4,8fdbe65c,2904058f,7da5e188,e71d194c,4e9dbfe6,8a55d18), +S(c900f57f,e9a31d4c,9715a822,5a906e90,22d81c12,714006d5,81be0c7b,aeb5a490,8493eb00,90517d9c,b70a4bc,39043ffb,e0863475,17cde2,a9bd0d95,f616bb66), +S(d74e842a,fe2da0df,df6342bb,582fc223,717e0641,f1ce0e14,584c5c63,f379ad72,cefdbd7b,b4ecbdaf,409a0fa3,9a0a305,b1bd986,4913f977,bec6c47d,5d525c10), +S(b00a5f4,f033d126,64366147,a1bbb9b6,ea60a38b,863c5f3a,e323e8e5,1aee200c,11e9f1f7,b7701a4c,26a881ce,30fac1e0,92e157d7,b9c2e4ce,cffeb38a,172ead87), +S(5772b134,68bf9f09,d26074c5,16dd7472,d3a83624,92306cc5,c7544ec0,d73de280,2e2a7931,aefe2a31,6dbad1c,e7f9d42b,7f38197f,43024f16,9e27fbc,7af31d0b), +S(8bf8af02,ccdafb15,598f6725,5f172fb4,ba8960e0,6c81ffa5,b4c1c313,6f95f29b,96041af,1efd128,ef133e5e,b0aa3d9a,6ac3a651,92598b09,ed649847,385a9b2c), +S(292889a2,d8329139,3410385f,cf5bf489,7e1ee23c,e0e3b5ed,82ceb340,d89f87a5,41099fb2,bcec7e07,d4d4ad14,3cf605d1,b0a32487,1736063b,e49b06f6,d648aa69), +S(ad227b2b,737dfd02,665c15d5,9b28c7e8,76413dfa,25c9068b,90efa79,ce83142b,82f1eef1,7e2f6b86,87137302,741f8486,26fad679,9c6a22fb,3a49e341,c7e51e9a), +S(b4245dc5,5df02839,4cff2610,4a4255ef,89f3e708,21541c3a,4631ee4c,145bf85,5a40f72b,7a67540b,6858e5e,b15005c1,3fee862f,3cc54a52,7643204f,d0b8be2f), +S(15aaef61,568537a4,695c1990,c05ecb9,2c605232,f705c3e3,729720de,7e9c2400,e6efd1fb,b74e9e43,ec1244e0,bb4cff2,2a5ede8c,848a4f5f,5eec6f8c,77b6f5af), +S(ade2e63d,4a828328,b4c53763,30790331,734d7f90,37c1a584,59570c8,f31e72d1,c42898ab,3633dc7b,f3a454f9,d5475c4e,fcf1f786,d1f609fa,23616f26,b23a1a97), +S(d8a9043d,297681ea,c5ed63a5,de306500,6b66e4fb,167aa5ec,c76a8e2e,df426e7a,cd3de058,a0a93d7d,7122d777,1446b2b4,d4cf53a7,1759fea3,78adcf03,5093f4f6), +S(30651cb,592d282b,5348f192,5be3f04d,da5033bc,39e2fc7b,1e61500d,9769b57c,dadf77cc,44853f67,53b1dbdc,17a97d3c,e6d5b2e7,8c6087fa,800c5af9,ccdc54c), +S(aa21c60d,6f7d6253,9d42bafe,95c58f30,33c0396c,fa0ceef9,6d2f91ed,d6569044,4d519779,3b19515,92e2d952,2be520b1,11a5453e,ec6d7ccb,3e6db3bd,3d0c84c9), +S(5335cea5,e99eeb23,765b3444,d9bc7be6,1da67d6,91bcc42f,d43ae543,e9c22bc,c4072fdf,8963addb,5f980f7f,f314795,373cf3dc,935e0e64,c3d3d98c,342530cf), +S(708a530e,9e52c73b,ee87c9d8,8161c810,5d5762,2c29ae69,1cf999a8,3a1187a5,6477b7ee,1e065768,569a923,4492c7d7,c13258c3,92cac175,a75b0e63,b8c2426f)}, +{S(3fbd5a4d,ebbeff54,8c2271e5,33dbaed3,fb8ccc23,e3fa2579,4c8f7fd4,47ae186e,fdee4625,45bf75f5,5c29a724,6496d970,4616c54,ba01d0ba,feb9155b,cafdb555), +S(c1483ec1,78ba8414,c371b57c,49c687fa,69669e2,e3e1067,cc6d2a93,b1a9d24e,edf94395,962adfed,c2ebb3bb,29346136,e4dc870c,5c76299e,3b07da35,6bb26bed), +S(26df4b09,693a3905,2cb7a1be,5bc2cc97,222b70e3,3d297a54,43741228,beb77017,a3d6b908,cc6d5f80,aecda93,99e17a8,ce33c423,f00cfc4,dea8354,af502760), +S(b6c265d5,90475506,e15b2388,b894718b,be67aee5,ba40ceca,51876946,e336d903,b451d3f1,2c666c85,bf9486cb,296c39f9,49f9f98e,96d50a19,80f86f85,a1efb999), +S(da6cf69c,feec7b1f,c848639a,7e27932a,f49cd695,a2e56a50,693fa862,6e257c66,4506f44e,e6e0d822,7e67dc4a,9f8e2ec2,d3ec0c3a,c2a70c7d,d25fa9c,34cbe3ae), +S(d57648db,adf18b77,db185ffe,3f86f859,6adeec05,ffb86215,4b894a0,75776eac,a3f2fec7,7186d81e,4228cb1f,691e00e4,82a125a5,bbe9e6ec,45a53604,4932491e), +S(4de6cc4,d64d52c8,49c0e8d2,45409ba0,88248399,1916df3c,238be4de,ee2504d2,b389e7f1,ca72e9e,1cec2ed7,70f21441,590f0bab,1b963f1c,411f9bff,d3df03f0), +S(15f1bb11,78b01439,f26412,1d36a44d,b8333fbc,eabeb471,da2e6c1,1b8b3ee3,bf137117,35e10854,95acf3ad,97fe510b,33d6628f,e67d0067,499169e6,6c12274c), +S(badc76d5,481e77,9df71d6e,223c6965,9e9ecba5,8415a95b,eb7118cc,b1f931a4,475e47ee,115d258,3f0607f1,7542ccde,626e6d57,6ea884f9,61b41354,aef37247), +S(13015ae5,d770f4a9,75825bae,a6cbbece,78536dcb,78d7116e,d304aaca,199add2b,f5e28585,7a99ff0d,a4fd15e,8ac650a,98421629,aa102bca,25df3930,7e5cfcbb), +S(7734d2ac,707b9b53,afbd2a64,50c9b609,1905c391,958d7215,f92353ee,fd3c7be5,751d38f,ef48bfea,8fa5de06,8188a658,ae6c9c75,a359a4ea,efaac5e0,b5e859aa), +S(91814384,7fe2ed34,e9cc9c61,3fc2c67f,2b76a208,561d0e06,271b812f,6c678856,9a97f6e0,9888e076,93c9ebec,b8773485,c3c5d208,c793a77c,6984fb09,cdfd67b2), +S(98c516fa,2a2c8073,70ca9d7c,b4187108,ea345652,c8f814b8,b4a9405f,b48c2469,7b3446f3,2e8c4764,a8eb0846,4be3bc6d,f42b8d14,b7da65a2,ac96a018,d0831c7a), +S(5691d1e3,713302c7,48bf633,189ce032,10832e4a,9af1dbc2,abc3e99b,cb4faa01,d802e21a,fab84c54,5d665ed3,54130d9d,f7f18283,30b3a1fe,e30c2298,8b71654b), +S(1f8cb624,6440b640,aadba62d,c02f4ce7,a0ba9be7,d535987,64072fed,95c0d1a1,647a9dea,abf8247e,f46b60c6,53cdcd5e,cff0d1c6,88b7519b,a778f9ff,c894e1f6), +S(1489af53,94878f07,5cfb2e20,931fa3a4,e585d494,78818e4,f47f05e1,2be54d14,cd5bd721,4e535822,43270bc2,dc692ba4,c57e494c,eba92d4c,dd2e13c8,e24d8550), +S(66159248,2b2229d,ea70ff76,d2a5e70f,ad1905c0,9211e3d6,2d1d652f,ccd709a7,8f5ab85,57948aec,67e7b538,fa9c704b,ae939c22,4041e6e1,65f6045b,a6fd0fdf), +S(bc894efc,d0fb7497,ba70d654,961aa79b,6ac5a795,95537c80,82c525c,2c44c3a1,d5254292,ef0fb6fc,db587393,3b17adfd,87d13320,858ff783,75e356fb,b0d3415e), +S(f117d7f6,85457601,9b559bf5,f5bc150c,13363e7b,72123435,b441d98b,d169dd27,a8f4a23e,dd0d8f2f,8950c124,1abac43e,e629b0e1,8505c3bf,780ea378,20c8623f), +S(2a8d99c2,65a66a51,56b60556,775c61bc,b2a81a62,34896a31,16238c2a,b7716ec3,5e842306,efe11f66,5a049c0b,fe3ac74d,d72c5033,6dbd04bf,2a77b0d2,4d7ea651), +S(ea747597,1a6b6d94,2e368bcd,9979876e,afa4622d,313d819d,5e8291c8,2da95830,41d4a478,e0950bb9,e6595bef,3c197e5,d0f77ae,6340ca8f,2947fec4,70465193), +S(114150c3,fe8853ed,9f3e26f7,bc9f3d6f,aa50ba0e,6ae2d8ff,97924b04,dd9678b4,5530c22f,4ac30716,2b272015,460426ba,9602256c,ab735174,1a2fbbfd,cd71d134), +S(65d96017,c91a746a,656eb595,d39dc9bb,3476dc0b,1a1036f2,df7a4ea8,1846631,de46bfad,6999b108,1f358edd,7809919e,4de768f1,fb21dc09,4b248bbd,56b3dc76), +S(f2aec214,61c040c0,ebd18204,bc277312,732b452,266bfd55,aa071853,e458bea7,52a1b71a,eefe2c48,5ae2918,e236f1d2,1622d37,13b4bc04,36124567,d48cc453), +S(370ef89d,c39e637e,8bf6be31,63a4f76,7cebb202,c868647e,db18f991,977681de,e6d402ba,9769363a,b963729,822bd6aa,9794592f,36e54461,579ae53d,4c8bc4cd), +S(8db6356c,4f31f46f,961e4342,a1ff50a1,8240629c,a0decc36,e1bb24af,f6742e57,8ee033bb,96958466,15626ad6,736e9025,fb76320b,c2d0ceb8,ce3400cd,743f934f), +S(14a1a08,502510e7,1060f291,1316ee01,b1fc2bd3,c88eaa1b,656cba0e,8e3515e4,5a4dc536,b62c349b,c9bfc6d7,fb677231,1368655e,fcb9c89e,572aa58d,a57f08c6), +S(d530fc7c,4d5b4fd1,5f44ba0,c0f08f24,889b278a,93ee30ab,935fc112,5e244a58,39c0ea88,5984c2d1,d5119a28,7cd842ca,d3cb54c8,ab6aa222,c01e7152,98aad10f), +S(50f3c13c,a474f604,ca992658,bca68207,76acff7d,d507d63a,b5e18b28,5c5be81,685e151c,7d8fddee,6c9d8513,dbf167e2,c32dd70f,b6932397,38eb63fb,3e4f7afe), +S(c0a72dda,13174682,726ede1f,7ecbaa68,b4b137f6,d44298d3,4e17b7fc,10e19d4a,1e45ff3e,4a4239ba,4a897489,a265a60d,9a91f3f2,83fe2e75,9e770156,c9ebb3ca), +S(7121e14e,7e2a2c57,76b5702e,c83a845c,28785c79,9099a007,54b50fca,b4d9279c,e6b3ff5,ce62fa35,adf45e69,2ccafb91,b805d7cc,b6eff2e1,38dfd680,d0684401), +S(c0c01f34,ae41b8cf,e466b4c9,c6a5d5f6,14f570d6,fcbef768,a81a6c8f,5ff4adb,f47b0a41,1bca80a3,836c85f4,bf8a4731,3243bc2e,8f2ea47a,3b1008b,53caebca)}, +{S(4f20ce51,84fb2949,443286cd,8ea201eb,15248749,6e15aab6,f3ea2597,d4cbf47c,bf37770,62691c5a,d6c6cb8d,c30fd3b1,73578a3,bcac43c2,c8404b6e,c085c97c), +S(17ceec36,7fad4365,520599d7,62c66c12,5abeff81,ce7242dc,bde4e799,402759c0,91e024e1,e2147fe9,73091001,984dd3c0,9f887257,73bbbedf,47f00c7b,c5c9f626), +S(dcffc4a,5557f2a6,ac7a3527,5a8228ec,325ea0bd,d9bf52c3,8a78217,6bd716,87658163,dcfc39e2,ad08a499,898a1505,988d9b86,72b6d1e9,64e6845b,cb41129e), +S(625fff43,45337aa2,1efa0884,73a6662e,d5340470,a79576a4,362e30dc,bcf762d4,92ad0a66,d0bea2a6,d7eedfe0,e33295b9,3a656e45,9220026a,5ff3be8f,83184187), +S(410b96fe,7db23faa,7d123e97,c1a82a9,7b24a26a,80143e50,dcc6d9a9,1a6e81d2,ca0da356,dce88799,5f8cc790,64d197aa,6532dcf1,20fe93c3,7e2ff4e2,f14394a7), +S(8136e51d,ca68170b,136d40fe,76980b4d,d4f435fd,e38f3017,99de734c,b2491551,823dd1ed,de1d326,676649a3,9d5ba083,7c48e180,ecd0a648,eaffe7c8,2894e819), +S(64a67d9a,a7a31390,3ed9e348,e7300917,6c1d52d0,be63f54b,aa3ee8f3,f1227a52,ef770581,df4aa013,6d191e99,cde7f42,a14fdfbb,11e1b709,bb540100,1dcda1ed), +S(5fcf0465,a905aa8a,a1da5073,d524e8a3,30af663e,f4307359,c03a4c6c,c423dd9a,58641e67,fa821fc1,2307a66e,fe0129e6,4ace7c36,c3f5395c,db87667e,5e742a42), +S(aae6747f,ac3d8c9a,148009ea,c2d25574,39a8b546,455fb3a4,5016891a,f9372dbc,66084f19,b1d97f2c,22e182c,d5450d43,d56636e4,92651cf6,22772a7c,5b46d9), +S(377dc2c8,13e36bb4,642d1e02,cafce754,2ac6d9fd,c2212edb,5432674f,38e242c7,8395dc2a,39d3b1cd,ae9d7d37,d0c4597a,11f931d8,75c8bcf5,8eab03d3,674d5841), +S(35c598c0,7ac5dc3,7afe6895,29d815e9,406e2608,292ffa0e,7b24df65,3278d8ce,e793aaf1,45f538f6,c133309e,53cb5343,dc1dcc74,985c57f,27361c6,aae23e7b), +S(e9666336,6bb286d6,c86f425a,2d5658cc,1d733223,9ec2e9de,c8ab7295,4b329845,908dc533,b6098e9e,9b737e4,b96e7345,e635f591,60bb3df2,75e165bd,d1cc5998), +S(46fab0d4,7fc6586a,31cf861d,ff5e0bb8,cc12b60a,53103007,c8974ab8,204af703,845ab7de,7654fb36,618dbfb1,287534a9,2d43db6f,2a2cdfe4,5365b4b1,893fbe9d), +S(4d80486f,fe748d1e,f88aabff,76bb82c6,a45db736,76ee0ff7,d77cdffa,2c69d07c,2a52044b,d4fc6a59,fd16dabb,df35bb6,8057ad4c,292e87b5,528a3847,c8784638), +S(2c1d108b,f4945c0e,df62cc15,6bf0830f,7a45ca,1baa636e,9f759bb8,bf078a55,81e34495,d269afbc,1be39ce7,5417ebf7,d45decb6,eaddb635,4480a7f7,8d7dd34d), +S(320a08af,eac009eb,7f254b8d,395d836f,ca6ea527,4e2f309d,dfb7f120,2f1b3cdb,75269a2,41199c0e,5f1cd9e2,d102a294,2324a3ea,cfae231f,99ccc5f3,e0af00c2), +S(8b893fcb,9a524af2,6de5aa38,8ac3dc,2159817c,7062e5c9,d5c9e7f7,dd889ad8,cec6a5ba,481f7e3,88c1cab,c11505f2,39afa143,68977ed6,52ea2d6a,19d2cbfd), +S(ea89b95b,36cd5203,22c8e5af,7461f9e1,a054f23d,2720469,fa74cd67,3a52aab5,5325d16c,4b866865,2437b6b8,598b31c4,59e6101,2cc1b147,e0473527,5935ada5), +S(cdfea79a,8c16ce78,75a9fa1c,5b7647fb,ad641ffc,5b73fb31,d9354a1c,3c1cabfc,184c309b,b0f52999,2a3f6b93,77b9e6a7,6da6b943,d8031408,b71223cf,b3ba9100), +S(3daaaf0f,785a6397,c652331,630931ee,a975c522,35899736,1b7e5fcb,409880fa,952efec1,ebd4c107,b26a98f3,c6683903,a498c840,ff4a36c7,ade569e4,c899919b), +S(7cea5226,a56d21cd,45bfdbb0,7fea6670,40247c70,ef43da28,d1f8bbf0,6e4ef2a6,b03edff9,6a5f32c5,6f8f63f6,ba9feb68,f43cca62,391ea587,81396c7,5d963b67), +S(1f5f4c27,847ba921,c63cef52,8b57fef5,5bdb5344,ea67a23,c173828d,c59199e1,d37f6918,e0b774ad,317dbcac,75c82188,c8a421f0,ff5756bd,853a05b0,c95ef089), +S(36cd4da9,2a77613b,6417deac,1d9a0dad,1bf0e506,de26b529,7fffbd03,4a4663f3,ec1dd8f6,6226bf5f,fedb071f,7027f9d8,d931e6af,e378396c,d0d296eb,a63737e3), +S(9835c156,1be21ce5,db788f1,3c0aea13,fde6861e,97cb2cc7,a67fbd37,17eefadc,7fad454b,7372d969,a6e754ef,c73415d7,fcd4d589,c8e255c5,1adf5a9a,82228f42), +S(5e218414,d9c9f0ad,35ded20e,76a484a1,d41b3894,ba9d3be4,bcb4546b,371d0e4d,76966ecf,9c8f1c9a,452cf971,10ca6555,2ca59d31,21092e93,333bbd61,6eb9cfcb), +S(b105f4f4,40e7ea66,e3272da9,d6b2b76e,d00e96a5,6f95224,34ca0df1,5340c585,9e8fea7f,35bc9eec,f82ae118,bcb6dc33,acae587b,f37b149,1f8312e2,4ffc86d8), +S(81d5713e,a732b4d,98d085a9,75cac9b5,3fa65171,e5cf49f4,684a7856,7c24fea9,32480cf7,a0bc0c50,a4de8200,9343b524,4a0f2aa8,ce67b11f,4a5482cc,6fa00bf2), +S(d47b4f1,88f5e7ed,a9eab2e5,8ad2c140,c6278d63,517bfaca,8cfb64aa,cfbcc7ec,524f6580,9d3ee034,afb1e64b,1a0f8ae1,1e464915,3722e345,bfda9671,1b94a5), +S(16e85ad8,6a953564,39b97957,7bedd0e9,6e2eed72,76ba269a,626fbd58,447996c0,8bf74f51,4bdbb6c1,4de81a3,1ff12aa5,de49bd52,63a962ab,b777439a,47eadee7), +S(c299c6b0,6e6c78ae,852bd55c,dea35f99,d264cb5a,e836b77d,ab209ac9,c05201e1,a558c66d,c9ee7fa4,c777b0db,288b328,428b230a,7c53d516,522ccec4,af0ae08c), +S(63c4624,35ef974b,393b05b3,7d1c89d7,b0d8958,ebd541d7,584e2bbc,7235c795,1d806446,ecfc7bfb,bce099f2,6ce37a49,61b53453,5b65642,c0cd23f5,a4eef9d7), +S(6d36d105,ed8cc5ce,53f2cb69,8ab620f9,469a3e5c,b25bf6e6,d413f414,c5af726a,1b45a3cb,1c889961,8d273993,6a3affd6,233a66c9,4bef75ca,3a8fb6e4,ec05ffb2)}, +{S(abdd85c7,a2f8bc31,343382d4,e405978,3874c8d0,1405ef14,85047cf7,f0f71d50,d5a03157,798fe828,a03ab63e,84bb007,b53a5315,1db7af14,e4ab612a,736232d4), +S(31297c6c,f567267b,3c8d65a9,72afc752,e8525eb3,de2958aa,76f72e14,5ad903d7,f4735877,a6c6d89b,d1beb50b,edd1235b,5f5e5d0a,878e4610,e7d756c5,34813389), +S(64706e69,11a7d0a1,2e587c86,91117a27,cbfa64ad,1d5617fc,81e55b8f,64e0da86,59d9af3a,419957d2,b3de7570,15fd8531,a5d07430,5cfd7444,5e7e70b3,57e62772), +S(a4988ed2,89d8397c,f1b897d3,b81d80fa,92658ce,2b935f4e,e2e3f0f9,b193af51,813fb8,73270570,50f23c3,f8082bcb,563ee366,1f6b2af3,f631f5f,916c8478), +S(3c2769bf,af401993,595a01d9,9c72a6f2,699591fe,4b869077,8c6b5ee0,f172a866,f3e0d8b6,cff168c,95873f44,871d27b,df1e79a2,d9e0bd4f,6f90f682,538c1f24), +S(49d93e09,df655edd,19548fbe,affce201,4c6822a7,e196eb98,b9ddfad7,3cb70125,26e6957f,84ced17b,c64f710f,b37656d,31ba088a,98350337,8f7323cf,c57f0eee), +S(53c06842,49997cb2,6e5b4cc,5f166fe7,db0ec0bd,52639a27,d8fedea7,214a78bb,8a8dd3f1,b3081dd4,948255ed,dd178089,a0fa7342,1ea616a5,1f639057,34a489c6), +S(7a8e7d18,3f2aa640,d0e2ea02,4cdca5fa,1767d9f,9ae38805,5d38e8e4,a81d33b7,c2fb92e3,5556fd14,4a894be2,3d97c6d4,30872ccb,25e239c0,d959a24f,aaa77397), +S(a5221a2d,29cf3ef2,f066897e,4ee74ac2,95b34cd7,54390814,297537ae,abdf603f,ec0ff395,8c3a1d1b,5a379417,5a61cd97,782c9683,aa2c7c07,5d147db0,2b134278), +S(3f49da9c,1d62eccc,afc4b88c,814e44dc,8440341d,f347de1,fb60126d,59578dbd,c3cf8e96,2fa9478a,f1be08dc,961734ca,5021a65d,b1b45f80,78fa8e8f,d2813a79), +S(47b16636,f5a64b07,534be14d,6ae37af1,9da79b42,666b201d,d0afda9a,2daeb6b6,f1218111,31ebd87e,e1fd7c9b,d24a0a11,a12e842c,6c00f445,6a342309,9b171f12), +S(a7b5a8ea,1f23ff1e,c1768eaa,2fef0d66,b75744c6,dc925d3f,9068beff,d69b32f4,fe01a23c,b0e5acac,e60058a2,889f9434,9ffce6c,b24f4a3a,662e0079,99bcb690), +S(3e14e2c,e7044716,d42e9b6e,54cb0500,a1e4374e,18917336,e3205e31,4a878b47,18af982d,2c78ac23,818644f1,ec657da8,ad66bdb,3d5a9b84,3f8bb988,4ef8dc3f), +S(71393e6,746d3072,830299c6,c1244303,750742be,361c5f08,6eb314a4,76f1736a,dc30a7ea,9b644339,ce8f1fe4,eeeba07,5bb08934,8135e819,cb061559,aa14e42f), +S(37721b73,e6861f15,7993696d,aded49d3,78994f3d,e2b573a7,defc907e,d6f301f2,ee0e1755,d8efb25a,5cf4d783,ec847425,746fa442,d460cead,56e73a69,42561de1), +S(7803c663,509fc9cc,55b372e1,dc0fa76f,149a0ca6,3db4516c,4abc0ad7,5961e4ac,356c72f7,794a70e4,db3463be,eaa847cb,256c58cd,b6a7d862,fde4feef,d896a46f), +S(32976d3d,a3d033cd,c073b0f,c7d2f445,25646893,fbded1c8,1a0a1761,a8703206,5e6b7900,a069ce4c,65cd84cd,f290f092,2b936bda,af6ea40d,9c36a321,a7c9dcfc), +S(c52c7b18,b5fae5fd,a4e3597f,39c96b8c,6d6c856a,80f1210d,a1ebfc15,34850763,b87e50f6,20b66865,307d0747,a02ba22a,b310712b,cb0bab6b,963c589c,c5a208b1), +S(7de59c8c,3922fd51,68f4151e,cb783775,cd0bc0b,1185ecd3,6ee075e1,14e66cf7,688e2cad,e4d49da7,fe691497,412c9372,c67288e8,ca4b64de,308eabeb,723fda15), +S(ac49d6f3,32cda691,c345f099,667ace08,f6496126,830c39ed,877223a8,cedc8be7,267e6a52,5ddae4f6,7e05f0e8,52b9dfe,5101c491,64d791c9,82249937,c3a7b031), +S(5a92401b,698cc394,c9b714c8,bdcd92d1,20fa72e9,b1311839,1c383024,f469ed22,e29f2926,84c255a9,a739ef0e,5d13cc55,987f5b3a,5c6ed623,29431033,70edb4a2), +S(3609dfba,51616095,ab060e77,d6779025,6456eddb,f4b651c6,442cd673,f893878b,f85fa9b9,442050d8,ad9d9314,9ede8698,91dfc99e,c05a2a48,5854cbeb,55a6c380), +S(332bb85e,92c90a15,3bf602f,45dc33ab,3dea5ef8,7034af81,944113a7,4edc94d9,59b6c879,5f2a824,96d631b5,ceff8708,507db41a,375c7257,7533d8f1,461fbaf1), +S(16e9e054,916b894e,730d7126,27b1bc81,e7689efc,23cfeacb,a423362,df49d87f,303d0428,b701f1e5,fe8ae460,e54adeb2,d4b5aa93,a9c7d7ec,7b903cdb,20e440f3), +S(4e62ab89,1d4c4cf0,2c44915a,4e2fd522,88d75aa8,e22b7463,30dbfbca,97ed9515,a7c21be3,3b5cd522,4de0bd25,faa9c2de,5d6b2f50,b50a6901,b7167b3,c4def4fc), +S(649eedbd,5612c429,2aedbacc,b846e759,4a2b5870,f21452f3,1ac9e697,fc055db9,ca694303,ee206a4a,acfc4cb3,1aa9f117,8fcbe37f,d6bd11a4,669289cc,7c37b0a), +S(e858f72a,5fe2314,951ca096,8ba59760,e3d2a667,e76dcae8,c3ae2d7a,4721afbc,f1c7131d,3e2d0468,ebb89bce,700e0eca,ae83afee,75620938,60e1fc70,cfc7810a), +S(cd351498,29ccb1e6,9b18e35a,72a24b30,e074793d,aab4028b,1c5eefe2,b7b3163d,6bbd52b2,93b43cb3,a19f6291,69ba5b2a,59785099,16842093,1e58dc1,a040c57b), +S(19ffe344,69ba3e43,7d901863,3be7c298,ad8b65a0,49c30dc1,bae30ca5,97ab38fb,c33ca345,efeec662,96802e95,69f0f34d,12ceb64f,30fc704b,b77261f0,ce5c98eb), +S(8a2f772a,a38a5b55,a7081d0a,61bc27d5,89f9832b,1326a230,d81b9f58,4d634293,a4707a0e,a7bf528c,ac62e361,6f09287c,182aa3b6,6862430,dcfef3c2,69d1567), +S(e583bee3,1dbc8f0e,572eb18f,366f88e9,3a7a0484,b4299b9d,335f7836,a222636,8a4fae1b,be122228,be9d8afe,be223c53,dac161ae,ca77ff4f,e14d9c78,894fdfec), +S(8b6e862a,35566848,50b6d4f4,39a25950,47abf695,c08b6414,f95a1335,8dd553fd,15a1f76e,f12ee34b,f2ef43d2,b14605e,db53c3a5,e7cc7c2f,27fc252b,c1641642)}, +{S(1c185b5d,e988ae93,eebe0aa4,a98396aa,fff2671d,8246ce2a,4394db96,7a541ad4,dddf4244,3532024f,d225f86d,133b8156,3ea8c92b,f0ddc354,88e6a04a,d41da5fc), +S(addee173,b29de510,58dc107a,47fad47e,c48bf332,2f7c138d,51060322,571faacd,3890624e,c6920ca8,6a9aadb9,90a15156,799dd771,901823e4,9f3bfcb6,8bf05d5c), +S(9e20bbed,ccdd5c05,d683b2ef,852760b8,e246e5d9,6a8900ea,999ac8bf,5e8f12e3,9f28e5a,b4257f6b,b826d076,ffff259e,1caeda5b,7d34f658,ddfa0401,7cd4768e), +S(dc825d1,5f707c17,46920014,9d7be56,acf2d1d3,c444fa27,cefe5019,6f5b317f,226d4960,2f349d4e,9cd10a57,6bf01681,e4981cb6,4235d347,72a1e5ce,7694a20c), +S(812e2cda,3f473919,1f2ac087,7d70d0e0,2ca0551f,10c96d95,51ba4199,22780f90,c8d05855,6b6364bc,d9aff119,5b9ef26b,85cffa72,1e880b83,eed73cbd,d23b91e1), +S(aebb0870,76f5918e,68194fce,42d0b925,cfd2a506,359af62,146c8ceb,8502231a,c1c19605,e0456cb1,3e57229b,45c83ff7,c3695a2a,31908bc0,31b08140,9c2040fb), +S(af7332f3,3ec274c8,d34f47ac,fcbacf8f,7980cca5,7220012b,8fd5ff94,cbf3d8b,d439f1a2,89799dc8,92b7e53d,a84a9e82,7bf7bdb,7240c34a,caef59a,777188a8), +S(baf71cf,7851a758,12d7e09b,192741f2,1b5d2a36,6e31892e,e54c282c,81163a6b,1ef3bf2c,a81acdfe,17cd6b45,266241a0,22caf299,ed4d87cd,68d3d4d4,526b4d38), +S(615991c5,d250cebf,8c7bd1b2,969213f0,403c7da1,a3ba913,44fd0490,88c2474d,4f014177,12142cca,163f29a1,f5790004,32726712,93c2e87e,f46d2138,c14040b6), +S(b1574b39,26ff27c7,b2dace6,6108b93f,3fc75d48,478567cc,66bba29e,750c0c86,2759967d,8d05be25,3f88a66f,830dfb83,5139e32d,6f42cf3a,43b199ce,ab85b55c), +S(5fe92a7f,d1c407fc,967dbb19,e9fd4d,8361aefc,a3d5a9a4,2f8237a3,458e5e90,9b89ce35,57d469b6,9b9034d6,cee93609,c291d023,d1d9349a,d9bcf47a,aed8b2a9), +S(d65b0a5c,41b2dc6b,e5aa87e4,adfef952,621f9d99,550e424d,176ee180,65f666e,a76fad91,3b80b0cc,3d3ceac3,9a465cb9,4d8c79de,92adf9cd,7a4efae7,c85c30a4), +S(61d7de65,fe34ec4c,f82f67b1,75887263,11683263,145cbeae,18ed192d,14ced48d,effac049,d7e5412c,5052160a,6d1b2230,7157669b,856af0e,e3e46a25,2d2ee19), +S(9a77de66,5165a9be,3dd2758c,39aa7a14,1f052358,fbac634,5ea701c8,c93bc4a9,1044e428,bb381024,70108d56,b8b3e3bc,7512300c,5a6ae44b,93b2098f,a13fc023), +S(4ccb2426,b6eed0f9,651f80d5,72b23e78,d84d6928,57648077,3663216a,bc8a418f,1840c,bf5ccdd7,19f7fa8a,33e7151,aa351d,2f620972,6ec67d1f,fdada8c6), +S(53f96bb7,86516e0f,2ac7611a,1aac61d3,cfbca76a,9609fe,e4cae036,52f68271,97e3acbc,468b777b,bd1c8263,5332dcc4,b08b9fb1,9608fb35,cd51e49b,f09d9087), +S(395253a1,b6a349a6,dfdb0d6e,65695572,2a597411,fdea9294,6e48d107,596d8ac8,c57110d4,dd0d35a7,663fb3aa,e15d8c4,dce5cb67,d3173d91,a6ff7ea2,1bd28107), +S(d7becbeb,c47d0de0,899ffdff,8620124d,b29c8e5a,fd71a0ed,76e0df76,bd4e26e6,d8b52fa3,e16e7f19,e925e769,3b5a731e,18f3163b,1ad4db34,7f878381,da75fc15), +S(fa3afae0,4f8c1fa2,778446af,88e29150,256b0413,d9bfeb44,45288e41,29be15a5,9dc76b39,574453ab,2d46cf23,ce8cdb06,cbe7df15,d03fd390,4470a86a,822028df), +S(da56da00,dfdd788f,90a12219,db03cac1,403efef3,ae706031,e153aa16,b3a52eb3,1012ca8e,ae20efdf,41c77128,93fce97,fc66b187,caec55db,7aaa81ef,cc12838f), +S(f07866f0,cca3474c,40e7fa59,26df41c0,e46fbfce,faab92e8,9ccd1170,3ccf79bf,37ed66d5,5e891f4,e644fa04,182f34b6,1f1aedbc,d2a71aac,dd1523bf,f579dace), +S(853f72d1,edc4d953,348528b8,3656894d,67032333,28a16801,64a84511,15c5e968,197737d0,de83e73b,247d861,510ac76c,3ca214d8,ebbb958a,74ce1c31,5e715e87), +S(7c7eae74,dce7ef76,9ef0ce86,cf6ac861,ffc3d4a9,6313f379,fb2c0325,daa91aba,131e1689,fb017e15,e869d858,2dcfc4f9,153d1e8d,246fd613,b3922302,5b5c3767), +S(56028652,bce9dc6c,c8b4ad5c,f9f222c3,412e5bb7,8d556225,2c06c2e4,25a6e31a,2aa8e093,d8653f6,2153972c,e54806ba,666d49ba,3787934a,a37bd65e,79374ac0), +S(2eb98b01,550a00dc,59d280b0,71e472b5,a65eea89,298fe4b0,9f6f0e07,9315ad7b,74e22fc5,3daecdee,6a0b50be,e17f1d7d,d9481e77,28778957,274c8d29,a0d89fdc), +S(7268b61b,f65d73aa,37766a99,9960d998,18aa4ef2,ae8a97b1,db8476fb,32f891a4,824e99db,3157b706,38573513,618f6901,ce1fcff8,f25019d7,c5c45bb2,f3bb4d47), +S(cdea8771,4a764e3f,a94e7356,879b7d9e,da7c5b6f,28c172a6,1c0ab012,9b9ddd7b,daf49b12,34ce20aa,263b4349,f9f88cc5,1334db26,59b7c587,212f407f,cbb2644b), +S(38831af3,193c8860,690a9d74,cc0079c0,9e3ae0fa,ebe0da02,67ad6e23,99059d19,be188500,5193f11f,e34e70a7,e470cedc,902bee92,e7041403,c2f1ae53,7a8bb077), +S(df3acf55,bc6d97ce,34ebeb46,34fe1010,ed3d6d6,383c11a7,53a93123,e9c8381f,94c22735,ae6f858a,59f663e2,12532e14,4efe6a81,981c7619,e5002968,dcb81df5), +S(a8b08b86,4946ac6d,a101eb85,ee7bdf55,24282ca1,a9956e4a,eeb1afe9,87a43ddc,80ff0174,375c95fe,cea6e00,20f17123,5cda4bba,d4ef893c,78ffe37c,205d5577), +S(fd9941ce,e1c26864,248f7035,352787d1,aba9e93e,f5edd333,d08c89b8,4bb9dc8f,85be138a,42bf190b,921681fa,8777a619,878d4d02,11016c72,8bc151ab,1a687b5a), +S(7e2cd40e,f8c94077,f44b1d15,48425e3d,7e125be6,46707bad,2818b0ed,a7dc0151,6fa48af7,d523054c,7d59e574,cde106a2,776411bf,5111f7d3,65c43ac5,df8ddd68)}, +{S(282c5bc7,5b9c3f76,73e244af,29f22b80,c171bcac,d7e39b4f,ac7ba6cc,656d9010,e8db2eb0,a56699f1,73d5b5f7,99d39e14,dde34648,f159ad0d,c1c7767a,19ae72aa), +S(d5a3eb7,cad9c548,839ceb7f,67145e0e,96c60d8d,68415f76,73b73700,5ce3a8b,34ae4e12,355d1df1,25149efb,1a9050fd,490e251c,4404fb37,31b6dcc9,e233b9f1), +S(68718b29,86197989,3c5f7b1b,48abc254,13bd23c8,96c8828,7000ebe6,6db742a2,bef9d2a1,bb596fdb,3caeef3b,4d950568,8a94b436,4fd85f37,30b20de,b9e9a4fe), +S(a5ed1709,7932011f,9a597511,a526e61d,f22d0bd8,ae3e15ce,655820e6,b1ff1238,dd6dc7d0,81e70b57,4f235c10,c7c3dbed,a57743c1,15e6fe01,a20ac751,34cdace), +S(ec37904d,9662a487,1a471d9f,778bdef3,430df9e2,26fc42e4,7fc4bf5f,80e3a9c4,8413f2f,1ed55d8b,8448e336,ac9d1418,c48846e2,acb43509,f1a3d935,8cd18ed6), +S(b09f9c76,1cbbb685,f695328,61c459a4,d2b16989,3cbbad2f,dd49c87,1d860db4,dbbf9049,31b18454,21c41f2d,2185e3d6,c8f55dad,f1514ab0,655c856e,3391278e), +S(ed1a335,48864e9d,b41abcad,3344f4e7,ebe57841,9371095a,6b95fe4e,ae59edd7,d1146be9,83adc77d,bd9c107f,3092a9c2,9c271248,d78ce913,7831127c,c403f44c), +S(d39507d2,6ba377f5,c7116aca,78df331d,a795cdfb,54e5c912,8558c0e,997b74f3,fa7971d4,32cb5a44,589dc705,de28ad0,382206f1,6e11229f,86ff82a,efef3131), +S(641dc311,baa77b14,35f408e1,528445df,53c5ac5c,32803a3d,84e8fb66,60d71d,2b355a47,76980bfc,8a4e0ac6,a3bd7b02,a6b20ffb,f8650b16,89010456,6953e49c), +S(c3dd73bc,cfb744bc,57bc95f9,3c260df7,7f3b7e74,9e4a5237,f3865f8f,f0c89489,15d58dfb,83654754,80e53bb2,a1ba430a,ce213c38,ea71c7b7,51b4143a,fe2bd124), +S(3f883fa2,e834df1a,6e9b5c46,b663880e,9a0b42f1,891b92c,eb30600d,5641813e,7acff194,a5fb76e5,bd3d8fd4,2c7f07a8,3a991ba6,7f0e4edd,c55e1d8d,3025d590), +S(70c8d4f5,21d808e7,221bd5c6,31f171a9,5e7aa358,4477068c,2549c59e,228688bf,52badf20,6106d5a8,d7bff921,580eb5f5,3a53aeff,e0369f9a,1bcb282d,7b4cc26c), +S(ae08db34,874d39ff,bfb9c92c,5e4253ca,7ed508fd,d12841e9,63600461,b2b3a0e1,dc0504ef,d209be71,381eefd2,91508120,fb6ec1e,df62d24a,cb1d77a9,4eebf1be), +S(627027ad,4aa88477,c6240517,87a25b88,7d5b98f,b968221e,8e45d584,3db6e0bc,34b553a7,c6ac7004,69367afd,17c5eaf8,7605ca18,6a57667b,650fd8c7,18ab76aa), +S(573ef2ae,72ae8fd5,eeb0b720,f8967b44,f7d9d96d,c8a4825c,23a3dbed,fd2bb442,264f508e,efe5e0a2,55e55a54,bbf739b5,757d0a15,994ea9b8,4e139738,7c484786), +S(28907848,cf84eec6,773a384,ce5f4a5a,24c8afc8,606488a2,ccdeff25,6f896dab,ea87d4f,41df8727,2fe84537,d11126d5,62618bee,a51008ca,895a8375,4f05ec5e), +S(163db4c4,536114f0,75521627,c61f62d9,14214d64,ac9e66b0,d85b9991,62c54c5b,7ffc24e1,11c0c845,1c574e9b,e4b56610,696d3667,a6e6abbe,9d1a5ea9,4122aa1f), +S(2ec11f2b,71ffc28c,fb5e779e,7739098e,c969bc78,3cca5a22,77d2bf53,e6574d1c,c5e9fdf2,89a3090d,e24d13a1,bc8377d9,de0bcf4,63482ebd,9620cbdf,8b238fb0), +S(30549ae0,9a46820f,f49423b8,9c6fdd48,703132fd,ac166dc9,90609a32,49039f0a,b8c94b4b,36d39247,732976e,fc16d500,ccdc07f0,d7b97db5,7a1d9fbf,d8cb5d2), +S(98685f94,a043399c,89e74674,240322ac,5a595bf5,41aaa44e,d781781a,10fe9225,4506b1ef,7561b811,53f44e8f,325f9222,e999013,30523885,d8c59864,db13a3ef), +S(9acba196,3014ea9,1baba28c,e273c6e5,b9a2e1a0,98216c3b,194a0b56,dbda7db6,f0a3358e,eec737af,2e313262,b29ddf6,2adb9e97,9f56def2,65102272,6b976290), +S(e81e91a1,7aeec75c,19df0ef7,fd07ce2b,e477c031,179e3f99,4ca13857,e2b5ff93,65236424,aaa8b6cb,fdb2fb20,46ae3c3d,839d97ed,217edc6c,c774f889,d2ce8b45), +S(61e60aeb,821c3f80,b53ca78,2c3b4d21,960eb0d2,c90202f0,a5fba651,1725ddba,b029275f,690d10bc,b52e8bb2,acceb071,f07834fe,64175088,a97e26f9,8ff34432), +S(a931c410,8fcb4346,6802dd4a,8ec2cf62,cf4c5558,8129299c,b3a87e95,6fba2a34,c21a8dd1,43d4a639,339fec49,f56d717c,658a55af,ad72da1,c754fb9a,117cf6e7), +S(fb5c106f,da32fcfe,ffe9b5a2,7ac8cfd8,d9a73da1,5fa6340f,e09d187a,7a83cb88,a3f4c60f,90003375,11c39100,ba4c4721,c6c138c1,cbae09dc,46d1a1d2,5baa95fb), +S(dc25e18a,18f0035c,2a05e80d,d6b38830,7fb3b176,a66ae451,8c5640db,7540dd24,3ba83beb,3e6b29c2,97a0ead6,148f9b93,711556e2,e5fd513e,ee649228,c62d8f3c), +S(ecf7b689,ca03b840,739283e9,c3003a01,65ea3f,3bd17e06,9260c0e9,ad403273,5e0dbad6,47997fca,c0d7ba2a,170a7954,67036ae8,e61dc532,b5fe184a,deb8a7ea), +S(263e593b,10c982d5,1bf89ec9,71f6a3f4,60e53bf4,cb2f6af3,2381214b,2e981bbc,e255bc11,11470eb8,894ead67,c618d7ca,a6b76ae1,a230ef05,3830d028,4a7faf37), +S(f79781e7,a4137ac4,7a9a9d00,9d239b37,6cd0fa3c,b9f5de46,8cba5a11,ffcdd69,d10ba78,896e086d,5e25444,165e79d9,7b3d485,1a448e03,26d8906b,2f27745b), +S(a4d28024,11f577c1,c5d08fbc,457a46bd,428f4d2a,b29475ea,ef622876,593e49f0,e4855491,ac0342b1,dc804bc2,7ae23877,82eeaf22,52874a00,4d4e0d66,b07b434f), +S(87195a80,dc83be4e,cfc9d4b8,29725cbe,11101c26,13c98f2,641753af,1ee840f8,f9fce233,66931c51,4ea09224,b565dec7,22763d8f,6f572057,fdd7d96e,9811289a), +S(210a917a,d9df2779,6746ff30,1ad9ccc8,78f61a5f,1ff4082b,5364dacd,57b4a278,98f1e4ab,af4a1a84,85c6417e,7298c82,c87619e5,500df403,80d8ec01,f384d9fe)}, +{S(6c16768c,433a000b,adc47b10,ba4e132c,f5480e65,ae83d1a6,8aec34d2,c00c76dd,ca1a47dd,66c2d74a,ddb69283,2ea289a6,ae679669,edd80bdd,4ffdab2a,defbb542), +S(f757e860,ed04db61,594bd647,5ae81b7e,d6d2fa58,80cad10a,7756fa26,810b8543,f2aad599,4e491e02,9b1ae256,2c90912a,1c9aa6cd,dfc2331d,a0069a79,861208a), +S(d9f269d2,9aa777c6,9989d706,91403dfd,9025b491,ba03ddf2,dab8c9,af7dc764,1b39b85c,cb4749fb,7f47086a,ce63924f,3ebb4213,af5dfc95,fda796e6,c6b0b8b0), +S(d05e14f6,fe6ca50,a23e9339,e449f771,98e842d4,80a72d5f,8f5e4c06,43547cb9,869e3bea,6b19e0f2,de83fa8a,e932086d,d66e838b,637ea603,5f0fa081,5912c8f1), +S(9f723d81,1818046f,b7512abb,faeb46d3,52d8da9b,3abe819f,3861f9c9,963c583b,37df0657,3f2bb428,6c8b3efe,f6941e2c,4e48d90b,931cd0a5,78a4b52c,6581ee7a), +S(e65f0b42,54ad9df9,681c0db,3428ccaa,11194df3,9e837aab,4564e1fa,254e6f97,43e59d10,54aa35b5,80373e08,cfc02aaa,4f581406,58341e67,7e50977e,5bd893dc), +S(605d61db,589fd91,78a65cb5,99697001,73afca81,23f663ac,5fffd0b9,8f5e7a64,a976a9d,a47745f,447ad4dd,7eb63875,c228b979,a7dda50a,d994df7b,545d0ede), +S(43298aaa,faf20e9d,c2240256,493ef19f,5630db6b,f6376e4a,356bd034,98f1be7e,737551c3,653af1cb,4f8c1e8a,347f50ca,142c03e0,29007f29,c76bb763,b52ed053), +S(8afba782,d6373f0c,54734f1b,4b854e63,bf2a3b4f,23f57a3e,6c2eae86,25c691c6,da3054aa,228b9757,b7321da0,64516249,652fd814,15017584,2c7683ce,1a3638a2), +S(3156d359,e01d64fa,9c8fd8b2,c47c3492,82dd459a,fe89d94f,35906da2,c6d0208,85a23f48,f0a7448f,c57ee545,3978e2cb,6f2bbe54,864477d8,a63775f7,7ff7289f), +S(88e1a44b,1e206eab,49fe97af,30be5e47,25e1011f,312a5222,e9e80819,b3f26357,63dfe52e,10317c4e,227b2a5a,d61b713e,2d93aba7,f0a51e0,b5621191,40c58ded), +S(d10de96b,f2e4a6f8,78e0f37e,15569f3c,b9717a38,7fb98928,6d65d171,4b81b301,2c0a46c9,6a2e3884,e7f3b146,acc170d2,6d12b959,4b75a901,dd535016,f0355ae2), +S(eb36b865,812ae4bd,7893e50,5aef6f14,bfc90c1b,42e75ea5,91615aa,a2101784,1523537b,790b2a61,fb6696d0,a622ff31,efea1255,e1dceb86,763985e2,6c5ca8df), +S(d54be697,e41396c6,3d63f96f,bde9bba2,36ab1649,3c156159,3df81d69,c906fe60,89de1769,433b5678,1f7a2206,ca98258,20d0c7dd,a6d5b672,f77029c2,6bb59f33), +S(d5aa72fc,9063c2f8,bd0fec97,da30dcd2,a5b36aee,7894463a,f7042795,1998c979,ed90095d,bf2d3a67,2d2f1a0f,9737c4d,e8f3e773,c04b77d3,a2345dda,ab662199), +S(ee8cd53e,8ab64281,b5cad323,f03fd06d,7aa166eb,df9185b4,8d0eb0e6,1bd0bc61,4781263d,fc518e4,809e5ea7,7f9df238,1ee7b6ee,ab25c1d9,5cbf3fce,72fdd615), +S(ddc5e95e,2a46736d,9bbeee74,74364bf9,e1d2724f,c43522c,cffa05a8,7d078be9,60908fb,809ae964,98a26cd9,67532df2,409491aa,73c46803,eb58861,7ad86745), +S(ae503a2b,b6250ff6,6ee615d8,41cae4e,751160fe,aef7f33b,dd1feaad,ab236b58,6e53d2a8,8f09f78f,96d49a6,2f98773b,a282b575,ab6e24f8,4d604c3c,8583a66c), +S(8a502d08,bb3cc1da,438c5780,e2120c50,12c1a972,8aaab6bc,5d908b6e,2a83dbdb,fa02e62b,85d7de78,8cf11d9e,ab406523,bba1f912,53006a89,f3a491cc,dd99575c), +S(b52891bf,5acb0019,a8d10b94,87fa47c4,22f83a00,ef539e91,44bd9f7a,d5075716,ae58653a,b167a9e4,b71eecd7,4f4a8786,19c19026,29c0018d,9f082e7d,5920b2f), +S(176170af,b40a3e79,8a88b98f,fb6c578c,d1ab56b5,b7f4142e,b2d84a59,1b009f97,6e1d5682,36176d58,ce5fcac6,4d4d2885,5db107dd,5215c71f,b4076aaf,d31c5d24), +S(27359f7e,8d3e3dcd,ea35f603,d8fb15c0,bd63c08c,3ae4d2fe,8cb6434a,ae2e716d,a0d64207,8fba00dd,4683d597,27f3c67f,3c25075d,802a4ea8,eb08c20b,47a941f9), +S(1e9d955a,2f68478,5227e866,491990a5,62c802ed,1b106bb5,42d02d29,93542067,fbf5f466,57707b3,3f116a23,fe5991a8,90a9583f,fd063943,37a19aa7,e125ccab), +S(b5c4c10b,1b0e0813,37deef6f,c089d2e1,ee14da2d,cbb48e6,74b7dbd4,429e22eb,fdac245,b109947,8f6a53a2,8a1ec4fe,da43b4a9,2ef49e25,8f9296c2,88c48378), +S(bd2f651c,ff6e614b,1d6535cf,c3a2c5d2,da5307b0,1cbd3f48,655623c2,55503916,3715b0bd,bcf29d97,63d7fb35,f9c5b54c,769a863,3517a2d6,8dde74e4,c4277779), +S(c4c2a8e8,f1e257a8,fcd0b11b,30635c5e,782fedcf,f99b0b95,828e1369,3ee0af73,3a08abb4,777a066b,49ec4c01,aa5b0868,f100a473,e555def1,7c5a9d84,b1fd9ae), +S(4aa77ce,15dd97ff,47c1125a,77bcf0e9,d302b79a,e8a919c6,a875e5ed,eab8c2ec,31a09dc4,89a90240,334836f6,302d7e81,57f19762,a9b5f727,6c276e63,560a9d10), +S(3731162e,66a8d2d8,ff4df3e,95950103,f5a03f9a,86bf37e5,605746,cf4be846,e19d7835,10af5daf,724be4b1,932dfac6,23899ccf,7e3e58ab,5bf3265c,667cbf28), +S(6e2114ed,297ba44f,c3926603,bc03a87c,af3e9f2c,8bd84e64,afcd9846,bd9c8f0a,faa6e5f3,3d90f91d,82592af0,7f3a26e2,f6f4138a,2f06a6a1,4286eb71,2e95cf94), +S(50d775b5,f72d186b,266a14e5,254cb5aa,49fd8633,81c36b09,842632d7,ff004130,cbfe11c4,f0b15aa8,3ae8dbcb,9feff9c0,d68a26ba,11095b3c,ba94739a,2091bbc2), +S(8f3ccf31,f8b74b9b,624a5d1b,7cb1096e,202fe5e7,233777aa,859864d3,775732c0,980e32c1,d2c61ace,7610b926,6831ac27,56f19788,ab7a77da,18c421a0,9a46bad4), +S(24cfc017,6da2b46f,a8bb5bf9,636be1ef,fd7e297f,29122fb3,e84c9ab0,c18ada5f,14007044,f8639e59,67978eb2,a21256d8,126a635e,5b07eb0d,97059ec5,6875a3c4)}, +{S(6efcde8b,e99d9ee8,ee0d6b8f,a76584bd,5deb67b1,415e729b,48f3d41a,f1cc1386,4ddcef4a,a6ad5be2,d1e83449,9eca4a8c,73219f80,464a4a9e,ebb7f3f1,b70c9fd2), +S(24fdd052,a1e535e2,4eb79ffd,f03093f8,5778241a,b845b548,31b9a82,730ee3e,c6ff8ebc,7edfd9df,9b7410a,7f54c93d,ff0c682b,152bf4db,1b79c0a6,9889797d), +S(aaaf86ed,31dbf395,687c959,6c445b6c,dcd1fe7e,ba2aa13d,1bf41867,dc87b30b,582b9683,729be5c,85fa83e,2ba2abac,e3037262,2a24aa35,c7753312,1de2fb93), +S(23930d0d,2400db1d,56525bb4,67172fe5,e930bf86,21124fa4,6c5a421e,10b059ea,5e11f202,beca3d5e,dc9b282c,2e86d5d9,30f8f5d,27a5c4d,d2cd6dde,6d1497ef), +S(76ad10d0,bc92ad8f,55b665a1,8ee84e01,2e92dcc9,37e0c604,59bd6fd4,ded2d9d2,d4ca7386,ce0c4c5,fd37da9b,eb8fb040,97d98891,35a5ecc0,320dfffc,95ed3c10), +S(10b324b,e959f0c8,c8a82142,4a8f87c1,fdeb7f88,258e1021,c9cfaa66,b131f3a4,590e672a,daa8d547,161f635f,153fa12,b3500694,677af3f8,90dd4ca6,9620bb56), +S(afdb2acb,ebfdc11b,3577177c,d8bcde00,65151495,79c6ad2b,f7386275,a9314317,87d7786f,5ba775c0,ea47b141,cd0d4274,c7e58634,b64e4c58,f7f0c595,5a307250), +S(574cddbd,59b34df5,30f5dc4,61884ebd,1c867ed5,6cb60832,4a11b1f5,29ebf733,1bfea852,34256807,1fdb4f5c,485caa73,7136e3c3,b4b8a39a,389d7dc8,724f16fa), +S(97ffea2b,5de34e1d,495ce082,d0097b72,e7daddb8,1cb622c,2c14e814,bb0ae278,45fd3d2a,9d1e6530,61b4a356,65aa9e70,43766950,622e1c25,2baab265,6d4ed95f), +S(de627f6a,a7b56d85,535c398,80d0276b,b910ce4a,6066435b,512e5e0,21ef55ef,753033a6,ef89f053,c0e662c8,1557e6cc,d8b4c8d4,5204f5d,e1c8c742,72b96277), +S(b126c35a,d7993bd0,164867c,58c88421,d2cddb6f,d16a5966,7d9683bb,1b428eb5,a9ed1bb9,e9eacf9e,e712bcda,be629143,ad0e7652,82cbfab8,e586cb07,131e5b1d), +S(847b90cb,8837f488,ef027a05,71b2be6c,620cf86f,ead235ad,e76e3408,d0dd1073,9a2667be,6ce36e7b,d76117a9,fdb8f1b8,7c7cb45e,1a03f53e,7b32bc63,6f274b4e), +S(8ea21457,6f1bc2c8,fbee9065,c2cf5c3e,7a3b9fe5,403fb980,96040c2e,c6fe1488,dd75b454,acef4d3b,1b355a63,f0cd17a6,66aa9e65,f1262629,f0c7d1e0,33571b58), +S(9e11bb60,ba4b2d5d,fe53bb9c,598edb16,f3926bea,1cc90eb4,3e05ca34,e83f1896,263d7ea,50d83b8,791fc911,a4f73cac,4d42a09a,85f5ae68,86cb268a,fd562dd0), +S(f741856e,f353a7c7,17db9a13,4ab4aaf9,13c1f7da,cef08bfd,6f81dce5,b1130e20,ee63dd2f,48e15f68,d1acbf49,705fe010,231e26b5,14146c47,1a689960,d568eca4), +S(671ef05a,410b41d9,3b092b04,e523468d,44837d2d,26dba670,27400715,eeefa2b5,686d318b,b49eccbf,40dc18af,f1938fa9,b16d4d2c,c19dd2ac,47c7830f,89b8d55c), +S(59ea10a1,e5bffd6,a34593f4,b986e37b,5294ddbc,60d92906,52c6e9d5,75f88c55,c0a2eb5,6d04ab99,abb5b76f,7b2b55c9,c09d44f3,3785e3d4,64554c3e,dc7a334c), +S(37f2c7c5,69c6fd15,9b721d8b,8d40138e,a8873b6b,452af0a7,89a50551,e9703c1e,d114109f,f9e6d7c0,c51a542f,b2e3ef5b,74654bef,5eb84aef,c87f5096,2a30c078), +S(1d280637,9d77e509,126a440e,b1e56f1a,8723728e,97c92420,5ed13081,98c868b9,85003989,93a4a600,dfd0f092,b13a1186,c1c52dd8,8fc8eace,9bd4f1c1,b47741d8), +S(39aed6e6,a123061c,228d3d1f,857e0c9b,29b70cdc,549b4ea1,9fb6802a,8d8beacf,6bf86967,98e3dbf6,75865a1a,b86d5bbb,10f16e8,4f9104a0,87602c,e6946aec), +S(aa770804,4a996b1d,5bda074c,941b30c1,d1474da6,47d7c4ed,248d3a9f,c3c3c525,10ba5652,b20482f,fc2434ce,ac185d8d,af6cc6e3,61e77d3f,258abc0b,55610879), +S(7626a96,9f9ef188,3ea82737,83e5571e,4054fb73,6190977a,299c2a05,d29f60c7,172d4618,e5f88055,ebfcdf9f,55267ee5,cdf18396,1d5a2a22,55b87ba3,c7d7d2b9), +S(1a550684,d1195da7,c4b09349,f149eae2,5a1ef23,c9a81109,115d93e4,c98cdbda,c31d7dc1,b7efd019,c491010e,30f90ed8,7503c4bb,1b37fbce,3dae199,6609e3b1), +S(8d2306d2,dd8c753f,2b093e62,86fc282,ba3e1dbd,7b4ba101,83d1070e,d2d06e67,97dd14c2,d2c1d147,486a3dfc,d608ba28,d63fc03,251a106c,9811b088,978e3a5e), +S(f31a69ab,97039589,940851f3,cdc98bc5,d400ff93,63794f81,4d88215,4f00db99,56e510be,7f41b009,89792401,13641590,40f5f305,f27fe1e2,db1cd7ae,887ff5e2), +S(ce96b3e9,6eb94b7c,8bdc7b57,efd2186f,62e23e72,f11337ab,be7405d3,43b4d762,cc0dc898,33e7a632,d0fed52d,487f2c60,96c69664,f698a71c,3f7f8a29,4f181add), +S(bed97e25,7d31b5fd,36b41227,462d9122,706da670,d432ceff,5d37d83e,fefda56c,c0cfe30a,2c3b3074,1af492b6,e3797c4f,3b00593c,6806e2e2,f2cff401,6e877ff6), +S(923bc6c9,960f6e4d,ca2a7070,6d160e19,83a16b6c,8535783f,12c5ac69,4aad226a,c47f08b,6b2056d2,8e9f119,9ec6d5ce,b48801b8,7ee56280,d6a48352,b2b42b1), +S(b3cb28fb,7465cdda,85823dcf,819400b,357bce11,23d9229a,eddb8262,53b246c3,cf035ed0,b624dd68,8a31eb5f,3b28e83e,c0bf9453,649dfe4f,44078eac,9345f2a6), +S(c69aa2b9,ab3c5e45,8713a912,e7f95bb,4e5498a6,d4090323,5cfed1c9,c2a60709,2e95e198,85637d55,744e32a7,98c02c7e,b29f3bf5,7cf7c870,7cafdf41,f6710f0c), +S(45996af,5795ea6e,43e0fd29,671e119b,8b8d6ad2,4eac90ec,d27d5db1,b4fb6a39,2c0651f3,1c7d93cc,98d79d7d,f21110fc,8c1dd74b,f1ffefac,a3d52484,f8da40cd), +S(264559d8,7829256b,ed116900,d82d0c37,9f0e4d12,53c68e6f,cf2d41ae,7cddab8b,861a42e6,d92caed3,108439c8,fcbf8d28,8579ce50,c6350e19,3609b4b9,ffe217bc)}, +{S(ac13e0db,846df259,fc38d6,3b0248ec,9fcfa8d4,bcee368b,1f4a66c6,d41f9163,6721b0df,2ed06fda,9b485cc2,aa56f1f3,3a913e99,f6809577,95280451,9ddc96ec), +S(b6b7227f,228da269,a0e5640b,8a2cfa34,555ccdec,2243dd0d,4b2da0a9,b4cb5e4,6afe41f9,dc129d28,4786bb76,17786c8d,42597435,240f998a,f970620,90d32059), +S(460672e4,4f2768b9,842a98a5,ca8b90df,7d9f52bc,3fa2665c,4272d7ad,5f48b992,6d7f8b36,13b38fa5,80ed1d4a,21d196bf,be491b46,49c96da8,342441d3,f4af4ca2), +S(1d3d4ab8,b7c06136,8dfd612a,25f04016,2bd3f6cd,cd9cf58d,c11647a0,d28b629f,434dca08,17bbf964,eb0a316c,b2b0df20,eb2e965d,c4d8d795,1d4a6e66,5ed23d38), +S(9c5d6342,303bc7c,73763cb9,2e3d7069,7d913f6c,1a6e2f47,39470da3,22b7c1b,825c1a54,395b9b41,ccc2e3b5,3fe1092,f04c382f,b2ee3a29,fd59e255,5f22fc15), +S(5c751285,a4b55535,fe24fe27,568868f3,afb43cf,aad1d2b1,c6367daa,ac9493b2,e2388ab4,414c4e4f,e34a4c78,c869dd93,7094ce2d,4f4666a8,2eef8047,3b681fb6), +S(8c1592f3,8d73e277,d3c18d4,ee3eabce,32e86f92,2b27c2f0,1f50509e,74dbc211,399c9507,43cd9e7b,200c255b,bd25670e,cc111462,2d5dfacf,9dbebdb,53ee59ab), +S(85320e36,5f40235e,621171d5,c8008845,890f521b,d7e2cccb,88c7fb7f,a08200c,96bbe8ec,74b5f1b1,2a6ecbee,2aea6f0c,b6d0657,aac3556c,ddc4e46f,17cd31f1), +S(5fc21f20,13403705,687b8ad3,387a725a,f2e6300e,13d28403,569d4cb6,5dda7f34,bb709fbf,be95aeef,c00846b6,a4645b72,dbb4e1ed,866edb57,7bc5d9a8,2b774b0b), +S(fa40e658,588f8a5e,29d380e9,c1a6482c,888f53e5,e331f8ed,9b1273a,56d094e5,5486cff5,3b7baaaa,de8a51a6,1d1a9255,95ecbea3,39955c0e,172de4c3,4762eca1), +S(9f87d04c,5fcc48f,375c40af,3197c28f,c62cf3c5,10fcdbde,5aec79a7,4e6a6bc0,9a6cc172,23a770c7,a03b5333,6922170d,e9409f3b,9846b9f4,41832ae1,f70f5c57), +S(bb66dd5b,2f88786e,736b50,e536a0f0,3d59b86,511e95ca,1bab2cb8,875bb187,f8215527,c76a5af,e5e76a33,eb2622d,5f822ad1,d284c68b,c840f65d,4f731c63), +S(74d223e4,bce2d6b9,b2fa9482,46327e04,18eda6c,cfdd76c7,cda8be62,3f6dd3a9,b7276bb3,817c0e72,e1ab002d,50531065,e1c4ca30,9c6d6f18,bb5796ee,457b4270), +S(80298b62,eb4d3ff2,e10607dd,dbcacda4,3bb30e57,f3c8c7e7,6f9f3968,bf391316,fc72362b,48c8b606,4e428e6d,1ef2ac87,931caf75,e936a33c,228a5caa,c460c5f0), +S(8519f27d,9560acdc,509fddee,9b4a4a7a,8b13496f,14760a08,22609f3b,2ae07963,193aa9db,b98293f8,e70d7253,51d3893,a9f5fc73,6f3c8e65,28a2dfd6,5dedc220), +S(49d734f9,c8eff915,fd66757b,d6484bc9,548f20a,d8c05959,f651eb36,e45cb88,4c594f79,7651b49e,929932a4,59e3bf21,3e74c0b8,acb20907,697a25a7,ed21057b), +S(6a528c6d,19b1e28d,b4d9ec9e,19c4f7be,184ef845,1f41b322,e5932f05,575bcc4a,7350b90b,c22ab41f,40c13a80,18749e8c,275d3e5e,5d687df0,ddd47133,c092eadc), +S(6f3df40f,5647143f,cb93b23,4795d9a7,708db6b8,2e2df53c,f214de4b,61eebaa9,dee10664,54b625ba,34ce4b54,f7285714,7874b5d0,6b38b1dc,37b7471f,9208dcbe), +S(5abfd7eb,c4c5dc14,cbf0e335,f2e87e7a,7db96a2c,b78000aa,64fa8aca,517ee1e5,d65a98d4,20d872e4,4c43997,55cca5c0,bb94ccc0,b25e30fe,8b5a4fcc,7006364f), +S(1bf3714b,da04d769,782e37cb,c4a4b347,f9fc769d,a18e4940,d19a205a,bdd22a23,d0852b21,33b04274,183f4de4,9a20769e,4a08ea16,ca8782bd,84a4da7c,64c928a2), +S(773ab884,a4e90454,ea467caf,f18c3b64,e316468c,b5789fa6,4958f73e,ec3204f1,62213b85,b4838d8a,fa3a14f9,32db7d79,dec538c7,d872d9d2,be1640a2,4e367caa), +S(33a283d9,9b7564ed,6ed10d88,ba26ba,fbf3a375,e00e10d1,577fce27,2c204324,bf84dac3,40736625,cf0e6be6,98072c6c,5fb8bf9d,2850be84,ded3f652,569370d2), +S(62bdb467,596ffefa,22b735fd,d3dfd959,d4a6e187,a19d4c1f,4d647b4e,db380c3b,210a8e93,d1a184d0,a3548be7,6283d180,8e4f32d9,52834c,515953f0,4ecf9acf), +S(ef16d3a3,233f03da,5864801a,c246756b,d1356137,971bc164,b5512067,b369dad2,480e3d32,7f1df8b0,646c3b58,a51126a3,e91522de,ab77d6d2,f2bedadf,1219b877), +S(a6834869,c006d044,a9dcfb9,8a5a14df,86469fd1,fd0cba06,a4e8ec1e,1fba89d6,c1a3e0ff,7abeb1e,8cac11a6,8c1b4c1c,f663e615,9f508c35,f4747f50,84b247e9), +S(203d13c6,53a3c36e,55a836de,b38c7443,681d7b7,c681d71a,38fb0fde,986ce9c3,5d7dba97,573ffd85,b3fd4417,f09192e1,92461c4c,125a9947,ced9c737,ecac65b2), +S(c48819,b8f32966,bd50f162,30f5c0a1,45cb3570,d9c4b104,4c306696,2f4d6667,feb08ff9,1f543c1,35b6e0f0,b21d7624,91ac096a,181bf093,fcf8f4b7,bf6559a2), +S(31441031,ceabfbf8,59bcdd8b,6e177f91,df7bfe08,f9015172,1ead3acd,ab64acff,e36315bf,6f087118,32894704,8d2fd259,6b8beae2,e1917341,d690a1f,786db5f9), +S(e3e4750a,310c48,38920654,b6afa032,79589d52,74e48139,6e22d9cd,3c05fbdd,f05868fe,5452da6f,fadcafb6,69e5edfb,4b9a7840,3a305004,345ddce1,eaca43ac), +S(3659ba70,60d8200c,9512facb,5c730111,4cdc2b9b,aa5bde14,8ad9bf9d,d8f8fb8c,b1185617,f91fe5e8,ec68da07,138b6780,e1ebd12b,1bb44eca,8a1b9472,8337585e), +S(1a46b7e9,fe99a4ea,492fbc90,3281b924,6831fe59,9360af53,bde4ce8b,43ed5996,97c317e1,5c0e23a8,f1c11f7b,5f9c140a,af786b56,10ad8ba3,d11b12ed,17379f81), +S(f16a409c,677a40be,402f8efb,3752373c,aced053c,6f702b82,8bda222c,a412b6fd,d5becee8,ebacd866,285958a5,8b1cf1b1,e9abf9a6,db61435b,d9725187,135fa955)}, +{S(32c932eb,6fa35974,90a408a6,ce962d7a,ef2bd22,72cdaa,cb80f798,9836abc3,3e145848,c2f8197e,f0264d7c,370d1784,7d21a09c,77fd9f7a,73245ce7,2ce5f3f6), +S(49d837bb,63890b4e,8a4a63ea,6d88599a,c9961c20,80dcc955,aca6a101,bc935f16,358a7f6d,b540ac03,78d83bc,304cabf1,84c7580c,46c258ec,58f22254,e3e03aa), +S(23516ddd,40dab9d8,63dcad6c,cd325503,b783379,d870ace0,9a0b238c,d7b6b2bf,b1fb8268,a7814efc,54f3d637,88956b67,a3997a31,10a738a4,94786d95,a5fa1c59), +S(6b4e215e,df56e6ce,6378fa98,5d604f68,e3561275,788283d6,c40cb249,6d16310e,cdf9537e,e6f4304,dbcb9df,f8b97a71,a12f014e,29867e5,6b09b388,78c9ce8d), +S(f4f30433,c933dddb,949ad868,cc0d52e5,247149a,7ec98f12,3e7f63b4,acf6b7b9,949123eb,9fb848fc,d7b94401,a64b21a3,53fde44c,d93dae3e,b7a2d3d4,78055af2), +S(dc3523f4,cd24be1b,30787dd7,5140fff,b66e4487,55e9a3c9,6124fe59,c07faa28,47b945d7,6d37b855,8ede59fe,e297a8e7,81d3ea96,f0a81588,b68db767,9b9641f5), +S(b92cace4,e31dc724,3b3530b1,f90de1c3,47cc39e5,5b247455,a1296912,4e3c2a09,78f89163,c735cb13,b1d8fe7e,547027f,68d8f864,a1f093b,22c0d9cb,95fe28c2), +S(8f7ed1f1,77238a68,bbe32e4d,ae6d67fd,be07c9a2,9fc6b940,6ef81a77,65a8fb75,98e627d8,d32095bd,5913daa5,920c5c60,334691be,537b08d6,da5b8c19,7bf81c8f), +S(47fa27ac,e035176f,34c59581,8d3dca2c,a2b40e53,29756c55,7cf81f75,4f99316a,ddee5921,f381ce26,3634a34d,1b4f9513,4d9f0e50,5e96bb79,b87d98b5,282aee7c), +S(7584cb68,60ae81f2,e0df701c,97d7aa29,8132cb96,fee4ad59,15424bec,2e280dcd,4b76458b,e3926b5b,bf59ad77,da4a96c9,1f9147bd,88a234c0,74b0e09c,a6993228), +S(2cd4c11e,70d432ff,38550aca,481667f4,d09ad11f,9aed62d4,968492d7,5de28dae,82514708,3e5bf46,341177e8,9ad2cfb3,a215578c,52f9436,d3952432,e9acd430), +S(2b524c99,2b18a6e0,30863716,362d236d,e385a10c,3679eec,2774edb7,a1a89be9,1abb3b28,3477769a,5c7b4580,93efb22e,f2e61296,da90d4d3,1d6b2ff9,1766f89d), +S(d642c258,9d0e47ef,f5b2b60d,9321db58,727315ad,522daf58,3bdf35d3,336f1081,1019505a,994030be,484e5340,abea0b7a,51276c99,29cd1f1b,9d19798d,aaacf3d9), +S(3e5e09b,451bcf5d,549f1d66,b96da0ea,25e63270,dae59606,bfc3165b,f89f29fd,2ce591f5,32d57be6,4fc48aa4,ba40231d,9c104615,b76ed6bf,11957694,16d2f0e9), +S(4756965b,82fc23bf,64041d23,a23cba32,cb71d3e7,ef3e6c03,51b20f3f,dec049b6,75f3a293,eae07f4,362c47e9,44a78561,323244ac,bcecef0c,6ba2f5fe,d1933679), +S(f296e9c1,41694ce2,c197ba85,bb9f172,54fc0bc7,f89347,a0e92b8,58491a39,73c7fbdd,91c88ce2,bbcadaae,df8880f6,aff07e8d,3a1ce05,a468e3c2,3008d98d), +S(b437d387,ddae39cf,e26edc85,b0e600bc,2a199b6d,b521f9c9,88d921dd,7e6fc761,ce2111f4,d937905e,2af7f2dc,559f9eb8,bef286dd,909a5965,53c7f61c,f51aed18), +S(bacd4a38,f3e1b7b1,b601fa5a,2a579e87,459fd189,a607314,5a0dcfb6,1ad3c21b,8be8d6b3,9553648f,2a94754f,4c6c14,c4917296,aa9987f0,deeb7e66,d81c3777), +S(d8164748,8ac6bca,945fce70,e8f6a256,90512c8c,dd4c8fbf,b553c131,96f7f607,16b75474,65a80a67,86b5246f,e086d32c,4db03b83,58271938,41877c38,2b5bebed), +S(9c2b0749,cef57b4e,36b31328,e01503dd,ddbd2834,5cd86ca2,5224b967,1b7897d5,f020f978,4eed44cf,cc4aa33f,b2eb4b71,f24b5f3a,a8dc1d72,569bdefb,5f6276fc), +S(ea277814,9f0ab428,63b05bb1,c113ea7b,91afb815,e8f0791,12c11573,eb044e4d,8199dc4f,4e72b691,1c562ded,1220aec3,ab967029,139d30ac,58c753d2,f4548030), +S(4be6fcf8,40673659,5a9e4f2e,877ad7bf,28e25177,63d74238,6e43e6da,1c1c43fd,eb5456f3,d1c40592,2eec37ab,3e0d08da,b7cd257d,9babab02,44e5b2d6,a827a7cb), +S(3f1e9ab5,160733e2,9e7aeb6a,378d169f,9be5c266,a6462e2d,e736be07,f88c1da1,907fa0b9,814da057,9bb11309,aab51902,a0699aad,9422e1f,b8f1a8c4,aa9d4399), +S(eb730dbb,1ba9b2f,50453837,35ec6da2,ac4b5019,86cf03f0,3f5061e2,a28285f9,41dc3a0f,f42fb1b5,d3b464a5,6e305fe5,c60c4561,d6e5a6a7,8cba87ce,15c392fa), +S(aeac891d,f7032059,54d0bab7,41927702,1a595a4c,37bfc34c,5d315876,3e85f3ce,168f8260,1331b5c5,edf941d9,9f1cfe0b,72fd2a1c,3e4bbc2c,c62d47e6,6399105d), +S(667e04e6,daca6315,4888ac26,a268876a,f4b754fb,87687ca7,3c4cff77,d6dac204,1826a26a,cdca828,8e2ac81b,855a4d40,86f3009b,162fba82,83cb1d17,b9f7aa4c), +S(240ec754,24e46326,8e2e4ce0,240f335c,78c46150,1e18cedc,b32e3c51,77ade3e5,be09c744,cf6e9c6a,75976c03,530329af,5e11e5ed,3fb13e8c,af40bc5f,95872645), +S(7b83e4b7,70e7a442,3efbb501,c23881c5,2bbde4b9,d5aacc38,7071decf,79690025,d242ed74,441d1ae6,61b97c83,70be2f52,dcbc2831,1e8707e0,1b44c827,420dcd45), +S(63589c41,fa8975f4,c8738f57,579cc0d8,447218c,69da1a34,ee06af0c,215f6c27,c34f2ede,7589760b,80dbae48,94a3c13c,7351bf5c,33a35351,9988ba67,c2a56d48), +S(db092b0f,4638ee45,190473c7,cb60cfec,45c94d96,99aaf289,82d28af,16ba1c66,8a96ecdf,29ad2fd6,3a85a7fc,b73ab6d7,719bbd6b,98d052b3,3a0cd91,ab924f46), +S(11c4dd8d,3eddc0cd,9a832dd2,dc91c8bd,491fdb51,f5da21c5,732dfb7a,362b8df9,ba4c2789,740b53d5,51bc9fbc,776f049b,e848182d,9d13abb7,e7cd860,96911eff), +S(a65a3a01,df3b5ef2,e620d431,49fbe1,4d71457f,19d1ed35,aea39d57,89303fdd,86715f6b,f300a390,470bc272,6f12d389,7979e2fd,b0512c35,252bb571,fd19752c)}, +{S(d8558716,b7033a9b,29afb346,fd71663a,79b6e86,2719bf12,6e532dc3,f581b7d,a790d460,1e5b2630,1ad6ec43,62f79120,d75449d,8a500e2e,6f17c021,8037a405), +S(842c01b3,54353026,c43dedc7,8829ead1,db35b63d,8c4d0d36,8cd7b661,2eb5e11,f173cab1,a37ee0d0,68e097af,17bf859c,13bb4823,255abddb,f0dbeffc,573e06e7), +S(acac5cae,414c3556,38e293fa,e7cda051,18924e9d,abb81bdd,29123768,c7f21443,5d17b909,5b997254,5f56770c,dcb8af40,e37e1a8b,6e01a989,34ec22fb,f7d04537), +S(c8e73810,c024c6eb,d5398bda,3784261e,542279e5,3438d49e,83b2639f,80889aea,7a2183e7,be4f81,b0337993,935657c4,c55d20df,729d2e8d,b25af238,f3d85f4b), +S(f78c5f53,5e7ccb53,555a6f2c,b1de1c5f,da379360,f6a7fc52,eaf86ecb,dbb3bf90,cf2d33f5,eab2ee1d,5a32eea3,18f9927b,cc982fed,cc9add2e,2461ba14,9def0292), +S(4cd40c43,bdb8a042,2babc95d,eb00a405,59519074,5906a8b7,b5ea00da,b7f995f5,a0bd1c74,79125d2f,5baec520,21fb7c62,415817f7,2afb80,b2315dda,40cf4c4b), +S(647c5950,f8a7fe9,e6945b3d,6da91932,b486a4fb,ed903836,9fbc20f9,a849ac08,d331cf32,d72e148,b47af547,6794a33d,55f49ffb,be47db02,7d2de73c,542bbbc5), +S(97664e78,980a49f0,8269ff19,649e86cd,7da88a76,eb1441d8,a5f3fd2a,6ea335d2,b2898268,9a8cd91b,b1b16be8,ee46b4bc,252f7016,f72432c0,431f1264,8d7450a7), +S(523f68b,b39c2ded,81d22a4e,575483ee,d8748c9f,52c06081,391c27d7,7afe3805,5c331672,4464dc47,cc9cfe32,864b6095,ee8bd6a8,42c1af98,b3e33183,a46e2471), +S(cad866de,5cbf4938,989b835d,5aed958,cd7c316b,980b7c76,2109d688,d7ef5b25,3ae79c30,e77d6d4e,fe404b8f,324179c2,f677f434,8a1c4367,2a0fb5eb,b706607a), +S(ba065cef,b47170a,d6796033,d157fd1c,f22052d0,7b7f9992,6cd58e03,316f95a5,26177c08,bc535702,7f5d03a4,9d982637,d74a6b20,696be76e,742243be,b9ecddca), +S(27ca8178,be756f12,22cebe6c,d05310d8,5a6c4f59,eec71613,7777b625,e6d44c97,de547a17,ddee9fc5,1fecee01,45f9cda1,b65f097,5d1b9544,aa2317f5,102537cb), +S(bfab1d94,d04f4909,dee00998,78f77cc7,d9de94a7,96b5b770,5f3c759d,2ae97ec1,6ec39a8d,9e900a79,b8b88098,d1e5d79d,b75ef91,e442cb2f,27ea531a,2db21bb9), +S(b48a4f25,9d82242,59f08a08,29b05ac8,ae6b97b5,56cccb84,20a479f5,df92701e,beef137f,9f9acdc,8d31a780,2290fe79,9d9470a7,3c8a01a,35abcbee,9730d17a), +S(e3f5d307,ed2f2f13,d23ae5b5,9dd567f0,8161996,776d506f,b53e14f2,70a52370,40ecc697,7da3771f,32a66438,cf70ea9e,550194be,1af85a08,c8a4515d,32365803), +S(818b0462,d5a815b1,57216ab2,4d795886,17cc99bb,7a7abd91,655cacb7,ba99335e,c6ad05a6,7d2a391,a15b6600,7716e02c,9fe40db2,f82283ef,c9c0a7d5,ebe854f4), +S(7e3c52ed,23220b73,ba47613a,bf39a9fb,b3a6bb6e,22c972a9,3ef21a61,50cdf830,b3e4a95b,875719b3,bec1b113,9e29670d,4ba8f39a,2fb76700,f69961fc,bd01fa2c), +S(594e4129,9c1a117e,ce8564bf,ba88ce04,297f2e14,7ecda07c,5f12913c,14d9a5cc,60bd54c8,7395fee2,7fedccfb,ca9524a9,b5750b2d,d712621d,e73e0692,46c2e347), +S(3686bf4c,f387e340,6fc314e,f02c637,ee6f5062,ee9bb567,235b00e6,4d516648,915e5904,b106e057,a0db43,151ac9f8,4871e843,126d5285,337dc3b4,52c67165), +S(338dbd1f,42480753,516d3cb2,c535492b,72849870,a7828b48,643dc143,b966ea61,e51f11ec,86104334,9e9dae17,78116032,949c66c5,3c4d441d,3c88cf4,c7ad61c9), +S(56f935ae,f58bb403,7649198d,1a5da704,26fd944e,c5694c18,38c94287,2130215e,a9c48fd0,3b059474,e528016f,9c998e02,cac7c40b,8c859852,b58b9082,b638222b), +S(1faadcd3,da472591,cc723754,82546c81,c4f53c14,d0d8dc5e,ab95a58f,379e6899,5bdcc45f,42d0ba3f,783a0806,a5d08c74,a1b1b9f5,a559248a,8681b153,74e74958), +S(532d8cd8,fdf838c7,70b87ca1,4703a884,116dd928,74acc660,6ddddd61,8eb053e8,67a31325,853db4d,3e5877b1,c76e7e39,468d2d77,37cb8a6d,af4f16b8,17cd8ad8), +S(8a8cbfd6,d45e5740,aa9f0a21,f40e3671,ef897fe,bf2bf753,ee2d2f75,844ab648,d00eed6,efefa26,46c36895,3a54045d,96da4cce,8ffc554b,9bc989ac,2f62acaf), +S(38ae095a,3c705343,38e542ff,6789902b,cc1b0b5,7763cc43,2f50cd9a,d26d0f1f,100de239,87026f09,e483839c,fe9e1f10,11bcfafa,662a9331,95a8e4ec,e4fc804c), +S(82d9e5a8,385de1f4,fa541796,a00533d9,a3aa4656,74583d07,c4b3c344,b6ff8cb6,70bf2bd3,5765165b,a466171e,f26439e8,f790e178,f67ef5,d2e15e98,435b4261), +S(1843988b,42ddec86,dcc6c9ab,36b381ad,a0ca745e,aba36bf0,237e2830,579aaafb,f1bdc95c,d76337e,cb3cfd65,d9c30b7a,e7c7d667,65c9db5a,6130edf5,e240cec4), +S(a32f7415,9c2743c7,2ef192bf,4a68e838,97a86a0a,3997d1ce,fda3c581,b4fbe683,8862903b,db791be1,dbab5031,ca57f161,b6449bcc,db061438,f45e610d,50ff3bef), +S(b09dcc04,d9c30c35,2bd63880,a766da1,f6314287,dc201bbf,9605516,3db2a09,7580cf9b,7e30dbf2,8f72e9c,a5152ff1,956ae42b,3e952b18,512824c4,7f4e5b9c), +S(ca07cbfb,b24ad1a5,edd9a12a,8ac54157,6f3f2ba1,4b878d82,ab7dc996,bd7e2c95,5123ceef,cd20f120,b575dd98,43ef9936,c53cf90c,c481f340,fa166452,72af1c8d), +S(f8058324,c6b9c2e7,e62147e9,a41ad78d,60e3ecf4,17524c05,80832add,f11349e2,6a39f1a5,f577a932,3217e559,f15eeddc,af6b674a,9d921772,a053b960,a4dfd633), +S(2e3c0532,6255d80f,a42fc69,d5c92aa4,cd326a5,3e8535f0,435efb7b,694a09ec,ffe0076e,9a93904a,42251dbf,47d03e54,1fb75ac3,8f8499ae,dacb797d,7738c9b1)}, +{S(7bd8469f,80f009fa,b4960cdc,bbfbd4ad,d8e37bb,a4b2a34e,d5c95d17,7a94c207,f3062154,c3bcc160,b2aee99,aac98446,516a277d,85b37fe9,34be9359,4af905c6), +S(139b7c10,ce844844,f5d0a9db,bd7e1679,17b37e93,9bb6fd2b,4f19643,f22a6af1,32d4e929,27f5951b,ffa4ddde,4b091ec8,531a6f23,f1772c9d,ada292db,2b88c1da), +S(f49cdd14,14b38e5a,2dd34bff,3d01e1cf,ddefb954,2a641edb,df698d83,774ee70,5c10a6d9,200253e4,a932a42d,2e770f18,69d0336f,3c44f480,ce4a3305,83050c31), +S(ee145304,4771c862,745f03b,4776ade3,104ea0cf,eda8710a,5fa108eb,1e946826,b91f14,b6127808,f1175b72,2c09e02c,66eae622,109f4156,261d65ff,506b88bd), +S(c9ebbdda,867f333d,39142483,2e4150a8,c98090ec,d8ba9c09,3673330a,8777d790,c46d72c6,6028477c,e4754960,d40bd10b,b2defc1a,17dbf018,538b71b2,d208372b), +S(707bf0e3,9f2c8c6c,73a5d0d3,3edb32e3,46e73ac5,dbeef6c,60fb5ebe,b95ece24,adc6edbe,151bcb7c,2ed5fab,1cb9b2de,3ba2f3c5,ca762082,902582cd,e9e27f54), +S(4a002722,9fda7d33,320fc533,27b6c9cb,88a09c2d,e95aad01,65f68f45,1c82e2a9,233416cf,1cc1ee38,90816a09,17c5fd0d,da0bb8f5,d33c709f,6f1b07b9,916282e0), +S(8efefe27,b45a4cc0,3088b6e2,2a0baeb0,3e772763,58af3217,f39c7222,1e20b59a,b9f3fcdf,65771acf,cc7b7486,9b10bc3f,b0e8fb2,960cad82,24ea2430,fdad1634), +S(7bd3815d,6779f321,195047a5,b1772b19,ab29a99f,cc082e93,c442e927,b1ddb235,eeeb4bb7,480f3dd0,92e627a,a042533d,a9eb598a,6cd1ed9,2d75aa89,a592ae8f), +S(883f939b,6bc9169a,3860d36,9894c4b5,2863b5d8,d0348c4c,62368a94,737fc3cb,96e37629,c05b7231,8800ad96,8e922f7e,5b8a2c39,62a25210,9b3e4949,4b24934f), +S(4ad8cfb8,e8ba3265,4d32a656,76822176,95c40b92,e97c6d3b,af26449e,149f4b3c,491d3eda,89930ffe,e401b994,54919947,7ef33a8d,6cfdfb9,eb28295a,c5ce94fa), +S(ff15cd1a,4b185632,c6f11ee7,19319bd3,abce5167,65539608,b1ee3a4e,1671369,24df322b,ab157296,40aeb039,c00ab8,91c96833,4142f87a,1e00d105,b08c63a2), +S(3fc8e63e,995fda97,1d09d96d,4c84e18c,3e0f4d6a,9f8bca41,20c7c832,c4e9d49b,e17b239d,8e6f7fe7,3c4e46d,3aef9040,6bd631f2,da1677c8,db698484,85922ae0), +S(d88b3d3,6bfe995e,45812e9f,63e8b6e7,d5a87562,1c4a23b7,ab46f6ad,2f7d1e81,63079694,7c97b00e,311bfdb6,198c2c4e,eda57d09,b17fd74f,7140b40e,d2842d06), +S(da6971d1,4c0e9c37,e5b1379b,9cedd83e,218ba47,95e4af56,7956922,c64750cc,a14a0bd1,ebd0727a,258c1246,3aaff478,fcb490f0,53d08a40,44cedc97,61be43fa), +S(d098ccf,e2fee442,74377e1c,57d0b924,45f0954f,7af643d8,b7ed5d9e,956fba23,85c99754,17df24ef,2786621b,c0be5069,a9c59da1,61e14759,ee26b524,e9587d18), +S(633f9b18,9dd98f3d,8c4de,528f7170,1c9d5972,cabe3219,cc4e5f0e,e7e094e0,3d69c877,28c859e5,d9e8ea27,3c04ec98,ca084df5,d7c9cb34,9fa537ad,f7da0b5e), +S(2e14be9,af0dda46,8d59df19,9ac9edb0,c875f829,5715cdda,5ba3bed5,d54fcab2,a04688b,64c5d34c,752396d7,f864a9e1,59eea9aa,db8c93c1,5b4d7cd2,539bfa0), +S(adc92567,7678b197,1e45ed31,38a991dd,a4cd3586,a1ce1498,3ea30be0,642a2dbf,70f2c69b,7e47aa55,cab6ab22,e6482571,e8e1ea52,a52df934,d5ab99d9,acce2770), +S(ab89aaff,b04be186,183e8076,46c64111,476c552d,10df84ba,10a1efdb,32c01162,fccc1e20,17ac63a4,b9f78ca5,af245a74,4174c952,cfe29491,11ce1d71,e4be8f87), +S(1195576c,ca3a49b9,4db3f827,1ff2308e,66b66739,a30d73cd,e8acda4,a382002c,6a2be3a1,c6ae9f0d,b314a7d4,728977f2,17e7c7d0,199868fb,c7f79d31,6cd7d32), +S(8a15bed9,bfa215f5,42c62c89,da0adb8,c68cbc33,d9c879d7,a2f2803,b7068556,ef437bc1,1786cd73,6dc321d0,a3360517,3e7572f5,bce04b7a,3c8cdb85,cb56e697), +S(b4521d6d,f9b20080,4d3799ca,4cdc87bc,ea970d60,a3005071,e910210f,5654da88,c4ddf348,2a23e98f,b86ab9e8,4decc6b6,ad18d879,e96435d7,4b944d8c,f7cc1587), +S(4074523e,b75634f7,6442c3bf,ed9a52d4,5f6636f0,77a10e84,5e6ed950,b673a9ea,d8889a02,ec95b511,aa74db1a,10c91547,45b89b57,981011a0,9d4ce57b,e4e1f032), +S(b2e71794,e6ac98d1,ce532974,df79215e,bed8c668,561dc391,505e9e26,8444a858,94d8ff19,b8a74599,fbe5f471,e7f3e1ff,e0238cc9,2504f99a,9c4f5fbc,2e482854), +S(2e672209,8a6b4ca3,905a8910,6d23daf5,aeee63e4,34e7bade,70395df0,e5a1af87,708e9fd2,a3c0a3b1,b0e03f96,c3d477d2,abf6dc0c,bb8a7181,ca4b18db,ed12e3f7), +S(7ec0fbda,63fe7404,438e36,d567d9b0,bdf18b09,d929329b,24a8bc91,816fd433,f80ab84a,99d214fa,5d288e3b,c2b5560f,a1791412,9c3d16ff,cabed23,736e4f85), +S(f166252a,34572146,8bf3a3d7,bdd2c67c,b0d36b02,d7a70033,add26f97,128b1637,134eea4a,42b482c7,ad625407,bb89a615,656e3a2d,232f4bbb,a33660b2,403d6f63), +S(7af860e0,27d3b1df,aa0244e2,51f9459e,488afbce,6a3aa610,e5e223b7,81ba2d93,6ad22116,415c668,7dd3f4f7,b5a00599,bd35705,951e1093,3f85f815,4d0c8af7), +S(e4ad03b7,e01c5d04,7030fe59,6e7e7960,77d9847a,e604d2c1,d801a5eb,e21c0731,c7757ea8,f57af58f,b64f3eb9,c7762bc9,544f28d,a80d760f,c46b0c9,589019e8), +S(ffb2f941,f27aa8ad,6a59ed01,24e83bb,d49f2588,a5602389,15329f6d,f77220dc,6812c00,7dd44185,fc3f0687,6f7a62d0,d31adc40,c0a1a060,c67df13b,e4cd4873), +S(42ca15ab,9f245041,ce991e19,3d696f4f,4c277df9,8cad603,8ad0772c,2da6e03,972d10d9,37e3a836,9b831b2e,347ff11,29917a59,7ef94158,7c977604,73cb849c)}, +{S(576abbcb,8b768480,882aefc,81380709,831625a4,b9de63a7,b9c3390b,9cb4c7fe,b49453e4,6e17bbae,2f1f8f9b,91c3ed04,80d5f194,33917cbb,d28b878,bc6e6c4e), +S(f9d8a157,c151181,3e085c1d,ef2958fb,df2a17b2,6b330a0b,2d512c87,69e5c14,7eacca29,26aa402f,f8b78d57,f5e02add,91087da9,d607bb41,b56a40f8,f7b19b78), +S(d31dff73,7d2d3422,7fe39dee,b2eb4bcf,dc84bd39,d6cfc4ea,ff09812,23400a80,4af55e8a,fe8e8ab1,2e2c4463,d41824df,7b53e44d,efd946ad,b6128214,4244055d), +S(9ff2bce8,a9fe6c7e,e68a8292,f0d2f4c4,8d963c47,63018a55,89a2c130,667bc861,eb138923,94aadfc9,6eca7c5,78c0fcc,bb31a40f,98d02e93,a140abd3,cdf041b3), +S(1397cd8b,aed3c601,b6eee616,243a61dc,fead22fa,da50db4c,1f9e2776,6e5bc9da,534a8e23,59316503,cae233f0,3b6ef0bf,1c7e0105,119d1a49,ee688f04,40695c66), +S(4ee38986,511024ab,5385f710,42bc3778,7cbedd0a,ad13ba24,b77f42c8,2ae935d6,cf87468,24a38404,f313965,a64c927e,4ba0b7e0,140f6b36,47e2049e,35a74e4f), +S(7614cd7f,9b5f1455,74d0d38a,370f69ca,f3050297,10af5242,e5ccf19b,187dd189,b946eded,e4b72db1,6dad876e,396e836a,875d7c9a,28a9c739,f665c741,29ab7648), +S(67fd2372,5bfb445e,5254bc42,f7dbc1a1,65bd4017,cd1019b0,8a3f96cb,7b3c7cec,b556e950,a144febd,a81dd3f2,f729ecb,fe43fc78,8658bb7d,2b9735d7,b06a920a), +S(57572b1f,1f17070e,e9b30b6b,c7168cb2,4741ec5a,b3496b1a,c06ec0f2,5f910fce,8cfe2940,3dc97084,7ab28da7,167e78fe,f2310c83,ca476a97,91ca35a9,610bc560), +S(1f111332,1e31a294,cab4df73,5a0ef333,e753c2f,7c83705c,9a5bf27,1321c4f8,8fed26de,202c92dc,5b51b13b,6e9bae41,3c7c88d7,b858dd72,a11f073b,e2945f9b), +S(23c9e313,b04eebff,15fb0625,43de6975,d19decf6,6416f4d1,855083bb,d738f882,90673370,f380ca49,e876d5f4,b6649de0,24f4454,29cf9d91,96f4f196,8a49ed99), +S(b9251407,6ef7f01e,379aafe8,8f22c156,65a85ead,f671d8c9,89602c5f,804725e7,b3a9409f,7bf973b4,aebe08e1,5ac65562,56983f89,23415e0d,eeda4f4a,c0d7c5f2), +S(1bf9deee,948b3fe1,b4345800,51c67266,8fdb7af2,99275a83,706f9716,7e38e38a,688fc563,771b7d27,f9c09953,c40cf009,a55d7329,5fae0b7d,8fc37710,729a3911), +S(34e20de5,9d00dd45,19a70b3f,2994fc4,588ca9b2,beaf6afe,4a1daae2,10692f33,7804aff0,a43f1ba0,438c05ff,8d013e3b,e5180bb7,3a969825,fc97ef52,6da1b6a8), +S(80fc119e,85e88b0c,8c84d23f,9e44e96,1c7722d8,51d4c9bf,f1824fb3,365823ef,efee941a,a60743a,28b6ffd,39762f9e,437d2b00,206e718,7fc423bf,4eff0caa), +S(89ab0f45,e3860393,f24b1845,7578fe79,b812926a,6bff3788,c8baf283,89fdbf0e,57d4fc21,42bf446f,8e4d9331,659e7673,90391fe6,62e77ee7,f7a4886c,8f440c8d), +S(1f092931,664bb98b,79d8fb4c,efb287a0,f72641fb,1cebe711,820c92e0,42f26437,59f63ca0,b8e2e959,a97b1c1d,1cfa4c02,380dc42f,db7cb5b0,995ceba1,d7e45d94), +S(95ac9f36,f447928f,344eb4e1,9ea806,717600e5,148ad222,fdd52a83,86bc3537,cdef5355,e928b1e8,225b5a53,bb976822,6fb50d1f,6c6cde20,758d5ab0,e9f28543), +S(a9ce5ddd,9941ea69,1343ea71,c85fcd73,6269826d,6eda5008,44cdd1b9,4a66044d,29504563,1fcb7590,27d904c5,4ffc325,2ce3c8a2,169f4649,907db751,2ef3ce43), +S(2edf81,45c4bcf9,62425707,ccb36a3e,7fa1fadb,4062d14d,f78771eb,f3ec15d9,dcfc961c,547548f2,73206d9e,aa0d829,a235f66c,5afbba92,68fdf9e6,abc8260b), +S(fcf5b985,c935e207,92907b93,e9976ceb,ed320a14,3cf286ad,b38540ad,b4077dee,8a0e0b4d,1ab114b1,caf7d0d,f749f219,b75acea5,6a71b3f6,aa18557b,1da85262), +S(2bd4391f,42b70803,2baf4816,54569f48,95f1434e,be6f146d,41447f45,f14581b3,dbc9937a,61f43af7,42635810,5cdfa02c,49a5186,ce67bbbd,7ced2842,19a37506), +S(eb00deae,6cf69ccb,abe6b93e,e5493e05,d22e53c1,b069a6c,4660330a,4e3bc069,18002f2f,61b08dbb,60c784b8,4c6d71d4,6b004e6a,3089a0d5,f853d659,83242d9b), +S(c7c62a5f,ce15326f,25b2fc5b,697cc7f7,26d231e9,e7e9f15f,5998b8b0,10605524,8ad4b370,ea0506f6,f25eb16a,78f87ef2,f408cd17,fa4ec63d,4ee21448,1d5286b7), +S(aa1c2baf,632673de,6f6704aa,5a76c077,be0c24b5,223de654,88d1386f,15a1a002,de4648e4,fda7db79,41efc5e8,6fec516b,c6aef164,62d6dc08,fe93ebc7,a85261f5), +S(11871161,13c3c670,e7f5366,edd22282,1f76ec98,d1a3500d,f0e483d1,e53f2666,d0042c9e,8dc1d72c,f53836f3,2c76b5b6,52fd5ec1,9e8fde42,aed1a7e0,9d242745), +S(e232a92c,9ffdabcf,24422182,34078534,6b6b79f5,983ddd57,2580c3df,e4ee4118,6c1144c7,471342d8,7a784fe1,587ef576,483f8980,bbab12f9,35aa0d84,83c1d76d), +S(1ab6237,3998ded,e50aec45,8043f830,8a7b4564,2dd3c9bb,4804f98e,a7c2e0c9,5528e158,6a23aec9,81f04b51,b90576a9,a9e7feb5,53200e51,e604898f,e55996f3), +S(3bc24bc9,cbc58de3,46644de9,b17ffa7,39a0f7d8,83eb9f52,af19eaf4,d8d52891,f71cf5b,7587c275,8014127b,f404b70b,b257bad7,f5b78d2e,c792e1d6,b2fa4493), +S(a2bf9afe,e6eec182,ef5866a,b4bdfe2e,9d045323,343aa422,8c1a13ae,fee515dd,a5ee438e,3aa35484,c5f5a1d5,43fa15d7,ff0d1c55,6571678b,a3c5694e,f93cfa1d), +S(a0b2b4f,ed0ddd23,8812806c,fccdfa9,7fb3b42a,748721ae,6477dc9b,18953133,325ee7d3,4a540d0,fc3e3935,79ba7372,905c7b17,4f12b456,b43db5c7,cb50ec66), +S(e7b9796b,5ca006d1,632f482d,7f0fe393,2cf16a5a,e104eea7,a7ea1c25,1073e879,ed476773,e6e961d0,20bdefd5,8c833e35,634a40da,1256750c,c718ef75,45575e97)}, +{S(a8565dfb,75f8eea8,ca9ca6e7,c7d18a5,bf3e437,5d1f4e87,68d5f51a,57199ac5,daa7d7c6,cb86b215,a682141f,2308d9b,4c204196,eb779f32,fcddf0a2,da194921), +S(974619cb,86016199,20f507ee,62d10295,44abdd66,456952a0,54e945bd,7890250f,6c8d8bc8,21da8234,1ffd0cf0,548be1dc,a1bb7e1f,47354dc8,3e5d96c8,2c9676f3), +S(24bbdc24,1396b6e1,75f23a6,4bfb41fe,f8329b80,d306586a,ecb69e41,2a2014b8,aa6448ec,f00a0710,27b46f09,d696642b,9274ce3a,11a3e986,e84536e3,7fd7b2f8), +S(eed9a6b4,68004486,e3bd388d,591d3b65,2f35a3f1,9401e5de,81a86f5e,b7cd972c,c81f9aaa,d7300671,b3dbdd73,a095c79a,d73ffbd5,9f845eed,9fe3a57f,a41e9468), +S(5260e0f6,fdc6858a,8d519d3f,6c71929e,36979b65,431a6f3a,a7507797,e54654e2,5af860e5,fbcf9676,bb00c329,d3e2e058,efc860e5,cb9006ad,224caa32,9fd49f07), +S(11e53f67,d844c511,b8118f28,de6ed9b8,66b70bf,214d4d1,ed79adfc,18f7d6bb,20dd984d,7b9eb626,77e411da,2e823045,685a4bc5,2a3f4e5a,3aedea95,1060b330), +S(98c9f3f6,81e220e6,d4bba711,fa8b212a,dcc21bc4,8219b813,eabdfac5,70e6fffe,bd0890be,d9cf4ec9,44f6abb1,56250329,a37d2cc4,64c931ba,8606c2ce,55127aa2), +S(f644f4f0,43d7713,ba4380d8,26ad0f3f,44106352,142fef13,7c6e05ce,5e9f1571,3192280b,f3971223,c00ed336,94779866,536020b6,79ba8cb5,c4f9c515,69d2f97d), +S(334ab869,32c4097c,8d8d8a23,d529b079,6a759d47,a907b047,548e735,5b3b766b,18f11736,d54c9d00,89149b07,35f5a9de,b15d9c,cde4ee06,155a4f3f,de98a7bb), +S(983542dc,61b43ee5,c4a7f36f,22da008e,832d4eac,6791d838,1a095d0e,6d8a14b5,cd225f2c,334d1ba9,94b0a681,d6be7696,16bfb2a2,426e9939,d2238cd4,43bebd02), +S(dbbac008,1b678270,4a0fcef0,73683822,a3d4107,d7f1a71b,41497da2,9cc942a0,cd25ef66,36f21a8b,532371ae,b91b67a,deea5797,983dc36f,54aed202,d9845515), +S(477949e6,9ed28a74,879bc8cc,660696cb,115e6392,5a63817b,60e5187f,1f77f3be,dd8ca490,fb8e3bc1,44f5fe9f,aa41ce73,56a1dce1,cc8e11c3,ca5725e,d1b764ae), +S(7616b9e8,b451d4e2,e4826586,9bfad6c8,ddbf5fd2,2342c6c8,42d6bbe0,398f94a2,4e3bb1a9,76efd345,3c4474ad,e6a494f6,4f97c6dc,c98cf68,72bca24b,dd9e946f), +S(b87fb86f,6ec4ad7d,5bec3bee,e8d68618,c8e4906d,1c584368,ec819f2f,871ca8c3,c64723c0,aa587911,4dda9c75,493f739b,e8c2221b,b2e75ee5,b25def54,a1d40c2f), +S(56ea4572,61a6ccfb,46fced99,1258b31e,8573a488,aa53b7ad,65333452,b06d41c4,d8529601,4145e12e,a72ae4d1,5ae6e5f6,9cc88ba1,4d79467a,3df3bfef,33d84290), +S(e4c6540a,19682e0d,e1f1258a,103037a0,af4df5ad,f27cbb7c,9e3ce67d,e23e13d8,a31e1b08,4bdb5728,36e53d93,1de035,c90b1efe,b5343b23,cac0e7a2,bf5b3868), +S(1902cf3b,90fae93,1855d758,24995b03,e1604861,199853c6,ece84903,c8bd67de,3b3d41e3,a2dd4c28,16d492c3,e6c53c83,e5203c7c,a8100d41,24cbdcd0,e12fe222), +S(6519f4d3,b5d731fe,eada6806,727623a4,daf924d9,b6337a51,56096ec4,16ab42d4,62e2c1ea,afa990bd,6dd91675,e3b2d1e2,acb2fee8,e56ec30b,eb25bdce,2d3ad30e), +S(e1128682,519b965e,a933f197,eb0997a0,16114459,4c0915cc,9c55ea4,a30c1ad1,cb1370ba,f8707c78,84817ee2,8227da3b,7b7c97c8,266af491,e0d52bc4,ea0f9614), +S(4366960c,6ff595d4,143d4cd4,f0f0df2d,3bf864d5,73790abc,23419c7d,6ed9201b,623faab8,2caebb5a,b4c42bf6,b2a686cd,4640cde1,a95a65a1,f8d32836,9e5ee0cb), +S(5acdf691,3c1e283,c1220355,6efd99c5,d347ef69,bda1d040,44cbf0d1,ae41b16a,1bca567a,71698c35,e35e031c,e8a98dd,e34270d1,4e2e2439,9276a7c3,6a1f35df), +S(807ecc04,81aae374,1efec46c,8c6c194b,faa0607c,cf5b7cda,fc270fb5,f5b416bd,cc60be6a,6736dd94,848fbb05,375f6459,d556866d,165a2c16,41984411,dda33fc3), +S(29c470bd,97737284,765adcaa,68a98af7,5e6c275f,fa4fcd5d,6c71d428,bd3bfd79,b19ab40f,33c15201,41fed31f,681f176,4a464373,23283677,a40b4018,99a6eec0), +S(41a6d6f9,40bb8abd,9e8748,dcfd23f0,5333eafc,4ce311a3,161440a6,619efabb,b2a3702e,900788cd,bf35204,27e0facd,b090804,62f65418,89a3c34f,ae2cc008), +S(d5f5096d,776ffdb,f694b9c5,c9a9ae0,ab5897ff,c5ca3320,82cb2a2b,8afcfe89,6461e24e,28560d11,336244da,2038e13,c69ed5,a7a435a6,d07a1d72,be43daa0), +S(f65a00d9,5707ce6c,6bd55e8b,4b0ef381,1eca65b2,9845433,d7b307e,518ea724,7ae079e,9aecabf0,4ec5210a,b85328f7,e60c8ff7,3deb037b,c8e6e1d3,34774734), +S(346cff42,23c9ed2d,a1082d46,eeaff341,f7866e72,d95561b9,678def2d,9f7cd187,f97f85d8,92002750,11efcc9e,f8ff58e4,894f105f,b94e7390,7e185806,575698b3), +S(d0e3cdff,a47417f3,86f64a2,4029e3fd,9bc7a464,6e839bf9,232a0d50,349ecaac,5bdbecfa,2a2b35d3,ce2e9837,222535c1,57ec5bda,5fd70186,1920803d,a279989e), +S(f6bbbd77,b8dba8fd,704a3f02,1bc418c0,f8524c49,ccfcd14d,fcbf7f04,c9a18d,38184001,f39b257b,6755a132,86bdfd92,1a8ff771,fdd5530d,48eb8227,ea70be1), +S(6717bbd0,f019990a,c01a2996,e34f0912,9bf60a3a,71d8124e,fd86c777,9cfad879,9581f790,a16825d8,f44f316f,db3f0bde,108643cc,b390bdc0,75f3dccb,6520029f), +S(417c765,ca91a120,2b07459e,3713d5e1,bbcdfa82,bbc26cc9,279fa2d2,59251fa2,8d281a2a,ed38a80a,cb697989,9839d7c5,265b4e78,8a9e1176,66cfb6fc,4143a935), +S(e2f349b0,f89c69bd,3c8cf2a4,10730dc5,8e0beed4,7048c58c,15f9ffc2,508d2cc2,e014d0d7,f07d8dc8,7e79f513,89fdea45,bdcbb417,1f63424c,81cb8426,1f2b3be0)}, +{S(aceb57c9,187a5202,118c4dbe,573906e1,646b0325,781c1352,574ed15,e02b87b,68ece7f4,4037ff05,d4b89120,d90f08c6,f0499fee,d4e9e02a,a2e68bcc,2d7b70a), +S(365e555e,de9130af,99f996b2,106229c,c36c1ea5,8b065cb5,38af3a5d,2cec1145,81fc523c,b4b97bd3,cccce1e1,d1980769,fbc25a9f,a403adba,8e7e8074,13c87f9c), +S(d0a3812c,b9244d7b,c1f5b652,adbb0df,22d15d41,b1724071,fd297d00,bc8cbb01,f8d7650e,fda2be30,24ded196,eb3baf7f,351d2013,2479640,16ee4c6,b469951), +S(8f4ce1e2,a51c0ebf,f5e34cb1,c6aedd87,85e415dc,e7307119,143bbe9a,3e7fc632,617009a,ee7d4d81,1ba2bf14,d1647911,bf1a3bbe,cba8dfda,9030ead3,803fc217), +S(ea23d837,54cb2e9f,9b884ef,f4d1a708,bc1826c6,59fea53b,f52c51b4,9fe0e21b,7e8c691b,cfc3b7e,56a7699c,4f56a11a,fca5710d,963d602b,b102e1c5,b36dc3f7), +S(e3c970b2,c764c9f4,ad8bdc15,cf995690,807f5d09,4a849787,9d278d18,eed6ceea,aad8c7d7,13ce5439,b9125d9e,c14b5d8a,1c694cfc,f84e6922,b7e58df1,4ab8a34), +S(8ade30a,94b236b9,9597be14,bd421130,b6843895,a85f3613,efcfa0ce,9781a96e,78e4bf57,974cfc0f,c310330e,6aa47de8,2b0f5009,5a703fa,50093d5b,a8e8f0ef), +S(fa5f1cd3,4427d71a,de7e79b2,b0a17ba9,66d05324,1f9996e,be8143c1,9186d24a,3481bd18,2319ddf8,f344e4b0,196b3ddb,10deef4,d8d75c0e,49fc5fe4,cbd6e1fc), +S(8b88b79e,8cd28dc8,58e3f1a6,155146b9,af1e3697,d57b7435,c649f6c3,bf8574ca,e736106c,8ffb9bf4,d83d79f2,4faf8fe2,ba5dc258,e4ae1b1b,b58a1a7e,4922c95b), +S(12078a5,5c46d721,96a148d2,fdf6505b,d059e423,c5d5295e,facc2b82,aec51f5d,66a4332d,cd265085,add9a141,2fae2562,17441d7,dd9596ad,46309a0d,bfb4e55e), +S(841523ef,29f5bffa,b31a526d,bf74b16b,fac3a3aa,391f7404,6675cba8,7808c171,7a3fc3f5,bac300b5,7ef843df,e334c995,cf66de11,2283fdfc,767cb57e,e7e7329c), +S(c8831ece,f4545c2b,387378b4,f88173d3,f1cc7db9,d064774d,60394f0a,ecaf5af6,f32f1a48,bb802757,34e66cbe,58a3ed3f,adf28dd9,374a42a,a824a095,6701322a), +S(30001ff3,7b1b1691,9a135a31,287e3a3d,383ef3ca,94748e33,a52c146,586dc4b9,9d71b25d,6fc35db7,26b58d1f,642dabb,46dfa64d,e0ec2a12,c53c414a,9dd2574b), +S(a17d3621,74d3c789,c4e00888,fd4b0f4e,ea3929cf,afea9e9f,7439901e,d6b0fe44,2bcf09ef,2d374194,510fc057,dc973fe1,bb687428,91e9056d,a5b4df7a,de79bf), +S(4725e2cb,19f95359,2da72565,d8405e09,92a64299,9ad74ed5,b41f5d24,44cb6b0f,be23fa82,7aec3121,7b90028d,b61d1092,764b2824,9f3fa0ef,91929db9,b2e0246b), +S(67c560dd,74c276c4,df3efbe3,b95dca4e,a56c4563,cc7ae225,ebea90e0,f5e212fa,2c9e3120,d52ef31d,7e9e36d6,eafbcdbf,ed8a28c6,7edefb94,1df7f38b,cb05c160), +S(8468da98,7b33b79b,e08da5fd,57cee298,ef86f624,3bb975da,2f4261e8,f7531d92,455d8a8e,b4f45693,2e8b6f77,ddefe070,591dd37f,d6ad3a27,5774055b,8a63e650), +S(3416d4bb,78de7570,b1e9e912,83a3e8fc,be6524d7,4463dee6,82e84e52,72c0953c,94e55458,2c17fffd,321364c9,16658093,986b56,f88b4818,129e19c8,ce685dcc), +S(5c66928c,a39a6e22,672c1dba,8bb6331b,41a7f43c,a72276a6,afd3e209,6416a9c5,181cdfc4,15e7d6a3,c24be94b,7fe328cc,ab624c0d,dfabb1b8,f9a73b56,cdfe1b28), +S(971f7a13,210680a3,ff6a12ad,17481a63,ef624d0c,e4121166,7e63aaf7,9cafce,5de2fd1b,3149e321,2980c7d,88a49018,26f83f18,7438061e,9bdb8d33,6a4b08f6), +S(650277a7,9ae7682d,c5f3526b,8411342e,b48277a4,9876caa7,61ec6815,9a1f13c3,a903255,fcf09808,cd97d92a,26dbd2e4,7a29571f,ae91107a,7cb6f0cc,3aea1985), +S(76a79cc9,7fb80ab3,e8d31e5a,d11f5ce4,74696d23,f1ee7aab,3928848b,556f483e,1779bc5d,c763d1ef,7611b402,4583f07d,c7dc9c96,7afcf83f,e6b6ee42,da75972e), +S(6e0b4015,474fe250,d372400f,13efa0b,70c4e8df,816c0e8b,8d27a7,a8168d54,f01dafc8,8178dcf7,15f8fcc2,e7163137,9e1dd4cb,6c88cfbd,e9a051f,ad204c3f), +S(ee5dd472,b5efeba9,d0e354dc,21228d22,40a69088,842d00dd,6b6358e4,309d1f5b,bce93ac,3fd4a098,9e74448f,5832643a,a2a172f2,eff1e2c6,c61ea99,cc6e7cdc), +S(df99a925,ef2e9f9e,57208fe6,5373ff94,876b1448,368dd453,436c59d0,f2a857e2,88dcfe81,4397f990,56f92a27,143c902a,2a6a66f7,f7e9652e,e0b16f13,33252a1e), +S(9186f095,43dc64db,ad582561,cab96a38,89be54ad,e1cdb27d,674af836,22b5d284,71ae31d5,a73b29f,54af1aa3,2d8e541b,14f7cebc,9279ac26,c846d466,aa975e20), +S(645da454,63357bfb,61b5b932,1897a73b,87af6077,81487bc8,af1a66ba,49bc5e37,4b925aab,aa7bbc19,5963025e,f1896cb5,b6463242,cd8a35f3,b1b404b0,7faf8e94), +S(5cd9a6c4,e9d372db,90a65f11,1f1a1b5,f28bc3b8,3d05f599,39979c91,5277eab1,c147420f,7dfc4ef4,d7d1f08c,1c523771,86a8d7a7,10cd7017,82b97c55,63287aa8), +S(4fd699b1,2c720ccd,7b977e5b,dc622671,18ac3028,bd635b26,fce648cf,335cacbb,3936f10c,aee5f51,26b86240,3249e1d3,5566714d,17ddc19e,cc4d1056,71e523f6), +S(b3fa0545,83510d6b,91226711,4bac7f4,ba4ae5fb,baad7230,3003efcc,4c3c18e1,57a3db8a,6cbf0a94,845e7d67,f9b01902,55aa5b66,ef31abd,34ee0410,ed55d0e0), +S(fd73c052,b194c6c6,dd46aca9,d640981a,ec796009,17a565eb,e77fd534,649a2115,9df8973e,37e877bb,fdf5454f,d9082926,fb09fea9,d162bde0,fb635483,59458f55), +S(2982dbbc,5f366c9f,78e29ebb,ecb1bb22,3deb5c4e,e638b458,3bd3a9af,3149f8ef,59e4a416,5099ddf5,4605acc6,384a4362,f6a2466b,ed1c127b,a918d94e,e93859e7)}, +{S(8aff982a,fbe09f67,6d6e0f49,e2b68f88,8f20dd2e,6387b420,8157ab24,d19027ed,f2350ea9,d00fd861,41259f03,b51b5326,6ce05a34,74508bd4,31ca74e1,366eaf92), +S(27ff285b,1e14961d,a042bd31,56aa44af,5e73717d,fa413a47,b300f358,e1960dd0,8b578851,264a8fea,2e29bbcb,cb9c90e4,93e8c731,983f4bba,65381e88,bc83a8a7), +S(fc6acf61,4a214859,1418ab5e,e0f0274a,309a8248,2cf01f73,db8a9790,825486df,190b9c0d,46953d99,c9de2bdc,bcc15d23,ee90485c,c4c152d8,e28322e5,4c927d54), +S(743bcc6,ac86b0be,a25cce81,1fdcfc13,73f23926,e3116fc8,9415b8c0,4c1983ac,f3df10fd,4afbd3b2,dc0678c9,102150e6,3d005680,6a5e45fe,c95ea495,9f2b8555), +S(bb165428,2c13362b,b1e017e6,6402613e,f82bbe22,9429f29c,6a1a522e,4956d67c,ec542c4f,7fbf3c6c,32e71aaa,86e3e4e7,e52b0d43,98589e15,1f17417a,40b31b07), +S(b3f74ed2,5a7fd474,5820a2f6,221349aa,e41af762,25c2b706,160a463d,1d59e7bc,a9af9d2d,89dcdfe0,21ca46e8,5f09bdb5,197c8f23,bc56d705,851974da,1608dad2), +S(20c0914e,f88902a8,6af0ff68,a08f96ea,25f15ea6,b1128900,120028a1,1049a77a,339567f2,71a1f1c7,16eb1d56,2f009537,68ff4cd3,9a81c6d9,6359d2f5,5d04db9c), +S(a3555aea,2e96f05,d25a145e,4ad0d2f7,fb453974,8c4a3097,a703c0f5,404a0e7a,ee236b76,8fa04380,b0448beb,d2589665,e43299ee,b9fc78fe,5a64db69,ac92b7df), +S(37191a66,1d2a7bd,c96a0767,ce47d97d,7acfb8c0,ce251e9a,1421e2d6,29230c2b,57093393,4783afd7,2df6524e,871c8e67,ff2f48c9,c73e2054,fb219cf,d3c2a68c), +S(1a2f5b6c,5fbe300,8b01407a,b0b28c3d,c823cca9,b4c71a1e,4fc814f1,e186e062,b2f1c632,a9d92a4c,82d31a55,f4fd50bd,d53ee99a,2e1452a4,e43e5ac4,b8cbb7c6), +S(2976575c,c5e70e47,cd9c10e1,32a593dd,12b65215,38613cb7,22390022,73fb41d0,c3f0b08d,a2a3a046,d87dcb13,38c35824,1a8b9959,e2567543,852dcf73,c4f5cba2), +S(bca28e75,5cd6ab74,85884b30,ef399f,44188695,fe9c4143,6016bdec,25d502f7,b67538d4,a571e935,cbefe237,c5a01f77,4ade337c,fec9f95f,3e9cf042,f0dbab6c), +S(3dfe1718,beafee83,b858048d,25d46ee6,7741d3bc,bec1e52d,3ce308cf,738b715,8499a8b3,a0c7c599,f62f056a,a8364494,ec6e0198,2c47bbf8,7e2df591,de0ff537), +S(bde6252e,a9e4823f,36bd1737,ce188fae,be4a271,9984c9e6,76f9f4ff,d070c1c1,2e5db82d,e02a1fe1,39d903,7e7adeef,12d40366,de0eb164,c04b2ef4,b1e849b6), +S(2c74b766,eebac93c,479fc0bd,78a3805,de50be2d,a6ad70c6,9048e43e,c91343af,ab7a929d,588ff993,55094f83,6e7b3b58,c6381bfb,b284f9bf,7dc44cc2,67cc741c), +S(f0e084a7,af9abfaf,b6ebf3c5,b526d545,b8b1cf5e,8e09a06c,3670aa37,6af83a3d,6bb279db,abdb2b2d,fcc97510,2b075dfe,b42d9e6a,5a8af760,f4b63788,c315f8dc), +S(715aa28f,4e52fc26,a2f4b9f,391894b0,6adc3b69,b508827b,4732396f,5eb7edb5,c5d0d68b,3a8c6532,2f6303ab,99b6c48a,88572c4c,56c780d1,d51d2441,86ba110c), +S(8f980e69,3511ec3,cca89b2c,362835bd,24d9c8a6,97deff86,5540f7c2,b0bacf8b,2d5e8470,f2041ca6,f158ac83,e92a2345,4059492f,af27ada2,92bbe51a,d67ee5aa), +S(6823a4e9,d80838b2,750dada3,cc31f59f,3cc9d6c8,3f33aa5,38d949aa,c4d6d657,e087127a,3ddc19cb,e4088a2a,6df61863,e8e81cf5,c5cea4a8,8cd2ab51,bfbcba8d), +S(8c9af14b,11add28a,818f85f3,276d1d7a,1e3478f4,23e74b72,caaf2440,24558538,a7c17174,da1eed2,7eeb7b6,c1d93e4e,9e4515c5,3cd888d5,e4527cdb,94a64fb1), +S(5fadb7c4,74b13592,a1a27f76,b7c2011a,102b66a0,c6ffbc02,a7306e1b,a9ccf49c,7bf61c4f,134f8b4,7a5f90a1,938918a1,4d151f2c,7f1c4bea,cb8c4773,cf11609d), +S(79a21b82,9325fbe5,c01ac979,8b89cc47,379eac4b,682fd747,47e0c04b,879b404d,abfa4d5c,7ff916c4,9f489c12,5235bd9d,a0395b6b,84d6699f,c96f9c0a,5a4cab2b), +S(b213d11d,e4b5601a,5f10827e,d39a7825,adc36bc0,1130a055,cf8b3e8e,fc96d10b,27c0e5b7,a739fcd0,5eb73321,3fd1bbb7,873de0a1,2b92cbc,21de57c6,2bc812b1), +S(299ef8e,e131f523,72949d7e,fc2f0f7f,9965e69b,56725b55,4d513435,ac8b0b3e,8ba93fa0,2a4d97b3,54d47c10,d5d791c5,f724b68,4f501eda,1931e563,2c6faf06), +S(5143ab76,43a21de7,7ffd0f3b,c4746fb0,589be22d,9d9ca2fb,89403a39,86d1cd37,20991000,a7c01e4b,26d9236a,45568bbd,91c968d6,c87dbe05,15063af,d8db5a03), +S(738ce787,49783066,923ceec9,a841d60b,56855e09,93e67cb9,9d52a0ca,7a64b5b2,aba44aa,272945fc,5eee0330,976b659a,a6455dde,feb5c894,cd274414,71610384), +S(6bb9bbe0,4c3dbaf,6c60adcf,5ec5fa59,29cdb04b,14633c10,5dfca2c,183e1d97,b7dac59b,5c35c3cc,15521da5,89c0d333,9dac05c6,614acaf1,d8b9e834,8e02c3c9), +S(f325eeb8,49a32b2a,fb19491d,8c3c112f,a7ca3443,438c8c19,99bdf791,6981472a,169df94,a26f26b1,e5aaf810,7a148faa,17742c3,10cac320,6daa69,f8aad67b), +S(d279bc0c,f7f58a85,b5abbe25,936d5088,4d8ae8a4,b415ea30,2c0f1133,de98603c,1e69875e,2e38f9af,222e03b1,6c833bd1,12bc10f8,1724da7e,bc780e6f,5228fd17), +S(224d079c,750eb1b4,2d70aa25,5fa0c3fd,c2d07c1d,ae4d6cb1,17c1e61c,5ec1c6b3,e54dc4fa,b0e05362,60d27fa7,ba53c37c,a37ce30e,617365dd,1c58a59d,2c93ed00), +S(f4741ca2,b3de5414,49426531,d546272d,ab8fc55d,8f65eb3d,5ea780a,d25cb53b,3b7290bf,dda0d0f,e3704f27,d8537063,f2fe9571,4a0791a3,e1a25865,96a5b0b1), +S(e931258e,8eb5559c,6d697272,8a704c17,b775a26,5b4527d4,a4d4d742,bbfd71fa,4e1ccc9,b3c0211f,17a14be9,636ab4bf,4c6b931e,44a1ca0c,c2642f2b,e8b2c928)}, +{S(fa01dd32,fada2843,c51845e6,3cdc1b76,79dee47b,d2f4b767,5133aa5e,62029057,6ea6596a,b0ea0201,b6c8bbbc,e9d07fd0,8040e1fa,198c8767,67ab6055,34a33), +S(97ec9d33,a9d88115,471619b5,3fc58a08,e6997662,7a28afc0,b75b2f49,55eba300,92ad1d6a,f8a0a100,27d9ba90,4f7fea6a,571f3c32,53393a7c,79abb0cf,9a558390), +S(ef364ba7,626d72a6,87bc9776,3f2c0833,50640bec,6ff4d80,9dabcf2,9ea9145c,7f8d7c48,1bd80ff4,8eccfa9d,2de5eeb9,800cb98,c02da539,3b3d6c83,8fe4a2ff), +S(45961303,a778b47a,89109231,3242304,30a17859,7d940e9f,fc2f25bd,1be61c00,5fa356b6,daad2b1d,7bb19cce,b9148d31,58d2651a,b4b436c0,b99193f6,61cb037d), +S(8aa677f4,d73c0725,e2163e5d,ed3dc312,7ad5ee29,f9bad8b8,5ab8f50d,ec6d77e9,1fcb9da0,d3fb9bc3,3a45bcdc,50aa2ba1,16c2b05e,836b539c,863163c7,2436c334), +S(8c6b2873,33082bf5,a3597a26,7cc14696,2b689f20,59caf1d9,35972c98,9b14c86b,aa86d282,a1107f8e,21307e0,2ad1420a,a4061fea,3e3dd6f5,9b5d6900,6bf4827c), +S(46c963f0,3bdbf433,cbd60858,5a4d659e,9815c286,9f684eaa,cd879d66,ceed05ed,be2a8d60,636c5b80,e443b13a,9e21c91e,90a9e781,1c35101a,dfd61a49,88193e86), +S(cdbe43bc,582f3936,314a88f9,fa21b29d,f4b5acf5,96cdac3,4667e9c4,b02b926b,8f2a5b62,4f20b20d,cce97348,d73d5653,8651dd41,dfedd476,8792fa61,1bac16fa), +S(6f9c5a84,1ffededc,ec45dc63,7ad15aea,207116aa,a3036ea,ddfb0656,1dfd074d,ddf1c22f,9168232d,cf9c36a5,dfb7835e,62d28405,bd32ec15,5e3ddb3e,df834088), +S(42000663,3223b99,e15a2a65,bd95b229,820abee9,5ba5be39,6f8879b7,3f421e7b,9f3f3d66,40de91bf,c6872619,87487226,57e60a4,3ac633cc,48f684c0,cf42696b), +S(f02335b9,9cb524b7,45fa9167,41da4259,f70279d8,efe851ab,f5b0b8a5,32a087ff,e1bc6767,ba068b22,cb7389e1,36805da5,c30ca62a,e59b92f5,48e4dd1d,5327cfbc), +S(5bbda2dc,cf8154e8,28ed49b1,2fdabc3e,eb8c3f9,d0da5878,77611ff4,49d72e7c,312377c3,6277addb,d5b044e,fe136626,d5f7e7e7,a73cfc4b,9751e8ec,e4f77084), +S(5cd5cb83,ba2f225d,1ef4faf6,22e226e1,eaa85a5e,99721d3,82aae23a,f9dff565,254f58ba,9c49244a,4178a067,b0e4bf6f,dd7f3e15,65e21637,bc41f9f3,55045908), +S(3b20ebc6,b453aa16,e5b61381,1d81ca1,f87dce6d,b54ba85b,d8578ee3,23bff228,8c9d3054,56627a,7313505b,4aa5140d,9fc40d83,bcc298a6,43842f04,70a335f4), +S(cd531999,cf33db75,df4430c6,bbcf32d0,642be18,5736d79b,f2947989,e52c8da8,c7e99c34,2a5c1112,400edc69,f58246e3,d3cebbef,2c43ff47,7520b027,e2aa7d78), +S(40b3856b,273bd2a5,145b70f,d16a2972,e488b33a,f3719143,db7bc567,26ff23c4,d8bf895f,71d96e6e,20d523dd,1256bd56,44e11442,c4757d74,f116ae44,69dc9b21), +S(1a0cf029,2d7cce75,32b74bae,acec6864,9e682788,3cef4bbd,c8b24fdb,53e885a5,32c87d92,6f969f69,7989837d,d8ec8ef1,c284d9db,2a86ecd3,5bbb6772,dea06692), +S(7fd5d251,93dd6c17,8d0be92c,342f94a3,c92c061,27998f4d,54f7dfb6,1326fefa,ea7d0755,e0a804bb,8b7ac8f2,dbe1dd7f,9ccd36ca,2fa94365,631ae455,5d080075), +S(51820145,6c07fa3e,70d7b24a,7754b11,e42828e9,c1b96b0f,fd79bead,2f44050e,126f5526,1a55b724,7d08c868,366d697f,a6898c66,d14094f3,44b0a6b3,613d043c), +S(86f2c87d,46038770,3be5ddc6,c2ba1ccc,7dfdd56c,a9986663,882f85da,345886da,ed34fc59,4b66f7e,f06f54de,84f3c7f6,ea1d877b,bbfc4185,3df800f2,fa805027), +S(7f7d8a69,5b86ca13,d6a0ba07,99e60cbe,f5c4e1f4,c74a62bb,93d94d4f,8c1f296e,44a14061,b2c741c4,6a52639e,9bf08776,5db5d496,92bb6d1b,e97f9ced,a89953e7), +S(ec61e956,83714c55,1b72ed5f,c5b09663,6dbdea9a,64d13ef8,c9cf0c55,89da5ae4,39a6e38f,9f7927cf,ffcd0847,df91e856,4188bf58,276bb4df,3721335a,5357c77a), +S(e5906c85,4a75bee9,322d70be,a5d31c76,31a59389,2f479bf,8dc11bef,9ad5101c,125b3a58,8c6c1c5f,288402f4,3ce74ec5,fe9c2dd3,3f3605df,9ab41210,32641524), +S(6c9faca8,b1b435b9,213fde17,ce967f05,46e6f27a,cf0e131,8496bcfd,d856b092,a04ac67d,4bb07624,6b59df97,2fbe2c1f,bb04be99,e269d33f,ccc81f76,3f567577), +S(61031a0c,730cf279,d929b4f,5608f16e,6b1b1440,c04e5a9,fa300ff8,27303def,acc4d732,afb4730e,39a10c0f,5ae2cee9,5099be03,bf5612ac,391900fd,b51238c2), +S(e58fa07f,ebc3aa4c,61ff4fe3,bfc8d04d,48a1e3c9,935317e1,83d537f9,7f35826b,d2402844,7e63c3e0,be630190,8139a75e,2e1a2b22,b05ce52b,e453ccf7,7c35f1fa), +S(4d4d2982,b45a339,1720af,cf6b92df,2c201d38,5b9b6c3a,8fc53b4f,fd3bfdd1,d72650fb,d130482d,116524fa,e2b3dd71,c68b4bbd,54fc55a8,f9824578,cff67503), +S(9adeb6f9,6ffcbb56,f171919c,a8a64c70,9b8ae835,828bd573,b7a1bbc1,3efb0360,6d920a2e,d2e3f41b,4820d838,ca342b66,9af35a7f,7b6d09fd,b1ba4298,9abe027c), +S(64ba9514,d8680f6c,dd66895d,9c5ad45f,6e29,33506f8e,d7be9770,822aa9b8,7ed8c0dd,59bce424,481f88d7,3e641b61,a010e490,97cf84ca,16c2e045,49e9c6ca), +S(9e4ac64d,9ca58a04,46ca18bf,c1700f2c,16937ef9,c82e8b55,9ccbd751,2a0c0222,315ba2e2,601b18b2,cf7f1720,9c4cff2f,e39dfcf0,c2546fb1,e930898b,5b023274), +S(f13a99e5,8dc72fcb,c62a492,d2850704,621ddf48,f1f433e6,9a9814c4,17d4b84a,cc3d3732,f0f4166a,55946e32,e1c01f91,491c82b8,ef0d269d,7a66f039,ac02dfae), +S(fd6451fb,84cfb18d,3ef0acf8,56c4ef4d,553c562,f7ae4d2a,303f2ea3,3e8f62bb,18ba314d,4e78ea87,490185a3,e43cbb33,5d54b6d,2dff17c0,2f526f78,ecd3f31e)}, +{S(f1a749e,6cab100e,2aeef8ee,6a654551,c0ff906e,e7d11d77,f390955e,9d29d783,a60f7295,3c8c3bf7,f1dc1358,e39baf76,3dba22a0,1ce7917e,aeabd996,e21e845b), +S(e8c45020,4c9d9ad,f7878aa4,184a1576,d4c65d5a,c1c4d494,ff427e86,8b42ec1e,aabff02d,8a715c2c,34414b27,808882c3,f656389c,71c26d6b,d7ac8013,83f4c57c), +S(c1febd79,1784fea9,bf378237,a05522de,1081df6c,27d22ea2,aad805dc,7c2f1c4c,c38782e9,fcc1004e,aa677f79,536aa069,7dd9002d,ac16936a,1f0b8736,8734174e), +S(91925564,4d9bdf2d,4522825b,5758b3f0,4d32da73,3a4e772,bfe3eb2c,9909f4ef,2568e18c,1a0448ab,d038ae62,a652d152,4bdec1c1,a0293695,9772bb65,d78450af), +S(25bb4202,9880c39,f5bde432,c1fa357c,7f4867f,6fee48b9,24ecc824,5e1a5253,5d43db2,64c23715,b4b0eeae,63127cf6,9b4bc79e,f96ea8cc,d17cb53c,c3ac0fc5), +S(2597e080,e772d36f,df500782,5f92f797,c61c72c7,8d801dd1,3deb1bfb,9e91b12a,fd5918b8,938ded17,a458d0ae,559c552f,bd45feb2,5b4f59a8,f5b735cb,bdab92c1), +S(70231b28,f578dc12,9f8ac54d,fd4e3577,73d0fcbf,65be0dcd,51132882,5a36e7e1,d12aaf89,4dff3e42,405a4140,58524e30,b7c6c4a1,83763268,6852acff,83d2b7cb), +S(f8ddfd5e,5f3b46a1,ab363169,12b74c97,b0bd654d,87824040,bf6d2cad,b4fcbf95,931fc58f,5b429636,5e080d5a,8fb35ba0,f92104d3,891d6584,8d24c0f7,fc95bda3), +S(a033f432,670a382c,57e2408d,3bdcd2a6,6758e63d,77574598,6b123e4,d927bf10,83b52f69,d79e7445,b6e33545,c23f16fd,52691151,96ee60d6,2ecf6de5,b2961a0c), +S(8e77f9ed,9a643f3c,bf197b09,80f92860,f37d8b83,93633230,6c902c38,3bb7f96d,71b4da9f,f736f9f1,f8c3c099,c34c1bc4,30bb5d26,3c861e2c,726fe891,cdf7d1ce), +S(f34153e2,29934c71,5d895102,778425f5,e92f4ee5,b96d1333,df207e62,6761b328,954584f1,64c8f35f,2c4e0188,76186ceb,3e91523a,5e8ac03,d5998253,49b7b8ac), +S(e133aa94,c0252f05,379b5bd7,75ba3f1f,92de2876,68613613,28946904,11b3ed52,40363801,613423b7,cc6c0cc5,af3641f4,dc2a7ac4,48b178ae,d1393605,103bd6dc), +S(28119c6f,a57d02ac,856edb00,f594c7be,22772b0d,700ad14,713affe5,7e385b5c,969b6cb2,8ef483a0,db4a96bb,92e2d332,6e6d86a1,73bc3d5,831bcbf2,5efc437d), +S(8c728d65,8b78d96,44003708,dadb48b,65dcf6f,6d9412c0,e31cce3d,b5384d00,bb3cf660,9908467d,285f1c7f,40f4f18,ca618093,92633beb,b4ce30c4,72680662), +S(477321b6,1fd5b4ef,3acd1e8d,8432ef5d,e70576ee,6b8490e6,839f1985,dec96490,88008466,2244e3f9,7d2ded5d,2193c70e,2d72c67b,9b7cd70e,9f14cb05,70306bee), +S(ebedd345,ccdd0e04,4bd3d4d7,e1f1cb6b,ec06ad10,5ec2cec8,821580f5,d08a63d4,4278bfb0,88e4ff81,a3fe15bb,e01be36,40450f85,885da0ae,e15c6b9f,e78ad14a), +S(f4795df9,41b315e2,24a98dac,d9149ff2,8b9a7bf,e758a1f3,5cb6336e,8e1f9814,6982bc20,285c27d8,12c5c648,d0635c7,fdab85e6,fc6905d8,65da387e,596da791), +S(65a5964e,ea76e30c,74c472bd,3ddd5169,11dcfb3e,1f2d7ff2,9661e254,4a38ea30,a7c394af,80ebbd32,e442271f,b061bb42,a7b1758f,44d7d952,89152fa2,a88fe3f9), +S(f3d10725,da6b6c76,6da6fb5b,969ba7c6,3e33b4f2,d062a446,4ffb20bc,dea2d376,4d65ff69,64518942,bc3142a6,2148137,7bb609dd,6545bc26,9678ea19,62812ddb), +S(f5fe0f35,cde00589,301584a2,f4f5b1e9,3977082e,9c9bd50d,7c2c672b,ef05cc9f,1b49ac82,486e6344,dea32ca3,c96cd5c1,446ac2fb,2a658a42,50425f32,e8d72e94), +S(fce17cd4,d9519a53,f0a100f,ca54d1f9,fa87eded,98a12654,769c95be,151e33c3,40d342ef,83a4d715,bd13df0,f21197c6,e189681b,efa0d925,248733f,5ee07b8), +S(fd5d90d4,a97c1d1c,4fe18a10,6808f46,f6ea4422,c4408860,c2256b66,618af8e0,7ffc76c3,539bdec8,f59a9a7b,b36fd534,99306cf3,2dd1fe43,a2db5b59,af2f7e3b), +S(1c71f824,1b147abd,9e3c1ca3,fad5146b,e531dae7,c9c0d586,4f2d8bd8,7a6457aa,23e7e758,2cfc92dd,e498c0af,b942182a,92e02bb0,7e95bc1b,763d8030,9ddc9137), +S(dfb018bd,9bc352,f36889b8,2a46512,8850a158,872554cb,3a3dad28,a0496f20,2daa780b,d615d778,3de8f5e8,25cbd934,5c021df1,9ef80a6d,39ff87db,67a1e5ca), +S(bbd320ee,dacc1282,d3fd2109,c26f6bcd,46205ec1,d96b806,dca35dc1,4baa823d,ae7beed,3b5f72bc,ba66c794,89c05666,efa85966,14bacc45,9a99d882,8edbdbfe), +S(c9cd8f21,a068f78b,ce5129c0,9084be52,e48d688b,f474e690,b7720360,e362dfce,a10b9fe2,78c7814e,37851b5a,36aa4246,54c6279e,89df8fc2,ed189ad8,11518f22), +S(ddcf39db,aba52181,72c36a53,50883245,39ccddd8,46ec4258,e72dcd71,40041491,85cadc4a,a569265d,412c8fa9,4872bce1,51a750f7,b43385e2,2db405e3,54428a5b), +S(391562c3,f19436b1,a6e41d06,7435fbe8,27de66b5,555540c5,3ca7a0cc,c7876457,c3a5d917,5b56f67c,66ff269f,72c0a1ac,74503106,9059aaad,f3e66dad,45a80ee0), +S(63d4b224,7b2d441d,680a0437,604533cf,1dc48c9,bdcb9e10,e0249960,f966b2d4,e25cb896,ba165d4,46f73344,61e6856d,4c186736,402dc6a0,d866f97e,bd5cdfff), +S(5fe057df,5d2508c7,611dc21d,412739fe,3e7cf9e9,670812df,cbb00255,4d44cb22,33b88e83,9f22a7bd,17c149bb,65bd4a49,29b2a29e,b975776c,e82189de,80c7d45c), +S(5ac83bf,498f7eb0,79507ac,d5fbc587,f758afa9,b6a1ee51,4c857f8d,608a7b1f,1c866393,8a91904,f0530bdd,ba15390a,4c10fc4c,ef8a2f07,d799c89f,69a33097), +S(b0f9e4b9,b29790b6,33bcc04f,d860cb0f,823d8d1a,4cc1a1c1,413c1606,cc9a8e2c,b617d40e,7bc52192,be344f46,f9021c0f,ccaf33fd,3e8e3118,93df993a,20c2ee7b)}, +{S(eccf169c,9514a854,8f7e1131,a7438469,4df7dc2,fab96462,20e5799d,6d3f672d,452e53a2,aaf17617,37055bb7,24b64f4a,8fef29ed,f8571ff9,a3a6d2c4,6acdb91e), +S(a77bcddd,a0fecd39,a99c6387,57bda1bf,30257248,6a3fa08a,e2d6ff17,e6e4b6ea,debf4c03,b4bb5c7a,8a386a7b,1e459426,6c78eec6,55f01cd9,f137ff18,c5fbdb1d), +S(a77b91ec,6db6a66e,a48de424,65079a2e,ce220fba,da221601,840546ec,2295c2a2,3c721fea,81f5fe05,163562a9,849bdb15,90bc818e,86674ea2,57fe8d0f,4050086c), +S(99a28a1a,3bf2af79,ef2bf134,d31880a,71c2aad3,824fb7df,23fc4fb7,d54b2910,620e2918,df14e3c5,dbfceada,1905941d,32d77592,89ec607a,f9851a6c,5592803d), +S(7eb52616,71402db8,905c7097,2af96b72,2bd77d,f124bbcc,5418f217,f6d8c7be,ce1e663c,8276bf42,99919592,11feb13b,66aefa37,5d6dca15,8b7b66a3,ffc6d7ec), +S(c88b1815,f183e6ea,3ce8469f,ada5b88b,805288d6,828473ba,368d52f,2145e7a4,55e78f2d,3784952e,cb47f6b0,113eb471,8cc58225,85f9d1e,2198dc60,af3f90c9), +S(dd893c5e,a2e4e70a,fcc161ac,47232d3b,77f16c95,54c98770,9a7a6f64,c0cf7ab1,a1a58b41,c7d4d0c5,6d6c908b,32d97467,b8b6ed20,73e6a677,54935665,6a92a480), +S(591b8422,eddbfaf9,d2c27c28,dd84dd30,712a15a0,deb752dd,dee682cc,34722ea7,877b0c99,6a248082,fd442509,b0ce4cc1,b181d4f8,8ff755dd,5f0dba66,ebf95d1f), +S(75f9e3a1,ffdd902,be5d1d2b,3ed18b37,62e42e95,8b024ce8,f892ee13,ab35c674,57fabc84,7c68cfdf,272effee,e7a6ee2c,5fecdeb4,8e4877c,ccf2a8de,2e2264cc), +S(c8a53d5,e1895cdf,db61c1a2,395a866b,ad803773,23ea43ca,775408f7,a4141cc6,ddeff9c9,97a11e4d,d0afab30,f63229f8,1b52ac,c25749ae,2749ddb4,2b201196), +S(8827d23,668f3006,b966cb19,698a066d,aea556b7,4108739d,d6414d8,e8dd78c9,3d009ac7,2baabb53,2e3658e1,8941d4b1,efe512b8,fd7696d5,14b12216,215f10e0), +S(dde6b713,5cf165c6,53c7f5db,542501bc,b0a41e3c,c6779aa6,194ac1d1,8a830b01,25c04b4a,937e16b6,e72616e2,d64a413b,6a7c29ac,71dfcbf6,826261dc,2507c16), +S(8cf6210c,5426b3a5,ed594699,da6cb8b9,8069a3d7,b926cae9,fedb2e96,25d20010,78017fc1,7915e3c8,62557896,acd002fc,7263bd7f,aed38fca,d63ccaa3,57391f30), +S(35772904,91661db6,340e7d1c,a98db8bc,2f50f557,283ccf11,8e446f71,925ade9b,fd8a4a56,b82dff95,a59e29ea,bd5d8e8b,a876bf95,4abf0537,60832d1b,d7edc31c), +S(60e4201c,4dbd9c99,c5eda030,f041f51d,f648f77b,13ec2072,4d89b6be,f249d793,ebd96057,d60b7cae,71349c51,1a3ca99e,847419ff,cdcaa0c8,54d75d40,8263d81b), +S(f39d686,b17ad518,3a7d300f,1bfd015c,57541f08,a96b5943,43d2ef82,bf20bb6e,f1298c9c,633a958a,a0d12b87,8c95836d,f9f93b5f,5e3a6bbd,93a75ba1,1b96d4d0), +S(37ea7dc7,2a3a0b4e,72412814,bc1e1233,17ea3e1c,c4ede35f,cab5d31c,93cc330b,aebaca93,8b14b315,708360e,5662e6a1,af25069b,cc07f581,225dd131,c656c607), +S(ff1f61ed,ba3cfc6f,2fdf3043,37205bab,301c965b,501e4f2f,fcacde00,dd127b25,fb1edca5,90e00f87,eeb56ef9,94e9bb12,b64ad1ea,f5ef0afe,6f0125b4,e100a483), +S(3376e0a5,b93f15b6,c46b92ea,e313ea2d,c5d0b961,a2623487,8919cf5e,25e9ae38,a4cfc1be,fd24647a,20ae014b,2041ab3f,6cb7585d,48a607f8,299e0c10,96bcfdf1), +S(be575f99,842187b,30bcb312,987ea218,3d613442,8878804,b5e7d920,12e58d9c,154e02b0,b573c81b,d2079a4f,4a6efe5f,5f37502b,33225064,4eb38b2c,3f0a1767), +S(5a215836,f1f2997d,9b09d4d0,6473c55c,46cd3006,70d85d6f,6b5531aa,c8da043f,ef5fba1e,b6e1deaf,bd83e480,fcd4984d,cf60f91f,4799e8b4,3f4edd15,f94b6d33), +S(d73fee2,16a503e3,a7d6b0a2,675adb1d,197c3fae,4d43835c,b6b043f5,d44909f5,6f2cc9ee,fbc36b4d,a5b3e704,c13daee9,cb81ce9d,470f1290,8b32f047,ae231053), +S(26fda2e4,d07ec613,ded58e14,ee84e421,ea58e5b9,5beed698,d847f6a6,db185f6,683c0002,bcd6d8b7,1d06e592,db4b961d,f2518fbb,47cb4ad9,96020d84,ed8a5909), +S(cd3d4e87,e433f2b5,5dc55c6,a3f280fc,57f899e1,f8f0777f,32705f3,eb24551c,2315d85b,7521e4e3,8e69f29b,a49a3203,abc7f280,ad49365a,4c78f21c,3ee12542), +S(652476ac,2c9b871c,e108fa13,6a739766,879a76ec,60d787ac,a1b7447a,67f8afd8,b66bf6db,cd3a1393,f70ac7b6,d53069d2,5f084dd7,f05c97a8,76f7f646,c7b67fa8), +S(61ab4f97,61c96446,ea7a75de,7ed36224,7b5ce8b9,e7b442c3,432f9fa0,ec74355e,f391652b,17a910f,6d476c29,89e854f7,d31a5f31,fead5fbd,5013ea56,e44985db), +S(36e4bb36,e62f78a6,a6155351,36a73637,13fe8be8,1c8c3460,a94bb642,4f7c80de,12b38983,c10079f9,b0016df7,fba0685d,5eb87518,234c65c0,7dff006,dbb6a563), +S(f5e4cb89,101e90d4,b2f50097,aa0b22fa,df076932,f4045e9b,7a9ce8d6,ba178780,c12ec4ae,56db7971,3a1bb0f,2559e3a1,de3f8200,650c809,74101940,181eb52b), +S(1138ad12,333790f9,20e979f6,a6471274,2a9bb567,2356e3c,80ffff89,a9de533,4caada48,a78ae26b,790f23c1,606a5820,98642f4,bab5bfff,95748f6a,2ccd6bc), +S(e0346d21,121ff741,fe4eaa23,938a4347,a71df442,9e55359e,aa20d691,c9f40840,c1197c8e,c36676a9,28a92b56,811845d5,d9632c65,9142cc12,3c65e54f,c282dbd), +S(d42011d6,1061388,fec6b7f,3f332b20,24ab318f,2a9ba7ed,23731207,3e32478e,451a2b16,5c82b1f3,e4d2a0a0,bb407b84,904db4d0,caaf733c,e31fa97d,2fb1735b), +S(63964eee,619074e0,780140fe,2e90836,e72328d2,448386d4,59c5be23,187f5048,c49304c5,947630be,5c60064e,3cb40436,c2a7f46c,b221937b,c7c5d7b1,76cf5e37)}, +{S(8f741868,43906722,ab9f5c6e,c796573b,622fa2ae,6d985bfe,ea4d51a1,8f141792,61ecd858,d6992c4a,bdc22472,fb8fd242,929dc5b5,36ea8e35,d1c8c513,bcb9e31e), +S(f2dd67e5,6f75c397,76b29366,149ba4ff,69385651,53afb385,3853acb7,9fc2bd59,3a24641c,d48ca39f,fe992bf1,50291604,79066af4,a0cf364c,9e52a9f,9b51eb66), +S(9386aa5e,c3452728,a8f65141,e2f43a14,c250173,9349c96d,e1968a4e,48cd30,a3a38a85,4f68048,d8f81002,3eef9966,780262cb,aacbe859,a8fc66fc,27c37f32), +S(6c9901ea,920c0f4c,ce51fde7,ab283f98,eebc30dd,c76a3219,1df4c4c9,db467aac,6773f8ae,e601201a,84dd4485,fa560e22,81d5eabb,25a3b3d8,525f4a56,65f79d05), +S(ed1eafec,876154e0,58597caa,8250b0ef,7262ff70,b719ec9b,63c0b2ff,9d167fe3,73505073,2b563f93,89078cc3,93ff9837,227ab8a6,c7d789c,6d2bc835,2018f77b), +S(515806b5,13d4d4bf,83533b56,3b39bf9c,4e808426,f2e4cf16,562e759,cf2d56ab,83c2fb,673a08a6,b8a86b1f,e1ba23d9,3347903a,d6855059,130d8d39,737ddead), +S(30a726d4,d8db1cfa,d59331a0,8f4b5376,36848547,914dcd75,37a80e40,109b8e35,8f628b92,6a11ddc0,dfb1cebb,934aeaa4,3840d442,a61145d1,803f771f,7bf65d7d), +S(116867a8,d72fb00e,80a6f267,e8163770,34affeff,36d667cd,38219f0a,e3c9038d,270f15be,b2a3d50a,4088720a,e9a2c3dd,df00817e,31e1a5b1,d850fe23,dfe51657), +S(abea2899,e4575c6a,201c96fb,a60a24ee,1f1fe0c9,b718b54d,18981938,4f33a1f4,d43d54e3,9e8d433a,ce66ad94,e52662fa,8013e778,f8bc2e3f,31938a6d,5681c660), +S(1fa796d,9f658aa8,6ccd0fb4,6a735651,102e3181,302e371b,8c965dd4,5f078b30,69815d18,43c3b4d9,f7fa4af7,3d2e5dda,390e5372,28608912,79826a53,a437031b), +S(f5022faa,c8caa29f,304ab6c3,d00931c5,e09085e2,73beab04,c1d18f87,1c0fde73,c6abd143,73213fe8,ffa5ec64,8a22dddd,fdf2cb25,e32afd58,4f92dca7,838e8249), +S(8190b10b,97bc72b9,301b1dc,cc60e69e,460e389e,ce7d5d11,4e2284de,853ea02f,f1ffb850,dbff0f06,561b75f6,5d2ae823,cb13881f,d1150eff,274db4cf,112d2253), +S(ea230fbe,c58d7e2f,1a3cea60,f9018562,d2fefb49,8efa312f,4beafcd3,139da094,6045d69d,b27bee6f,3357180c,e92d3866,b480faf4,2debc033,cfa118fb,b89c3bd2), +S(333d063,ccef6aa1,f78c81b3,4a84975c,82bc2cc2,bb897608,f0bed49d,cd08829,90ad105e,f72b7e4f,a927240d,9c69729b,a0aae3a2,3a45342,3be2c385,488840a1), +S(4d95cb48,58d808a3,be82f42c,da4f64a8,c64ae176,3b50257f,2e4ae655,fcc4802,5f6efffc,99bdde54,6d8ffde5,e9a551d0,121a39c3,86db540d,1caf74b4,894c5559), +S(b87b5eca,6e0111bc,5b756816,fa82acf9,77f81376,af796cdd,1e8fcb09,4d363d1,442fa845,9c2a7799,2c09015a,db80f26a,28428851,62432660,56026009,5f2f9d8), +S(34baf43a,a82cce1b,19945590,ef3cb582,2ab03142,6538ea5f,74571582,ee14cf00,9a76705b,c0141e29,75d11543,215377b5,3c051c31,156697cb,e8f56721,da386e2b), +S(f07c5d98,a2579c17,53b3fb58,22a139a1,53e7deeb,ae9304b,114bb188,d61cdd0a,ec18ce0c,1e51b8bc,e12f3d85,23739f8,bc25708f,32deb81d,a780cc4a,1010692d), +S(9a146c80,5ee261ad,3e708885,aa41041a,53bd3758,b3d1ab7a,1a44aa7e,29acca7,fc553e71,4ad8a192,90f94ed7,7c171f9d,9ad9a047,6791f045,4a3ab7d3,f8834f02), +S(c8088409,650feb74,9f9fe21,61772279,128db1d7,58610a9a,8b9fc4b,ef9683b7,692a6be3,132a08d3,82295ee7,1c469465,ae7d63d6,c20c7357,36935003,28799639), +S(53bdc8b2,3edd83b6,b149b79,c88130c6,b207f999,e7045285,7e828f81,b325b9d8,a9a039d1,79486167,8fda727b,1706e9ec,7ec3eba3,26e6a4a7,e27db3f0,8a6ee238), +S(fd08fb47,4af98207,3d8b4ef6,d39012f4,78225f1a,bde3c841,6fe3881b,4fd276c6,d38b53a9,100da1fd,1d2a987e,6907370e,7bca492e,98a22e5d,74a10c9b,93a197e1), +S(5c42ad93,2306363e,a0edf86d,31d14b04,c3f7bc09,c9fe1326,d1ad085d,c84fb7ca,1bdbf812,e9ad6486,ff572d4e,de5be4c9,59de7be3,f21e0dd8,76534091,f13ca3d3), +S(66257876,115e7eef,fc0e6132,9f177d3a,437c81c4,1150f86b,45904f86,30bae971,df830e1e,33aeded,721a0a6a,62a3a402,1d2b7ab7,438b7b3c,d834d67,3a857aed), +S(4feea8d8,2cc6601,c847deff,35581c1d,bf1f4070,402bb948,ce9a41ee,16661627,c09a7686,ad6bcec4,ea9ab0f7,8316adc0,7c7a2899,9332cee7,5d70c50d,249a0007), +S(2d3bb180,73f5345e,cff0c901,9a6f2fb4,e0a237a3,9315fc11,fd53c7d5,aec43670,58a9459c,2710ac75,ff2510ce,4c9c5fb8,b4f739c9,c6611494,daf896db,e43b080), +S(bd539f5f,47b25116,7159153,f402e0af,8650c17a,de7c5dde,2d9d9cc2,d0a3103d,407cab4f,ca581f10,eb386e20,9158541b,8649951e,b2f5e454,2a7032b6,53f0caa), +S(c7a72935,87ba5114,744c3d0,9030be19,9ccea57c,7f80be87,bfb5b79a,8f8e200,7c2a98f8,b4526422,b211bea0,875a81f1,d379012,486db005,e31b9682,404e14a3), +S(cdf20316,f4b63ca4,c472e1cd,b3a938be,291d98b9,3ad8f3f2,4f3e1a4d,f1a6cc80,ab993e8a,68988d4d,2749760f,241399c8,136ee9d2,3d4ae7d1,e6d26df4,6056587b), +S(1d341e6,2eca1f48,165bb2f3,86207da1,f2c7fc86,dff7a75,cb63976e,f21bb074,923b53ed,fe2f5bb5,56aa7cae,2a08ff86,160e3344,c4adc09a,e7aeadfd,f31e2b9c), +S(8704f69d,9d335975,f0e3bb83,5aa3024a,60103d89,e5578253,fbb3d537,1983ce4e,94f4adfa,31dbd13d,95c738b2,8a569453,cba45efd,1cfd20b6,78f6a724,e9a8d025), +S(7175407f,1b58f010,d4cda4c6,2511e59d,b7edcf28,f5476d99,5cf39944,b26b64f1,bc4baabc,bb1c2aaf,c92cbfe,ecb33791,4fe01748,8bb8e2d5,bd918104,4dbdc75a)}, +{S(a16a4734,9afd167f,d5e79d24,9784d87,5121fa24,2c3a54a,88f9b176,72669aa1,4df3fb81,7021efdc,e5296735,3a177b5c,51cc7762,4755ba28,1084db5c,4809e02c), +S(91d1abe3,8d3f9671,54337e03,d27fa6f8,c3007f32,323d15c8,31306b3a,30900328,b1b8c71d,b388009b,98000f9f,291b66e3,f890d42c,a5812f34,5c070f6,e73b89f6), +S(61b64b1c,f2a0e720,e9bb4853,537b9f38,66baff87,388df7f9,f14c06c7,12080b96,44444011,b6ddadc5,7ee00eed,b6af3772,e4116711,c3853f13,7f9c7b00,2bf2a1dc), +S(3b96b2ee,d9cf1ed6,3aaed8e9,aca3a464,d6a6fbf5,e6fd48f0,5aacc318,dfdbc87,51c41c26,506cac9e,bd0c5dbc,8ce8788a,3469e42d,de794707,9e0cd0d9,826e9c58), +S(7bbd147f,77b293ac,ff797b9,a52778de,5874b754,c08df397,72ed8ef7,53242efc,3e843df6,75abef2b,e4d32c83,205322cb,f53bde0,2563eb8e,b5dfbe6f,27d4cada), +S(becb7fc5,de84f994,9f97e55d,bdb6981e,f38c0c45,1e0e454,519c9411,5bae3d7,754145ec,ee6f9c7c,f91963fb,5b0a683a,ef24313f,1125570c,c9b9c7d2,afab99a8), +S(87936626,aa88346d,6d4330d9,3a188ed6,992bdbb8,387b395e,d21dab93,63d833eb,a28c868a,18dbe0e7,12ca5237,53f6a50b,9313e687,85f3b31f,ec778fac,87aa9327), +S(e79d4b2d,e33de1e2,e7eeeb44,d197aec1,f5883ad6,1394dd79,de274ef9,76e3b022,9c73ade7,7c661527,ec2ec6cd,b370c130,380bdd9a,4bcb668a,86e8259a,ca85f293), +S(863f0d65,34de1222,237a07bd,ebb066b5,2c1cdd83,d7a6d3df,278e57c8,bb59b8c7,c546940b,99d04ae2,5cf7c881,28a985cc,9b6223a6,ffc06fe9,8a3e0f68,439b9db6), +S(71e9b0d1,3972d9e0,2225bbda,5a1024e9,c373eeb,f6514eb1,c113ef88,dffdc3a,4436c52e,c58a34c,562638c7,8d76e3fa,29e3586d,fa667577,2fe0b932,c4a1ade2), +S(ef4a500d,c9369125,78fcfcbe,3c313bbf,f0323caa,75750b6b,a317e1e3,dd8054e3,e807e9cf,7911c919,fef82e40,a3ae1b9b,ed8ded38,e74126ed,863199de,c031f2a1), +S(806dd4e0,fbf72904,c7b0080b,4e7526bc,c71fc52d,f143da80,e571041,dd964915,2f4e2e67,3348c32d,6bcc0741,2e76f4fe,944f96bb,d73382c8,c6880cf6,629eac8a), +S(9ea889e8,acf0441d,6e299687,c532ea8f,8b9453ed,5fea0d47,f735056b,1eb3bfa1,e43f79a8,4d302f3c,88698896,5fa7b8f1,a92c620,dfcb3462,c4befe3f,4afbff5e), +S(9a990a22,1d27d8f3,40e79489,58cff3ca,2720dd3d,ac71688d,9c3c9e2f,afeee215,4957ac76,db370918,7992b0b,63370656,7e0f4a0a,9e5f1d9a,be8f7d5e,8a950eef), +S(d3291003,98ad3d92,1d6cbc6e,b37ac3f3,9360cea6,23edd794,64d34a51,fa7adc60,657c110,5bd8df6b,fe52addb,2fdfc41b,810a1ff7,8662021c,7c220b0d,b3509d14), +S(65eac576,e149d97,3cbd772c,60570870,e437e92c,2e5138ac,9c0534df,b7a45582,ebecb6a,edb87cc1,417e066e,fef8e52e,c61eb00c,dfd98205,91d63c08,9dfd5347), +S(b6976b99,c2515be2,2bc901fd,8671255b,f8fd76ca,1f3474cd,5eebe39e,98f6f14f,84ab17d,da67b61c,fd01881e,b1087e69,845aecc9,ce1535fe,1c7245fa,8df98181), +S(c7f5967f,f9910e10,54c93e1e,d0290102,9bf31787,15f53758,f5c53cd3,c79a52bf,bfb01210,5c1ec69c,847ceffc,d1105ac0,528129fe,3b4d3086,2b6e9562,836f5eb2), +S(ffa0da7a,e8984e4,d02a0fe3,acfb4e81,2a63d6b1,682dcd78,fd2635bf,88cfdf1d,49459ee5,3fad1097,2da786fe,45a2d201,e4a52260,7779b1d4,23defafe,29e70098), +S(5a53d683,3bc1740f,d02f278b,2ac15a87,f137f2,c798f157,725a4aac,63f1798d,ac5e7ec5,86d5960f,e25f9e25,7cf9ee05,110d9595,e440d032,c416d444,6242d10), +S(70f67487,9b030a4d,9ccc0bf2,90d5b78,c455f8bd,a1fa2b52,efaf0200,6b70a6cb,10f5b1c5,dc46c0c0,68757804,93805aa7,5a259dbd,95b4bd14,d031daef,a81bf7bb), +S(a4baf0d7,d3a53c29,e78ff81a,52d634a,e009391b,30a9aa91,df8f7bb6,13e3c16,c9f9d001,7f388f09,b6802c45,e1fa036e,99443467,c3847937,8b384a9,dada35cc), +S(351b8e4a,dd336c28,5d140c57,9f2b089d,3c656a05,b1ed6,4cdbaf7e,e5bc671b,b996e61c,cb14553c,b7b79803,c82332b6,704ce97,fb4e19a5,1f70b13d,f8e2732f), +S(d248350,92898c0,5dbb4465,18695efa,e59ac007,d58b5df5,bb3b7038,82f18e61,23455e7f,5104051a,44600be5,2e242a90,95213d25,b4fd65a7,62c3f9fc,9234c2a5), +S(d3fc6d75,10cb0b20,77b52b00,93e84d47,54dd1a28,4f3928f2,a9e3cc02,f1869588,26e86b02,c16171d4,4238aecf,666146f4,9386e0eb,52dfed87,7ac0b409,51ced10b), +S(1c611335,3d115906,182b0e4a,7eb3d39f,552c49f0,c5928aa1,15ae00dd,c23a3b70,1c3e3c4e,ed65ce47,ea82a33f,df8fa6b5,532977d9,53aed38a,f0f4dab3,98477c6b), +S(6487c5c6,abb6e673,821c4b0,2c485f83,3e149af1,83b3f025,71a81fbe,660e98e3,63c4f6b4,7eb37ed6,7668b41,1e83d9c8,9ea323f3,2d9e8918,20b65276,a8a7b7d6), +S(1b0baf63,6daaf2c4,28a62bce,bdd41de2,a4d7cf69,93f0b931,222a40cb,9f5f9a2f,af9a62cd,f91e2c6b,47f308af,e2de8f16,def4972f,24bf4c5b,2b1f92ac,f63a21d2), +S(95bbd974,78e1b8a4,1622e460,8aa82fe9,e77d43e7,492a0d21,1146d987,f9b8f255,412bc52e,d61c3880,210d3df7,f0d2f27,d458d51,388803e,fef1c016,d7c9e7f6), +S(a3466715,5b6ea598,2d3945fb,743a1510,c671b96f,a3494a57,e0349010,55ae087,de35a05a,1a943a42,7210165e,55d5cfae,3ac15490,dc6b0f43,34c0c99b,dd778608), +S(2ed76c11,52ac3600,7aa17c85,a5f902f1,7c845a05,a4e0aaa0,7b05e836,cbcad59,9c60b2bf,bc47a0dd,d3259151,37e89812,a08d39fe,cf5806be,eb538575,3b159531), +S(20e6e2e7,96946bb6,30c7071e,f1b92ea3,d53d280e,e450111,5f5da36f,840dd273,2c528501,b0eaa61b,b5f45e52,6878b9aa,7ee13686,c25796c3,3f8302e9,44b9469c)}, +{S(f040a2fa,b839c753,4e216425,6c2e8dd8,57c52dac,e75cab3d,512a7b1d,562075d2,9e211cf4,bab24e0e,f745e2a0,9b59565b,be7b2449,8123f6b2,ba383b25,29554b36), +S(c66813b,904831cc,12f89e3f,bde93eb3,11ade6dd,f6cfdf72,21cc61a2,ff46bf26,3b60c8c9,9da35a58,7b9650af,f85ca785,ece41146,e7ed8d6d,ef8d26d1,f3d055ce), +S(cd38ece8,7c7a9cbb,e23b58ef,59925633,734de285,f93b3ac4,eb01e03a,adab904b,a5f48fcd,afe414f4,1a44917a,5dcb80b9,30373af9,70e9f22d,c1af80f,a8b06320), +S(72d6f7db,199564a2,6e823a49,eb0171cb,ebb76a2a,add56c7c,6d3102a,9c3ee18c,bd2039ec,c390839f,e2d4451c,9437fef6,3e98dc62,3ab0eea4,c56376f2,e270f626), +S(2ea6c313,1e101867,2454e15c,d34d5fad,13829d5,4ca86062,f074e512,a274167e,67e3d34a,56f12e1b,43687f51,c2d56395,14355d7d,9cc52726,22f62ab8,91c8d5de), +S(d66bdd78,8b20da57,b2485804,a2f6e2ef,78c7ca87,ae1c5c66,fc533533,5b624162,1a8688a1,300e6d39,e130037d,3f074ccc,57addd1b,88977e64,2ab296ac,d6e054c9), +S(6d6458d5,d1683d85,8f9e40,15e5a94a,73868bda,54f6139c,446b5283,6d211542,e44c7ca8,33761e13,ca5458ff,dc682f22,3819411c,a3c5feb6,24f06412,471b9f5a), +S(49f8063,b3d98f6,f159f2e6,65b0e07,8ef8c7df,44da06c3,55b592ac,13402b9d,b0b2d838,4b24ab11,de895013,e897e825,45c3e8dd,6cdb0990,555cd871,5841f8cd), +S(8b2fb6bd,e60449da,2684f8e3,6267fff7,254051ac,faea37cb,102c9bfa,91abb2ca,c82cb9ab,c33c1817,10d3fb19,60f2850b,5072eb47,404266f7,c7964fb,f98027d3), +S(cf90331d,73644476,47c8f86e,eaa6e67b,f3fb4b3c,4c895b82,30ab2f38,80df1e42,9c493d94,3471efd5,ea90f723,db576a35,8cd1ee6,1a119b56,6c65b16,112eb2b4), +S(e70667cd,8d2759e,43f99417,ecc505a7,953d80dd,e7ce2cba,3c8c948b,d43a912a,92a534b3,51449a66,82395a3,b75877ae,851923a2,e791acc3,7293d728,777a2247), +S(4cc07d11,4a715e9f,4b4d0811,f0337c7e,f4bdff74,2fb008d2,1ce8a9ea,50520d47,478b279,613d92d3,dd24ae31,2658eda8,28a7d628,f0346e04,5d5d9dff,7178f093), +S(2a1cee60,4cdd3b2c,1f859bfa,af63d7e3,9aaad910,92c2a38f,a9362798,9753c30d,325c248e,d409e8f3,b96dccab,6fdb62a6,83b7eaf3,36d2864e,b821663d,ed31a6f5), +S(7c18d0bb,9a01969d,302616cb,bad8722e,d00103fa,9985a50b,765f0e2b,9a2ea14c,f6365a6c,b06e4749,c48c212c,63fff571,8f46e0cf,6fdc8c42,34d4db64,ceb72080), +S(a706754,65cde407,e853e882,8fb7a2fe,98638d7e,64b8df0f,b0a7a0b4,e629d0ee,fd694b2c,1354a5e9,415926d0,1590eaac,dbd1b36b,5ecc46b5,72467c3f,e2cc5393), +S(7ff57a63,36ec73da,cc1dc527,928cc6ff,4ec063b1,56b36292,23b8bbb0,a8ba2c7d,4d6dfc43,da0fe33a,1e75dbf5,5e5d669e,be6471d,eb8a4102,6db1a41e,9d5da637), +S(d4b1f7bc,87558c27,7e0fdf91,22bfe488,b3182555,599dd384,5cc039b5,93218e9f,992f79dd,c8f46682,5c44a54d,626b352f,7f59139b,d545f78b,44bd0b10,55c3c1fa), +S(897773f,a9de63a7,46ebf58e,248d0c21,10f90230,a792f0b6,ea5a25a0,9d1940d2,b7c7dd27,d561dde6,ca7588b,8e3a09c7,16297ba3,9d501744,f9639a25,b16b4f64), +S(2f9cb312,b071a600,e5d24cfc,79b0fdbb,f6da1527,10ec395d,53078453,1a3b07e7,49260f95,757b9b66,feeb5c20,16aa051,b444bfc8,836fd8a2,ab913e98,731fa97e), +S(5c53b27c,4c0ae241,8569c806,8dd43a5c,6fa23ac6,74d001b4,eee6a748,d86c9e6d,4e0e720a,f430972f,b0ab89b8,79a56eb4,f0af5161,cae83ca1,964a8099,f9d497c1), +S(2671ef50,5a321387,9560f0d9,e8588707,1c2b87b5,d06bb9d,dec3d179,6275b098,750ea18b,dbdcbd58,be994eb5,cb3539f5,8c3dc630,7d50bbf1,f69050d6,235826be), +S(59baa5ce,9d6e707b,b0738f4f,d37c9890,801ed796,a82afb2a,ecd2c5ba,195be65b,e6b66356,20a8a106,b58dc202,10cccdd1,e0e8c579,c92f3fbf,8b335765,b30d8291), +S(bb422d0,88abedca,e4686479,295aa1a1,77d7e68b,293bcd31,4097ddc1,af764b90,a96d33f6,46d4861d,a471f853,e0c6ae32,b1eea619,a7441504,a773f5e6,fc548805), +S(8d7df8a5,f08ba2b0,923662fc,e594f111,5295cf6e,c5aec9ca,df0f7236,fe51b362,26452215,7d8572d0,f057ec9,6f572f11,ebad3fd0,56032240,26b54df2,991f9046), +S(9e2b1637,352d8988,1e76fdec,c2dc8533,6a71b18b,3c98e59d,397602f5,8b9087d7,b997404f,1c0b1e64,90cff078,fdc47c42,aedf245a,e69d844c,18a146fa,6d8c3d13), +S(972c7bc4,6362bca6,b58f1d0b,87c0b8dc,fe91a217,7f0cd7af,404f6f06,47e09358,cfda778,a59d944b,4ec08bcb,3aabd70a,cd6f29c5,204c9161,fe2e5bd5,71d03f6c), +S(f7dd32ed,89ceaace,52e7f26b,202ea6a5,c7e8ff42,6c7ebc16,12106f7c,6fe51a54,7349c17d,d8ea6ad1,cb346e3d,26989950,3de00c11,4205b3b5,50d27ff7,67efe75d), +S(c9f96f88,3e34aed,97351928,fa77b07a,f4b01bb4,e4515f0,59745ee5,decc9fbc,6fd62453,dd6c9dab,10fb7d79,c15b4822,178eba31,258800e4,519e627e,91ef20c9), +S(9c28cc93,809b35b3,96a4c9cd,d6976391,17402ffb,5588cd76,7c41a92f,e971a9a,ca3b2634,28513516,86a661c4,747aece4,c8130d93,ff4108a6,3365e725,2bbb80ce), +S(263a3fca,437c4dbf,48ca36e6,aa892d61,abf58f6a,d3c82b1f,fe945dc,c45a15f8,604c5bec,69e0f1a7,3e8f8a80,4f762cda,96ba2198,35268887,910c8df0,e83d3044), +S(7fe42dfb,b3466ed4,d7cb8242,5e66b5e1,14a70516,b118911f,9170656a,3dbb04fa,d11385f4,b0a3a0bc,cf09374f,868cb30f,55175d77,2d3e463a,a298b6ed,1e6f6fa6), +S(53f2432b,a8171714,3fa9df3d,ff41ced2,4a29b314,bc5a8c96,f5f6400a,d7c0979,42ad1004,3e0f8648,332b1c1f,6ee4f821,b42a5b0a,361747ba,60816f2,ac84c58d)}, +{S(b8b52efd,bc367a5c,a1534bb2,f339a048,50fc4941,1668780,dcdb8b51,2daa7526,306a2236,856070ea,1e0fd846,cd571889,e20968cf,cd490bc9,facfc4e5,a5970b2a), +S(27e226b6,ed59c89,5bd20232,bc677c35,495d9601,5f37493f,5075718c,2017e42c,a130a5c8,54ed8ab3,ed657e0f,ee4a04cc,1b59a291,6e96465a,74b36144,7cc621f0), +S(1733f1c0,da38fa79,a7b37988,1822ef51,2392d8cb,59d1ad1e,afaf535a,e151fb64,a93ddb00,af779565,eeb230af,815f9434,958ad39b,387d9069,a03cfcb,8563a920), +S(e3f4b777,d06c8839,c63dfb41,73281787,72debac0,ed45b991,724c19bd,85ab3c58,2d6a84ea,745decd9,e6444b7a,dbb59fa3,21957b7c,3f8141e6,fd633d3f,7539dcdb), +S(a2b42fb8,9ac10df9,ebe804b6,c105e855,25cb05eb,7407d383,3031e216,64491ff5,d0973dbd,346a87b4,f4ddfddd,12be3131,e6c6a397,8e17be2c,bda23683,62f80765), +S(66d441a2,6b28378b,cf23d33b,ffac1163,7c23bbb7,7ad352e7,ff5cc09f,41bf6e91,982aa46e,5fa0b19a,28ecfdee,539c0ec,b5f06e2a,217f7687,6c3cbf1d,e92a6068), +S(3721fccc,20338f8a,779aceb8,eae3fc7f,bb0e4040,1de2c8e5,27941ad7,f789d0f7,d9516c54,8f457b6e,d44f6bbb,23f36c7c,e6fdc548,60e5042a,b3dd4f67,ad5ae3ea), +S(959e980,4618bed2,73b5cc48,5565df27,b8e09c9,a128a9e5,ea92e347,66e02015,cee3a227,1bddee01,3582d65d,c3e26c8a,f80a4601,abcff432,b1737127,91ca15a4), +S(f2e81d16,c19466a6,1b56931,935d03e2,aad6b8d0,7f193d97,bacdc29e,13cdcf38,afb8e973,8d563dc4,1e7688f6,c6b43b71,f366b576,9479f093,88fd09e5,faa1063f), +S(98305a48,800f92e0,bd815192,7b8658fc,60a97c64,c9f97383,68812614,3563910e,d32db8e2,6699b969,5b644c08,39f2399,f8ef45ad,a0d857c5,2d0c7c3f,96a62993), +S(8dbd4fba,113c50ba,ff3f251c,96aba9c0,440d8e69,8a1e4ec1,84fba97a,e497c443,f642b1d9,b012eef2,40c6ad38,fe441d11,cfb42ec2,a3c15540,45e64c76,c15be491), +S(deea5bb6,c7eac0a2,93e90817,836a3e55,2a7f1354,395296c8,97964c2a,4527a727,4cbe143c,c9fde617,c6142335,4323b9d8,bba13dd7,fbd46db5,cbf4ce2a,11c9c00), +S(349f46a5,8621034,9f207a07,4558787d,336cb0cf,a56c1e67,8dd3b04a,4d717f4b,a6479d8,f7f017a6,32c369c0,8679fecd,985b3c16,ff444ba0,3fe43575,8b96455a), +S(a6d818c9,dc182fd7,81343bc,b737811f,611c8499,e44a6cdb,33a36beb,7e44b545,1a8ee36e,d6e9b191,b9cbf840,3924e6b8,ac3c3f8a,cbc9a0b5,ff965d6c,734d741d), +S(f9cad333,7b82ea41,b00f3ef1,bba37b8b,fcb24e8a,175fe380,8e399b67,d21837e7,cb206854,4e7f2cda,28c035f1,b8b50009,319797da,bb498b99,d31e24e2,4fa27ca9), +S(25042b59,f9b29a9c,83d04515,c78f1c25,5b72f97f,7b387113,e88c36b9,9da3ebdc,d966ba9e,a7eb9734,e1481cb7,2df63252,7492e1c4,43f1fc9,c0efe0af,442b5a13), +S(e19c4319,b5c9a01e,b588c629,8a7c6b76,1b80bf4b,e39424e0,666ddc45,fd57e0f6,1b0a2c30,4a1bb1b1,9dd0b50d,29df625,bf958a73,46cc6b1d,81a213a3,b6636285), +S(59c26fc1,6d151c0c,7da0edf6,c474463c,587c45cb,7e407589,d15aad89,de223fa0,f7b227b5,4855c1c4,1e576431,8a7106eb,ea214686,ef815b42,db8c18ae,d5c940a5), +S(d967d546,e07ac1c2,31fd50df,a1d25a51,60594d88,3e816f6a,bd62c15c,446aeff6,8eee6c03,6e22a014,5d9cf3af,9b44e005,cd1d36ce,d7c420f5,e2db918b,e4fbf83a), +S(424b149d,9104254e,3f5772b3,7d973cf2,a46bd110,89d8f850,7666f04d,382c972b,7272ad07,54c18fbd,66e2abb3,952c526,d8113d5b,166283a3,9ac8ecb6,2b7a3e46), +S(40b4b2ac,bd299270,e64bc470,8607c586,3bb50913,45e573f3,a5e2461b,47dbc053,d094311e,fd81bb1f,4622d17e,68044107,a2a8ed54,3cd5ff8c,b531b28b,9b8ec99e), +S(79e79ded,6bc0d851,fa769b5e,8d65857c,f3c1c18e,6c990cb6,116fc45b,63e9f924,4fa89e89,ae4214fc,ba2aecdb,41984788,8154eaa6,bcbbe29f,f04a6262,7299f469), +S(a11ad5ea,59c644b2,8dd7402a,5f96a970,68d96e2e,eb77d59a,fe0c2fc,cc6b252f,38e379d5,150109df,36ed7ad3,a2daa41b,4fb9c731,718cf5e3,8f8f8cf7,d1f3d770), +S(b3002b00,ec5be154,cd8e5226,4b97f5c9,f444b305,8f59c4c,bcda5edf,9d10dc88,f7e9ae65,6ad2c823,8e8e0436,e007d821,b17d9405,984eccc4,617e3977,2f25d636), +S(8d1267b1,94da1334,fd20cb8f,77fa01cf,9e9ced90,43107e41,d1ec4057,eb6115a2,a7ba1b9e,2c6f0f19,5ff1f50a,7a8da22f,da3003fa,44b818b9,953b44d3,e6d6a0df), +S(dde6a3a0,87ef41db,2359e4e7,ca7cb064,424301e7,c5cbb5bc,4b6e504a,f3af4837,24175b1c,b4b39b7e,23718e26,be4a22bb,8bf54302,1f156234,e7f18010,d538aeb), +S(79efa584,2fb89f4e,85f556e,c4be170d,5c1ef88a,3f3f75cf,6b20fc1a,96984ad,b0704aaf,e4d8f30f,4f29fa85,6d55da13,91f5f3ce,36cdef6f,25133999,cc8541a), +S(3aa09dc0,5546977f,7369fa0a,7b60c94b,eab86a1,10d85af7,7b826475,7d67eaf5,343b4cf3,aa6c5ebc,ed041d7f,2381be57,f7fd32d0,29a2f42,a7c8821,4f425d8), +S(53fe8af9,8f9419fb,1445bb6a,94750d46,46be9f37,b7155763,88b11064,df2e6ffa,6cd77e81,84aeab9d,e9bf3093,bb9b21a3,a04a0719,fc428f3d,d5e14c8c,9b16cd7a), +S(fc395dc4,a5114dc8,bcb0f7f0,3a4d3e9,38a87a3d,78d33864,d1dc4cba,9e41e20e,c7991f6e,f72f82f6,b3147e56,74224929,fddeb8a5,97a1b1d4,8852733c,1830b941), +S(b1d25d51,b4558f5f,d0ccb868,3af9a9cf,62a169c6,91627fa5,92d80b18,36695f94,8f92258d,fcf16f4e,8415f53,e65457e8,9f090e72,5479c123,5a481464,a11cd4f9), +S(b866d6b1,42df940f,2cf28b54,c92f0c12,94e0b6a2,2a91f2ef,44bcd88c,4384480d,e6eb4f4c,bd95148f,765d8728,15652853,db1add7f,b4e27929,f19a64b7,f3b34c87)}, +{S(d4aaf32e,dd897f48,5ab16466,76d747cd,fec5b7a0,a05c917b,60c07311,45d16f89,4857e649,beff4089,2470f700,cadb73ae,d4866a84,c3f0b975,6fd8570e,df9d29d8), +S(4ebe5b8a,f3b1583c,9f41bd98,afaba549,f45c381e,c93ec9d1,4a543d87,9cefbaf3,63ed1d17,9b215f34,f1f580be,4b3f671f,2fa14689,74cd03d1,19fadae3,c92935ff), +S(20df6160,556dd3c5,a26620a8,70ff5323,cbbab94,be3e3bdd,ad8b936c,554f28f1,7168e7ab,cdbafad,26fbb5be,a09dadde,ed36c20f,c8deafaf,75a480b5,f980e981), +S(86c663f2,cc6f7ee2,50be25fd,fb35fd8e,5873481b,c477bf5b,c0f1bc1e,3f1320f,c13c5795,cce0ad92,e31240da,90a823d0,d2352314,f2852e67,cb62e0c2,8570994a), +S(3fd8085e,57f6870,b25e41d9,7df00126,150f6022,a7ede22f,d27da581,d234ccaa,c6657746,98d6ac03,ed1ea2d7,bd3f70be,86351c5d,407a4d7c,227fd7d0,c330ef04), +S(1510fcf0,b0fb5a23,c15e041,2a7f6d89,9fac4244,8ce316bf,d88fb58b,10e23118,1879dc07,b34d0a62,f0b9517f,3629ae0f,e8aa6d30,5a783f37,69bdf65,3b40408e), +S(67e9982b,c40f427,98df055c,2d8bdcc0,2ea97bad,68d34024,85498e27,d99e19e4,4f087caa,efc5fd7f,b099c134,a273635c,d1d5ace3,26e3103f,9b2fe22c,e95f288e), +S(e8eeab21,6c3395d6,d16338ea,de4108da,1c25e471,67fb13d5,99e8daaf,93e7345f,7fd2ba87,7c7266a5,65a31548,99950ea1,e5e3d73f,612addea,318ad5bc,a965228d), +S(ab20c7c8,9dd74c20,447bc762,e374c548,e7a8ac31,eec11123,1a040cd1,36e9a546,facacfb2,52eb9532,9106a26a,60128a0f,ae1d7e5c,fd39483c,aeb54dd9,231b55ee), +S(a9004211,b7cf5494,1c530a0e,d658fb6e,3b5d2ee1,37b7d7de,45fef6b5,efddbf0f,58cbaf67,5cc5a131,54eef7a1,462b5d1c,408d5d56,3553ca55,45388d77,c6391d4f), +S(8db64274,422ae0f5,6474b83a,89912fa,e3a39b6c,b3fb8370,308a572e,b6b3c020,9b71a72d,431fd44,aa8632ee,23bc678,61d96edd,b7ec72ab,4b1679b8,a4ba73e4), +S(301b330,c478189d,dce4314f,380cb2d8,38bbd416,5dfad8c4,90f2443f,2a56148b,737da0,1c05cf73,db36a1a4,5005f562,1327167f,d3b60ece,3da3705d,131903fe), +S(b9cbc7a3,4a1cbdd1,300e789d,b7ffec1c,dfe1f738,fbe1fe19,67dd7c14,92ee3ba7,5a816a0,9d08c4be,2b8d062f,200fde4c,534fbdbf,854c7e53,64532c08,60c97c01), +S(6a15e51,6f9f0a7c,25f2eac7,649285ea,d86a1e01,5a386dc,c7f94ba8,4782b45b,63eafaf4,660642ef,988aeee7,642e7c4b,71124a1c,2ca2f5c3,d4f2eec9,ea72d70e), +S(f4c696f3,34c56e08,2ab2e627,4d450f34,fa7fbce,29f3e14d,332bcadf,87d5fe0d,6ee44edf,f574d9a8,363f98b6,b863a648,27d3020,1e652935,be12041c,1bbcc7c3), +S(d2f3d5ad,237ba177,ed312bbb,1d02fb2a,e4bda20f,41f5c217,8b70dd9a,c26ee9b0,cc5912d4,2ea1af01,aa914b98,8c42cef8,46a5a059,664c8545,fc00b662,e0327920), +S(5588b0a4,757beb33,e668af5f,adf87fb3,2aed8e16,e6ceabf1,1576ae17,c6a2b843,70d8961b,ac203e89,c437b88b,ce331309,c4f7eca8,d614299c,74aef9b2,17c741de), +S(f993cd07,f6eb75ad,d41426d5,cc653886,18dde1f0,88aaf3cd,b2631eea,158373e0,1e74f804,5f60349e,a85b90e1,206f0ea4,b0cd3740,861186be,648063e8,58c2b395), +S(2cd04170,78291a50,750218b9,44a11a64,1cb75e7d,cd5cc4f9,64f53c8d,a1ef08f4,1f54a70f,f66ce343,c7ed3001,78d7b99e,49129e23,90b5a026,7ba25af5,3467b6d3), +S(52fc09a1,d4f0cc2e,c7ba6cba,1b30e1f0,b9e37f31,3bf59c33,60fc02e3,3b0c15e8,9bd14bcd,a7c7b6ab,dd7e17dd,ab81a1cf,846be336,a76858a1,8e8a0194,776f0a80), +S(90d29aba,764a9b49,1e2878c2,9b964bf6,e510af,3dd5aeb9,3fe29e13,b8f03b23,396b1f6d,e9b8fd1f,463ca064,11b09823,26cb6ab7,4bbbcaef,43031497,f149a620), +S(ce1d6e8e,ddd063f4,316cb006,b4a4213d,9e0952c8,43e6e1e7,570a35e,aad7fa53,a1abcd7,e2c23ad0,895c5aa8,82a805cd,1d7d434c,72f0c528,2ceec0b7,a7016f7c), +S(4df6e1d3,93a4be66,6fd88c75,e1e686a1,e2cb1844,f5f1303e,f7b0a751,99b42bf5,262d8b9,f7e202a3,78a51928,91ee3fc9,f269ef5d,e14dd0ff,f1fec9f4,4cdb9058), +S(f71b9bfa,bcc353a4,11a055eb,a7d6f48f,47c4e437,96382bcc,d5b882cd,a9059638,bfc1c3f8,fea7df8b,d1cd088c,b1f02e47,377d6656,9b3bd8a2,8b457ba5,e6453468), +S(ad5e9212,d3ef76d,8319fd98,72ee753f,ec99fab0,6244f4e2,a9567068,a635eb53,65fb538f,cb570092,7b0f775a,73ffb0c1,4e6c2274,e253f3a6,2dba9caa,27a3e5e4), +S(81a7dfa0,7659fdbd,57e1c8ae,20c14a80,ee8bfc51,46caa8db,b077b653,23bad4a,ac9d2438,3ef0d99f,26744be4,77e69d51,49d44ab9,84801bb,759d3a5b,7fed1e2e), +S(3bf8c1d0,a613316b,e90eab62,6788c8c3,b1641d65,d0e50245,9e5b19c1,ab1eb617,e1edb59a,8594d73,669e6f93,ca10e210,1254946b,8c9e8eac,3fa84a49,e4e2944f), +S(30f9283a,767c551c,e9fe87d9,5730eff6,fc302a4a,1810e4de,11ba62af,fa17eaae,1f383ac5,e714240d,67980617,d96b0c05,76008599,f8e3fa04,d57454e9,927e729b), +S(1c5d4ac6,91d37d0c,9db5e071,c809a59e,99056263,fbd83028,ee9530e9,c2b3f3c9,b98c7be9,7a2fb196,3d3d4a75,4f7fecce,2fbeb8fd,cf23c229,73b6875,86bd276a), +S(3dfe48e5,2f055be1,1db79fa4,501b44d8,f5ae8447,c5a1293a,a79f683f,1e1e9bf,2d7e8303,b988fc17,18c9b64c,1c03373d,27fd0c32,13c26e6c,b684ca94,49f79d5e), +S(adc4251b,c3ef6d5a,a4d6eb22,46ab2787,bc835b65,1d17ceae,489f181d,57d37248,4f0c489d,1c3a1814,a2f9c1c9,d6fe908f,4623aa44,ebaf4143,79fb8352,15234014), +S(edfe16b2,db401803,11f98920,7a2fef7,d05b2a3b,b676899f,9c6e2192,d38f93e0,1196fd0e,35a24c9,6b28b055,b4fa2f2d,a4c2aeff,3b91dd81,c2fe86c1,1d6bf682)}, +{S(b4b57b34,6e1b41b,7394e655,e059cc93,44c5d83e,f0ef17db,2789db5d,13777b78,6fa187a7,4d983b7e,cea6a268,61039430,63e599e7,cba73144,fe3eb23,677c6265), +S(9937238,7300054a,1a8713b7,6942f003,99818b28,6c6fba5d,ca60b9da,1aa7767,6c003e1,848ce30a,65601eb,e7b76acf,b2e122b6,882d7439,f463c042,ef1b31a), +S(ebd177f8,b5757665,58851c7f,a7ada38b,e3596080,f2679181,f994efd3,82714784,d0fe8eb0,97c852f7,b284d5f,bd81f77f,79c35af7,cc30338f,4e63211e,9e20a244), +S(367ef258,b279f923,a18215b7,67d396e4,c6bc874d,2be6b369,b01afffa,2e041741,bd961242,2452eddb,33831dcf,fb3a0273,30ef141f,6db77d91,5bec2ecb,553b6e6c), +S(d89f40c4,f752cff4,5bae5762,37f5096e,f27d46d0,d934d4de,c3011a28,59464e8e,9d32661e,e2319d6,f6427ea,a3014b5,cf98306c,666c4a9e,970dba2e,65e04886), +S(ef6ff862,1d84c5d5,22e490f4,db21181f,a17bafea,3e097868,4f1f0215,759772b9,ae006f11,aa85db2d,3624cf51,ae319ad2,8b4970e7,eac03301,1eb15db8,dc59d62b), +S(8b0a1b1b,d476bbfb,6da1d071,68d3a988,3b49802f,8ffa04a3,bbba1313,17c67a00,d8c74ae5,65c38597,8d9fda2e,dff6b932,1512e40b,ec5b62e2,59d4d81c,9b657b55), +S(9aa9250f,12ffde38,21384434,849d7eb7,bcafbae5,9a3b861f,68a3addb,d75d3715,19b4b1a8,8d8bfeee,38b54564,30d5f73e,ed0365fe,49092d4a,2f52fa12,b65e3ac7), +S(aaccc00f,55e96f0c,e66d9b43,12f9abd2,6772d8b4,30a6c62,edd2aab4,97acbc22,5af203cf,97d11147,82374056,f012f5f9,2825476a,820dce2e,6e1c4b33,cef5337c), +S(43c34546,2836b544,ddd6e432,6aa19b4a,9de7fdfb,86f43cae,ce98ce7c,32b1ccaf,dd518249,f1fbc1c7,1f905860,17a6f60b,15be97d4,18c66d42,f4f9adcd,d722c096), +S(9a38eb25,935441ab,8983097a,d58c821f,d784f091,5f85dc26,3f0c020b,b80c39a0,d8e6dc57,41e4ba5c,576179e8,9a6dcb4a,bd7178c6,13a1100b,e2bd731b,f3e819e2), +S(6b10527,204a4f7c,e8afcacc,fe771634,376f18da,f12774e,50f23a90,9efe0223,b443a451,529b4208,c8c98904,f5eb2ee,2e2ede2d,80ca50c5,aa29b95a,714181a), +S(1a88fecc,71d7550a,abf7faf0,8e884e95,835f6dc8,1815d2d7,7dab66ea,b238d6b2,82cf6711,1dd38ff,d0daebbc,ea2c064b,17b6b21d,34804f93,4a037936,9edec692), +S(a6b1751,f30507fe,5927b6d4,a92ebbbd,77358c02,9b750d05,a56e4d41,efb99144,ccf7c048,a2a0983d,fdcccfd,a071b80,e8035866,c479ea3a,3bbe7c80,12dfd618), +S(e186601e,8b545292,f23ae7fa,4cadc80f,1fcaa1a3,430ddec6,cfd2af47,c835cdf9,fd471f16,7c3683c9,2e5fc0c2,89b646a5,c8ebda6d,5b6da213,d862c3f6,2c292e9c), +S(91b3935,d8ce2b80,c179ee0b,87850140,4c418c7f,7cf94e4a,64b9fc9c,e396a093,45a5043b,8184546c,9083982f,550807d7,d61fe677,ce73ef21,9b3aa573,97c4eca1), +S(3fbe61fd,2a387654,dfc428e7,dac09e91,5e1ae7d6,d3794288,743f2535,20858ef5,206fd9a0,e3265118,e0a6475c,4df87e43,cc7c8898,59d8aa08,23b6dfff,b68b34d7), +S(31a35020,697d9d52,55476289,ce4fcbdc,4e1e0690,c2c36d1b,a4f4640f,e4c5ba18,91f660f9,159d463a,857f08ad,fc3c5ddd,804507c5,92f73de4,2ee44555,da538553), +S(7dc6b83a,10f26e71,e12c0bd,7ebcccc6,61b4394a,68f576fe,bfca1c23,256e8aa2,b4796977,bd386b98,f3e2fa8e,798b6548,fae52a80,40bb12ea,7e6ad675,64fc8736), +S(67a9c3ff,9c7b99b2,5318ff9e,2b85ee23,ec244655,8042ea8b,d880e23e,7d3ce221,a7bcbbbb,895ca7b1,847a43fa,98809ce4,98016123,bbb3c099,7d34debd,cb023f8d), +S(36602997,eba2c6c5,aab4cb65,8d4efd46,65ab3965,f643ff66,831646dc,f6443bf3,c82d0e80,ef775f9c,7ec7862a,e3158556,a57038d,e6850dd1,e349629c,2546239), +S(9eb9244b,299bfd76,f63bb140,ae2f42a1,4af1e072,83f8259f,6478ac03,d411df24,e43f91da,13c2ba21,a9d17d2f,7a8a629d,9051346,93a6552a,538d590,9d2bdd38), +S(ba4450fa,27d57993,3d949a1a,66013906,7d1a9716,6794993d,e45d9426,b4bfc5ed,8e3f3b9b,d8cb8210,7a5ae2af,92b96259,b73633f,6528ac04,20c3e101,6bb6d8a8), +S(e6d5335f,b67abd36,2712c7fe,575ee769,53d488b,236e8589,5664fb04,7f385248,9e255154,e070a5bb,e98e97f6,281fb999,a75e68ea,7681fdf6,fea093bd,919aa5a4), +S(63c099a9,300a331a,3bc4348a,a373e514,c84a810e,1ea8a8d1,4ac8d7cb,818eb534,ed7d4029,3cc4a086,b1d40c24,6086109,a02dbcb5,a864777,27939024,6fd6bf91), +S(7088617f,66cd93f,8130eaeb,874c3f77,3bcb0daa,78923b70,a65512a2,992554dc,5a3ff995,3c712066,291ac4a2,dfc2573e,1d0aed56,75ef526b,b15f61b0,d20f8156), +S(cc354aaf,746d756b,9387730f,2f12b999,4fcd815c,6d25cdab,2e1185aa,4aa639b3,fb1dead9,4fd76859,1aac8d79,5c337924,dc155fbe,5cd5c953,4d55ee31,f6d284a6), +S(e7e47c3a,e2bf4307,7f33ec3d,ac1ae2a7,5c669e61,e248f588,590cfe07,3e2186e0,46e9c4d5,4429fdcf,5efb375e,18f46cc8,3fa7a403,6013777f,e450e228,aebd4cd0), +S(c6ed5e63,28ec31b1,37041108,42d4ac23,fbb883bb,349d88db,1d747cf7,325fe9cc,21b8bfa4,b62807cf,d6cd11ed,a38084d5,7bb068d4,9f0dd30e,f3f431e2,b57022e4), +S(331924c7,50b3417e,48e279ff,6ed7f3dc,ba2e121e,9f69f8fb,e64093b6,c38a8cc6,357086be,e4cc0fe7,d45a49fe,41d004ce,80466165,316164ab,3b171f03,b9a7841f), +S(b4319cc9,f3e0d3b,313626ae,5385796b,c49b300c,88ba4553,dec0aa4a,77829372,b8f82bb6,6590afd4,48501f,63de3a5d,8f84edea,35c1ee44,88d6333e,f522a808), +S(da433d5e,11ceccc0,abc5c762,6ce7bab4,2e89b221,f785c409,282de545,f3fceb19,1b67242c,de57efcf,e214423b,506a1ade,718803d2,6dd84d88,97b18ede,590a2fcb)}, +{S(ebae7464,ece277b8,309d056c,cf3775e2,11a77aa,81c316a4,b6b7b953,6f90f539,62a4d6a2,95fdd811,f2051715,322f17e5,1753c9d0,835ef9a0,3e8dc9f5,c69bda31), +S(5b20700c,1af63394,a3e4cadb,b0ea682e,19cf495a,b908418a,d41f4c6c,ea4477f0,8435d15e,34b03a22,ca89c73d,326c2f88,142d2e23,8964ef6d,99287125,79738f78), +S(b2f25f91,138b974b,561328c0,92f50fdf,8a694004,fd4879d0,12a4a6cc,c8059d1d,d9ec0b2d,b8e81b2,f6feaf55,9776ff78,cda3401b,47826de0,ca06e579,9d866c09), +S(64e79790,7783d6fb,321eb785,acdeb2ff,4628270,fec3342c,527c8db0,a34c516e,c0c4da5d,abf3da9c,a8613f82,ca28e84,a1a18376,c9967c08,aaf70bea,7a2f34c2), +S(a50cae84,a08f4f32,4984853a,d4c6bdaf,77eaa788,9cb8fe95,72fd56e,9078ee73,120ecbf,76e47b38,503067c8,36853003,60ed261a,40fdf440,161ef2cd,19786b93), +S(76ff3ac8,80a451a9,6741fc70,82bc4c82,7bd51c08,95eea8c8,b422b8a9,96ba4794,25555d71,d4313a60,b189a154,58e0a40,c643c204,277334e,966e2abd,3a23f6c3), +S(307e5caa,8b708760,3d9f845b,b78f4f10,72c49c10,9747f91d,192f8d6e,70c0f4be,f5992f76,37167e1d,55cd31a6,1cdb4756,85eb1503,34fb6009,e0240a18,fa8302b8), +S(d8e62e47,b28fd165,4d420137,884dcf21,c10cb159,d9885843,da34b0d9,d09b2758,675c75b4,b903ad28,2055a71b,2c470e2b,1dce69bf,ecf160cf,3a027de2,55b723a9), +S(ec5639c7,73dac23d,3008dabf,732dc005,3154703d,26ee3bbc,7689286e,4a73e39f,aaa5ea4a,2cf5c23d,57cdd0d8,8accbbf9,9fd2c213,97bb45f8,83547876,3aab1248), +S(3d928ee3,2065557a,27722f08,5202f48f,40917ed6,c7ac1963,2a122226,8b0cb9df,ece112a4,e7a05ad6,17c2fd83,76f89102,9eb94eb0,930fb23c,a342d7f1,f021a0c7), +S(616228a5,cc6c3a92,cd694cec,4b2b8574,5dfffa90,b2a36d8f,32eaa6cc,2530de51,50d8d140,4d506a78,700f8e82,967b36a5,1b4de644,a8e22271,d509c8d2,4adf3148), +S(6f85f308,e847b145,c13a07be,bebdd4ba,6c138939,6afd8670,733f44a8,969406d0,864bcde1,be36c9c7,b7e04ef8,cd2366e2,b3c22902,5ee7efce,d005ef5b,ff7dae2b), +S(f3d1ecc3,53a82621,1bd78f0f,aa029076,c6ca779,9bdc54b2,128fa3d2,aec00c6d,75aa0cf9,fd0b7bed,19183e34,58142f66,c94a5aa9,3915435e,ae51c1fe,96625ccd), +S(a5918de3,f18cd8d1,2a234f9f,3a19fcaa,2d83671d,ad566f16,8aea2b1f,b9de41b0,c515dda6,43c0f6c8,d8fea16,5d595917,16b7f521,43d3b941,f28585ed,8a49c06c), +S(3c49e2ef,1d2d3464,81e05fa0,33366609,1615ebcf,535f68,be257f35,7bd91592,57901e0a,c8af3a31,aa404987,72c903fd,175c9b00,5c7458ee,ed667f11,57754132), +S(6c45ff2,c0c30320,83c343e6,dc80b4f7,bb64502a,52f412ff,ada521d4,a544a9f0,e9936037,f1e641eb,1cd6f801,a25271d3,cffe67d,c9bd7162,babf9855,9628a9a8), +S(66df5d95,acdf4260,ee0e465c,e3916d79,395df522,aa086aeb,6c283bb7,18296d46,cb1f3deb,8aea0337,625f46dd,903416d1,5647be91,1633c4c0,cf0e629a,413476fc), +S(428bbba5,ef351762,9eee4059,a3339213,40c7fee2,5ccb051c,88d75e53,ba618858,ef18809c,28227ccc,115876df,b3f378cd,374c0670,2c658501,7990e767,922c3999), +S(e8993820,d782657,ed8badc2,d515e360,df336730,860ef49e,65ca58dd,1a385815,feb41189,16c7e8f6,53c7f5a6,5fd7b6be,7a029814,149c4645,847073be,770959de), +S(2b77e42a,63502244,d6c7d1be,54b7857,9e2742d2,7143d689,fa3f70a3,5986ccf1,721e9da8,bee88ad4,2155dc9a,28be505,86648378,1d6af5b1,382cd47d,771e6428), +S(acffce3a,ed6beea3,2ad71633,21e1ca53,6f69ce76,fb5cd394,9d9dcc14,bbcee96,5384c97d,eac946c0,afc85b54,f3a56b79,fe263bff,63e1894c,6d52ef1b,9b456602), +S(e13d8d4b,25bece8d,90a008e4,c004824e,223b06b,7cf65ebd,1215e910,2e67b639,3e92b1f,14cbee57,9640b377,6ed5938f,9aee0e11,b139a678,3f207cf4,6dd7e20b), +S(d8f356d9,d2498eaa,b3fa12a,cb64562b,dff3e270,c7809a31,25a9ae65,9cb1f3c5,a5403cda,2d499a7c,7402b57c,c9f99e3,64f5085a,91fd8cfd,8a67c7a8,dbce04fb), +S(350062b5,22fb5d0a,8c79a5db,29e92216,79b9fbc6,3e1f95ca,e7d087f3,fedffc49,74cacf57,5e79c85b,d7e77a40,796e8750,a3ca57f2,a47cce8f,3d2de02d,b014df0b), +S(c159e630,9ab23135,58ebfb6b,22edaf93,eac8e16,77cd9f3b,1cd9492,20bf8e54,99244263,53f32608,831c6d74,da51d61,c344defe,f4c1e401,6a3db44b,4c57f4ae), +S(9e568b70,36a2daa2,fe7a3a52,49c56eb8,3fe4afa2,decebd60,c6c3245f,17bc6a13,b6643644,274eab9f,5e83c598,14978681,17c5a078,765156ae,3cb65fd3,830e06ae), +S(9bee7471,6b6c1ff5,62c1bc36,57a65de3,99a91d72,115703f4,4c3819a1,87828478,bb23a3da,ed34028a,7d39a7ed,fe2e23b,73e085a2,d6c2e51a,ef2a2076,a7c902ad), +S(c430c044,91228a7a,ea835698,ecf0f552,9aeef469,a36305cb,52902ccd,1c897473,40d0ee56,61cca82,80d11da,bffe97c4,f10c93aa,5e07224c,154b666e,bcd58c74), +S(2be073f6,b294a01b,eda0b0db,6832e4bc,23ef3889,7a859853,5ee726ef,ae0f15b1,6153f846,349c2a98,26008065,8be2a7d8,311a5e70,cc310ff8,7935a901,8d575813), +S(2934de46,a6d921f8,720567e6,b46e6362,36a7ed53,483b13ed,20958452,3225accd,5979698,26927cd7,abfe4c57,c53fc72a,48b71679,174c749d,aecdb057,e6a2d961), +S(4e9991b,92fa8c4e,4e8efe45,66966073,319e80d3,a54d4b7a,b61cfcc4,7ddaa5d5,9d03ea22,21d4d80e,261952e2,73f6a8cf,c31f6091,e5aa0a8f,2281ffbf,1345df9e), +S(ff3d6136,ffac5b0c,bfc6c5c0,c30dc01a,7ea3d56c,20bd3103,b178e3d3,ae180068,eccdc641,7b1bfff1,bf2fc8d3,2269523e,ab89890d,bffe0a19,8f594490,e7739bb8)} #else # error Configuration mismatch, invalid COMB_* parameters. Try deleting precomputed_ecmult_gen.c before the build. #endif From 7a33db35cd5ca3f71510b115a0cd57d2b1fb71b0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Dec 2021 18:37:53 -0500 Subject: [PATCH 022/383] Optimization: move (2^COMB_BITS-1)/2 term into ctx->scalar_offset It is unnecessary to recompute this term needed by the SDMC algorithm for every multiplication; move it into the context scalar_offset value instead. --- src/ecmult_gen.h | 2 +- src/ecmult_gen_impl.h | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index edac5a8b..ba0c818a 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -103,7 +103,7 @@ typedef struct { /* Values chosen such that * - * n*G == comb(n + (2^COMB_BITS-1)/2 + scalar_offset, G/2) + ge_offset. + * n*G == comb(n + scalar_offset, G/2) + ge_offset. * * This expression lets us use scalar blinding and optimize the comb precomputation. See * ecmult_gen_impl.h for more details. */ diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index b8b40038..9995c877 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -91,19 +91,17 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 * * Adding precomputation, our final equations become: * - * ctx->scalar_offset = -b + * ctx->scalar_offset = (2^COMB_BITS - 1)/2 - b (mod order) * ctx->ge_offset = b*G - * d = gn + ctx->scalar_offset + (2^COMB_BITS - 1)/2 (mod order) + * d = gn + ctx->scalar_offset (mod order) * R = comb(d, G/2) + ctx->ge_offset * * comb(d, G/2) function is then computed by summing + or - 2^(i-1)*G, for i=0..COMB_BITS-1, * depending on the value of the bits d[i] of the binary representation of scalar d. */ - /* Compute the scalar d = (gn + ctx->scalar_offset + (2^COMB_BITS - 1)/2). */ - secp256k1_ecmult_gen_scalar_diff(&d); - secp256k1_scalar_add(&d, &d, &ctx->scalar_offset); - secp256k1_scalar_add(&d, &d, gn); + /* Compute the scalar d = (gn + ctx->scalar_offset). */ + secp256k1_scalar_add(&d, &ctx->scalar_offset, gn); /* In secp256k1_ecmult_gen_prec_table we have precomputed sums of the * (2*d[i]-1) * 2^(i-1) * G points, for various combinations of i positions. @@ -245,14 +243,19 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Setup blinding values for secp256k1_ecmult_gen. */ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { secp256k1_scalar b; + secp256k1_scalar diff; secp256k1_gej gb; unsigned char nonce32[32]; secp256k1_rfc6979_hmac_sha256 rng; unsigned char keydata[64]; + + /* Compute the (2^COMB_BITS - 1)/2 term once. */ + secp256k1_ecmult_gen_scalar_diff(&diff); + if (seed32 == NULL) { /* When seed is NULL, reset the final point and blinding value. */ secp256k1_ge_neg(&ctx->ge_offset, &secp256k1_ge_const_g); - ctx->scalar_offset = secp256k1_scalar_one; + secp256k1_scalar_add(&ctx->scalar_offset, &secp256k1_scalar_one, &diff); return; } /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ @@ -268,7 +271,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const /* TODO: reintroduce projective blinding. */ - /* For a random blinding value b, set ctx->scalar_offset=-b, ctx->ge_offset=bG. */ + /* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); secp256k1_scalar_set_b32(&b, nonce32, NULL); /* The blinding value cannot be zero, as that would mean ge_offset = infinity, @@ -278,7 +281,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const memset(nonce32, 0, 32); secp256k1_ecmult_gen(ctx, &gb, &b); secp256k1_scalar_negate(&b, &b); - ctx->scalar_offset = b; + secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff); secp256k1_ge_set_gej(&ctx->ge_offset, &gb); /* Clean up. */ From 15d0cca2a6920400ce061c397203dbb931fc8dcd Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Dec 2021 19:05:49 -0500 Subject: [PATCH 023/383] Optimization: first table lookup needs no point addition --- src/ecmult_gen_impl.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 9995c877..8e308cc8 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -56,6 +56,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_fe neg; secp256k1_ge_storage adds; secp256k1_scalar d; + int first = 1; memset(&adds, 0, sizeof(adds)); @@ -177,7 +178,6 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 * secp256k1_ecmult_gen_prec_table[b][index] stores the table(b, m) entries. Index * is the relevant mask(b) bits of m packed together without gaps. */ - secp256k1_gej_set_infinity(r); /* Outer loop: iterate over comb_off from COMB_SPACING - 1 down to 0. */ comb_off = COMB_SPACING - 1; while (1) { @@ -221,7 +221,13 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_fe_cmov(&add.y, &neg, sign); /* Add the looked up and conditionally negated value to r. */ - secp256k1_gej_add_ge(r, r, &add); + if (EXPECT(first, 0)) { + /* If this is the first table lookup, we can skip addition. */ + secp256k1_gej_set_ge(r, &add); + first = 0; + } else { + secp256k1_gej_add_ge(r, r, &add); + } } /* Double the result, except in the last iteration. */ From 6247f485b6be461d5036608b9e8cd2f5adc912f1 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Sun, 26 Dec 2021 22:50:09 -0500 Subject: [PATCH 024/383] Optimization: avoid unnecessary doublings in precomputation --- src/ecmult_gen_compute_table_impl.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ecmult_gen_compute_table_impl.h b/src/ecmult_gen_compute_table_impl.h index 5ad0b0b3..80c6af64 100644 --- a/src/ecmult_gen_compute_table_impl.h +++ b/src/ecmult_gen_compute_table_impl.h @@ -54,16 +54,18 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons secp256k1_gej_set_infinity(&sum); for (tooth = 0; tooth < teeth; ++tooth) { /* Here u = 2^((block*teeth + tooth)*spacing) * gen/2. */ - int bit_off; /* Make sum = sum(2^((block*teeth + t)*spacing), t=0..tooth) * gen/2. */ secp256k1_gej_add_var(&sum, &sum, &u, NULL); /* Make u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ secp256k1_gej_double_var(&u, &u, NULL); /* Make ds[tooth] = u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ ds[tooth] = u; - /* Make u = 2^((block*teeth + tooth + 1)*spacing) * gen/2. */ - for (bit_off = 1; bit_off < spacing; ++bit_off) { - secp256k1_gej_double_var(&u, &u, NULL); + /* Make u = 2^((block*teeth + tooth + 1)*spacing) * gen/2, unless at the end. */ + if (block + tooth != blocks + teeth - 2) { + int bit_off; + for (bit_off = 1; bit_off < spacing; ++bit_off) { + secp256k1_gej_double_var(&u, &u, NULL); + } } } /* Now u = 2^((block*teeth + teeth)*spacing) * gen/2 From 5005abee60ad03d2967c9aadf4e25d208c90d98a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 7 Apr 2024 10:02:02 -0400 Subject: [PATCH 025/383] Rename scalar_get_bits -> scalar_get_bits_limb32; return uint32_t --- src/ecmult_const_impl.h | 4 ++-- src/ecmult_gen_compute_table_impl.h | 2 +- src/ecmult_gen_impl.h | 2 +- src/ecmult_impl.h | 6 +++--- src/scalar.h | 4 ++-- src/scalar_4x64_impl.h | 6 +++--- src/scalar_8x32_impl.h | 6 +++--- src/scalar_low_impl.h | 6 +++--- src/tests.c | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index 7dc4aac2..0d78f7c3 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -214,8 +214,8 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons #ifdef VERIFY /* Verify that v1 and v2 are in range [0, 2^129-1]. */ for (i = 129; i < 256; ++i) { - VERIFY_CHECK(secp256k1_scalar_get_bits(&v1, i, 1) == 0); - VERIFY_CHECK(secp256k1_scalar_get_bits(&v2, i, 1) == 0); + VERIFY_CHECK(secp256k1_scalar_get_bits_limb32(&v1, i, 1) == 0); + VERIFY_CHECK(secp256k1_scalar_get_bits_limb32(&v2, i, 1) == 0); } #endif diff --git a/src/ecmult_gen_compute_table_impl.h b/src/ecmult_gen_compute_table_impl.h index 80c6af64..9c296249 100644 --- a/src/ecmult_gen_compute_table_impl.h +++ b/src/ecmult_gen_compute_table_impl.h @@ -34,7 +34,7 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons for (i = 255; i >= 0; --i) { /* Use a very simple multiplication ladder to avoid dependency on ecmult. */ secp256k1_gej_double_var(&u, &u, NULL); - if (secp256k1_scalar_get_bits(&half, i, 1)) { + if (secp256k1_scalar_get_bits_limb32(&half, i, 1)) { secp256k1_gej_add_ge_var(&u, &u, gen, NULL); } } diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 8e308cc8..ae99de04 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -189,7 +189,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 * bits[tooth] = d[(block*COMB_TEETH + tooth)*COMB_SPACING + comb_off]. */ uint32_t bits = 0, sign, abs, index, tooth; for (tooth = 0; tooth < COMB_TEETH && bit_pos < 256; ++tooth) { - uint32_t bit = secp256k1_scalar_get_bits(&d, bit_pos, 1); + uint32_t bit = secp256k1_scalar_get_bits_limb32(&d, bit_pos, 1); bits |= bit << tooth; bit_pos += COMB_SPACING; } diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 2cf38399..07d8477e 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -174,7 +174,7 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, memset(wnaf, 0, len * sizeof(wnaf[0])); s = *a; - if (secp256k1_scalar_get_bits(&s, 255, 1)) { + if (secp256k1_scalar_get_bits_limb32(&s, 255, 1)) { secp256k1_scalar_negate(&s, &s); sign = -1; } @@ -182,7 +182,7 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, while (bit < len) { int now; int word; - if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { + if (secp256k1_scalar_get_bits_limb32(&s, bit, 1) == (unsigned int)carry) { bit++; continue; } @@ -209,7 +209,7 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, VERIFY_CHECK(carry == 0); while (verify_bit < 256) { - VERIFY_CHECK(secp256k1_scalar_get_bits(&s, verify_bit, 1) == 0); + VERIFY_CHECK(secp256k1_scalar_get_bits_limb32(&s, verify_bit, 1) == 0); verify_bit++; } } diff --git a/src/scalar.h b/src/scalar.h index 98b1287b..e5a10ca4 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -23,10 +23,10 @@ static void secp256k1_scalar_clear(secp256k1_scalar *r); /** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ -static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); +static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count); /** Access bits from a scalar. Not constant time in offset and count. */ -static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); +static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); /** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`. * In: bin: pointer to a 32-byte array. diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 82cd957f..9fa2ca28 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -45,20 +45,20 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK(count < 32); VERIFY_CHECK(offset + count <= 256); if ((offset + count - 1) >> 6 == offset >> 6) { - return secp256k1_scalar_get_bits(a, offset, count); + return secp256k1_scalar_get_bits_limb32(a, offset, count); } else { VERIFY_CHECK((offset >> 6) + 1 < 4); return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index 58ae51bc..d49c464b 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -62,20 +62,20 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK(count < 32); VERIFY_CHECK(offset + count <= 256); if ((offset + count - 1) >> 5 == offset >> 5) { - return secp256k1_scalar_get_bits(a, offset, count); + return secp256k1_scalar_get_bits_limb32(a, offset, count); } else { VERIFY_CHECK((offset >> 5) + 1 < 8); return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 7f53e626..2c176e83 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -27,7 +27,7 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); if (offset < 32) @@ -36,10 +36,10 @@ SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_s return 0; } -SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); - return secp256k1_scalar_get_bits(a, offset, count); + return secp256k1_scalar_get_bits_limb32(a, offset, count); } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } diff --git a/src/tests.c b/src/tests.c index e8b22a63..b38409a5 100644 --- a/src/tests.c +++ b/src/tests.c @@ -2149,7 +2149,7 @@ static void scalar_test(void) { for (i = 0; i < 256; i += 4) { secp256k1_scalar t; int j; - secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_limb32(&s, 256 - 4 - i, 4)); for (j = 0; j < 4; j++) { secp256k1_scalar_add(&n, &n, &n); } From e03dcc44b5fa9cac5aa6ebe855f825116b24791a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 28 Dec 2021 18:13:04 -0500 Subject: [PATCH 026/383] Make secp256k1_scalar_get_bits support 32-bit reads The old code would trigger UB when count=32. --- src/scalar.h | 4 ++-- src/scalar_4x64_impl.h | 7 ++++--- src/scalar_8x32_impl.h | 7 ++++--- src/scalar_low_impl.h | 8 +++++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/scalar.h b/src/scalar.h index e5a10ca4..70f49b1c 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -22,10 +22,10 @@ /** Clear a scalar to prevent the leak of sensitive data. */ static void secp256k1_scalar_clear(secp256k1_scalar *r); -/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ +/** Access bits (1 < count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */ static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count); -/** Access bits from a scalar. Not constant time in offset and count. */ +/** Access bits (1 < count <= 32) from a scalar. offset + count must be < 256. Not constant time in offset and count. */ static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); /** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`. diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 9fa2ca28..4aaec85b 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -47,21 +47,22 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); + VERIFY_CHECK(count > 0 && count <= 32); VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); - return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); + return (a->d[offset >> 6] >> (offset & 0x3F)) & (0xFFFFFFFF >> (32 - count)); } SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count < 32); + VERIFY_CHECK(count > 0 && count <= 32); VERIFY_CHECK(offset + count <= 256); if ((offset + count - 1) >> 6 == offset >> 6) { return secp256k1_scalar_get_bits_limb32(a, offset, count); } else { VERIFY_CHECK((offset >> 6) + 1 < 4); - return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); + return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & (0xFFFFFFFF >> (32 - count)); } } diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index d49c464b..c7d87b17 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -64,21 +64,22 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); + VERIFY_CHECK(count > 0 && count <= 32); VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); - return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); + return (a->d[offset >> 5] >> (offset & 0x1F)) & (0xFFFFFFFF >> (32 - count)); } SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count < 32); + VERIFY_CHECK(count > 0 && count <= 32); VERIFY_CHECK(offset + count <= 256); if ((offset + count - 1) >> 5 == offset >> 5) { return secp256k1_scalar_get_bits_limb32(a, offset, count); } else { VERIFY_CHECK((offset >> 5) + 1 < 8); - return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); + return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & (0xFFFFFFFF >> (32 - count)); } } diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 2c176e83..45d2f3e4 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -30,10 +30,12 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); - if (offset < 32) - return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); - else + VERIFY_CHECK(count > 0 && count <= 32); + if (offset < 32) { + return (*a >> offset) & (0xFFFFFFFF >> (32 - count)); + } else { return 0; + } } SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { From a0d32b597d4f9c8a20547dd21677716d4df8da54 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 28 Dec 2021 18:13:43 -0500 Subject: [PATCH 027/383] Optimization: use Nx32 representation for recoded bits The existing code needs to deal with the edge case that bit_pos >= 256, which would lead to an out-of-bounds read from secp256k1_scalar. Instead, recode the scalar into an array of uint32_t with enough zero padding at the end to alleviate the issue. This also simplifies the code, and is necessary for a security improvement in a follow-up commit. Original code by Peter Dettman, with modifications by Pieter Wuille. --- src/ecmult_gen_impl.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index ae99de04..8ca97a53 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -56,7 +56,11 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_fe neg; secp256k1_ge_storage adds; secp256k1_scalar d; - int first = 1; + /* Array of uint32_t values large enough to store COMB_BITS bits. Only the bottom + * 8 are ever nonzero, but having the zero padding at the end if COMB_BITS>256 + * avoids the need to deal with out-of-bounds reads from a scalar. */ + uint32_t recoded[(COMB_BITS + 31) >> 5] = {0}; + int first = 1, i; memset(&adds, 0, sizeof(adds)); @@ -103,6 +107,11 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Compute the scalar d = (gn + ctx->scalar_offset). */ secp256k1_scalar_add(&d, &ctx->scalar_offset, gn); + /* Convert to recoded array. */ + for (i = 0; i < 8; ++i) { + recoded[i] = secp256k1_scalar_get_bits_limb32(&d, 32 * i, 32); + } + secp256k1_scalar_clear(&d); /* In secp256k1_ecmult_gen_prec_table we have precomputed sums of the * (2*d[i]-1) * 2^(i-1) * G points, for various combinations of i positions. @@ -188,8 +197,8 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Gather the mask(block)-selected bits of d into bits. They're packed: * bits[tooth] = d[(block*COMB_TEETH + tooth)*COMB_SPACING + comb_off]. */ uint32_t bits = 0, sign, abs, index, tooth; - for (tooth = 0; tooth < COMB_TEETH && bit_pos < 256; ++tooth) { - uint32_t bit = secp256k1_scalar_get_bits_limb32(&d, bit_pos, 1); + for (tooth = 0; tooth < COMB_TEETH; ++tooth) { + uint32_t bit = (recoded[bit_pos >> 5] >> (bit_pos & 0x1f)) & 1; bits |= bit << tooth; bit_pos += COMB_SPACING; } @@ -243,7 +252,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_fe_clear(&neg); secp256k1_ge_clear(&add); memset(&adds, 0, sizeof(adds)); - secp256k1_scalar_clear(&d); + memset(&recoded, 0, sizeof(recoded)); } /* Setup blinding values for secp256k1_ecmult_gen. */ From 07810d9abb8377e8f0056032bca51f8ca54ed18f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 28 Dec 2021 18:25:04 -0500 Subject: [PATCH 028/383] Reduce side channels from single-bit reads Co-authored-by: Tim Ruffing --- src/ecmult_gen_impl.h | 27 +++++++++++++++++++++++++-- src/util.h | 12 ++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 8ca97a53..feb3ce13 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -197,9 +197,32 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Gather the mask(block)-selected bits of d into bits. They're packed: * bits[tooth] = d[(block*COMB_TEETH + tooth)*COMB_SPACING + comb_off]. */ uint32_t bits = 0, sign, abs, index, tooth; + /* Instead of reading individual bits here to construct the bits variable, + * build up the result by xoring rotated reads together. In every iteration, + * one additional bit is made correct, starting at the bottom. The bits + * above that contain junk. This reduces leakage by avoiding computations + * on variables that can have only a low number of possible values (e.g., + * just two values when reading a single bit into a variable.) See: + * https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-alam.pdf + */ for (tooth = 0; tooth < COMB_TEETH; ++tooth) { - uint32_t bit = (recoded[bit_pos >> 5] >> (bit_pos & 0x1f)) & 1; - bits |= bit << tooth; + /* Construct bitdata s.t. the bottom bit is the bit we'd like to read. + * + * We could just set bitdata = recoded[bit_pos >> 5] >> (bit_pos & 0x1f) + * but this would simply discard the bits that fall off at the bottom, + * and thus, for example, bitdata could still have only two values if we + * happen to shift by exactly 31 positions. We use a rotation instead, + * which ensures that bitdata doesn't loose entropy. This relies on the + * rotation being atomic, i.e., the compiler emitting an actual rot + * instruction. */ + uint32_t bitdata = secp256k1_rotr32(recoded[bit_pos >> 5], bit_pos & 0x1f); + + /* Clear the bit at position tooth, but sssh, don't tell clang. */ + uint32_t volatile vmask = ~(1 << tooth); + bits &= vmask; + + /* Write the bit into position tooth (and junk into higher bits). */ + bits ^= bitdata << tooth; bit_pos += COMB_SPACING; } diff --git a/src/util.h b/src/util.h index b04a239d..ca73752c 100644 --- a/src/util.h +++ b/src/util.h @@ -394,4 +394,16 @@ SECP256K1_INLINE static void secp256k1_write_be64(unsigned char* p, uint64_t x) p[0] = x >> 56; } +/* Rotate a uint32_t to the right. */ +SECP256K1_INLINE static uint32_t secp256k1_rotr32(const uint32_t x, const unsigned int by) { +#if defined(_MSC_VER) + return _rotr(x, by); /* needs */ +#else + /* Reduce rotation amount to avoid UB when shifting. */ + const unsigned int mask = CHAR_BIT * sizeof(x) - 1; + /* Turned into a rot instruction by GCC and clang. */ + return (x >> (by & mask)) | (x << ((-by) & mask)); +#endif +} + #endif /* SECP256K1_UTIL_H */ From 644e86de9a8f4d8faf4b6d9e2780157ab5a72314 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Dec 2021 22:45:30 -0500 Subject: [PATCH 029/383] Reintroduce projective blinding --- src/ecmult_gen.h | 4 ++++ src/ecmult_gen_impl.h | 12 +++++++++++- src/tests.c | 3 ++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index ba0c818a..7a640d9c 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -109,6 +109,10 @@ typedef struct { * ecmult_gen_impl.h for more details. */ secp256k1_scalar scalar_offset; secp256k1_ge ge_offset; + + /* Factor used for projective blinding. This value is used to rescale the Z + * coordinate of the first table lookup. */ + secp256k1_fe proj_blind; } secp256k1_ecmult_gen_context; static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index feb3ce13..7d2f4c8f 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -27,6 +27,7 @@ static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx ctx->built = 0; secp256k1_scalar_clear(&ctx->scalar_offset); secp256k1_ge_clear(&ctx->ge_offset); + secp256k1_fe_clear(&ctx->proj_blind); } /* Compute the scalar (2^COMB_BITS - 1) / 2, the difference between the gn argument to @@ -256,6 +257,8 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 if (EXPECT(first, 0)) { /* If this is the first table lookup, we can skip addition. */ secp256k1_gej_set_ge(r, &add); + /* Give the entry a random Z coordinate to blind intermediary results. */ + secp256k1_gej_rescale(r, &ctx->proj_blind); first = 0; } else { secp256k1_gej_add_ge(r, r, &add); @@ -283,6 +286,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_scalar b; secp256k1_scalar diff; secp256k1_gej gb; + secp256k1_fe f; unsigned char nonce32[32]; secp256k1_rfc6979_hmac_sha256 rng; unsigned char keydata[64]; @@ -294,6 +298,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const /* When seed is NULL, reset the final point and blinding value. */ secp256k1_ge_neg(&ctx->ge_offset, &secp256k1_ge_const_g); secp256k1_scalar_add(&ctx->scalar_offset, &secp256k1_scalar_one, &diff); + ctx->proj_blind = secp256k1_fe_one; return; } /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ @@ -307,7 +312,11 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); memset(keydata, 0, sizeof(keydata)); - /* TODO: reintroduce projective blinding. */ + /* Compute projective blinding factor (cannot be 0). */ + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_fe_set_b32_mod(&f, nonce32); + secp256k1_fe_cmov(&f, &secp256k1_fe_one, secp256k1_fe_normalizes_to_zero(&f)); + ctx->proj_blind = f; /* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); @@ -325,6 +334,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const /* Clean up. */ secp256k1_scalar_clear(&b); secp256k1_gej_clear(&gb); + secp256k1_fe_clear(&f); } #endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/src/tests.c b/src/tests.c index b38409a5..862e3beb 100644 --- a/src/tests.c +++ b/src/tests.c @@ -249,7 +249,8 @@ static void run_selftest_tests(void) { static int ecmult_gen_context_eq(const secp256k1_ecmult_gen_context *a, const secp256k1_ecmult_gen_context *b) { return a->built == b->built && secp256k1_scalar_eq(&a->scalar_offset, &b->scalar_offset) - && secp256k1_ge_eq_var(&a->ge_offset, &b->ge_offset); + && secp256k1_ge_eq_var(&a->ge_offset, &b->ge_offset) + && secp256k1_fe_equal(&a->proj_blind, &b->proj_blind); } static int context_eq(const secp256k1_context *a, const secp256k1_context *b) { From 39b2f2a32102b9319c8958715c1e708e95e06191 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 1 Jan 2022 13:35:53 -0500 Subject: [PATCH 030/383] Add test case for ecmult_gen recoded = {-1,0,1} --- src/tests.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/tests.c b/src/tests.c index 862e3beb..ec9cd0e0 100644 --- a/src/tests.c +++ b/src/tests.c @@ -5600,9 +5600,29 @@ static void test_ecmult_gen_blind_reset(void) { CHECK(secp256k1_ge_eq_var(&p1, &p2)); } +/* Verify that ecmult_gen for scalars gn for which gn + scalar_offset = {-1,0,1}. */ +static void test_ecmult_gen_edge_cases(void) { + int i; + secp256k1_gej res1, res2, res3; + secp256k1_scalar gn = secp256k1_scalar_one; /* gn = 1 */ + secp256k1_scalar_add(&gn, &gn, &CTX->ecmult_gen_ctx.scalar_offset); /* gn = 1 + scalar_offset */ + secp256k1_scalar_negate(&gn, &gn); /* gn = -1 - scalar_offset */ + + for (i = -1; i < 2; ++i) { + /* Run test with gn = i - scalar_offset (so that the ecmult_gen recoded value represents i). */ + secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &res1, &gn); + secp256k1_ecmult(&res2, NULL, &secp256k1_scalar_zero, &gn); + secp256k1_ecmult_const(&res3, &secp256k1_ge_const_g, &gn); + CHECK(secp256k1_gej_eq_var(&res1, &res2)); + CHECK(secp256k1_gej_eq_var(&res1, &res3)); + secp256k1_scalar_add(&gn, &gn, &secp256k1_scalar_one); + } +} + static void run_ecmult_gen_blind(void) { int i; test_ecmult_gen_blind_reset(); + test_ecmult_gen_edge_cases(); for (i = 0; i < 10; i++) { test_ecmult_gen_blind(); } From a043940253e1e44ea6ccd3e89a7fd807b56817ef Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 4 Jan 2022 18:46:22 -0500 Subject: [PATCH 031/383] Permit COMB_BITS < 256 for exhaustive tests --- src/ecmult_gen.h | 89 +++++++++++++++++------------ src/ecmult_gen_compute_table.h | 2 +- src/ecmult_gen_compute_table_impl.h | 4 +- src/ecmult_gen_impl.h | 2 +- src/precompute_ecmult_gen.c | 5 +- src/precomputed_ecmult_gen.c | 6 +- src/tests_exhaustive.c | 2 +- 7 files changed, 64 insertions(+), 46 deletions(-) diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 7a640d9c..43dd10c3 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -16,9 +16,12 @@ * - COMB_BLOCKS is the number of blocks the input is split into. Each * has a corresponding table. * - COMB_TEETH is the number of bits simultaneously covered by one table. + * - COMB_RANGE is the number of bits in supported scalars. For production + * purposes, only 256 is reasonable, but smaller numbers are supported for + * exhaustive test mode. * * The comb's spacing (COMB_SPACING), or the distance between the teeth, - * is defined as ceil(256 / (COMB_BLOCKS * COMB_TEETH)). Each block covers + * is defined as ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)). Each block covers * COMB_SPACING * COMB_TEETH consecutive bits in the input. * * The size of the precomputed table is COMB_BLOCKS * (1 << (COMB_TEETH - 1)) @@ -36,55 +39,67 @@ * doesn't support infinities) */ # undef COMB_BLOCKS # undef COMB_TEETH -# if EXHAUSTIVE_TEST_ORDER > 32 -# define COMB_BLOCKS 52 -# define COMB_TEETH 5 -# elif EXHAUSTIVE_TEST_ORDER > 16 -# define COMB_BLOCKS 64 -# define COMB_TEETH 4 -# elif EXHAUSTIVE_TEST_ORDER > 8 -# define COMB_BLOCKS 86 -# define COMB_TEETH 3 -# elif EXHAUSTIVE_TEST_ORDER > 4 -# define COMB_BLOCKS 128 +# if EXHAUSTIVE_TEST_ORDER == 7 +# define COMB_RANGE 3 +# define COMB_BLOCKS 1 # define COMB_TEETH 2 +# elif EXHAUSTIVE_TEST_ORDER == 13 +# define COMB_RANGE 4 +# define COMB_BLOCKS 1 +# define COMB_TEETH 2 +# elif EXHAUSTIVE_TEST_ORDER == 199 +# define COMB_RANGE 8 +# define COMB_BLOCKS 2 +# define COMB_TEETH 3 # else -# define COMB_BLOCKS 256 -# define COMB_TEETH 1 +# error "Unknown exhaustive test order" +# endif +# if (COMB_RANGE >= 32) || ((EXHAUSTIVE_TEST_ORDER >> (COMB_RANGE - 1)) != 1) +# error "COMB_RANGE != ceil(log2(EXHAUSTIVE_TEST_ORDER+1))" # endif #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ -/* Use (11, 6) as default configuration, which results in a 22 kB table. */ -# ifndef COMB_BLOCKS -# define COMB_BLOCKS 11 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") -# endif -# endif -# ifndef COMB_TEETH -# define COMB_TEETH 6 -# ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") -# endif -# endif +# define COMB_RANGE 256 #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ +/* Use (11, 6) as default configuration, which results in a 22 kB table. */ +#ifndef COMB_BLOCKS +# define COMB_BLOCKS 11 +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_BLOCKS undefined, assuming default value") +# endif +#endif +#ifndef COMB_TEETH +# define COMB_TEETH 6 +# ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_MSG("COMB_TEETH undefined, assuming default value") +# endif +#endif +/* Use ceil(COMB_RANGE / (COMB_BLOCKS * COMB_TEETH)) as COMB_SPACING. */ +#define COMB_SPACING CEIL_DIV(COMB_RANGE, COMB_BLOCKS * COMB_TEETH) + /* Range checks on the parameters. */ + +/* The remaining COMB_* parameters are derived values, don't modify these. */ +/* - The number of bits covered by all the blocks; must be at least COMB_RANGE. */ +#define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) +/* - The number of entries per table. */ +#define COMB_POINTS (1 << (COMB_TEETH - 1)) + +/* Sanity checks. */ #if !(1 <= COMB_BLOCKS && COMB_BLOCKS <= 256) # error "COMB_BLOCKS must be in the range [1, 256]" #endif #if !(1 <= COMB_TEETH && COMB_TEETH <= 8) # error "COMB_TEETH must be in the range [1, 8]" #endif +#if COMB_BITS < COMB_RANGE +# error "COMB_BLOCKS * COMB_TEETH * COMB_SPACING is too low" +#endif -/* The remaining COMB_* parameters are derived values, don't modify these. */ -/* - The distance between the teeth of each comb. */ -#define COMB_SPACING CEIL_DIV(256, COMB_BLOCKS * COMB_TEETH) -/* - The number of bits covered by all the blocks; must be at least 256. */ -#define COMB_BITS (COMB_BLOCKS * COMB_TEETH * COMB_SPACING) -/* - The number of entries per table. */ -#define COMB_POINTS (1 << (COMB_TEETH - 1)) - -/* Additional sanity checks. */ +/* These last 2 checks are not strictly required, but prevent gratuitously inefficient + * configurations. Note that they compare with 256 rather than COMB_RANGE, so they do + * permit somewhat excessive values for the exhaustive test case, where testing with + * suboptimal parameters may be desirable. */ #if (COMB_BLOCKS - 1) * COMB_TEETH * COMB_SPACING >= 256 # error "COMB_BLOCKS can be reduced" #endif @@ -93,8 +108,10 @@ #endif #ifdef DEBUG_CONFIG +# pragma message DEBUG_CONFIG_DEF(COMB_RANGE) # pragma message DEBUG_CONFIG_DEF(COMB_BLOCKS) # pragma message DEBUG_CONFIG_DEF(COMB_TEETH) +# pragma message DEBUG_CONFIG_DEF(COMB_SPACING) #endif typedef struct { diff --git a/src/ecmult_gen_compute_table.h b/src/ecmult_gen_compute_table.h index cd4f9233..bd41803a 100644 --- a/src/ecmult_gen_compute_table.h +++ b/src/ecmult_gen_compute_table.h @@ -9,6 +9,6 @@ #include "ecmult_gen.h" -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth); +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing); #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ diff --git a/src/ecmult_gen_compute_table_impl.h b/src/ecmult_gen_compute_table_impl.h index 9c296249..6aa8d840 100644 --- a/src/ecmult_gen_compute_table_impl.h +++ b/src/ecmult_gen_compute_table_impl.h @@ -14,10 +14,9 @@ #include "ecmult_gen.h" #include "util.h" -static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth) { +static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, const secp256k1_ge* gen, int blocks, int teeth, int spacing) { size_t points = ((size_t)1) << (teeth - 1); size_t points_total = points * blocks; - int spacing = (256 + blocks * teeth - 1) / (blocks * teeth); secp256k1_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); secp256k1_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); secp256k1_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); @@ -95,6 +94,7 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons for (block = 0; block < blocks; ++block) { size_t index; for (index = 0; index < points; ++index) { + VERIFY_CHECK(!secp256k1_ge_is_infinity(&prec[block * points + index])); secp256k1_ge_to_storage(&table[block * points + index], &prec[block * points + index]); } } diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 7d2f4c8f..2fbf623c 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -109,7 +109,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Compute the scalar d = (gn + ctx->scalar_offset). */ secp256k1_scalar_add(&d, &ctx->scalar_offset, gn); /* Convert to recoded array. */ - for (i = 0; i < 8; ++i) { + for (i = 0; i < 8 && i < ((COMB_BITS + 31) >> 5); ++i) { recoded[i] = secp256k1_scalar_get_bits_limb32(&d, 32 * i, 32); } secp256k1_scalar_clear(&d); diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index 25ab445b..4d153a65 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -24,14 +24,15 @@ static const int CONFIGS[][2] = { }; static void print_table(FILE* fp, int blocks, int teeth) { + int spacing = CEIL_DIV(256, blocks * teeth); size_t points = ((size_t)1) << (teeth - 1); int outer; size_t inner; secp256k1_ge_storage* table = checked_malloc(&default_error_callback, blocks * points * sizeof(secp256k1_ge_storage)); - secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth); + secp256k1_ecmult_gen_compute_table(table, &secp256k1_ge_const_g, blocks, teeth, spacing); - fprintf(fp, "#elif (COMB_BLOCKS == %d) && (COMB_TEETH == %d)\n", blocks, teeth); + fprintf(fp, "#elif (COMB_BLOCKS == %d) && (COMB_TEETH == %d) && (COMB_SPACING == %d)\n", blocks, teeth, spacing); for (outer = 0; outer != blocks; outer++) { fprintf(fp,"{"); for (inner = 0; inner != points; inner++) { diff --git a/src/precomputed_ecmult_gen.c b/src/precomputed_ecmult_gen.c index 95c18bcb..248fb077 100644 --- a/src/precomputed_ecmult_gen.c +++ b/src/precomputed_ecmult_gen.c @@ -9,7 +9,7 @@ #define S(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) SECP256K1_GE_STORAGE_CONST(0x##a##u,0x##b##u,0x##c##u,0x##d##u,0x##e##u,0x##f##u,0x##g##u,0x##h##u,0x##i##u,0x##j##u,0x##k##u,0x##l##u,0x##m##u,0x##n##u,0x##o##u,0x##p##u) const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = { #if 0 -#elif (COMB_BLOCKS == 2) && (COMB_TEETH == 5) +#elif (COMB_BLOCKS == 2) && (COMB_TEETH == 5) && (COMB_SPACING == 26) {S(7081b567,8cb87d01,99c9c76e,d1e0a5e0,1d784be9,27f6b135,161e0fd0,3f39b473,ad5222ac,f062cb39,21b234a7,15b626ae,f780b307,9b5122d1,53210f42,d9369242), S(228af17e,df90d1cc,a40173e9,478fa445,9780dacd,c3f15b90,fda5d00e,1faa1b51,8ff47c4d,a4ba636a,f656da9,12a81f79,6252496d,1e519886,b2c2b073,25be2b4a), S(b515ebe0,f48fb34e,9e01824c,d90553af,db116579,96667847,5ebaa700,242fd722,4cf08191,510fbf0,51f9e19a,198f11f6,ea31268c,2a6d384c,60557250,f0553c50), @@ -42,7 +42,7 @@ S(f7738800,b7fdf237,dc7f03fc,43724011,8b53aea4,4d7953d4,276f3b4d,bf5c0ff8,c1de79 S(5cb07874,ac4ffb86,2da619be,4c8fa38b,e8b261ec,3ec73a12,cd4cf8fc,4f8d5dae,549d1896,4931dabf,ba4553a2,461f2660,87733454,ea8eec6b,f671e3de,60c70340), S(5cc85d41,7b2ae9ac,dedb1b44,ce78d8a7,8f56b878,1a4b3af6,635a55c1,fead3be7,66a48c79,301e57d4,54cc8644,d2e778a8,45d85762,2c10eb98,d77eb873,e58bbeca), S(f27211c9,a067b01c,7fe7fbf7,7b5d9b0,eb0f2475,9d541457,6eb24ba4,19fd3db8,e26d28eb,89f7b518,e9ae0b88,fadbfb9b,641d3a44,c59c6f93,ec28a541,486e041e)} -#elif (COMB_BLOCKS == 11) && (COMB_TEETH == 6) +#elif (COMB_BLOCKS == 11) && (COMB_TEETH == 6) && (COMB_SPACING == 4) {S(629bee58,a391595f,eb20c534,4933937a,cdb2eba1,86d49f8b,845c1b5f,4ca87182,8dae4162,73c6c068,2e2aede4,76efa86b,7612c07e,f72070d0,dc4486f1,47e95085), S(6fd5e13c,a94b874b,28cd574b,726efdbf,143ab108,1089b846,7b5b2ebe,6c6a3c8f,4a4db306,52c9772a,868b2859,57c5a005,d83f6afa,6e65d87c,700da998,ce651396), S(609b6576,191514f4,83f5b428,500cfbaf,96871b8b,3348fe5c,1a131768,bb266b6f,90abb9c1,1bf184d2,8dbc424a,bbf74eb8,de4e0582,2ea5dd93,7d1e8b30,e5f695e7), @@ -395,7 +395,7 @@ S(96ca6bb4,bf74c748,75703386,ae02dc29,13329d9e,a5395892,df1c6f57,4a84fa4a,fcb510 S(36a066ae,694f2645,25cba884,956ebd46,ae568acf,11664965,63cee00d,a32f2199,5d1e975a,856ebd1a,cb1fe254,101e89ab,ea089e8a,b38bbd0f,1100e914,709fd965), S(4922879f,800234c9,63f4b572,d236843,4c4da5c8,ff741982,c3d1e341,841d1309,9b259470,24b5f4cb,97c68d18,f7f8dfca,1e57f7de,63208765,2ce15770,98f35494), S(ee27e2b,acf95f6d,dbb5ebae,bbf181bb,43322a3d,6db87e78,14e57a3d,41b581e0,3d6a18a,daf69ae4,88ecc9d8,7d6b1bf2,c8d65544,3f4b45b4,c5a0ac51,7b1dc3ca)} -#elif (COMB_BLOCKS == 43) && (COMB_TEETH == 6) +#elif (COMB_BLOCKS == 43) && (COMB_TEETH == 6) && (COMB_SPACING == 1) {S(e3adcb1a,fe947e6e,7cc4f5a2,df78310a,b235e2c3,bcd75eba,1904de80,c8814c50,e0b27ead,c4bbb9d2,37dad580,6e366674,4a9f9c3d,e024f2bd,1edb11d2,fafc0a22), S(612c2ec6,f0e9c4ec,c2200d23,ddca77eb,d003be35,61e52b1,890bf846,3bb53ea5,9e944d7b,dfc7a952,c1c5ee15,485d7199,dda19551,2d729628,c215a9e0,285f656a), S(42053dc0,9f90a7f7,86feca60,d68a5c3c,789e44d2,3479aa13,2d1a427c,621373a3,b338f891,f3930ec7,738669bb,3a29ae2d,637be08a,954f2a8c,acb661af,a660bd22), diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index a17d32de..5843b3e1 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -389,7 +389,7 @@ int main(int argc, char** argv) { } /* Recreate the ecmult{,_gen} tables using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */ - secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, COMB_BLOCKS, COMB_TEETH); + secp256k1_ecmult_gen_compute_table(&secp256k1_ecmult_gen_prec_table[0][0], &secp256k1_ge_const_g, COMB_BLOCKS, COMB_TEETH, COMB_SPACING); secp256k1_ecmult_compute_two_tables(secp256k1_pre_g, secp256k1_pre_g_128, WINDOW_G, &secp256k1_ge_const_g); while (count--) { From 4c341f89ab704205a89b5c5d404ed60f381f7c48 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 28 Dec 2022 16:50:07 -0500 Subject: [PATCH 032/383] Add changelog entry for SDMC --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04ac9b7e..36f53db0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Changed + - The implementation of the point multiplication algorithm used for signing and public key generation was changed, resulting in improved performance for those operations. + - The related configure option `--ecmult-gen-precision` was replaced with `--ecmult-gen-kb` (`ECMULT_GEN_KB` for CMake). + - This changes the supported precomputed table sizes for these operations. The new supported sizes are 2 KiB, 22 KiB, or 86 KiB (while the old supported sizes were 32 KiB, 64 KiB, or 512 KiB). + ## [0.4.1] - 2023-12-21 #### Changed From 7d2591ce12d8a9b85f210cf9d678e91cee125ee9 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 17 Apr 2024 17:33:51 +0000 Subject: [PATCH 033/383] Add secp256k1_pubkey_sort Co-authored-by: Tim Ruffing Co-authored-by: Russell O'Connor --- CHANGELOG.md | 3 + Makefile.am | 2 + include/secp256k1.h | 14 +++ src/hsort.h | 33 +++++++ src/hsort_impl.h | 125 ++++++++++++++++++++++++ src/secp256k1.c | 29 ++++++ src/tests.c | 231 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 437 insertions(+) create mode 100644 src/hsort.h create mode 100644 src/hsort_impl.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 36f53db0..98252da5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Added + - New function `secp256k1_ec_pubkey_sort` that sorts public keys using lexicographic (of compressed serialization) order. + #### Changed - The implementation of the point multiplication algorithm used for signing and public key generation was changed, resulting in improved performance for those operations. - The related configure option `--ecmult-gen-precision` was replaced with `--ecmult-gen-kb` (`ECMULT_GEN_KB` for CMake). diff --git a/Makefile.am b/Makefile.am index 54986179..322e44ea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,8 @@ noinst_HEADERS += src/field.h noinst_HEADERS += src/field_impl.h noinst_HEADERS += src/bench.h noinst_HEADERS += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h +noinst_HEADERS += src/hsort.h +noinst_HEADERS += src/hsort_impl.h noinst_HEADERS += contrib/lax_der_parsing.h noinst_HEADERS += contrib/lax_der_parsing.c noinst_HEADERS += contrib/lax_der_privatekey_parsing.h diff --git a/include/secp256k1.h b/include/secp256k1.h index f4053f2a..cfbdd528 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -474,6 +474,20 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_cmp( const secp256k1_pubkey *pubkey2 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Sort public keys using lexicographic (of compressed serialization) order + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * + * Args: ctx: pointer to a context object + * In: pubkeys: array of pointers to pubkeys to sort + * n_pubkeys: number of elements in the pubkeys array + */ +SECP256K1_API int secp256k1_ec_pubkey_sort( + const secp256k1_context *ctx, + const secp256k1_pubkey **pubkeys, + size_t n_pubkeys +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + /** Parse an ECDSA signature in compact (64 bytes) format. * * Returns: 1 when the signature could be parsed, 0 otherwise. diff --git a/src/hsort.h b/src/hsort.h new file mode 100644 index 00000000..d54995ca --- /dev/null +++ b/src/hsort.h @@ -0,0 +1,33 @@ +/*********************************************************************** + * Copyright (c) 2021 Russell O'Connor, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_HSORT_H +#define SECP256K1_HSORT_H + +#include +#include + +/* In-place, iterative heapsort with an interface matching glibc's qsort_r. This + * is preferred over standard library implementations because they generally + * make no guarantee about being fast for malicious inputs. + * Remember that heapsort is unstable. + * + * In/Out: ptr: pointer to the array to sort. The contents of the array are + * sorted in ascending order according to the comparison function. + * In: count: number of elements in the array. + * size: size in bytes of each element. + * cmp: pointer to a comparison function that is called with two + * arguments that point to the objects being compared. The cmp_data + * argument of secp256k1_hsort is passed as third argument. The + * function must return an integer less than, equal to, or greater + * than zero if the first argument is considered to be respectively + * less than, equal to, or greater than the second. + * cmp_data: pointer passed as third argument to cmp. + */ +static void secp256k1_hsort(void *ptr, size_t count, size_t size, + int (*cmp)(const void *, const void *, void *), + void *cmp_data); +#endif diff --git a/src/hsort_impl.h b/src/hsort_impl.h new file mode 100644 index 00000000..1c674ff1 --- /dev/null +++ b/src/hsort_impl.h @@ -0,0 +1,125 @@ +/*********************************************************************** + * Copyright (c) 2021 Russell O'Connor, Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_HSORT_IMPL_H +#define SECP256K1_HSORT_IMPL_H + +#include "hsort.h" + +/* An array is a heap when, for all non-zero indexes i, the element at index i + * compares as less than or equal to the element at index parent(i) = (i-1)/2. + */ + +static SECP256K1_INLINE size_t secp256k1_heap_child1(size_t i) { + VERIFY_CHECK(i <= (SIZE_MAX - 1)/2); + return 2*i + 1; +} + +static SECP256K1_INLINE size_t secp256k1_heap_child2(size_t i) { + VERIFY_CHECK(i <= SIZE_MAX/2 - 1); + return secp256k1_heap_child1(i)+1; +} + +static SECP256K1_INLINE void secp256k1_heap_swap64(unsigned char *a, unsigned char *b, size_t len) { + unsigned char tmp[64]; + VERIFY_CHECK(len <= 64); + memcpy(tmp, a, len); + memmove(a, b, len); + memcpy(b, tmp, len); +} + +static SECP256K1_INLINE void secp256k1_heap_swap(unsigned char *arr, size_t i, size_t j, size_t stride) { + unsigned char *a = arr + i*stride; + unsigned char *b = arr + j*stride; + size_t len = stride; + while (64 < len) { + secp256k1_heap_swap64(a + (len - 64), b + (len - 64), 64); + len -= 64; + } + secp256k1_heap_swap64(a, b, len); +} + +/* This function accepts an array arr containing heap_size elements, each of + * size stride. The elements in the array at indices >i satisfy the max-heap + * property, i.e., for any element at index j (where j > i), all of its children + * are smaller than the element itself. The purpose of the function is to update + * the array so that all elements at indices >=i satisfy the max-heap + * property. */ +static SECP256K1_INLINE void secp256k1_heap_down(unsigned char *arr, size_t i, size_t heap_size, size_t stride, + int (*cmp)(const void *, const void *, void *), void *cmp_data) { + while (i < heap_size/2) { + VERIFY_CHECK(i <= SIZE_MAX/2 - 1); + /* Proof: + * i < heap_size/2 + * i + 1 <= heap_size/2 + * 2*i + 2 <= heap_size <= SIZE_MAX + * 2*i <= SIZE_MAX - 2 + */ + + VERIFY_CHECK(secp256k1_heap_child1(i) < heap_size); + /* Proof: + * i < heap_size/2 + * i + 1 <= heap_size/2 + * 2*i + 2 <= heap_size + * 2*i + 1 < heap_size + * child1(i) < heap_size + */ + + /* Let [x] be notation for the contents at arr[x*stride]. + * + * If [child1(i)] > [i] and [child2(i)] > [i], + * swap [i] with the larger child to ensure the new parent is larger + * than both children. When [child1(i)] == [child2(i)], swap [i] with + * [child2(i)]. + * Else if [child1(i)] > [i], swap [i] with [child1(i)]. + * Else if [child2(i)] > [i], swap [i] with [child2(i)]. + */ + if (secp256k1_heap_child2(i) < heap_size + && 0 <= cmp(arr + secp256k1_heap_child2(i)*stride, arr + secp256k1_heap_child1(i)*stride, cmp_data)) { + if (0 < cmp(arr + secp256k1_heap_child2(i)*stride, arr + i*stride, cmp_data)) { + secp256k1_heap_swap(arr, i, secp256k1_heap_child2(i), stride); + i = secp256k1_heap_child2(i); + } else { + /* At this point we have [child2(i)] >= [child1(i)] and we have + * [child2(i)] <= [i], and thus [child1(i)] <= [i] which means + * that the next comparison can be skipped. */ + return; + } + } else if (0 < cmp(arr + secp256k1_heap_child1(i)*stride, arr + i*stride, cmp_data)) { + secp256k1_heap_swap(arr, i, secp256k1_heap_child1(i), stride); + i = secp256k1_heap_child1(i); + } else { + return; + } + } + /* heap_size/2 <= i + * heap_size/2 < i + 1 + * heap_size < 2*i + 2 + * heap_size <= 2*i + 1 + * heap_size <= child1(i) + * Thus child1(i) and child2(i) are now out of bounds and we are at a leaf. + */ +} + +/* In-place heap sort. */ +static void secp256k1_hsort(void *ptr, size_t count, size_t size, + int (*cmp)(const void *, const void *, void *), + void *cmp_data) { + size_t i; + + for (i = count/2; 0 < i; --i) { + secp256k1_heap_down(ptr, i-1, count, size, cmp, cmp_data); + } + for (i = count; 1 < i; --i) { + /* Extract the largest value from the heap */ + secp256k1_heap_swap(ptr, 0, i-1, size); + + /* Repair the heap condition */ + secp256k1_heap_down(ptr, 0, i-1, size, cmp, cmp_data); + } +} + +#endif diff --git a/src/secp256k1.c b/src/secp256k1.c index 15a5eede..7a327694 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -36,6 +36,7 @@ #include "int128_impl.h" #include "scratch_impl.h" #include "selftest.h" +#include "hsort_impl.h" #ifdef SECP256K1_NO_BUILD # error "secp256k1.h processed without SECP256K1_BUILD defined while building secp256k1.c" @@ -325,6 +326,34 @@ int secp256k1_ec_pubkey_cmp(const secp256k1_context* ctx, const secp256k1_pubkey return secp256k1_memcmp_var(out[0], out[1], sizeof(out[0])); } +static int secp256k1_ec_pubkey_sort_cmp(const void* pk1, const void* pk2, void *ctx) { + return secp256k1_ec_pubkey_cmp((secp256k1_context *)ctx, + *(secp256k1_pubkey **)pk1, + *(secp256k1_pubkey **)pk2); +} + +int secp256k1_ec_pubkey_sort(const secp256k1_context* ctx, const secp256k1_pubkey **pubkeys, size_t n_pubkeys) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkeys != NULL); + + /* Suppress wrong warning (fixed in MSVC 19.33) */ + #if defined(_MSC_VER) && (_MSC_VER < 1933) + #pragma warning(push) + #pragma warning(disable: 4090) + #endif + + /* Casting away const is fine because neither secp256k1_hsort nor + * secp256k1_ec_pubkey_sort_cmp modify the data pointed to by the cmp_data + * argument. */ + secp256k1_hsort(pubkeys, n_pubkeys, sizeof(*pubkeys), secp256k1_ec_pubkey_sort_cmp, (void *)ctx); + + #if defined(_MSC_VER) && (_MSC_VER < 1933) + #pragma warning(pop) + #endif + + return 1; +} + static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { (void)ctx; if (sizeof(secp256k1_scalar) == 32) { diff --git a/src/tests.c b/src/tests.c index ec9cd0e0..2eb3fbfd 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3676,6 +3676,78 @@ static void run_inverse_tests(void) } } +/***** HSORT TESTS *****/ + +static void test_heap_swap(void) { + unsigned char a[600]; + unsigned char e[sizeof(a)]; + memset(a, 21, 200); + memset(a + 200, 99, 200); + memset(a + 400, 42, 200); + memset(e, 42, 200); + memset(e + 200, 99, 200); + memset(e + 400, 21, 200); + secp256k1_heap_swap(a, 0, 2, 200); + CHECK(secp256k1_memcmp_var(a, e, sizeof(a)) == 0); +} + +static void test_hsort_is_sorted(unsigned char *elements, size_t n, size_t len) { + size_t i; + for (i = 1; i < n; i++) { + CHECK(secp256k1_memcmp_var(&elements[(i-1) * len], &elements[i * len], len) <= 0); + } +} + +struct test_hsort_cmp_data { + size_t counter; + size_t element_len; +}; + + +static int test_hsort_cmp(const void *ele1, const void *ele2, void *data) { + struct test_hsort_cmp_data *d = (struct test_hsort_cmp_data *) data; + d->counter += 1; + return secp256k1_memcmp_var((unsigned char *)ele1, (unsigned char *)ele2, d->element_len); +} + +#define NUM 65 +#define MAX_ELEMENT_LEN 65 +static void test_hsort(size_t element_len) { + unsigned char elements[NUM * MAX_ELEMENT_LEN] = { 0 }; + struct test_hsort_cmp_data data; + int i; + + VERIFY_CHECK(element_len <= MAX_ELEMENT_LEN); + data.counter = 0; + data.element_len = element_len; + + secp256k1_hsort(elements, 0, element_len, test_hsort_cmp, &data); + CHECK(data.counter == 0); + secp256k1_hsort(elements, 1, element_len, test_hsort_cmp, &data); + CHECK(data.counter == 0); + secp256k1_hsort(elements, NUM, element_len, test_hsort_cmp, &data); + CHECK(data.counter >= NUM - 1); + test_hsort_is_sorted(elements, NUM, element_len); + + /* Test hsort with array of random length n */ + for (i = 0; i < COUNT; i++) { + int n = secp256k1_testrand_int(NUM); + secp256k1_testrand_bytes_test(elements, n*element_len); + secp256k1_hsort(elements, n, element_len, test_hsort_cmp, &data); + test_hsort_is_sorted(elements, n, element_len); + } +} +#undef NUM +#undef MAX_ELEMENT_LEN + + +static void run_hsort_tests(void) { + test_heap_swap(); + test_hsort(1); + test_hsort(64); + test_hsort(65); +} + /***** GROUP TESTS *****/ /* This compares jacobian points including their Z, not just their geometric meaning. */ @@ -6629,6 +6701,161 @@ static void run_pubkey_comparison(void) { CHECK(secp256k1_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); } +static void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk) { + size_t i; + const secp256k1_pubkey *pk_test[5]; + + for (i = 0; i < n_pk; i++) { + pk_test[i] = &pk[pk_order[i]]; + } + secp256k1_ec_pubkey_sort(CTX, pk_test, n_pk); + for (i = 0; i < n_pk; i++) { + CHECK(secp256k1_memcmp_var(pk_test[i], &pk[i], sizeof(*pk_test[i])) == 0); + } +} + +static void permute(size_t *arr, size_t n) { + size_t i; + for (i = n - 1; i >= 1; i--) { + size_t tmp, j; + j = secp256k1_testrand_int(i + 1); + tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } +} + +static void rand_pk(secp256k1_pubkey *pk) { + unsigned char seckey[32]; + secp256k1_keypair keypair; + secp256k1_testrand256(seckey); + CHECK(secp256k1_keypair_create(CTX, &keypair, seckey) == 1); + CHECK(secp256k1_keypair_pub(CTX, pk, &keypair) == 1); +} + +static void test_sort_api(void) { + secp256k1_pubkey pks[2]; + const secp256k1_pubkey *pks_ptr[2]; + + pks_ptr[0] = &pks[0]; + pks_ptr[1] = &pks[1]; + + rand_pk(&pks[0]); + rand_pk(&pks[1]); + + CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_sort(CTX, NULL, 2)); + CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 0) == 1); + /* Test illegal public keys */ + memset(&pks[0], 0, sizeof(pks[0])); + CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1)); + memset(&pks[1], 0, sizeof(pks[1])); + { + int32_t ecount = 0; + secp256k1_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); + CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); + CHECK(ecount == 2); + secp256k1_context_set_illegal_callback(CTX, NULL, NULL); + } +} + +static void test_sort(void) { + secp256k1_pubkey pk[5]; + unsigned char pk_ser[5][33] = { + { 0x02, 0x08 }, + { 0x02, 0x0b }, + { 0x02, 0x0c }, + { 0x03, 0x05 }, + { 0x03, 0x0a }, + }; + int i; + size_t pk_order[5] = { 0, 1, 2, 3, 4 }; + + for (i = 0; i < 5; i++) { + CHECK(secp256k1_ec_pubkey_parse(CTX, &pk[i], pk_ser[i], sizeof(pk_ser[i]))); + } + + permute(pk_order, 1); + test_sort_helper(pk, pk_order, 1); + permute(pk_order, 2); + test_sort_helper(pk, pk_order, 2); + permute(pk_order, 3); + test_sort_helper(pk, pk_order, 3); + for (i = 0; i < COUNT; i++) { + permute(pk_order, 4); + test_sort_helper(pk, pk_order, 4); + } + for (i = 0; i < COUNT; i++) { + permute(pk_order, 5); + test_sort_helper(pk, pk_order, 5); + } + /* Check that sorting also works for random pubkeys */ + for (i = 0; i < COUNT; i++) { + int j; + const secp256k1_pubkey *pk_ptr[5]; + for (j = 0; j < 5; j++) { + rand_pk(&pk[j]); + pk_ptr[j] = &pk[j]; + } + secp256k1_ec_pubkey_sort(CTX, pk_ptr, 5); + for (j = 1; j < 5; j++) { + CHECK(secp256k1_ec_pubkey_sort_cmp(&pk_ptr[j - 1], &pk_ptr[j], CTX) <= 0); + } + } +} + +/* Test vectors from BIP-MuSig2 */ +static void test_sort_vectors(void) { + enum { N_PUBKEYS = 6 }; + unsigned char pk_ser[N_PUBKEYS][33] = { + { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, + 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, + 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 }, + { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, + 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, + 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, + { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, + 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, + 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }, + { 0x02, 0x35, 0x90, 0xA9, 0x4E, 0x76, 0x8F, 0x8E, 0x18, 0x15, 0xC2, + 0xF2, 0x4B, 0x4D, 0x80, 0xA8, 0xE3, 0x14, 0x93, 0x16, 0xC3, 0x51, + 0x8C, 0xE7, 0xB7, 0xAD, 0x33, 0x83, 0x68, 0xD0, 0x38, 0xCA, 0x66 }, + { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, + 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, + 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xFF }, + { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, + 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, + 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 } + }; + secp256k1_pubkey pubkeys[N_PUBKEYS]; + secp256k1_pubkey *sorted[N_PUBKEYS]; + const secp256k1_pubkey *pks_ptr[N_PUBKEYS]; + int i; + + sorted[0] = &pubkeys[3]; + sorted[1] = &pubkeys[0]; + sorted[2] = &pubkeys[0]; + sorted[3] = &pubkeys[4]; + sorted[4] = &pubkeys[1]; + sorted[5] = &pubkeys[2]; + + for (i = 0; i < N_PUBKEYS; i++) { + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkeys[i], pk_ser[i], sizeof(pk_ser[i]))); + pks_ptr[i] = &pubkeys[i]; + } + CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, N_PUBKEYS) == 1); + for (i = 0; i < N_PUBKEYS; i++) { + CHECK(secp256k1_memcmp_var(pks_ptr[i], sorted[i], sizeof(secp256k1_pubkey)) == 0); + } +} + +static void run_pubkey_sort(void) { + test_sort_api(); + test_sort(); + test_sort_vectors(); +} + + static void run_random_pubkeys(void) { int i; for (i = 0; i < 10*COUNT; i++) { @@ -7588,6 +7815,9 @@ int main(int argc, char **argv) { run_modinv_tests(); run_inverse_tests(); + /* sorting tests */ + run_hsort_tests(); + /* hash tests */ run_sha256_known_output_tests(); run_sha256_counter_tests(); @@ -7644,6 +7874,7 @@ int main(int argc, char **argv) { /* ecdsa tests */ run_ec_illegal_argument_tests(); run_pubkey_comparison(); + run_pubkey_sort(); run_random_pubkeys(); run_ecdsa_der_parse(); run_ecdsa_sign_verify(); From c0e4ec3fee2d4755c0421a4568ba3253c2063180 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 6 May 2024 17:42:03 +0200 Subject: [PATCH 034/383] release: prepare for 0.5.0 --- CHANGELOG.md | 7 +++++-- CMakeLists.txt | 8 ++++---- configure.ac | 12 ++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98252da5..ff466b12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.5.0] - 2025-05-06 #### Added - New function `secp256k1_ec_pubkey_sort` that sorts public keys using lexicographic (of compressed serialization) order. @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The related configure option `--ecmult-gen-precision` was replaced with `--ecmult-gen-kb` (`ECMULT_GEN_KB` for CMake). - This changes the supported precomputed table sizes for these operations. The new supported sizes are 2 KiB, 22 KiB, or 86 KiB (while the old supported sizes were 32 KiB, 64 KiB, or 512 KiB). +#### ABI Compatibility +The ABI is backward compatible with versions 0.4.x and 0.3.x. + ## [0.4.1] - 2023-12-21 #### Changed @@ -123,7 +126,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. -[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...HEAD +[0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...v0.4.0 [0.3.2]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.1...v0.3.2 diff --git a/CMakeLists.txt b/CMakeLists.txt index a70f2edd..9e4687ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.4.2 + VERSION 0.5.0 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -34,9 +34,9 @@ endif() # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -set(${PROJECT_NAME}_LIB_VERSION_CURRENT 3) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 2) -set(${PROJECT_NAME}_LIB_VERSION_AGE 1) +set(${PROJECT_NAME}_LIB_VERSION_CURRENT 4) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_AGE 2) set(CMAKE_C_STANDARD 90) set(CMAKE_C_EXTENSIONS OFF) diff --git a/configure.ac b/configure.ac index 68eae5ad..42f94c86 100644 --- a/configure.ac +++ b/configure.ac @@ -4,18 +4,18 @@ AC_PREREQ([2.60]) # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) -define(_PKG_VERSION_MINOR, 4) -define(_PKG_VERSION_PATCH, 2) -define(_PKG_VERSION_IS_RELEASE, false) +define(_PKG_VERSION_MINOR, 5) +define(_PKG_VERSION_PATCH, 0) +define(_PKG_VERSION_IS_RELEASE, true) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -define(_LIB_VERSION_CURRENT, 3) -define(_LIB_VERSION_REVISION, 2) -define(_LIB_VERSION_AGE, 1) +define(_LIB_VERSION_CURRENT, 4) +define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_AGE, 2) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From dd695563e68d605b837b7813ae7bfafbf866ddff Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 6 May 2024 16:28:01 +0000 Subject: [PATCH 035/383] check-abi: explicitly provide public headers Without this commit, the check-abi shell script outputs false positives because it consider some headers public that are actually not public. --- tools/check-abi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/check-abi.sh b/tools/check-abi.sh index 55c945ac..94a98831 100755 --- a/tools/check-abi.sh +++ b/tools/check-abi.sh @@ -49,7 +49,7 @@ checkout_and_build() { -DSECP256K1_BUILD_CTIME_TESTS=OFF \ -DSECP256K1_BUILD_EXAMPLES=OFF cmake --build . -j "$(nproc)" - abi-dumper src/libsecp256k1.so -o ABI.dump -lver "$2" + abi-dumper src/libsecp256k1.so -o ABI.dump -lver "$2" -public-headers ../include/ cd "$_orig_dir" } From 2f05e2da4b7a2a9ca67c5aa9f6ed26ac9fcc2f6e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 6 May 2024 18:26:05 +0200 Subject: [PATCH 036/383] release cleanup: bump version after 0.5.0 --- CHANGELOG.md | 3 +++ CMakeLists.txt | 4 ++-- configure.ac | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff466b12..9c588c21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + ## [0.5.0] - 2025-05-06 #### Added @@ -126,6 +128,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. +[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...HEAD [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...v0.4.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e4687ae..88994d82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.5.0 + VERSION 0.5.1 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -35,7 +35,7 @@ endif() # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. set(${PROJECT_NAME}_LIB_VERSION_CURRENT 4) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) set(${PROJECT_NAME}_LIB_VERSION_AGE 2) set(CMAKE_C_STANDARD 90) diff --git a/configure.ac b/configure.ac index 42f94c86..8b62e1db 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,8 @@ AC_PREREQ([2.60]) # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 5) -define(_PKG_VERSION_PATCH, 0) -define(_PKG_VERSION_IS_RELEASE, true) +define(_PKG_VERSION_PATCH, 1) +define(_PKG_VERSION_IS_RELEASE, false) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. define(_LIB_VERSION_CURRENT, 4) -define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_REVISION, 1) define(_LIB_VERSION_AGE, 2) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From d45d9b74bb85ebf5a82c29d6e7f9b293212726de Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 6 May 2024 19:19:28 +0200 Subject: [PATCH 037/383] changelog: Correct 0.5.0 release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c588c21..a2855912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.5.0] - 2025-05-06 +## [0.5.0] - 2024-05-06 #### Added - New function `secp256k1_ec_pubkey_sort` that sorts public keys using lexicographic (of compressed serialization) order. From 9f4c8cd730bba94f0c09cbef9b0cf9df44eb7b03 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 7 May 2024 12:29:25 +0100 Subject: [PATCH 038/383] cmake: Fix `check_arm32_assembly` when using as subproject --- cmake/CheckArm32Assembly.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/CheckArm32Assembly.cmake b/cmake/CheckArm32Assembly.cmake index 15c44b24..baeeff02 100644 --- a/cmake/CheckArm32Assembly.cmake +++ b/cmake/CheckArm32Assembly.cmake @@ -1,6 +1,6 @@ function(check_arm32_assembly) try_compile(HAVE_ARM32_ASM - ${CMAKE_BINARY_DIR}/check_arm32_assembly - SOURCES ${CMAKE_SOURCE_DIR}/cmake/source_arm32.s + ${PROJECT_BINARY_DIR}/check_arm32_assembly + SOURCES ${PROJECT_SOURCE_DIR}/cmake/source_arm32.s ) endfunction() From 9554362b1532d8292ab805cefb9c886cd55ac205 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Wed, 8 May 2024 19:13:35 +0200 Subject: [PATCH 039/383] tests: call secp256k1_ecmult_multi_var with a non-NULL error callback Function secp256k1_ecmult_multi_var expects to be called with a non-NULL error_callback parameter. Fix the invocation in test_ecmult_accumulate to do this. While at it, wrap the call in a CHECK macro to ensure it succeeds. Fixes: https://github.com/bitcoin-core/secp256k1/issues/1527 --- src/tests.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests.c b/src/tests.c index 2eb3fbfd..dab47608 100644 --- a/src/tests.c +++ b/src/tests.c @@ -5494,8 +5494,8 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); secp256k1_ecmult(&rj2, &gj, x, &secp256k1_scalar_zero); secp256k1_ecmult(&rj3, &infj, &secp256k1_scalar_zero, x); - secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0); - secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &secp256k1_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1); + CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj4, x, NULL, NULL, 0)); + CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj5, &secp256k1_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1)); secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x); secp256k1_ge_set_gej_var(&r, &rj1); CHECK(secp256k1_gej_eq_ge_var(&rj2, &r)); From cae9a7ad149d359c061372107d212cdcfad5d323 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 11 May 2024 11:05:12 +0100 Subject: [PATCH 040/383] cmake: Do not set emulated PROJECT_IS_TOP_LEVEL as cache variable Otherwise, downstream projects, which integrate the libsecp256k1 library using the `add_subdirectory()` command, will be affected. --- CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88994d82..27d6e643 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,13 +18,14 @@ project(libsecp256k1 ) if(CMAKE_VERSION VERSION_LESS 3.21) + # Emulates CMake 3.21+ behavior. get_directory_property(parent_directory PARENT_DIRECTORY) if(parent_directory) - set(PROJECT_IS_TOP_LEVEL OFF CACHE INTERNAL "Emulates CMake 3.21+ behavior.") - set(${PROJECT_NAME}_IS_TOP_LEVEL OFF CACHE INTERNAL "Emulates CMake 3.21+ behavior.") + set(PROJECT_IS_TOP_LEVEL OFF) + set(${PROJECT_NAME}_IS_TOP_LEVEL OFF) else() - set(PROJECT_IS_TOP_LEVEL ON CACHE INTERNAL "Emulates CMake 3.21+ behavior.") - set(${PROJECT_NAME}_IS_TOP_LEVEL ON CACHE INTERNAL "Emulates CMake 3.21+ behavior.") + set(PROJECT_IS_TOP_LEVEL ON) + set(${PROJECT_NAME}_IS_TOP_LEVEL ON) endif() unset(parent_directory) endif() From ec4c002faa350f02919fe0f710279d2922e254a1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 11 May 2024 11:13:41 +0100 Subject: [PATCH 041/383] cmake: Simplify `PROJECT_IS_TOP_LEVEL` emulation Detecting whether it is the top level by comparing the value of `CMAKE_SOURCE_DIR` with `CMAKE_CURRENT_SOURCE_DIR` is supported by all versions of CMake and is a very common pattern. --- CMakeLists.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27d6e643..fffa123d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,15 +19,13 @@ project(libsecp256k1 if(CMAKE_VERSION VERSION_LESS 3.21) # Emulates CMake 3.21+ behavior. - get_directory_property(parent_directory PARENT_DIRECTORY) - if(parent_directory) - set(PROJECT_IS_TOP_LEVEL OFF) - set(${PROJECT_NAME}_IS_TOP_LEVEL OFF) - else() + if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(PROJECT_IS_TOP_LEVEL ON) set(${PROJECT_NAME}_IS_TOP_LEVEL ON) + else() + set(PROJECT_IS_TOP_LEVEL OFF) + set(${PROJECT_NAME}_IS_TOP_LEVEL OFF) endif() - unset(parent_directory) endif() # The library version is based on libtool versioning of the ABI. The set of From 55e5d975db9a641bcbeffcc3fc086e54d322fe26 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 15 Apr 2024 17:07:41 +0200 Subject: [PATCH 042/383] autotools: Disable eager MSan in ctime_tests Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> --- build-aux/m4/bitcoin_secp.m4 | 12 ++++++++++++ configure.ac | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4 index 11adef4f..fee2d7b4 100644 --- a/build-aux/m4/bitcoin_secp.m4 +++ b/build-aux/m4/bitcoin_secp.m4 @@ -45,6 +45,18 @@ fi AC_MSG_RESULT($has_valgrind) ]) +AC_DEFUN([SECP_MSAN_CHECK], [ +AC_MSG_CHECKING(whether MemorySanitizer is enabled) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + #if defined(__has_feature) + # if __has_feature(memory_sanitizer) + # error "MemorySanitizer is enabled." + # endif + #endif + ]])], [msan_enabled=no], [msan_enabled=yes]) +AC_MSG_RESULT([$msan_enabled]) +]) + dnl SECP_TRY_APPEND_CFLAGS(flags, VAR) dnl Append flags to VAR if CC accepts them. AC_DEFUN([SECP_TRY_APPEND_CFLAGS], [ diff --git a/configure.ac b/configure.ac index 8b62e1db..085c3609 100644 --- a/configure.ac +++ b/configure.ac @@ -247,6 +247,20 @@ if test x"$enable_ctime_tests" = x"auto"; then enable_ctime_tests=$enable_valgrind fi +print_msan_notice=no +if test x"$enable_ctime_tests" = x"yes" && test x"$GCC" = x"yes"; then + SECP_MSAN_CHECK + # MSan on Clang >=16 reports unitialized memory in function parameters and return values, even if + # the uninitalized variable is never actually "used". This is called "eager" checking, and it's + # sounds like good idea for normal use of MSan. However, it yields many false positives in the + # ctime_tests because many return values depend on secret (i.e., "uninitialized") values, and + # we're only interested in detecting branches (which count as "uses") on secret data. + if test x"$msan_enabled" = x"yes"; then + SECP_TRY_APPEND_CFLAGS([-fno-sanitize-memory-param-retval], SECP_CFLAGS) + print_msan_notice=yes + fi +fi + if test x"$enable_coverage" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOVERAGE=1" SECP_CFLAGS="-O0 --coverage $SECP_CFLAGS" @@ -492,3 +506,10 @@ echo " CPPFLAGS = $CPPFLAGS" echo " SECP_CFLAGS = $SECP_CFLAGS" echo " CFLAGS = $CFLAGS" echo " LDFLAGS = $LDFLAGS" + +if test x"$print_msan_notice" = x"yes"; then + echo + echo "Note:" + echo " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to SECP_CFLAGS" + echo " to avoid false positives in ctime_tests. Pass --disable-ctime-tests to avoid this." +fi From e1bef0961c53b23dbaf35f5fa87149a1aadfad37 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 22 May 2024 15:10:33 +0200 Subject: [PATCH 043/383] configure: Move "experimental" warning to bottom to make it more promiment --- configure.ac | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 085c3609..9640a673 100644 --- a/configure.ac +++ b/configure.ac @@ -440,12 +440,7 @@ fi ### Check for --enable-experimental if necessary ### -if test x"$enable_experimental" = x"yes"; then - AC_MSG_NOTICE([******]) - AC_MSG_NOTICE([WARNING: experimental build]) - AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) - AC_MSG_NOTICE([******]) -else +if test x"$enable_experimental" = x"no"; then if test x"$set_asm" = x"arm32"; then AC_MSG_ERROR([ARM32 assembly is experimental. Use --enable-experimental to allow.]) fi @@ -513,3 +508,10 @@ if test x"$print_msan_notice" = x"yes"; then echo " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to SECP_CFLAGS" echo " to avoid false positives in ctime_tests. Pass --disable-ctime-tests to avoid this." fi + +if test x"$enable_experimental" = x"yes"; then + echo + echo "WARNING: Experimental build" + echo " Experimental features do not have stable APIs or properties, and may not be safe for" + echo " production use." +fi From ebfb82ee2f8c15ae6129932380b1dfb0942ea35a Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 22 May 2024 16:51:51 +0200 Subject: [PATCH 044/383] ci: Add job with -fsanitize-memory-param-retval --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2466820..0d3ca20e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -485,18 +485,24 @@ jobs: matrix: configuration: - env_vars: + CTIMETESTS: 'yes' CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g' - env_vars: ECMULTGENKB: 2 ECMULTWINDOW: 2 + CTIMETESTS: 'yes' CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3' + - env_vars: + # -fsanitize-memory-param-retval is clang's default, but our build system disables it + # when ctime_tests when enabled. + CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g' + CTIMETESTS: 'no' env: ECDH: 'yes' RECOVERY: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' - CTIMETESTS: 'yes' CC: 'clang' SECP256K1_TEST_ITERS: 32 ASM: 'no' From 59db007f0ff909de8d6f86b5c06ccf2d202c365b Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 27 May 2024 02:01:55 +0200 Subject: [PATCH 045/383] tests: refactor: rename `random_group_element_...` -> `random_ge_...` The rename was done with the following command: $ sed -i 's/random_group_element_/random_ge_/g' $(git grep -l random_group_element_) --- src/modules/ellswift/tests_impl.h | 2 +- src/tests.c | 52 +++++++++++++++---------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index f96e3a12..7fd7b04c 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -229,7 +229,7 @@ void run_ellswift_tests(void) { secp256k1_ge g, g2; secp256k1_pubkey pubkey, pubkey2; /* Generate random public key and random randomizer. */ - random_group_element_test(&g); + random_ge_test(&g); secp256k1_pubkey_save(&pubkey, &g); secp256k1_testrand256(rnd32); /* Convert the public key to ElligatorSwift and back. */ diff --git a/src/tests.c b/src/tests.c index dab47608..4a1c6c51 100644 --- a/src/tests.c +++ b/src/tests.c @@ -152,7 +152,7 @@ static void random_gej_z_magnitude(secp256k1_gej *gej) { random_field_element_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); } -static void random_group_element_test(secp256k1_ge *ge) { +static void random_ge_test(secp256k1_ge *ge) { secp256k1_fe fe; do { random_fe_test(&fe); @@ -164,7 +164,7 @@ static void random_group_element_test(secp256k1_ge *ge) { ge->infinity = 0; } -static void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { +static void random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { secp256k1_fe z2, z3; random_fe_non_zero_test(&gej->z); secp256k1_fe_sqr(&z2, &gej->z); @@ -176,8 +176,8 @@ static void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256 static void random_gej_test(secp256k1_gej *gej) { secp256k1_ge ge; - random_group_element_test(&ge); - random_group_element_jacobian_test(gej, &ge); + random_ge_test(&ge); + random_ge_jacobian_test(gej, &ge); } static void random_scalar_order_test(secp256k1_scalar *num) { @@ -3792,7 +3792,7 @@ static void test_ge(void) { for (i = 0; i < runs; i++) { int j, k; secp256k1_ge g; - random_group_element_test(&g); + random_ge_test(&g); if (i >= runs - 2) { secp256k1_ge_mul_lambda(&g, &ge[1]); CHECK(!secp256k1_ge_eq_var(&g, &ge[1])); @@ -3805,9 +3805,9 @@ static void test_ge(void) { secp256k1_ge_neg(&ge[3 + 4 * i], &g); secp256k1_ge_neg(&ge[4 + 4 * i], &g); secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); - random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); + random_ge_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); - random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); + random_ge_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); for (j = 0; j < 4; j++) { random_ge_x_magnitude(&ge[1 + j + 4 * i]); random_ge_y_magnitude(&ge[1 + j + 4 * i]); @@ -3975,7 +3975,7 @@ static void test_ge(void) { /* Test batch gej -> ge conversion with many infinities. */ for (i = 0; i < 4 * runs + 1; i++) { int odd; - random_group_element_test(&ge[i]); + random_ge_test(&ge[i]); odd = secp256k1_fe_is_odd(&ge[i].x); CHECK(odd == 0 || odd == 1); /* randomly set half the points to infinity */ @@ -4012,7 +4012,7 @@ static void test_intialized_inf(void) { secp256k1_fe zinv; /* Test that adding P+(-P) results in a fully initialized infinity*/ - random_group_element_test(&p); + random_ge_test(&p); secp256k1_gej_set_ge(&pj, &p); secp256k1_gej_neg(&npj, &pj); @@ -4437,7 +4437,7 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) { /* Generate a random input point. */ if (mode != 0) { - random_group_element_test(&p); + random_ge_test(&p); secp256k1_gej_set_ge(&pj, &p); } @@ -4553,7 +4553,7 @@ static void ecmult_const_mult_zero_one(void) { random_scalar_order_test(&s); secp256k1_scalar_negate(&negone, &secp256k1_scalar_one); - random_group_element_test(&point); + random_ge_test(&point); secp256k1_ge_set_infinity(&inf); /* 0*point */ @@ -4606,7 +4606,7 @@ static void ecmult_const_edges(void) { secp256k1_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); secp256k1_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); } - random_group_element_test(&point); + random_ge_test(&point); secp256k1_ecmult_const(&res, &point, &q); ecmult_const_check_result(&point, &q, &res); } @@ -4623,7 +4623,7 @@ static void ecmult_const_mult_xonly(void) { secp256k1_scalar q; int res; /* Random base point. */ - random_group_element_test(&base); + random_ge_test(&base); /* Random scalar to multiply it with. */ random_scalar_order_test(&q); /* If i is odd, n=d*base.x for random non-zero d */ @@ -4743,7 +4743,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi random_scalar_order(&sc[0]); random_scalar_order(&sc[1]); - random_group_element_test(&ptg); + random_ge_test(&ptg); secp256k1_gej_set_ge(&ptgj, &ptg); pt[0] = ptg; pt[1] = secp256k1_ge_const_g; @@ -4789,7 +4789,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi for (j = 0; j < 3; j++) { for (i = 0; i < 32; i++) { - random_group_element_test(&ptg); + random_ge_test(&ptg); pt[i] = ptg; secp256k1_scalar_set_int(&sc[i], 0); } @@ -4798,7 +4798,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi } for (j = 0; j < 3; j++) { - random_group_element_test(&ptg); + random_ge_test(&ptg); for (i = 0; i < 16; i++) { random_scalar_order(&sc[2*i]); secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]); @@ -4811,7 +4811,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi random_scalar_order(&sc[0]); for (i = 0; i < 16; i++) { - random_group_element_test(&ptg); + random_ge_test(&ptg); sc[2*i] = sc[0]; sc[2*i+1] = sc[0]; @@ -4823,7 +4823,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi CHECK(secp256k1_gej_is_infinity(&r)); } - random_group_element_test(&ptg); + random_ge_test(&ptg); secp256k1_scalar_set_int(&sc[0], 0); pt[0] = ptg; for (i = 1; i < 32; i++) { @@ -4847,7 +4847,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi for (i = 0; i < 20; i++) { secp256k1_ge ptg; sc[i] = sc[0]; - random_group_element_test(&ptg); + random_ge_test(&ptg); pt[i] = ptg; secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL); } @@ -4865,7 +4865,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi secp256k1_scalar rs; secp256k1_scalar_set_int(&rs, 0); - random_group_element_test(&ptg); + random_ge_test(&ptg); for (i = 0; i < 20; i++) { random_scalar_order(&sc[i]); pt[i] = ptg; @@ -4881,7 +4881,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi /* Sanity check that zero scalars don't cause problems */ for (ncount = 0; ncount < 20; ncount++) { random_scalar_order(&sc[ncount]); - random_group_element_test(&pt[ncount]); + random_ge_test(&pt[ncount]); } secp256k1_scalar_clear(&sc[0]); @@ -4902,7 +4902,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi secp256k1_ge ptg; secp256k1_gej ptgj; - random_group_element_test(&ptg); + random_ge_test(&ptg); secp256k1_gej_set_ge(&ptgj, &ptg); for(t0i = 0; t0i < TOP; t0i++) { @@ -5021,7 +5021,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { if (nonzero_result && filled < num_nonzero) { /* If a nonzero result is desired, and there is space, add a random nonzero term. */ random_scalar_order_test(&scalars[filled]); - random_group_element_test(&ge_tmp); + random_ge_test(&ge_tmp); secp256k1_gej_set_ge(&gejs[filled], &ge_tmp); ++filled; } @@ -5045,7 +5045,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { random_scalar_order_test(&scalars[filled]); } else { secp256k1_scalar_set_int(&scalars[filled], 0); - random_group_element_test(&ge_tmp); + random_ge_test(&ge_tmp); secp256k1_gej_set_ge(&gejs[filled], &ge_tmp); } ++filled; @@ -5118,7 +5118,7 @@ static void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_mu ecmult_multi_data data; secp256k1_scratch *scratch_empty; - random_group_element_test(&pt); + random_ge_test(&pt); random_scalar_order(&sc); data.sc = ≻ data.pt = &pt; @@ -5249,7 +5249,7 @@ static void test_ecmult_multi_batching(void) { for(i = 0; i < n_points; i++) { secp256k1_ge ptg; secp256k1_gej ptgj; - random_group_element_test(&ptg); + random_ge_test(&ptg); secp256k1_gej_set_ge(&ptgj, &ptg); pt[i] = ptg; random_scalar_order(&sc[i]); From 0fef8479be9d4a7fb878aac6ee4412a0c3b92296 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 27 May 2024 02:22:45 +0200 Subject: [PATCH 046/383] tests: refactor: rename `random_field_element_magnitude` -> `random_fe_magnitude` Note that the already existing function `random_fe_magnitude` is removed and the call-sites are adapted to pass the magnitude range of 8 (the maximum for secp256k1_fe_mul and secp256k1_fe_sqr) explicitly. --- src/tests.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/tests.c b/src/tests.c index 4a1c6c51..5fb2a285 100644 --- a/src/tests.c +++ b/src/tests.c @@ -96,7 +96,7 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) { (*p)--; } -static void random_field_element_magnitude(secp256k1_fe *fe, int m) { +static void random_fe_magnitude(secp256k1_fe *fe, int m) { secp256k1_fe zero; int n = secp256k1_testrand_int(m + 1); secp256k1_fe_normalize(fe); @@ -128,28 +128,24 @@ static void random_fe_non_zero_test(secp256k1_fe *fe) { } while(secp256k1_fe_is_zero(fe)); } -static void random_fe_magnitude(secp256k1_fe *fe) { - random_field_element_magnitude(fe, 8); -} - static void random_ge_x_magnitude(secp256k1_ge *ge) { - random_field_element_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); + random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); } static void random_ge_y_magnitude(secp256k1_ge *ge) { - random_field_element_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); + random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); } static void random_gej_x_magnitude(secp256k1_gej *gej) { - random_field_element_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); + random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); } static void random_gej_y_magnitude(secp256k1_gej *gej) { - random_field_element_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); + random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); } static void random_gej_z_magnitude(secp256k1_gej *gej) { - random_field_element_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); + random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); } static void random_ge_test(secp256k1_ge *ge) { @@ -3269,13 +3265,13 @@ static void run_fe_mul(void) { for (i = 0; i < 100 * COUNT; ++i) { secp256k1_fe a, b, c, d; random_fe(&a); - random_fe_magnitude(&a); + random_fe_magnitude(&a, 8); random_fe(&b); - random_fe_magnitude(&b); + random_fe_magnitude(&b, 8); random_fe_test(&c); - random_fe_magnitude(&c); + random_fe_magnitude(&c, 8); random_fe_test(&d); - random_fe_magnitude(&d); + random_fe_magnitude(&d, 8); test_fe_mul(&a, &a, 1); test_fe_mul(&c, &c, 1); test_fe_mul(&a, &b, 0); @@ -3829,7 +3825,7 @@ static void test_ge(void) { /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ random_fe_non_zero_test(&zf); - random_fe_magnitude(&zf); + random_fe_magnitude(&zf, 8); secp256k1_fe_inv_var(&zfi3, &zf); secp256k1_fe_sqr(&zfi2, &zfi3); secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); From 0c6bc76dcdf3be94c58772a88a2e94878cda6447 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 27 May 2024 02:38:30 +0200 Subject: [PATCH 047/383] tests: refactor: move `random_` helpers from tests.c to testutil.h Can be reviewed via `--color-moved=dimmed-zebra`. --- src/tests.c | 112 ------------------------------------------------ src/testutil.h | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 112 deletions(-) diff --git a/src/tests.c b/src/tests.c index 5fb2a285..9f2313c4 100644 --- a/src/tests.c +++ b/src/tests.c @@ -96,118 +96,6 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) { (*p)--; } -static void random_fe_magnitude(secp256k1_fe *fe, int m) { - secp256k1_fe zero; - int n = secp256k1_testrand_int(m + 1); - secp256k1_fe_normalize(fe); - if (n == 0) { - return; - } - secp256k1_fe_clear(&zero); - secp256k1_fe_negate(&zero, &zero, 0); - secp256k1_fe_mul_int_unchecked(&zero, n - 1); - secp256k1_fe_add(fe, &zero); -#ifdef VERIFY - CHECK(fe->magnitude == n); -#endif -} - -static void random_fe_test(secp256k1_fe *x) { - unsigned char bin[32]; - do { - secp256k1_testrand256_test(bin); - if (secp256k1_fe_set_b32_limit(x, bin)) { - return; - } - } while(1); -} - -static void random_fe_non_zero_test(secp256k1_fe *fe) { - do { - random_fe_test(fe); - } while(secp256k1_fe_is_zero(fe)); -} - -static void random_ge_x_magnitude(secp256k1_ge *ge) { - random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); -} - -static void random_ge_y_magnitude(secp256k1_ge *ge) { - random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); -} - -static void random_gej_x_magnitude(secp256k1_gej *gej) { - random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); -} - -static void random_gej_y_magnitude(secp256k1_gej *gej) { - random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); -} - -static void random_gej_z_magnitude(secp256k1_gej *gej) { - random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); -} - -static void random_ge_test(secp256k1_ge *ge) { - secp256k1_fe fe; - do { - random_fe_test(&fe); - if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) { - secp256k1_fe_normalize(&ge->y); - break; - } - } while(1); - ge->infinity = 0; -} - -static void random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { - secp256k1_fe z2, z3; - random_fe_non_zero_test(&gej->z); - secp256k1_fe_sqr(&z2, &gej->z); - secp256k1_fe_mul(&z3, &z2, &gej->z); - secp256k1_fe_mul(&gej->x, &ge->x, &z2); - secp256k1_fe_mul(&gej->y, &ge->y, &z3); - gej->infinity = ge->infinity; -} - -static void random_gej_test(secp256k1_gej *gej) { - secp256k1_ge ge; - random_ge_test(&ge); - random_ge_jacobian_test(gej, &ge); -} - -static void random_scalar_order_test(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - secp256k1_testrand256_test(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -static void random_scalar_order(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - secp256k1_testrand256(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -static void random_scalar_order_b32(unsigned char *b32) { - secp256k1_scalar num; - random_scalar_order(&num); - secp256k1_scalar_get_b32(b32, &num); -} - static void run_xoshiro256pp_tests(void) { { size_t i; diff --git a/src/testutil.h b/src/testutil.h index 4e2cb7d5..c4c5e077 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -7,6 +7,7 @@ #define SECP256K1_TESTUTIL_H #include "field.h" +#include "group.h" #include "testrand.h" #include "util.h" @@ -26,4 +27,116 @@ static void random_fe_non_zero(secp256k1_fe *nz) { } while (secp256k1_fe_is_zero(nz)); } +static void random_fe_magnitude(secp256k1_fe *fe, int m) { + secp256k1_fe zero; + int n = secp256k1_testrand_int(m + 1); + secp256k1_fe_normalize(fe); + if (n == 0) { + return; + } + secp256k1_fe_clear(&zero); + secp256k1_fe_negate(&zero, &zero, 0); + secp256k1_fe_mul_int_unchecked(&zero, n - 1); + secp256k1_fe_add(fe, &zero); +#ifdef VERIFY + CHECK(fe->magnitude == n); +#endif +} + +static void random_fe_test(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_testrand256_test(bin); + if (secp256k1_fe_set_b32_limit(x, bin)) { + return; + } + } while(1); +} + +static void random_fe_non_zero_test(secp256k1_fe *fe) { + do { + random_fe_test(fe); + } while(secp256k1_fe_is_zero(fe)); +} + +static void random_ge_x_magnitude(secp256k1_ge *ge) { + random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); +} + +static void random_ge_y_magnitude(secp256k1_ge *ge) { + random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); +} + +static void random_gej_x_magnitude(secp256k1_gej *gej) { + random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); +} + +static void random_gej_y_magnitude(secp256k1_gej *gej) { + random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); +} + +static void random_gej_z_magnitude(secp256k1_gej *gej) { + random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); +} + +static void random_ge_test(secp256k1_ge *ge) { + secp256k1_fe fe; + do { + random_fe_test(&fe); + if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) { + secp256k1_fe_normalize(&ge->y); + break; + } + } while(1); + ge->infinity = 0; +} + +static void random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { + secp256k1_fe z2, z3; + random_fe_non_zero_test(&gej->z); + secp256k1_fe_sqr(&z2, &gej->z); + secp256k1_fe_mul(&z3, &z2, &gej->z); + secp256k1_fe_mul(&gej->x, &ge->x, &z2); + secp256k1_fe_mul(&gej->y, &ge->y, &z3); + gej->infinity = ge->infinity; +} + +static void random_gej_test(secp256k1_gej *gej) { + secp256k1_ge ge; + random_ge_test(&ge); + random_ge_jacobian_test(gej, &ge); +} + +static void random_scalar_order_test(secp256k1_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + secp256k1_testrand256_test(b32); + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +static void random_scalar_order(secp256k1_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + secp256k1_testrand256(b32); + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +static void random_scalar_order_b32(unsigned char *b32) { + secp256k1_scalar num; + random_scalar_order(&num); + secp256k1_scalar_get_b32(b32, &num); +} + #endif /* SECP256K1_TESTUTIL_H */ From 0ee7453a997baf880fbe8c07ce5a5fb4b6cb9d32 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 27 May 2024 03:03:02 +0200 Subject: [PATCH 048/383] tests: refactor: add `testutil_` prefix to testutil.h functions --- src/modules/ecdh/tests_impl.h | 6 +- src/modules/ellswift/tests_impl.h | 10 +- src/modules/recovery/tests_impl.h | 4 +- src/tests.c | 196 +++++++++++++++--------------- src/tests_exhaustive.c | 4 +- src/testutil.h | 56 ++++----- 6 files changed, 138 insertions(+), 138 deletions(-) diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index 6be96eac..3c3acdaf 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -56,7 +56,7 @@ static void test_ecdh_generator_basepoint(void) { size_t point_ser_len = sizeof(point_ser); secp256k1_scalar s; - random_scalar_order(&s); + testutil_random_scalar_order(&s); secp256k1_scalar_get_b32(s_b32, &s); CHECK(secp256k1_ec_pubkey_create(CTX, &point[0], s_one) == 1); @@ -95,7 +95,7 @@ static void test_bad_scalar(void) { secp256k1_pubkey point; /* Create random point */ - random_scalar_order(&rand); + testutil_random_scalar_order(&rand); secp256k1_scalar_get_b32(s_rand, &rand); CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_rand) == 1); @@ -127,7 +127,7 @@ static void test_result_basepoint(void) { CHECK(secp256k1_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1); for (i = 0; i < 2 * COUNT; i++) { - random_scalar_order(&rand); + testutil_random_scalar_order(&rand); secp256k1_scalar_get_b32(s, &rand); secp256k1_scalar_inverse(&rand, &rand); secp256k1_scalar_get_b32(s_inv, &rand); diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 7fd7b04c..dc881ae5 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -229,7 +229,7 @@ void run_ellswift_tests(void) { secp256k1_ge g, g2; secp256k1_pubkey pubkey, pubkey2; /* Generate random public key and random randomizer. */ - random_ge_test(&g); + testutil_random_ge_test(&g); secp256k1_pubkey_save(&pubkey, &g); secp256k1_testrand256(rnd32); /* Convert the public key to ElligatorSwift and back. */ @@ -250,7 +250,7 @@ void run_ellswift_tests(void) { int ret; /* Generate random secret key and random randomizer. */ if (i & 1) secp256k1_testrand256_test(auxrnd32); - random_scalar_order_test(&sec); + testutil_random_scalar_order_test(&sec); secp256k1_scalar_get_b32(sec32, &sec); /* Construct ElligatorSwift-encoded public keys for that key. */ ret = secp256k1_ellswift_create(CTX, ell64, sec32, (i & 1) ? auxrnd32 : NULL); @@ -271,7 +271,7 @@ void run_ellswift_tests(void) { secp256k1_pubkey pub; int ret; /* Generate random secret key. */ - random_scalar_order_test(&sec); + testutil_random_scalar_order_test(&sec); secp256k1_scalar_get_b32(sec32, &sec); /* Generate random ElligatorSwift encoding for the remote key and decode it. */ secp256k1_testrand256_test(ell64); @@ -321,10 +321,10 @@ void run_ellswift_tests(void) { /* Generate random secret keys and random randomizers. */ secp256k1_testrand256_test(auxrnd32a); secp256k1_testrand256_test(auxrnd32b); - random_scalar_order_test(&seca); + testutil_random_scalar_order_test(&seca); /* Draw secb uniformly at random to make sure that the secret keys * differ */ - random_scalar_order(&secb); + testutil_random_scalar_order(&secb); secp256k1_scalar_get_b32(sec32a, &seca); secp256k1_scalar_get_b32(sec32b, &secb); diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h index 728ccfed..78ab6d1a 100644 --- a/src/modules/recovery/tests_impl.h +++ b/src/modules/recovery/tests_impl.h @@ -106,8 +106,8 @@ static void test_ecdsa_recovery_end_to_end(void) { /* Generate a random key and message. */ { secp256k1_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); secp256k1_scalar_get_b32(privkey, &key); secp256k1_scalar_get_b32(message, &msg); } diff --git a/src/tests.c b/src/tests.c index 9f2313c4..9f777642 100644 --- a/src/tests.c +++ b/src/tests.c @@ -328,14 +328,14 @@ static void run_proper_context_tests(int use_prealloc) { CHECK(context_eq(my_ctx, my_ctx_fresh)); /*** attempt to use them ***/ - random_scalar_order_test(&msg); - random_scalar_order_test(&key); + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); secp256k1_ecmult_gen(&my_ctx->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); /* obtain a working nonce */ do { - random_scalar_order_test(&nonce); + testutil_random_scalar_order_test(&nonce); } while(!secp256k1_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try signing */ @@ -2017,13 +2017,13 @@ static void scalar_test(void) { unsigned char c[32]; /* Set 's' to a random scalar, with value 'snum'. */ - random_scalar_order_test(&s); + testutil_random_scalar_order_test(&s); /* Set 's1' to a random scalar, with value 's1num'. */ - random_scalar_order_test(&s1); + testutil_random_scalar_order_test(&s1); /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ - random_scalar_order_test(&s2); + testutil_random_scalar_order_test(&s2); secp256k1_scalar_get_b32(c, &s2); { @@ -2171,7 +2171,7 @@ static void run_scalar_set_b32_seckey_tests(void) { secp256k1_scalar s2; /* Usually set_b32 and set_b32_seckey give the same result */ - random_scalar_order_b32(b32); + testutil_random_scalar_order_b32(b32); secp256k1_scalar_set_b32(&s1, b32, NULL); CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 1); CHECK(secp256k1_scalar_eq(&s1, &s2) == 1); @@ -2832,7 +2832,7 @@ static void run_scalar_tests(void) { static void random_fe_non_square(secp256k1_fe *ns) { secp256k1_fe r; - random_fe_non_zero(ns); + testutil_random_fe_non_zero(ns); if (secp256k1_fe_sqrt(&r, ns)) { secp256k1_fe_negate(ns, ns, 1); } @@ -3009,11 +3009,11 @@ static void run_field_misc(void) { for (i = 0; i < 1000 * COUNT; i++) { secp256k1_fe_storage xs, ys, zs; if (i & 1) { - random_fe(&x); + testutil_random_fe(&x); } else { - random_fe_test(&x); + testutil_random_fe_test(&x); } - random_fe_non_zero(&y); + testutil_random_fe_non_zero(&y); v = secp256k1_testrand_bits(15); /* Test that fe_add_int is equivalent to fe_set_int + fe_add. */ secp256k1_fe_set_int(&q, v); /* q = v */ @@ -3152,14 +3152,14 @@ static void run_fe_mul(void) { int i; for (i = 0; i < 100 * COUNT; ++i) { secp256k1_fe a, b, c, d; - random_fe(&a); - random_fe_magnitude(&a, 8); - random_fe(&b); - random_fe_magnitude(&b, 8); - random_fe_test(&c); - random_fe_magnitude(&c, 8); - random_fe_test(&d); - random_fe_magnitude(&d, 8); + testutil_random_fe(&a); + testutil_random_fe_magnitude(&a, 8); + testutil_random_fe(&b); + testutil_random_fe_magnitude(&b, 8); + testutil_random_fe_test(&c); + testutil_random_fe_magnitude(&c, 8); + testutil_random_fe_test(&d); + testutil_random_fe_magnitude(&d, 8); test_fe_mul(&a, &a, 1); test_fe_mul(&c, &c, 1); test_fe_mul(&a, &b, 0); @@ -3181,7 +3181,7 @@ static void run_sqr(void) { secp256k1_fe_normalize(&x); /* Check that (x+y)*(x-y) = x^2 - y*2 for some random values y */ - random_fe_test(&y); + testutil_random_fe_test(&y); lhs = x; secp256k1_fe_add(&lhs, &y); /* lhs = x+y */ @@ -3235,7 +3235,7 @@ static void run_sqrt(void) { int j; random_fe_non_square(&ns); for (j = 0; j < COUNT; j++) { - random_fe(&x); + testutil_random_fe(&x); secp256k1_fe_sqr(&s, &x); CHECK(secp256k1_fe_is_square_var(&s)); test_sqrt(&s, &x); @@ -3676,7 +3676,7 @@ static void test_ge(void) { for (i = 0; i < runs; i++) { int j, k; secp256k1_ge g; - random_ge_test(&g); + testutil_random_ge_test(&g); if (i >= runs - 2) { secp256k1_ge_mul_lambda(&g, &ge[1]); CHECK(!secp256k1_ge_eq_var(&g, &ge[1])); @@ -3689,15 +3689,15 @@ static void test_ge(void) { secp256k1_ge_neg(&ge[3 + 4 * i], &g); secp256k1_ge_neg(&ge[4 + 4 * i], &g); secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); - random_ge_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); + testutil_random_ge_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); - random_ge_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); + testutil_random_ge_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); for (j = 0; j < 4; j++) { - random_ge_x_magnitude(&ge[1 + j + 4 * i]); - random_ge_y_magnitude(&ge[1 + j + 4 * i]); - random_gej_x_magnitude(&gej[1 + j + 4 * i]); - random_gej_y_magnitude(&gej[1 + j + 4 * i]); - random_gej_z_magnitude(&gej[1 + j + 4 * i]); + testutil_random_ge_x_magnitude(&ge[1 + j + 4 * i]); + testutil_random_ge_y_magnitude(&ge[1 + j + 4 * i]); + testutil_random_gej_x_magnitude(&gej[1 + j + 4 * i]); + testutil_random_gej_y_magnitude(&gej[1 + j + 4 * i]); + testutil_random_gej_z_magnitude(&gej[1 + j + 4 * i]); } for (j = 0; j < 4; ++j) { @@ -3712,14 +3712,14 @@ static void test_ge(void) { } /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ - random_fe_non_zero_test(&zf); - random_fe_magnitude(&zf, 8); + testutil_random_fe_non_zero_test(&zf); + testutil_random_fe_magnitude(&zf, 8); secp256k1_fe_inv_var(&zfi3, &zf); secp256k1_fe_sqr(&zfi2, &zfi3); secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); /* Generate random r */ - random_fe_non_zero_test(&r); + testutil_random_fe_non_zero_test(&r); for (i1 = 0; i1 < 1 + 4 * runs; i1++) { int i2; @@ -3749,8 +3749,8 @@ static void test_ge(void) { secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); - random_ge_x_magnitude(&ge2_zfi); - random_ge_y_magnitude(&ge2_zfi); + testutil_random_ge_x_magnitude(&ge2_zfi); + testutil_random_ge_y_magnitude(&ge2_zfi); secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); CHECK(secp256k1_gej_eq_ge_var(&resj, &ref)); } @@ -3826,7 +3826,7 @@ static void test_ge(void) { secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; - random_fe_non_zero(&s); + testutil_random_fe_non_zero(&s); secp256k1_gej_rescale(&gej[i], &s); CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all[i])); } @@ -3859,7 +3859,7 @@ static void test_ge(void) { /* Test batch gej -> ge conversion with many infinities. */ for (i = 0; i < 4 * runs + 1; i++) { int odd; - random_ge_test(&ge[i]); + testutil_random_ge_test(&ge[i]); odd = secp256k1_fe_is_odd(&ge[i].x); CHECK(odd == 0 || odd == 1); /* randomly set half the points to infinity */ @@ -3896,7 +3896,7 @@ static void test_intialized_inf(void) { secp256k1_fe zinv; /* Test that adding P+(-P) results in a fully initialized infinity*/ - random_ge_test(&p); + testutil_random_ge_test(&p); secp256k1_gej_set_ge(&pj, &p); secp256k1_gej_neg(&npj, &pj); @@ -4009,14 +4009,14 @@ static void run_gej(void) { secp256k1_gej_set_infinity(&b); test_gej_cmov(&a, &b); - random_gej_test(&a); + testutil_random_gej_test(&a); test_gej_cmov(&a, &b); test_gej_cmov(&b, &a); b = a; test_gej_cmov(&a, &b); - random_gej_test(&b); + testutil_random_gej_test(&b); test_gej_cmov(&a, &b); test_gej_cmov(&b, &a); } @@ -4024,12 +4024,12 @@ static void run_gej(void) { /* Tests for secp256k1_gej_eq_var */ for (i = 0; i < COUNT; i++) { secp256k1_fe fe; - random_gej_test(&a); - random_gej_test(&b); + testutil_random_gej_test(&a); + testutil_random_gej_test(&b); CHECK(!secp256k1_gej_eq_var(&a, &b)); b = a; - random_fe_non_zero_test(&fe); + testutil_random_fe_non_zero_test(&fe); secp256k1_gej_rescale(&a, &fe); CHECK(secp256k1_gej_eq_var(&a, &b)); } @@ -4046,7 +4046,7 @@ static void test_ec_combine(void) { int i; for (i = 1; i <= 6; i++) { secp256k1_scalar s; - random_scalar_order_test(&s); + testutil_random_scalar_order_test(&s); secp256k1_scalar_add(&sum, &sum, &s); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &s); secp256k1_ge_set_gej(&Q, &Qj); @@ -4106,7 +4106,7 @@ static void run_group_decompress(void) { int i; for (i = 0; i < COUNT * 4; i++) { secp256k1_fe fe; - random_fe_test(&fe); + testutil_random_fe_test(&fe); test_group_decompress(&fe); } } @@ -4254,7 +4254,7 @@ static void test_point_times_order(const secp256k1_gej *point) { secp256k1_ge res3; unsigned char pub[65]; size_t psize = 65; - random_scalar_order_test(&x); + testutil_random_scalar_order_test(&x); secp256k1_scalar_negate(&nx, &x); secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ @@ -4315,13 +4315,13 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) { secp256k1_gej pj, p1j, p2j, ptj; /* Generate random n1,n2 such that n1+n2 = -target. */ - random_scalar_order_test(&n1); + testutil_random_scalar_order_test(&n1); secp256k1_scalar_add(&n2, &n1, target); secp256k1_scalar_negate(&n2, &n2); /* Generate a random input point. */ if (mode != 0) { - random_ge_test(&p); + testutil_random_ge_test(&p); secp256k1_gej_set_ge(&pj, &p); } @@ -4413,8 +4413,8 @@ static void ecmult_const_commutativity(void) { secp256k1_gej res2; secp256k1_ge mid1; secp256k1_ge mid2; - random_scalar_order_test(&a); - random_scalar_order_test(&b); + testutil_random_scalar_order_test(&a); + testutil_random_scalar_order_test(&b); secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); @@ -4435,9 +4435,9 @@ static void ecmult_const_mult_zero_one(void) { secp256k1_ge point; secp256k1_ge inf; - random_scalar_order_test(&s); + testutil_random_scalar_order_test(&s); secp256k1_scalar_negate(&negone, &secp256k1_scalar_one); - random_ge_test(&point); + testutil_random_ge_test(&point); secp256k1_ge_set_infinity(&inf); /* 0*point */ @@ -4490,7 +4490,7 @@ static void ecmult_const_edges(void) { secp256k1_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); secp256k1_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); } - random_ge_test(&point); + testutil_random_ge_test(&point); secp256k1_ecmult_const(&res, &point, &q); ecmult_const_check_result(&point, &q, &res); } @@ -4507,12 +4507,12 @@ static void ecmult_const_mult_xonly(void) { secp256k1_scalar q; int res; /* Random base point. */ - random_ge_test(&base); + testutil_random_ge_test(&base); /* Random scalar to multiply it with. */ - random_scalar_order_test(&q); + testutil_random_scalar_order_test(&q); /* If i is odd, n=d*base.x for random non-zero d */ if (i & 1) { - random_fe_non_zero_test(&d); + testutil_random_fe_non_zero_test(&d); secp256k1_fe_mul(&n, &base.x, &d); } else { n = base.x; @@ -4534,14 +4534,14 @@ static void ecmult_const_mult_xonly(void) { secp256k1_fe x, n, d, r; int res; secp256k1_scalar q; - random_scalar_order_test(&q); + testutil_random_scalar_order_test(&q); /* Generate random X coordinate not on the curve. */ do { - random_fe_test(&x); + testutil_random_fe_test(&x); } while (secp256k1_ge_x_on_curve_var(&x)); /* If i is odd, n=d*x for random non-zero d. */ if (i & 1) { - random_fe_non_zero_test(&d); + testutil_random_fe_non_zero_test(&d); secp256k1_fe_mul(&n, &x, &d); } else { n = x; @@ -4624,10 +4624,10 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi for (ncount = 0; ncount < COUNT; ncount++) { secp256k1_ge ptg; secp256k1_gej ptgj; - random_scalar_order(&sc[0]); - random_scalar_order(&sc[1]); + testutil_random_scalar_order(&sc[0]); + testutil_random_scalar_order(&sc[1]); - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); secp256k1_gej_set_ge(&ptgj, &ptg); pt[0] = ptg; pt[1] = secp256k1_ge_const_g; @@ -4664,7 +4664,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi for (j = 0; j < 3; j++) { for (i = 0; i < 32; i++) { - random_scalar_order(&sc[i]); + testutil_random_scalar_order(&sc[i]); secp256k1_ge_set_infinity(&pt[i]); } CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, sizes[j])); @@ -4673,7 +4673,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi for (j = 0; j < 3; j++) { for (i = 0; i < 32; i++) { - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); pt[i] = ptg; secp256k1_scalar_set_int(&sc[i], 0); } @@ -4682,9 +4682,9 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi } for (j = 0; j < 3; j++) { - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); for (i = 0; i < 16; i++) { - random_scalar_order(&sc[2*i]); + testutil_random_scalar_order(&sc[2*i]); secp256k1_scalar_negate(&sc[2*i + 1], &sc[2*i]); pt[2 * i] = ptg; pt[2 * i + 1] = ptg; @@ -4693,9 +4693,9 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, sizes[j])); CHECK(secp256k1_gej_is_infinity(&r)); - random_scalar_order(&sc[0]); + testutil_random_scalar_order(&sc[0]); for (i = 0; i < 16; i++) { - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); sc[2*i] = sc[0]; sc[2*i+1] = sc[0]; @@ -4707,13 +4707,13 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi CHECK(secp256k1_gej_is_infinity(&r)); } - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); secp256k1_scalar_set_int(&sc[0], 0); pt[0] = ptg; for (i = 1; i < 32; i++) { pt[i] = ptg; - random_scalar_order(&sc[i]); + testutil_random_scalar_order(&sc[i]); secp256k1_scalar_add(&sc[0], &sc[0], &sc[i]); secp256k1_scalar_negate(&sc[i], &sc[i]); } @@ -4727,11 +4727,11 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi size_t i; secp256k1_gej_set_infinity(&r); - random_scalar_order(&sc[0]); + testutil_random_scalar_order(&sc[0]); for (i = 0; i < 20; i++) { secp256k1_ge ptg; sc[i] = sc[0]; - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); pt[i] = ptg; secp256k1_gej_add_ge_var(&r, &r, &pt[i], NULL); } @@ -4749,9 +4749,9 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi secp256k1_scalar rs; secp256k1_scalar_set_int(&rs, 0); - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); for (i = 0; i < 20; i++) { - random_scalar_order(&sc[i]); + testutil_random_scalar_order(&sc[i]); pt[i] = ptg; secp256k1_scalar_add(&rs, &rs, &sc[i]); } @@ -4764,8 +4764,8 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi /* Sanity check that zero scalars don't cause problems */ for (ncount = 0; ncount < 20; ncount++) { - random_scalar_order(&sc[ncount]); - random_ge_test(&pt[ncount]); + testutil_random_scalar_order(&sc[ncount]); + testutil_random_ge_test(&pt[ncount]); } secp256k1_scalar_clear(&sc[0]); @@ -4786,7 +4786,7 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi secp256k1_ge ptg; secp256k1_gej ptgj; - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); secp256k1_gej_set_ge(&ptgj, &ptg); for(t0i = 0; t0i < TOP; t0i++) { @@ -4888,11 +4888,11 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { if (g_nonzero) { /* If g_nonzero, set g_scalar to nonzero value r. */ - random_scalar_order_test(&g_scalar); + testutil_random_scalar_order_test(&g_scalar); if (!nonzero_result) { /* If expected=0 is desired, add a (a*r, -(1/a)*g) term to compensate. */ CHECK(num_nonzero > filled); - random_scalar_order_test(&sc_tmp); + testutil_random_scalar_order_test(&sc_tmp); secp256k1_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar); secp256k1_scalar_inverse_var(&sc_tmp, &sc_tmp); secp256k1_scalar_negate(&sc_tmp, &sc_tmp); @@ -4904,8 +4904,8 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { if (nonzero_result && filled < num_nonzero) { /* If a nonzero result is desired, and there is space, add a random nonzero term. */ - random_scalar_order_test(&scalars[filled]); - random_ge_test(&ge_tmp); + testutil_random_scalar_order_test(&scalars[filled]); + testutil_random_ge_test(&ge_tmp); secp256k1_gej_set_ge(&gejs[filled], &ge_tmp); ++filled; } @@ -4926,10 +4926,10 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { while (filled < num) { if (secp256k1_testrand_bits(1)) { secp256k1_gej_set_infinity(&gejs[filled]); - random_scalar_order_test(&scalars[filled]); + testutil_random_scalar_order_test(&scalars[filled]); } else { secp256k1_scalar_set_int(&scalars[filled], 0); - random_ge_test(&ge_tmp); + testutil_random_ge_test(&ge_tmp); secp256k1_gej_set_ge(&gejs[filled], &ge_tmp); } ++filled; @@ -4963,7 +4963,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { } /* Transform the last input: a*P -> (v*a) * ((1/v)*P). */ CHECK(num_nonzero >= 1); - random_scalar_order_test(&v); + testutil_random_scalar_order_test(&v); secp256k1_scalar_inverse(&iv, &v); secp256k1_scalar_mul(&scalars[num_nonzero - 1], &scalars[num_nonzero - 1], &v); secp256k1_ecmult(&gejs[num_nonzero - 1], &gejs[num_nonzero - 1], &iv, NULL); @@ -5002,8 +5002,8 @@ static void test_ecmult_multi_batch_single(secp256k1_ecmult_multi_func ecmult_mu ecmult_multi_data data; secp256k1_scratch *scratch_empty; - random_ge_test(&pt); - random_scalar_order(&sc); + testutil_random_ge_test(&pt); + testutil_random_scalar_order(&sc); data.sc = ≻ data.pt = &pt; @@ -5128,15 +5128,15 @@ static void test_ecmult_multi_batching(void) { secp256k1_gej_set_infinity(&r2); /* Get random scalars and group elements and compute result */ - random_scalar_order(&scG); + testutil_random_scalar_order(&scG); secp256k1_ecmult(&r2, &r2, &secp256k1_scalar_zero, &scG); for(i = 0; i < n_points; i++) { secp256k1_ge ptg; secp256k1_gej ptgj; - random_ge_test(&ptg); + testutil_random_ge_test(&ptg); secp256k1_gej_set_ge(&ptgj, &ptg); pt[i] = ptg; - random_scalar_order(&sc[i]); + testutil_random_scalar_order(&sc[i]); secp256k1_ecmult(&ptgj, &ptgj, &sc[i], NULL); secp256k1_gej_add_var(&r2, &r2, &ptgj, NULL); } @@ -5348,7 +5348,7 @@ static void run_wnaf(void) { test_fixed_wnaf_small(); /* Random tests */ for (i = 0; i < COUNT; i++) { - random_scalar_order(&n); + testutil_random_scalar_order(&n); test_wnaf(&n, 4+(i%10)); test_fixed_wnaf(&n, 4 + (i % 10)); } @@ -5529,7 +5529,7 @@ static void test_ecmult_gen_blind(void) { secp256k1_gej pgej2; secp256k1_ge p; secp256k1_ge pge; - random_scalar_order_test(&key); + testutil_random_scalar_order_test(&key); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); secp256k1_testrand256(seed32); b = CTX->ecmult_gen_ctx.scalar_offset; @@ -5625,7 +5625,7 @@ static void run_endomorphism_tests(void) { for (i = 0; i < 100U * COUNT; ++i) { secp256k1_scalar full; - random_scalar_order_test(&full); + testutil_random_scalar_order_test(&full); test_scalar_split(&full); } for (i = 0; i < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++i) { @@ -6211,7 +6211,7 @@ static void run_eckey_negate_test(void) { unsigned char seckey[32]; unsigned char seckey_tmp[32]; - random_scalar_order_b32(seckey); + testutil_random_scalar_order_b32(seckey); memcpy(seckey_tmp, seckey, 32); /* Verify negation changes the key and changes it back */ @@ -6235,7 +6235,7 @@ static void run_eckey_negate_test(void) { /* Negating an overflowing seckey fails and the seckey is zeroed. In this * test, the seckey has 16 random bytes to ensure that ec_seckey_negate * doesn't just set seckey to a constant value in case of failure. */ - random_scalar_order_b32(seckey); + testutil_random_scalar_order_b32(seckey); memset(seckey, 0xFF, 16); memset(seckey_tmp, 0, 32); CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 0); @@ -6245,7 +6245,7 @@ static void run_eckey_negate_test(void) { static void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { secp256k1_scalar nonce; do { - random_scalar_order_test(&nonce); + testutil_random_scalar_order_test(&nonce); } while(!secp256k1_ecdsa_sig_sign(&CTX->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); } @@ -6257,8 +6257,8 @@ static void test_ecdsa_sign_verify(void) { secp256k1_scalar sigr, sigs; int getrec; int recid; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); getrec = secp256k1_testrand_bits(1); @@ -6354,8 +6354,8 @@ static void test_ecdsa_end_to_end(void) { /* Generate a random key and message. */ { secp256k1_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); secp256k1_scalar_get_b32(privkey, &key); secp256k1_scalar_get_b32(message, &msg); } diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 5843b3e1..0138f224 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -171,7 +171,7 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge CHECK(secp256k1_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); /* Test secp256k1_ecmult_const_xonly with all curve X coordinates, with random xd. */ - random_fe_non_zero(&xd); + testutil_random_fe_non_zero(&xd); secp256k1_fe_mul(&xn, &xd, &group[i].x); ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0); CHECK(ret); @@ -408,7 +408,7 @@ int main(int argc, char** argv) { /* Set a different random z-value for each Jacobian point, except z=1 is used in the last iteration. */ secp256k1_fe z; - random_fe(&z); + testutil_random_fe(&z); secp256k1_gej_rescale(&groupj[i], &z); } diff --git a/src/testutil.h b/src/testutil.h index c4c5e077..cb33a485 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -11,7 +11,7 @@ #include "testrand.h" #include "util.h" -static void random_fe(secp256k1_fe *x) { +static void testutil_random_fe(secp256k1_fe *x) { unsigned char bin[32]; do { secp256k1_testrand256(bin); @@ -21,13 +21,13 @@ static void random_fe(secp256k1_fe *x) { } while(1); } -static void random_fe_non_zero(secp256k1_fe *nz) { +static void testutil_random_fe_non_zero(secp256k1_fe *nz) { do { - random_fe(nz); + testutil_random_fe(nz); } while (secp256k1_fe_is_zero(nz)); } -static void random_fe_magnitude(secp256k1_fe *fe, int m) { +static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { secp256k1_fe zero; int n = secp256k1_testrand_int(m + 1); secp256k1_fe_normalize(fe); @@ -43,7 +43,7 @@ static void random_fe_magnitude(secp256k1_fe *fe, int m) { #endif } -static void random_fe_test(secp256k1_fe *x) { +static void testutil_random_fe_test(secp256k1_fe *x) { unsigned char bin[32]; do { secp256k1_testrand256_test(bin); @@ -53,36 +53,36 @@ static void random_fe_test(secp256k1_fe *x) { } while(1); } -static void random_fe_non_zero_test(secp256k1_fe *fe) { +static void testutil_random_fe_non_zero_test(secp256k1_fe *fe) { do { - random_fe_test(fe); + testutil_random_fe_test(fe); } while(secp256k1_fe_is_zero(fe)); } -static void random_ge_x_magnitude(secp256k1_ge *ge) { - random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); +static void testutil_random_ge_x_magnitude(secp256k1_ge *ge) { + testutil_random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); } -static void random_ge_y_magnitude(secp256k1_ge *ge) { - random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); +static void testutil_random_ge_y_magnitude(secp256k1_ge *ge) { + testutil_random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); } -static void random_gej_x_magnitude(secp256k1_gej *gej) { - random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); +static void testutil_random_gej_x_magnitude(secp256k1_gej *gej) { + testutil_random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); } -static void random_gej_y_magnitude(secp256k1_gej *gej) { - random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); +static void testutil_random_gej_y_magnitude(secp256k1_gej *gej) { + testutil_random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); } -static void random_gej_z_magnitude(secp256k1_gej *gej) { - random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); +static void testutil_random_gej_z_magnitude(secp256k1_gej *gej) { + testutil_random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); } -static void random_ge_test(secp256k1_ge *ge) { +static void testutil_random_ge_test(secp256k1_ge *ge) { secp256k1_fe fe; do { - random_fe_test(&fe); + testutil_random_fe_test(&fe); if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) { secp256k1_fe_normalize(&ge->y); break; @@ -91,9 +91,9 @@ static void random_ge_test(secp256k1_ge *ge) { ge->infinity = 0; } -static void random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { +static void testutil_random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { secp256k1_fe z2, z3; - random_fe_non_zero_test(&gej->z); + testutil_random_fe_non_zero_test(&gej->z); secp256k1_fe_sqr(&z2, &gej->z); secp256k1_fe_mul(&z3, &z2, &gej->z); secp256k1_fe_mul(&gej->x, &ge->x, &z2); @@ -101,13 +101,13 @@ static void random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) gej->infinity = ge->infinity; } -static void random_gej_test(secp256k1_gej *gej) { +static void testutil_random_gej_test(secp256k1_gej *gej) { secp256k1_ge ge; - random_ge_test(&ge); - random_ge_jacobian_test(gej, &ge); + testutil_random_ge_test(&ge); + testutil_random_ge_jacobian_test(gej, &ge); } -static void random_scalar_order_test(secp256k1_scalar *num) { +static void testutil_random_scalar_order_test(secp256k1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; @@ -120,7 +120,7 @@ static void random_scalar_order_test(secp256k1_scalar *num) { } while(1); } -static void random_scalar_order(secp256k1_scalar *num) { +static void testutil_random_scalar_order(secp256k1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; @@ -133,9 +133,9 @@ static void random_scalar_order(secp256k1_scalar *num) { } while(1); } -static void random_scalar_order_b32(unsigned char *b32) { +static void testutil_random_scalar_order_b32(unsigned char *b32) { secp256k1_scalar num; - random_scalar_order(&num); + testutil_random_scalar_order(&num); secp256k1_scalar_get_b32(b32, &num); } From e73f6f8fd9158a044c6fb22653105446f3542bb0 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 27 May 2024 03:08:07 +0200 Subject: [PATCH 049/383] tests: refactor: drop `secp256k1_` prefix from testrand.h functions The rename was done with the following command: $ sed -i 's/secp256k1_testrand/testrand/g' $(git grep -l secp256k1_testrand) --- src/modules/ellswift/tests_impl.h | 28 ++-- src/modules/extrakeys/tests_impl.h | 36 ++--- src/modules/recovery/tests_impl.h | 4 +- .../schnorrsig/tests_exhaustive_impl.h | 6 +- src/modules/schnorrsig/tests_impl.h | 50 +++--- src/testrand.h | 22 +-- src/testrand_impl.h | 42 ++--- src/tests.c | 146 +++++++++--------- src/tests_exhaustive.c | 6 +- src/testutil.h | 12 +- 10 files changed, 176 insertions(+), 176 deletions(-) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index dc881ae5..ed5658f3 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -231,7 +231,7 @@ void run_ellswift_tests(void) { /* Generate random public key and random randomizer. */ testutil_random_ge_test(&g); secp256k1_pubkey_save(&pubkey, &g); - secp256k1_testrand256(rnd32); + testrand256(rnd32); /* Convert the public key to ElligatorSwift and back. */ secp256k1_ellswift_encode(CTX, ell64, &pubkey, rnd32); secp256k1_ellswift_decode(CTX, &pubkey2, ell64); @@ -249,7 +249,7 @@ void run_ellswift_tests(void) { unsigned char ell64[64]; int ret; /* Generate random secret key and random randomizer. */ - if (i & 1) secp256k1_testrand256_test(auxrnd32); + if (i & 1) testrand256_test(auxrnd32); testutil_random_scalar_order_test(&sec); secp256k1_scalar_get_b32(sec32, &sec); /* Construct ElligatorSwift-encoded public keys for that key. */ @@ -274,8 +274,8 @@ void run_ellswift_tests(void) { testutil_random_scalar_order_test(&sec); secp256k1_scalar_get_b32(sec32, &sec); /* Generate random ElligatorSwift encoding for the remote key and decode it. */ - secp256k1_testrand256_test(ell64); - secp256k1_testrand256_test(ell64 + 32); + testrand256_test(ell64); + testrand256_test(ell64 + 32); secp256k1_ellswift_decode(CTX, &pub, ell64); secp256k1_pubkey_load(CTX, &dec, &pub); secp256k1_gej_set_ge(&decj, &dec); @@ -313,14 +313,14 @@ void run_ellswift_tests(void) { data = NULL; } else { hash_function = secp256k1_ellswift_xdh_hash_function_prefix; - secp256k1_testrand256_test(prefix64); - secp256k1_testrand256_test(prefix64 + 32); + testrand256_test(prefix64); + testrand256_test(prefix64 + 32); data = prefix64; } /* Generate random secret keys and random randomizers. */ - secp256k1_testrand256_test(auxrnd32a); - secp256k1_testrand256_test(auxrnd32b); + testrand256_test(auxrnd32a); + testrand256_test(auxrnd32b); testutil_random_scalar_order_test(&seca); /* Draw secb uniformly at random to make sure that the secret keys * differ */ @@ -349,13 +349,13 @@ void run_ellswift_tests(void) { /* Verify that the shared secret doesn't match if other side's public key is incorrect. */ /* For A (using a bad public key for B): */ memcpy(ell64b_bad, ell64b, sizeof(ell64a_bad)); - secp256k1_testrand_flip(ell64b_bad, sizeof(ell64b_bad)); + testrand_flip(ell64b_bad, sizeof(ell64b_bad)); ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); CHECK(ret); /* Mismatching encodings don't get detected by secp256k1_ellswift_xdh. */ CHECK(secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); /* For B (using a bad public key for A): */ memcpy(ell64a_bad, ell64a, sizeof(ell64a_bad)); - secp256k1_testrand_flip(ell64a_bad, sizeof(ell64a_bad)); + testrand_flip(ell64a_bad, sizeof(ell64a_bad)); ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); CHECK(ret); CHECK(secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); @@ -363,12 +363,12 @@ void run_ellswift_tests(void) { /* Verify that the shared secret doesn't match if the private key is incorrect. */ /* For A: */ memcpy(sec32a_bad, sec32a, sizeof(sec32a_bad)); - secp256k1_testrand_flip(sec32a_bad, sizeof(sec32a_bad)); + testrand_flip(sec32a_bad, sizeof(sec32a_bad)); ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a_bad, 0, hash_function, data); CHECK(!ret || secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); /* For B: */ memcpy(sec32b_bad, sec32b, sizeof(sec32b_bad)); - secp256k1_testrand_flip(sec32b_bad, sizeof(sec32b_bad)); + testrand_flip(sec32b_bad, sizeof(sec32b_bad)); ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b_bad, 1, hash_function, data); CHECK(!ret || secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); @@ -376,7 +376,7 @@ void run_ellswift_tests(void) { /* Verify that the shared secret doesn't match when a different encoding of the same public key is used. */ /* For A (changing B's public key): */ memcpy(auxrnd32b_bad, auxrnd32b, sizeof(auxrnd32b_bad)); - secp256k1_testrand_flip(auxrnd32b_bad, sizeof(auxrnd32b_bad)); + testrand_flip(auxrnd32b_bad, sizeof(auxrnd32b_bad)); ret = secp256k1_ellswift_create(CTX, ell64b_bad, sec32b, auxrnd32b_bad); CHECK(ret); ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); @@ -384,7 +384,7 @@ void run_ellswift_tests(void) { CHECK(secp256k1_memcmp_var(share32_bad, share32a, 32) != 0); /* For B (changing A's public key): */ memcpy(auxrnd32a_bad, auxrnd32a, sizeof(auxrnd32a_bad)); - secp256k1_testrand_flip(auxrnd32a_bad, sizeof(auxrnd32a_bad)); + testrand_flip(auxrnd32a_bad, sizeof(auxrnd32a_bad)); ret = secp256k1_ellswift_create(CTX, ell64a_bad, sec32a, auxrnd32a_bad); CHECK(ret); ret = secp256k1_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h index 45521d17..ab4ef4a7 100644 --- a/src/modules/extrakeys/tests_impl.h +++ b/src/modules/extrakeys/tests_impl.h @@ -23,9 +23,9 @@ static void test_xonly_pubkey(void) { int pk_parity; int i; - secp256k1_testrand256(sk); + testrand256(sk); memset(ones32, 0xFF, 32); - secp256k1_testrand256(xy_sk); + testrand256(xy_sk); CHECK(secp256k1_ec_pubkey_create(CTX, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); @@ -95,7 +95,7 @@ static void test_xonly_pubkey(void) { * the curve) then xonly_pubkey_parse should fail as well. */ for (i = 0; i < COUNT; i++) { unsigned char rand33[33]; - secp256k1_testrand256(&rand33[1]); + testrand256(&rand33[1]); rand33[0] = SECP256K1_TAG_PUBKEY_EVEN; if (!secp256k1_ec_pubkey_parse(CTX, &pk, rand33, 33)) { memset(&xonly_pk, 1, sizeof(xonly_pk)); @@ -152,8 +152,8 @@ static void test_xonly_pubkey_tweak(void) { int i; memset(overflows, 0xff, sizeof(overflows)); - secp256k1_testrand256(tweak); - secp256k1_testrand256(sk); + testrand256(tweak); + testrand256(sk); CHECK(secp256k1_ec_pubkey_create(CTX, &internal_pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); @@ -190,7 +190,7 @@ static void test_xonly_pubkey_tweak(void) { /* Invalid pk with a valid tweak */ memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); - secp256k1_testrand256(tweak); + testrand256(tweak); CHECK_ILLEGAL(CTX, secp256k1_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak)); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); } @@ -209,8 +209,8 @@ static void test_xonly_pubkey_tweak_check(void) { unsigned char tweak[32]; memset(overflows, 0xff, sizeof(overflows)); - secp256k1_testrand256(tweak); - secp256k1_testrand256(sk); + testrand256(tweak); + testrand256(sk); CHECK(secp256k1_ec_pubkey_create(CTX, &internal_pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); @@ -256,7 +256,7 @@ static void test_xonly_pubkey_tweak_recursive(void) { unsigned char tweak[N_PUBKEYS - 1][32]; int i; - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_ec_pubkey_create(CTX, &pk[0], sk) == 1); /* Add tweaks */ for (i = 0; i < N_PUBKEYS - 1; i++) { @@ -292,7 +292,7 @@ static void test_keypair(void) { memset(overflows, 0xFF, sizeof(overflows)); /* Test keypair_create */ - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); @@ -311,7 +311,7 @@ static void test_keypair(void) { CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); /* Test keypair_pub */ - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); CHECK(secp256k1_keypair_pub(CTX, &pk, &keypair) == 1); CHECK_ILLEGAL(CTX, secp256k1_keypair_pub(CTX, NULL, &keypair)); @@ -330,7 +330,7 @@ static void test_keypair(void) { CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); /** Test keypair_xonly_pub **/ - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_pub(CTX, NULL, &pk_parity, &keypair)); @@ -353,7 +353,7 @@ static void test_keypair(void) { CHECK(pk_parity == pk_parity_tmp); /* Test keypair_seckey */ - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); CHECK(secp256k1_keypair_sec(CTX, sk_tmp, &keypair) == 1); CHECK_ILLEGAL(CTX, secp256k1_keypair_sec(CTX, NULL, &keypair)); @@ -381,8 +381,8 @@ static void test_keypair_add(void) { int i; CHECK(sizeof(zeros96) == sizeof(keypair)); - secp256k1_testrand256(sk); - secp256k1_testrand256(tweak); + testrand256(sk); + testrand256(tweak); memset(overflows, 0xFF, 32); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); @@ -407,7 +407,7 @@ static void test_keypair_add(void) { for (i = 0; i < COUNT; i++) { secp256k1_scalar scalar_tweak; secp256k1_keypair keypair_tmp; - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); memcpy(&keypair_tmp, &keypair, sizeof(keypair)); /* Because sk may be negated before adding, we need to try with tweak = @@ -423,7 +423,7 @@ static void test_keypair_add(void) { /* Invalid keypair with a valid tweak */ memset(&keypair, 0, sizeof(keypair)); - secp256k1_testrand256(tweak); + testrand256(tweak); CHECK_ILLEGAL(CTX, secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak)); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* Only seckey part of keypair invalid */ @@ -446,7 +446,7 @@ static void test_keypair_add(void) { unsigned char sk32[32]; int pk_parity; - secp256k1_testrand256(tweak); + testrand256(tweak); CHECK(secp256k1_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h index 78ab6d1a..7a28a3ce 100644 --- a/src/modules/recovery/tests_impl.h +++ b/src/modules/recovery/tests_impl.h @@ -25,7 +25,7 @@ static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned c } /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ memset(nonce32, 1, 32); - return secp256k1_testrand_bits(1); + return testrand_bits(1); } static void test_ecdsa_recovery_api(void) { @@ -141,7 +141,7 @@ static void test_ecdsa_recovery_end_to_end(void) { CHECK(secp256k1_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0); /* Serialize/destroy/parse signature and verify again. */ CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); - sig[secp256k1_testrand_bits(6)] += 1 + secp256k1_testrand_int(255); + sig[testrand_bits(6)] += 1 + testrand_int(255); CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); CHECK(secp256k1_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 0); diff --git a/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/modules/schnorrsig/tests_exhaustive_impl.h index bc31d811..601b5497 100644 --- a/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -104,7 +104,7 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; unsigned char msg32[32]; - secp256k1_testrand256(msg32); + testrand256(msg32); secp256k1_schnorrsig_challenge(&e, sig64, msg32, sizeof(msg32), pk32); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { @@ -120,7 +120,7 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && (s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); } else { - secp256k1_testrand256(sig64 + 32); + testrand256(sig64 + 32); expect_valid = 0; } valid = secp256k1_schnorrsig_verify(ctx, sig64, msg32, sizeof(msg32), &pubkeys[d - 1]); @@ -161,7 +161,7 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign /* Generate random messages until all challenges have been tried. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; - secp256k1_testrand256(msg32); + testrand256(msg32); secp256k1_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 8ada90a8..aa4fc382 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -15,7 +15,7 @@ static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t msglen, size_t algolen) { unsigned char nonces[2][32]; CHECK(nonce_function_bip340(nonces[0], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); - secp256k1_testrand_flip(args[n_flip], n_bytes); + testrand_flip(args[n_flip], n_bytes); CHECK(nonce_function_bip340(nonces[1], args[0], msglen, args[1], args[2], args[3], algolen, args[4]) == 1); CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0); } @@ -50,10 +50,10 @@ static void run_nonce_function_bip340_tests(void) { secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); - secp256k1_testrand256(msg); - secp256k1_testrand256(key); - secp256k1_testrand256(pk); - secp256k1_testrand256(aux_rand); + testrand256(msg); + testrand256(key); + testrand256(pk); + testrand256(aux_rand); /* Check that a bitflip in an argument results in different nonces. */ args[0] = msg; @@ -76,12 +76,12 @@ static void run_nonce_function_bip340_tests(void) { CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, NULL, 0, NULL) == 0); CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); /* Other algo is fine */ - secp256k1_testrand_bytes_test(algo, algolen); + testrand_bytes_test(algo, algolen); CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); for (i = 0; i < COUNT; i++) { unsigned char nonce2[32]; - uint32_t offset = secp256k1_testrand_int(msglen - 1); + uint32_t offset = testrand_int(msglen - 1); size_t msglen_tmp = (msglen + offset) % msglen; size_t algolen_tmp; @@ -90,7 +90,7 @@ static void run_nonce_function_bip340_tests(void) { CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); /* Different algolen gives different nonce */ - offset = secp256k1_testrand_int(algolen - 1); + offset = testrand_int(algolen - 1); algolen_tmp = (algolen + offset) % algolen; CHECK(nonce_function_bip340(nonce2, msg, msglen, key, pk, algo, algolen_tmp, NULL) == 1); CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); @@ -116,10 +116,10 @@ static void test_schnorrsig_api(void) { secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; secp256k1_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL}; - secp256k1_testrand256(sk1); - secp256k1_testrand256(sk2); - secp256k1_testrand256(sk3); - secp256k1_testrand256(msg); + testrand256(sk1); + testrand256(sk2); + testrand256(sk3); + testrand256(msg); CHECK(secp256k1_keypair_create(CTX, &keypairs[0], sk1) == 1); CHECK(secp256k1_keypair_create(CTX, &keypairs[1], sk2) == 1); CHECK(secp256k1_keypair_create(CTX, &keypairs[2], sk3) == 1); @@ -813,8 +813,8 @@ static void test_schnorrsig_sign(void) { secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; unsigned char aux_rand[32]; - secp256k1_testrand256(sk); - secp256k1_testrand256(aux_rand); + testrand256(sk); + testrand256(aux_rand); CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); @@ -861,12 +861,12 @@ static void test_schnorrsig_sign_verify(void) { secp256k1_xonly_pubkey pk; secp256k1_scalar s; - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); for (i = 0; i < N_SIGS; i++) { - secp256k1_testrand256(msg[i]); + testrand256(msg[i]); CHECK(secp256k1_schnorrsig_sign32(CTX, sig[i], msg[i], &keypair, NULL)); CHECK(secp256k1_schnorrsig_verify(CTX, sig[i], msg[i], sizeof(msg[i]), &pk)); } @@ -874,19 +874,19 @@ static void test_schnorrsig_sign_verify(void) { { /* Flip a few bits in the signature and in the message and check that * verify and verify_batch (TODO) fail */ - size_t sig_idx = secp256k1_testrand_int(N_SIGS); - size_t byte_idx = secp256k1_testrand_bits(5); - unsigned char xorbyte = secp256k1_testrand_int(254)+1; + size_t sig_idx = testrand_int(N_SIGS); + size_t byte_idx = testrand_bits(5); + unsigned char xorbyte = testrand_int(254)+1; sig[sig_idx][byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); sig[sig_idx][byte_idx] ^= xorbyte; - byte_idx = secp256k1_testrand_bits(5); + byte_idx = testrand_bits(5); sig[sig_idx][32+byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); sig[sig_idx][32+byte_idx] ^= xorbyte; - byte_idx = secp256k1_testrand_bits(5); + byte_idx = testrand_bits(5); msg[sig_idx][byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); msg[sig_idx][byte_idx] ^= xorbyte; @@ -916,9 +916,9 @@ static void test_schnorrsig_sign_verify(void) { { /* Test varying message lengths */ unsigned char msg_large[32 * 8]; - uint32_t msglen = secp256k1_testrand_int(sizeof(msg_large)); + uint32_t msglen = testrand_int(sizeof(msg_large)); for (i = 0; i < sizeof(msg_large); i += 32) { - secp256k1_testrand256(&msg_large[i]); + testrand256(&msg_large[i]); } CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig[0], msg_large, msglen, &keypair, NULL) == 1); CHECK(secp256k1_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 1); @@ -942,7 +942,7 @@ static void test_schnorrsig_taproot(void) { unsigned char sig[64]; /* Create output key */ - secp256k1_testrand256(sk); + testrand256(sk); CHECK(secp256k1_keypair_create(CTX, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); /* In actual taproot the tweak would be hash of internal_pk */ @@ -952,7 +952,7 @@ static void test_schnorrsig_taproot(void) { CHECK(secp256k1_xonly_pubkey_serialize(CTX, output_pk_bytes, &output_pk) == 1); /* Key spend */ - secp256k1_testrand256(msg); + testrand256(msg); CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); /* Verify key spend */ CHECK(secp256k1_xonly_pubkey_parse(CTX, &output_pk, output_pk_bytes) == 1); diff --git a/src/testrand.h b/src/testrand.h index 721099d0..3c1ed3d4 100644 --- a/src/testrand.h +++ b/src/testrand.h @@ -12,37 +12,37 @@ /* A non-cryptographic RNG used only for test infrastructure. */ /** Seed the pseudorandom number generator for testing. */ -SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16); +SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16); /** Generate a pseudorandom number in the range [0..2**32-1]. */ -SECP256K1_INLINE static uint32_t secp256k1_testrand32(void); +SECP256K1_INLINE static uint32_t testrand32(void); /** Generate a pseudorandom number in the range [0..2**64-1]. */ -SECP256K1_INLINE static uint64_t secp256k1_testrand64(void); +SECP256K1_INLINE static uint64_t testrand64(void); /** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or * more. */ -SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits); +SECP256K1_INLINE static uint64_t testrand_bits(int bits); /** Generate a pseudorandom number in the range [0..range-1]. */ -static uint32_t secp256k1_testrand_int(uint32_t range); +static uint32_t testrand_int(uint32_t range); /** Generate a pseudorandom 32-byte array. */ -static void secp256k1_testrand256(unsigned char *b32); +static void testrand256(unsigned char *b32); /** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ -static void secp256k1_testrand256_test(unsigned char *b32); +static void testrand256_test(unsigned char *b32); /** Generate pseudorandom bytes with long sequences of zero and one bits. */ -static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len); +static void testrand_bytes_test(unsigned char *bytes, size_t len); /** Flip a single random bit in a byte array */ -static void secp256k1_testrand_flip(unsigned char *b, size_t len); +static void testrand_flip(unsigned char *b, size_t len); /** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ -static void secp256k1_testrand_init(const char* hexseed); +static void testrand_init(const char* hexseed); /** Print final test information. */ -static void secp256k1_testrand_finish(void); +static void testrand_finish(void); #endif /* SECP256K1_TESTRAND_H */ diff --git a/src/testrand_impl.h b/src/testrand_impl.h index fe976204..07564f7f 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -17,7 +17,7 @@ static uint64_t secp256k1_test_state[4]; -SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) { +SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) { static const unsigned char PREFIX[19] = "secp256k1 test init"; unsigned char out32[32]; secp256k1_sha256 hash; @@ -40,7 +40,7 @@ SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } -SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) { +SECP256K1_INLINE static uint64_t testrand64(void) { /* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */ const uint64_t result = rotl(secp256k1_test_state[0] + secp256k1_test_state[3], 23) + secp256k1_test_state[0]; const uint64_t t = secp256k1_test_state[1] << 17; @@ -53,16 +53,16 @@ SECP256K1_INLINE static uint64_t secp256k1_testrand64(void) { return result; } -SECP256K1_INLINE static uint64_t secp256k1_testrand_bits(int bits) { +SECP256K1_INLINE static uint64_t testrand_bits(int bits) { if (bits == 0) return 0; - return secp256k1_testrand64() >> (64 - bits); + return testrand64() >> (64 - bits); } -SECP256K1_INLINE static uint32_t secp256k1_testrand32(void) { - return secp256k1_testrand64() >> 32; +SECP256K1_INLINE static uint32_t testrand32(void) { + return testrand64() >> 32; } -static uint32_t secp256k1_testrand_int(uint32_t range) { +static uint32_t testrand_int(uint32_t range) { uint32_t mask = 0; uint32_t range_copy; /* Reduce range by 1, changing its meaning to "maximum value". */ @@ -76,15 +76,15 @@ static uint32_t secp256k1_testrand_int(uint32_t range) { } /* Generation loop. */ while (1) { - uint32_t val = secp256k1_testrand64() & mask; + uint32_t val = testrand64() & mask; if (val <= range) return val; } } -static void secp256k1_testrand256(unsigned char *b32) { +static void testrand256(unsigned char *b32) { int i; for (i = 0; i < 4; ++i) { - uint64_t val = secp256k1_testrand64(); + uint64_t val = testrand64(); b32[0] = val; b32[1] = val >> 8; b32[2] = val >> 16; @@ -97,14 +97,14 @@ static void secp256k1_testrand256(unsigned char *b32) { } } -static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) { +static void testrand_bytes_test(unsigned char *bytes, size_t len) { size_t bits = 0; memset(bytes, 0, len); while (bits < len * 8) { int now; uint32_t val; - now = 1 + (secp256k1_testrand_bits(6) * secp256k1_testrand_bits(5) + 16) / 31; - val = secp256k1_testrand_bits(1); + now = 1 + (testrand_bits(6) * testrand_bits(5) + 16) / 31; + val = testrand_bits(1); while (now > 0 && bits < len * 8) { bytes[bits / 8] |= val << (bits % 8); now--; @@ -113,15 +113,15 @@ static void secp256k1_testrand_bytes_test(unsigned char *bytes, size_t len) { } } -static void secp256k1_testrand256_test(unsigned char *b32) { - secp256k1_testrand_bytes_test(b32, 32); +static void testrand256_test(unsigned char *b32) { + testrand_bytes_test(b32, 32); } -static void secp256k1_testrand_flip(unsigned char *b, size_t len) { - b[secp256k1_testrand_int(len)] ^= (1 << secp256k1_testrand_bits(3)); +static void testrand_flip(unsigned char *b, size_t len) { + b[testrand_int(len)] ^= (1 << testrand_bits(3)); } -static void secp256k1_testrand_init(const char* hexseed) { +static void testrand_init(const char* hexseed) { unsigned char seed16[16] = {0}; if (hexseed && strlen(hexseed) != 0) { int pos = 0; @@ -155,12 +155,12 @@ static void secp256k1_testrand_init(const char* hexseed) { } printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); - secp256k1_testrand_seed(seed16); + testrand_seed(seed16); } -static void secp256k1_testrand_finish(void) { +static void testrand_finish(void) { unsigned char run32[32]; - secp256k1_testrand256(run32); + testrand256(run32); printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); } diff --git a/src/tests.c b/src/tests.c index 9f777642..6b401e52 100644 --- a/src/tests.c +++ b/src/tests.c @@ -117,9 +117,9 @@ static void run_xoshiro256pp_tests(void) { 0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF, 0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30, }; - secp256k1_testrand_seed(seed16); + testrand_seed(seed16); for (i = 0; i < 17; i++) { - secp256k1_testrand256(buf32); + testrand256(buf32); } CHECK(secp256k1_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0); } @@ -492,7 +492,7 @@ static void run_sha256_known_output_tests(void) { CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); /* 2. Run: split the input bytestrings randomly before writing */ if (strlen(inputs[i]) > 0) { - int split = secp256k1_testrand_int(strlen(inputs[i])); + int split = testrand_int(strlen(inputs[i])); secp256k1_sha256_initialize(&hasher); j = repeat[i]; while (j > 0) { @@ -653,7 +653,7 @@ static void run_hmac_sha256_tests(void) { secp256k1_hmac_sha256_finalize(&hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { - int split = secp256k1_testrand_int(strlen(inputs[i])); + int split = testrand_int(strlen(inputs[i])); secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); @@ -853,7 +853,7 @@ static void signed30_to_uint16(uint16_t* out, const secp256k1_modinv32_signed30* static void mutate_sign_signed30(secp256k1_modinv32_signed30* x) { int i; for (i = 0; i < 16; ++i) { - int pos = secp256k1_testrand_bits(3); + int pos = testrand_bits(3); if (x->v[pos] > 0 && x->v[pos + 1] <= 0x3fffffff) { x->v[pos] -= 0x40000000; x->v[pos + 1] += 1; @@ -945,7 +945,7 @@ static void mutate_sign_signed62(secp256k1_modinv64_signed62* x) { static const int64_t M62 = (int64_t)(UINT64_MAX >> 2); int i; for (i = 0; i < 8; ++i) { - int pos = secp256k1_testrand_bits(2); + int pos = testrand_bits(2); if (x->v[pos] > 0 && x->v[pos + 1] <= M62) { x->v[pos] -= (M62 + 1); x->v[pos + 1] += 1; @@ -1658,8 +1658,8 @@ static void run_modinv_tests(void) { /* generate random xd and md, so that md is odd, md>1, xd 256) { now = 256 - i; } @@ -2078,7 +2078,7 @@ static void scalar_test(void) { secp256k1_scalar b; int i; /* Test add_bit. */ - int bit = secp256k1_testrand_bits(8); + int bit = testrand_bits(8); secp256k1_scalar_set_int(&b, 1); CHECK(secp256k1_scalar_is_one(&b)); for (i = 0; i < bit; i++) { @@ -3014,7 +3014,7 @@ static void run_field_misc(void) { testutil_random_fe_test(&x); } testutil_random_fe_non_zero(&y); - v = secp256k1_testrand_bits(15); + v = testrand_bits(15); /* Test that fe_add_int is equivalent to fe_set_int + fe_add. */ secp256k1_fe_set_int(&q, v); /* q = v */ z = x; /* z = x */ @@ -3549,7 +3549,7 @@ static void run_inverse_tests(void) /* test 128*count random inputs; half with testrand256_test, half with testrand256 */ for (testrand = 0; testrand <= 1; ++testrand) { for (i = 0; i < 64 * COUNT; ++i) { - (testrand ? secp256k1_testrand256_test : secp256k1_testrand256)(b32); + (testrand ? testrand256_test : testrand256)(b32); secp256k1_scalar_set_b32(&x_scalar, b32, NULL); secp256k1_fe_set_b32_mod(&x_fe, b32); for (var = 0; var <= 1; ++var) { @@ -3615,8 +3615,8 @@ static void test_hsort(size_t element_len) { /* Test hsort with array of random length n */ for (i = 0; i < COUNT; i++) { - int n = secp256k1_testrand_int(NUM); - secp256k1_testrand_bytes_test(elements, n*element_len); + int n = testrand_int(NUM); + testrand_bytes_test(elements, n*element_len); secp256k1_hsort(elements, n, element_len, test_hsort_cmp, &data); test_hsort_is_sorted(elements, n, element_len); } @@ -3806,7 +3806,7 @@ static void test_ge(void) { gej_shuffled[i] = gej[i]; } for (i = 0; i < 4 * runs + 1; i++) { - int swap = i + secp256k1_testrand_int(4 * runs + 1 - i); + int swap = i + testrand_int(4 * runs + 1 - i); if (swap != i) { secp256k1_gej t = gej_shuffled[i]; gej_shuffled[i] = gej_shuffled[swap]; @@ -4857,29 +4857,29 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { int i; /* Which multiplication function to use */ - int fn = secp256k1_testrand_int(3); + int fn = testrand_int(3); secp256k1_ecmult_multi_func ecmult_multi = fn == 0 ? secp256k1_ecmult_multi_var : fn == 1 ? secp256k1_ecmult_strauss_batch_single : secp256k1_ecmult_pippenger_batch_single; /* Simulate exponentially distributed num. */ - int num_bits = 2 + secp256k1_testrand_int(6); + int num_bits = 2 + testrand_int(6); /* Number of (scalar, point) inputs (excluding g). */ - int num = secp256k1_testrand_int((1 << num_bits) + 1); + int num = testrand_int((1 << num_bits) + 1); /* Number of those which are nonzero. */ - int num_nonzero = secp256k1_testrand_int(num + 1); + int num_nonzero = testrand_int(num + 1); /* Whether we're aiming to create an input with nonzero expected result. */ - int nonzero_result = secp256k1_testrand_bits(1); + int nonzero_result = testrand_bits(1); /* Whether we will provide nonzero g multiplicand. In some cases our hand * is forced here based on num_nonzero and nonzero_result. */ int g_nonzero = num_nonzero == 0 ? nonzero_result : num_nonzero == 1 && !nonzero_result ? 1 : - (int)secp256k1_testrand_bits(1); + (int)testrand_bits(1); /* Which g_scalar pointer to pass into ecmult_multi(). */ - const secp256k1_scalar* g_scalar_ptr = (g_nonzero || secp256k1_testrand_bits(1)) ? &g_scalar : NULL; + const secp256k1_scalar* g_scalar_ptr = (g_nonzero || testrand_bits(1)) ? &g_scalar : NULL; /* How many EC multiplications were performed in this function. */ int mults = 0; /* How many randomization steps to apply to the input list. */ - int rands = (int)secp256k1_testrand_bits(3); + int rands = (int)testrand_bits(3); if (rands > num_nonzero) rands = num_nonzero; secp256k1_gej_set_infinity(&expected); @@ -4924,7 +4924,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { /* Add entries to scalars,gejs so that there are num of them. All the added entries * either have scalar=0 or point=infinity, so these do not change the expected result. */ while (filled < num) { - if (secp256k1_testrand_bits(1)) { + if (testrand_bits(1)) { secp256k1_gej_set_infinity(&gejs[filled]); testutil_random_scalar_order_test(&scalars[filled]); } else { @@ -4943,7 +4943,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { secp256k1_scalar v, iv; /* Shuffle the entries. */ for (j = 0; j < num_nonzero; ++j) { - int k = secp256k1_testrand_int(num_nonzero - j); + int k = testrand_int(num_nonzero - j); if (k != 0) { secp256k1_gej gej = gejs[j]; secp256k1_scalar sc = scalars[j]; @@ -4972,7 +4972,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { /* Shuffle all entries (0..num-1). */ for (i = 0; i < num; ++i) { - int j = secp256k1_testrand_int(num - i); + int j = testrand_int(num - i); if (j != 0) { secp256k1_gej gej = gejs[i]; secp256k1_scalar sc = scalars[i]; @@ -5034,7 +5034,7 @@ static void test_secp256k1_pippenger_bucket_window_inv(void) { * for a given scratch space. */ static void test_ecmult_multi_pippenger_max_points(void) { - size_t scratch_size = secp256k1_testrand_bits(8); + size_t scratch_size = testrand_bits(8); size_t max_size = secp256k1_pippenger_scratch_size(secp256k1_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); secp256k1_scratch *scratch; size_t n_points_supported; @@ -5531,7 +5531,7 @@ static void test_ecmult_gen_blind(void) { secp256k1_ge pge; testutil_random_scalar_order_test(&key); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); - secp256k1_testrand256(seed32); + testrand256(seed32); b = CTX->ecmult_gen_ctx.scalar_offset; p = CTX->ecmult_gen_ctx.ge_offset; secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, seed32); @@ -6261,7 +6261,7 @@ static void test_ecdsa_sign_verify(void) { testutil_random_scalar_order_test(&key); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); - getrec = secp256k1_testrand_bits(1); + getrec = testrand_bits(1); /* The specific way in which this conditional is written sidesteps a potential bug in clang. See the commit messages of the commit that introduced this comment for details. */ if (getrec) { @@ -6365,7 +6365,7 @@ static void test_ecdsa_end_to_end(void) { CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, privkey) == 1); /* Verify exporting and importing public key. */ - CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyc, &pubkeyclen, &pubkey, secp256k1_testrand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); + CHECK(secp256k1_ec_pubkey_serialize(CTX, pubkeyc, &pubkeyclen, &pubkey, testrand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); memset(&pubkey, 0, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); @@ -6377,19 +6377,19 @@ static void test_ecdsa_end_to_end(void) { CHECK(secp256k1_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); /* Verify private key import and export. */ - CHECK(ec_privkey_export_der(CTX, seckey, &seckeylen, privkey, secp256k1_testrand_bits(1) == 1)); + CHECK(ec_privkey_export_der(CTX, seckey, &seckeylen, privkey, testrand_bits(1) == 1)); CHECK(ec_privkey_import_der(CTX, privkey2, seckey, seckeylen) == 1); CHECK(secp256k1_memcmp_var(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ - if (secp256k1_testrand_int(3) == 0) { + if (testrand_int(3) == 0) { int ret1; int ret2; int ret3; unsigned char rnd[32]; unsigned char privkey_tmp[32]; secp256k1_pubkey pubkey2; - secp256k1_testrand256_test(rnd); + testrand256_test(rnd); memcpy(privkey_tmp, privkey, 32); ret1 = secp256k1_ec_seckey_tweak_add(CTX, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, rnd); @@ -6406,14 +6406,14 @@ static void test_ecdsa_end_to_end(void) { } /* Optionally tweak the keys using multiplication. */ - if (secp256k1_testrand_int(3) == 0) { + if (testrand_int(3) == 0) { int ret1; int ret2; int ret3; unsigned char rnd[32]; unsigned char privkey_tmp[32]; secp256k1_pubkey pubkey2; - secp256k1_testrand256_test(rnd); + testrand256_test(rnd); memcpy(privkey_tmp, privkey, 32); ret1 = secp256k1_ec_seckey_tweak_mul(CTX, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, rnd); @@ -6475,7 +6475,7 @@ static void test_ecdsa_end_to_end(void) { /* Serialize/destroy/parse DER and verify again. */ siglen = 74; CHECK(secp256k1_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); - sig[secp256k1_testrand_int(siglen)] += 1 + secp256k1_testrand_int(255); + sig[testrand_int(siglen)] += 1 + testrand_int(255); CHECK(secp256k1_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 0 || secp256k1_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 0); } @@ -6485,23 +6485,23 @@ static void test_random_pubkeys(void) { secp256k1_ge elem2; unsigned char in[65]; /* Generate some randomly sized pubkeys. */ - size_t len = secp256k1_testrand_bits(2) == 0 ? 65 : 33; - if (secp256k1_testrand_bits(2) == 0) { - len = secp256k1_testrand_bits(6); + size_t len = testrand_bits(2) == 0 ? 65 : 33; + if (testrand_bits(2) == 0) { + len = testrand_bits(6); } if (len == 65) { - in[0] = secp256k1_testrand_bits(1) ? 4 : (secp256k1_testrand_bits(1) ? 6 : 7); + in[0] = testrand_bits(1) ? 4 : (testrand_bits(1) ? 6 : 7); } else { - in[0] = secp256k1_testrand_bits(1) ? 2 : 3; + in[0] = testrand_bits(1) ? 2 : 3; } - if (secp256k1_testrand_bits(3) == 0) { - in[0] = secp256k1_testrand_bits(8); + if (testrand_bits(3) == 0) { + in[0] = testrand_bits(8); } if (len > 1) { - secp256k1_testrand256(&in[1]); + testrand256(&in[1]); } if (len > 33) { - secp256k1_testrand256(&in[33]); + testrand256(&in[33]); } if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { unsigned char out[65]; @@ -6523,7 +6523,7 @@ static void test_random_pubkeys(void) { CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); CHECK(secp256k1_ge_eq_var(&elem2, &elem)); /* Check that the X9.62 hybrid type is checked. */ - in[0] = secp256k1_testrand_bits(1) ? 6 : 7; + in[0] = testrand_bits(1) ? 6 : 7; res = secp256k1_eckey_pubkey_parse(&elem2, in, size); if (firstb == 2 || firstb == 3) { if (in[0] == firstb + 4) { @@ -6602,7 +6602,7 @@ static void permute(size_t *arr, size_t n) { size_t i; for (i = n - 1; i >= 1; i--) { size_t tmp, j; - j = secp256k1_testrand_int(i + 1); + j = testrand_int(i + 1); tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; @@ -6612,7 +6612,7 @@ static void permute(size_t *arr, size_t n) { static void rand_pk(secp256k1_pubkey *pk) { unsigned char seckey[32]; secp256k1_keypair keypair; - secp256k1_testrand256(seckey); + testrand256(seckey); CHECK(secp256k1_keypair_create(CTX, &keypair, seckey) == 1); CHECK(secp256k1_keypair_pub(CTX, pk, &keypair) == 1); } @@ -6828,27 +6828,27 @@ static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { static void damage_array(unsigned char *sig, size_t *len) { int pos; - int action = secp256k1_testrand_bits(3); + int action = testrand_bits(3); if (action < 1 && *len > 3) { /* Delete a byte. */ - pos = secp256k1_testrand_int(*len); + pos = testrand_int(*len); memmove(sig + pos, sig + pos + 1, *len - pos - 1); (*len)--; return; } else if (action < 2 && *len < 2048) { /* Insert a byte. */ - pos = secp256k1_testrand_int(1 + *len); + pos = testrand_int(1 + *len); memmove(sig + pos + 1, sig + pos, *len - pos); - sig[pos] = secp256k1_testrand_bits(8); + sig[pos] = testrand_bits(8); (*len)++; return; } else if (action < 4) { /* Modify a byte. */ - sig[secp256k1_testrand_int(*len)] += 1 + secp256k1_testrand_int(255); + sig[testrand_int(*len)] += 1 + testrand_int(255); return; } else { /* action < 8 */ /* Modify a bit. */ - sig[secp256k1_testrand_int(*len)] ^= 1 << secp256k1_testrand_bits(3); + sig[testrand_int(*len)] ^= 1 << testrand_bits(3); return; } } @@ -6861,23 +6861,23 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly int n; *len = 0; - der = secp256k1_testrand_bits(2) == 0; + der = testrand_bits(2) == 0; *certainly_der = der; *certainly_not_der = 0; - indet = der ? 0 : secp256k1_testrand_int(10) == 0; + indet = der ? 0 : testrand_int(10) == 0; for (n = 0; n < 2; n++) { /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ - nlow[n] = der ? 1 : (secp256k1_testrand_bits(3) != 0); + nlow[n] = der ? 1 : (testrand_bits(3) != 0); /* The length of the number in bytes (the first byte of which will always be nonzero) */ - nlen[n] = nlow[n] ? secp256k1_testrand_int(33) : 32 + secp256k1_testrand_int(200) * secp256k1_testrand_bits(3) / 8; + nlen[n] = nlow[n] ? testrand_int(33) : 32 + testrand_int(200) * testrand_bits(3) / 8; CHECK(nlen[n] <= 232); /* The top bit of the number. */ - nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_testrand_bits(1)); + nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : testrand_bits(1)); /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ - nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_testrand_bits(7) : 1 + secp256k1_testrand_int(127)); + nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + testrand_bits(7) : 1 + testrand_int(127)); /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ - nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_testrand_int(3) : secp256k1_testrand_int(300 - nlen[n]) * secp256k1_testrand_bits(3) / 8); + nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? testrand_int(3) : testrand_int(300 - nlen[n]) * testrand_bits(3) / 8); if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { *certainly_not_der = 1; } @@ -6886,7 +6886,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); if (!der) { /* nlenlen[n] max 127 bytes */ - int add = secp256k1_testrand_int(127 - nlenlen[n]) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256; + int add = testrand_int(127 - nlenlen[n]) * testrand_bits(4) * testrand_bits(4) / 256; nlenlen[n] += add; if (add != 0) { *certainly_not_der = 1; @@ -6900,7 +6900,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen <= 856); /* The length of the garbage inside the tuple. */ - elen = (der || indet) ? 0 : secp256k1_testrand_int(980 - tlen) * secp256k1_testrand_bits(3) / 8; + elen = (der || indet) ? 0 : testrand_int(980 - tlen) * testrand_bits(3) / 8; if (elen != 0) { *certainly_not_der = 1; } @@ -6908,7 +6908,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen <= 980); /* The length of the garbage after the end of the tuple. */ - glen = der ? 0 : secp256k1_testrand_int(990 - tlen) * secp256k1_testrand_bits(3) / 8; + glen = der ? 0 : testrand_int(990 - tlen) * testrand_bits(3) / 8; if (glen != 0) { *certainly_not_der = 1; } @@ -6923,7 +6923,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly } else { int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); if (!der) { - int add = secp256k1_testrand_int(127 - tlenlen) * secp256k1_testrand_bits(4) * secp256k1_testrand_bits(4) / 256; + int add = testrand_int(127 - tlenlen) * testrand_bits(4) * testrand_bits(4) / 256; tlenlen += add; if (add != 0) { *certainly_not_der = 1; @@ -6974,13 +6974,13 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly nlen[n]--; } /* Generate remaining random bytes of number */ - secp256k1_testrand_bytes_test(sig + *len, nlen[n]); + testrand_bytes_test(sig + *len, nlen[n]); *len += nlen[n]; nlen[n] = 0; } /* Generate random garbage inside tuple. */ - secp256k1_testrand_bytes_test(sig + *len, elen); + testrand_bytes_test(sig + *len, elen); *len += elen; /* Generate end-of-contents bytes. */ @@ -6992,7 +6992,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen + glen <= 1121); /* Generate random garbage outside tuple. */ - secp256k1_testrand_bytes_test(sig + *len, glen); + testrand_bytes_test(sig + *len, glen); *len += glen; tlen += glen; CHECK(tlen <= 1121); @@ -7655,7 +7655,7 @@ int main(int argc, char **argv) { run_xoshiro256pp_tests(); /* find random seed */ - secp256k1_testrand_init(argc > 2 ? argv[2] : NULL); + testrand_init(argc > 2 ? argv[2] : NULL); /*** Setup test environment ***/ @@ -7664,9 +7664,9 @@ int main(int argc, char **argv) { /* Randomize the context only with probability 15/16 to make sure we test without context randomization from time to time. TODO Reconsider this when recalibrating the tests. */ - if (secp256k1_testrand_bits(4)) { + if (testrand_bits(4)) { unsigned char rand32[32]; - secp256k1_testrand256(rand32); + testrand256(rand32); CHECK(secp256k1_context_randomize(CTX, rand32)); } /* Make a writable copy of secp256k1_context_static in order to test the effect of API functions @@ -7793,7 +7793,7 @@ int main(int argc, char **argv) { free(STATIC_CTX); secp256k1_context_destroy(CTX); - secp256k1_testrand_finish(); + testrand_finish(); printf("no problems found\n"); return 0; diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 0138f224..6efa8898 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -375,7 +375,7 @@ int main(int argc, char** argv) { printf("test count = %i\n", count); /* find random seed */ - secp256k1_testrand_init(argc > 2 ? argv[2] : NULL); + testrand_init(argc > 2 ? argv[2] : NULL); /* set up split processing */ if (argc > 4) { @@ -395,7 +395,7 @@ int main(int argc, char** argv) { while (count--) { /* Build context */ ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - secp256k1_testrand256(rand32); + testrand256(rand32); CHECK(secp256k1_context_randomize(ctx, rand32)); /* Generate the entire group */ @@ -459,7 +459,7 @@ int main(int argc, char** argv) { secp256k1_context_destroy(ctx); } - secp256k1_testrand_finish(); + testrand_finish(); printf("no problems found\n"); return 0; diff --git a/src/testutil.h b/src/testutil.h index cb33a485..8296a5fb 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -14,7 +14,7 @@ static void testutil_random_fe(secp256k1_fe *x) { unsigned char bin[32]; do { - secp256k1_testrand256(bin); + testrand256(bin); if (secp256k1_fe_set_b32_limit(x, bin)) { return; } @@ -29,7 +29,7 @@ static void testutil_random_fe_non_zero(secp256k1_fe *nz) { static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { secp256k1_fe zero; - int n = secp256k1_testrand_int(m + 1); + int n = testrand_int(m + 1); secp256k1_fe_normalize(fe); if (n == 0) { return; @@ -46,7 +46,7 @@ static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { static void testutil_random_fe_test(secp256k1_fe *x) { unsigned char bin[32]; do { - secp256k1_testrand256_test(bin); + testrand256_test(bin); if (secp256k1_fe_set_b32_limit(x, bin)) { return; } @@ -83,7 +83,7 @@ static void testutil_random_ge_test(secp256k1_ge *ge) { secp256k1_fe fe; do { testutil_random_fe_test(&fe); - if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_testrand_bits(1))) { + if (secp256k1_ge_set_xo_var(ge, &fe, testrand_bits(1))) { secp256k1_fe_normalize(&ge->y); break; } @@ -111,7 +111,7 @@ static void testutil_random_scalar_order_test(secp256k1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; - secp256k1_testrand256_test(b32); + testrand256_test(b32); secp256k1_scalar_set_b32(num, b32, &overflow); if (overflow || secp256k1_scalar_is_zero(num)) { continue; @@ -124,7 +124,7 @@ static void testutil_random_scalar_order(secp256k1_scalar *num) { do { unsigned char b32[32]; int overflow = 0; - secp256k1_testrand256(b32); + testrand256(b32); secp256k1_scalar_set_b32(num, b32, &overflow); if (overflow || secp256k1_scalar_is_zero(num)) { continue; From 122dbaeb371cf65b8ebbc713bcbdb05203670d49 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 27 May 2024 10:56:37 +0100 Subject: [PATCH 050/383] autotools: Remove "auto" value of `--with-ecmult-window` option "auto" implies that a value is being chosen based on build system introspection or host system capabilities. However, for the `--with-ecmult-window` option, the value "auto" is hardcoded, which might lead to confusion. This change replaces "auto" with a more appropriate default value. --- .cirrus.yml | 2 +- .github/workflows/ci.yml | 2 +- configure.ac | 15 ++++----------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 6e77403b..6431465d 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -10,7 +10,7 @@ env: MAKEFLAGS: -j4 BUILD: check ### secp256k1 config - ECMULTWINDOW: auto + ECMULTWINDOW: 15 ECMULTGENKB: auto ASM: no WIDEMUL: auto diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2466820..f42f7852 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ env: MAKEFLAGS: '-j4' BUILD: 'check' ### secp256k1 config - ECMULTWINDOW: 'auto' + ECMULTWINDOW: 15 ECMULTGENKB: 'auto' ASM: 'no' WIDEMUL: 'auto' diff --git a/configure.ac b/configure.ac index 8b62e1db..c0f809e7 100644 --- a/configure.ac +++ b/configure.ac @@ -203,15 +203,15 @@ AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_wide AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm32|no|auto], [assembly to use (experimental: arm32) [default=auto]])],[req_asm=$withval], [req_asm=auto]) -AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto], +AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE], [window size for ecmult precomputation for verification, specified as integer in range [2..24].] [Larger values result in possibly better performance at the cost of an exponentially larger precomputed table.] [The table will store 2^(SIZE-1) * 64 bytes of data but can be larger in memory due to platform-specific padding and alignment.] [A window size larger than 15 will require you delete the prebuilt precomputed_ecmult.c file so that it can be rebuilt.] [For very large window sizes, use "make -j 1" to reduce memory use during compilation.] -["auto" is a reasonable setting for desktop machines (currently 15). [default=auto]] +[The default value is a reasonable setting for desktop machines (currently 15). [default=15]] )], -[req_ecmult_window=$withval], [req_ecmult_window=auto]) +[set_ecmult_window=$withval], [set_ecmult_window=15]) AC_ARG_WITH([ecmult-gen-kb], [AS_HELP_STRING([--with-ecmult-gen-kb=2|22|86|auto], [The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms).] @@ -335,14 +335,7 @@ auto) ;; esac -# Set ecmult window size -if test x"$req_ecmult_window" = x"auto"; then - set_ecmult_window=15 -else - set_ecmult_window=$req_ecmult_window -fi - -error_window_size=['window size for ecmult precomputation not an integer in range [2..24] or "auto"'] +error_window_size=['window size for ecmult precomputation not an integer in range [2..24]'] case $set_ecmult_window in ''|*[[!0-9]]*) # no valid integer From 26b94ee92a7928d0e3ceb265f8e4b5bbabf01a77 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 27 May 2024 10:46:36 +0100 Subject: [PATCH 051/383] autotools: Remove "auto" value of `--with-ecmult-gen-kb` option "auto" implies that a value is being chosen based on build system introspection or host system capabilities. However, for the `--with-ecmult-gen-kb` option, the value "auto" is hardcoded, which might lead to confusion. This change replaces "auto" with a more appropriate default value. --- .cirrus.yml | 2 +- .github/workflows/ci.yml | 2 +- configure.ac | 15 ++++----------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 6431465d..4bd15511 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -11,7 +11,7 @@ env: BUILD: check ### secp256k1 config ECMULTWINDOW: 15 - ECMULTGENKB: auto + ECMULTGENKB: 22 ASM: no WIDEMUL: auto WITH_VALGRIND: yes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f42f7852..98f5e2b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ env: BUILD: 'check' ### secp256k1 config ECMULTWINDOW: 15 - ECMULTGENKB: 'auto' + ECMULTGENKB: 22 ASM: 'no' WIDEMUL: 'auto' WITH_VALGRIND: 'yes' diff --git a/configure.ac b/configure.ac index c0f809e7..ed3c4b80 100644 --- a/configure.ac +++ b/configure.ac @@ -213,12 +213,12 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE], )], [set_ecmult_window=$withval], [set_ecmult_window=15]) -AC_ARG_WITH([ecmult-gen-kb], [AS_HELP_STRING([--with-ecmult-gen-kb=2|22|86|auto], +AC_ARG_WITH([ecmult-gen-kb], [AS_HELP_STRING([--with-ecmult-gen-kb=2|22|86], [The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms).] [Larger values result in possibly better signing/keygeneration performance at the cost of a larger table.] -["auto" is a reasonable setting for desktop machines (currently 22). [default=auto]] +[The default value is a reasonable setting for desktop machines (currently 22). [default=22]] )], -[req_ecmult_gen_kb=$withval], [req_ecmult_gen_kb=auto]) +[set_ecmult_gen_kb=$withval], [set_ecmult_gen_kb=22]) AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind=yes|no|auto], [Build with extra checks for running inside Valgrind [default=auto]] @@ -350,13 +350,6 @@ case $set_ecmult_window in ;; esac -# Set ecmult gen kb -if test x"$req_ecmult_gen_kb" = x"auto"; then - set_ecmult_gen_kb=22 -else - set_ecmult_gen_kb=$req_ecmult_gen_kb -fi - case $set_ecmult_gen_kb in 2) SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=2 -DCOMB_TEETH=5" @@ -368,7 +361,7 @@ case $set_ecmult_gen_kb in SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOMB_BLOCKS=43 -DCOMB_TEETH=6" ;; *) - AC_MSG_ERROR(['ecmult gen table size not 2, 22, 86 or "auto"']) + AC_MSG_ERROR(['ecmult gen table size not 2, 22 or 86']) ;; esac From a06805ee7428d2786e631c9b5650c25fb0d46fe0 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 27 May 2024 13:26:03 +0100 Subject: [PATCH 052/383] cmake: Remove "AUTO" value of `SECP256K1_ECMULT_WINDOW_SIZE` option "AUTO" implies that a value is being chosen based on build system introspection or host system capabilities. However, for the `SECP256K1_ECMULT_WINDOW_SIZE` option, the value "AUTO" is hardcoded, which might lead to confusion. This change replaces "AUTO" with a more appropriate default value. --- CMakeLists.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88994d82..216d6465 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,13 +92,10 @@ if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS) add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1) endif() -set(SECP256K1_ECMULT_WINDOW_SIZE "AUTO" CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. \"AUTO\" is a reasonable setting for desktop machines (currently 15). [default=AUTO]") -set_property(CACHE SECP256K1_ECMULT_WINDOW_SIZE PROPERTY STRINGS "AUTO" 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24) +set(SECP256K1_ECMULT_WINDOW_SIZE 15 CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. The default value is a reasonable setting for desktop machines (currently 15). [default=15]") +set_property(CACHE SECP256K1_ECMULT_WINDOW_SIZE PROPERTY STRINGS 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24) include(CheckStringOptionValue) check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE) -if(SECP256K1_ECMULT_WINDOW_SIZE STREQUAL "AUTO") - set(SECP256K1_ECMULT_WINDOW_SIZE 15) -endif() add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE}) set(SECP256K1_ECMULT_GEN_KB "AUTO" CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. \"AUTO\" is a reasonable setting for desktop machines (currently 22). [default=AUTO]") From 4d9645bee06e732f5d7d9e72b0c26c22c5006eb8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 27 May 2024 13:32:23 +0100 Subject: [PATCH 053/383] cmake: Remove "AUTO" value of `SECP256K1_ECMULT_GEN_KB` option "AUTO" implies that a value is being chosen based on build system introspection or host system capabilities. However, for the `SECP256K1_ECMULT_GEN_KB` option, the value "AUTO" is hardcoded, which might lead to confusion. This change replaces "AUTO" with a more appropriate default value. --- CMakeLists.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 216d6465..3d0c99b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,12 +98,9 @@ include(CheckStringOptionValue) check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE) add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE}) -set(SECP256K1_ECMULT_GEN_KB "AUTO" CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. \"AUTO\" is a reasonable setting for desktop machines (currently 22). [default=AUTO]") -set_property(CACHE SECP256K1_ECMULT_GEN_KB PROPERTY STRINGS "AUTO" 2 22 86) +set(SECP256K1_ECMULT_GEN_KB 22 CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. The default value is a reasonable setting for desktop machines (currently 22). [default=22]") +set_property(CACHE SECP256K1_ECMULT_GEN_KB PROPERTY STRINGS 2 22 86) check_string_option_value(SECP256K1_ECMULT_GEN_KB) -if(SECP256K1_ECMULT_GEN_KB STREQUAL "AUTO") - set(SECP256K1_ECMULT_GEN_KB 22) -endif() if(SECP256K1_ECMULT_GEN_KB EQUAL 2) add_compile_definitions(COMB_BLOCKS=2) add_compile_definitions(COMB_TEETH=5) From 7abf979a438f9dfc3517ab913f9075b950628835 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 28 May 2024 09:37:00 +0100 Subject: [PATCH 054/383] cmake: Disable `ctime_tests` if build with `-fsanitize=memory` Clang >= 16 has `-fsanitize-memory-param-retval` turned on by default, which is incompatible with --- CMakeLists.txt | 20 +++++++++++++++++++- cmake/CheckMemorySanitizer.cmake | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 cmake/CheckMemorySanitizer.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 88994d82..ef079cd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,17 @@ endif() set(CMAKE_C_VISIBILITY_PRESET hidden) +set(print_msan_notice) +if(SECP256K1_BUILD_CTIME_TESTS) + include(CheckMemorySanitizer) + check_memory_sanitizer(msan_enabled) + if(msan_enabled) + try_append_c_flags(-fno-sanitize-memory-param-retval) + set(print_msan_notice YES) + endif() + unset(msan_enabled) +endif() + # Ask CTest to create a "check" target (e.g., make check) as alias for the "test" target. # CTEST_TEST_TARGET_ALIAS is not documented but supposed to be user-facing. # See: https://gitlab.kitware.com/cmake/cmake/-/commit/816c9d1aa1f2b42d40c81a991b68c96eb12b6d2 @@ -358,7 +369,14 @@ endif() if(SECP256K1_LATE_CFLAGS) message("SECP256K1_LATE_CFLAGS ................. ${SECP256K1_LATE_CFLAGS}") endif() -message("\n") +message("") +if(print_msan_notice) + message( + "Note:\n" + " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to compile options\n" + " to avoid false positives in ctime_tests. Pass -DSECP256K1_BUILD_CTIME_TESTS=OFF to avoid this.\n" + ) +endif() if(SECP256K1_EXPERIMENTAL) message( " ******\n" diff --git a/cmake/CheckMemorySanitizer.cmake b/cmake/CheckMemorySanitizer.cmake new file mode 100644 index 00000000..d9ef681e --- /dev/null +++ b/cmake/CheckMemorySanitizer.cmake @@ -0,0 +1,18 @@ +include_guard(GLOBAL) +include(CheckCSourceCompiles) + +function(check_memory_sanitizer output) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + check_c_source_compiles(" + #if defined(__has_feature) + # if __has_feature(memory_sanitizer) + /* MemorySanitizer is enabled. */ + # elif + # error \"MemorySanitizer is disabled.\" + # endif + #else + # error \"__has_feature is not defined.\" + #endif + " HAVE_MSAN) + set(${output} ${HAVE_MSAN} PARENT_SCOPE) +endfunction() From abde59f52dd901287fa774225d3dbd22933d90c2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 26 May 2024 15:53:42 +0100 Subject: [PATCH 055/383] cmake: Report more compiler details in summary --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef079cd1..a02cc8ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,7 +343,7 @@ message("Valgrind .............................. ${SECP256K1_VALGRIND}") get_directory_property(definitions COMPILE_DEFINITIONS) string(REPLACE ";" " " definitions "${definitions}") message("Preprocessor defined macros ........... ${definitions}") -message("C compiler ............................ ${CMAKE_C_COMPILER}") +message("C compiler ............................ ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION}, ${CMAKE_C_COMPILER}") message("CFLAGS ................................ ${CMAKE_C_FLAGS}") get_directory_property(compile_options COMPILE_OPTIONS) string(REPLACE ";" " " compile_options "${compile_options}") From 396e885886b2665850c3b10e4cd029cffffce1b7 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 28 May 2024 09:44:47 +0100 Subject: [PATCH 056/383] autotools: Align MSan checking code with CMake's implementation --- build-aux/m4/bitcoin_secp.m4 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4 index fee2d7b4..048267fa 100644 --- a/build-aux/m4/bitcoin_secp.m4 +++ b/build-aux/m4/bitcoin_secp.m4 @@ -50,10 +50,14 @@ AC_MSG_CHECKING(whether MemorySanitizer is enabled) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #if defined(__has_feature) # if __has_feature(memory_sanitizer) - # error "MemorySanitizer is enabled." + /* MemorySanitizer is enabled. */ + # elif + # error "MemorySanitizer is disabled." # endif + #else + # error "__has_feature is not defined." #endif - ]])], [msan_enabled=no], [msan_enabled=yes]) + ]])], [msan_enabled=yes], [msan_enabled=no]) AC_MSG_RESULT([$msan_enabled]) ]) From f55703ba49454fc46226f4846fe292d4a3dfa3ef Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 28 May 2024 09:47:00 +0100 Subject: [PATCH 057/383] autotools: Delete unneeded compiler test This change makes both Autotools and CMake build systems consistent. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9640a673..b6d20cc9 100644 --- a/configure.ac +++ b/configure.ac @@ -248,7 +248,7 @@ if test x"$enable_ctime_tests" = x"auto"; then fi print_msan_notice=no -if test x"$enable_ctime_tests" = x"yes" && test x"$GCC" = x"yes"; then +if test x"$enable_ctime_tests" = x"yes"; then SECP_MSAN_CHECK # MSan on Clang >=16 reports unitialized memory in function parameters and return values, even if # the uninitalized variable is never actually "used". This is called "eager" checking, and it's From 158f9e5eae583b1520af9ee727db342e7408dab1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:44:15 +0100 Subject: [PATCH 058/383] cmake: Do not modify build types when integrating by downstream project The `CMAKE_BUILD_TYPE` and `CMAKE_CONFIGURATION_TYPES` variables must be managed by the downstream project. Suggesting to review with `git diff -w`. --- CMakeLists.txt | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef2b07a1..3a92a329 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,23 +213,25 @@ mark_as_advanced( CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) -get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -set(default_build_type "RelWithDebInfo") -if(is_multi_config) - set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING - "Supported configuration types." - FORCE - ) -else() - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY - STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" - ) - if(NOT CMAKE_BUILD_TYPE) - message(STATUS "Setting build type to \"${default_build_type}\" as none was specified") - set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING - "Choose the type of build." +if(PROJECT_IS_TOP_LEVEL) + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + set(default_build_type "RelWithDebInfo") + if(is_multi_config) + set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING + "Supported configuration types." FORCE ) + else() + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY + STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" + ) + if(NOT CMAKE_BUILD_TYPE) + message(STATUS "Setting build type to \"${default_build_type}\" as none was specified") + set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING + "Choose the type of build." + FORCE + ) + endif() endif() endif() From 3a1c39625e7f9c05234df71c35bee3dae5b785e6 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 19 Jun 2024 15:27:06 +0000 Subject: [PATCH 059/383] rangeproof: add unit test for malleating single-value proofs I was a bit confused reading `secp256k1_rangeproof_getheader_impl` because in the case of single-value proofs (`has_nz_range == 0`) some bits of the header are unconstrained. At first I thought this was a malleability vector. And I think I've had this same confusion in the past. But in fact it is not a malleability vector because the whole header gets hashed into the proof. Add a unit test to confirm this to reduce future confusion. --- src/modules/rangeproof/tests_impl.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index d1abe204..49cc16cf 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -422,6 +422,7 @@ static void test_single_value_proof(uint64_t val) { uint64_t val_out = 0; size_t m_len_out = 0; + size_t i; secp256k1_testrand256(blind); secp256k1_testrand256(nonce); @@ -463,6 +464,30 @@ static void test_single_value_proof(uint64_t val) { CHECK(plen == 73); } + /* Test if trailing bytes are rejected. */ + proof[plen] = 0; + CHECK(secp256k1_rangeproof_verify( + CTX, + &min_val_out, &max_val_out, + &commit, + proof, plen + 1, + NULL, 0, + secp256k1_generator_h + ) == 0); + /* Test if single-bit malleation is caught */ + for (i = 0; i < plen*8; i++) { + proof[i >> 3] ^= 1 << (i & 7); + CHECK(secp256k1_rangeproof_verify( + CTX, + &min_val_out, &max_val_out, + &commit, + proof, plen, + NULL, 0, + secp256k1_generator_h + ) == 0); + proof[i >> 3] ^= 1 << (i & 7); + } + /* Test if unchanged proof is accepted. */ CHECK(secp256k1_rangeproof_verify( CTX, &min_val_out, &max_val_out, From f87a3589f4d3bfd7a398232971bdb1ff125b8e9d Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 20 Jun 2024 21:16:30 +0100 Subject: [PATCH 060/383] cmake: Do not set `CTEST_TEST_TARGET_ALIAS` An alias for the "test" target can be confusing for the downstream project. So remove it. --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef2b07a1..0ae8bb54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,10 +273,6 @@ if(SECP256K1_BUILD_CTIME_TESTS) unset(msan_enabled) endif() -# Ask CTest to create a "check" target (e.g., make check) as alias for the "test" target. -# CTEST_TEST_TARGET_ALIAS is not documented but supposed to be user-facing. -# See: https://gitlab.kitware.com/cmake/cmake/-/commit/816c9d1aa1f2b42d40c81a991b68c96eb12b6d2 -set(CTEST_TEST_TARGET_ALIAS check) include(CTest) # We do not use CTest's BUILD_TESTING because a single toggle for all tests is too coarse for our needs. mark_as_advanced(BUILD_TESTING) From c2764dbb99e7b8769df6814cf71beaeb59552701 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:46:42 +0100 Subject: [PATCH 061/383] cmake: Rename `SECP256K1_LATE_CFLAGS` to `SECP256K1_APPEND_CFLAGS` This change follows the naming convention currently used in the Bitcoin Core's CMake staging branch. --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef2b07a1..26ca2e8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -284,14 +284,14 @@ if(SECP256K1_BUILD_BENCHMARK OR SECP256K1_BUILD_TESTS OR SECP256K1_BUILD_EXHAUST enable_testing() endif() -set(SECP256K1_LATE_CFLAGS "" CACHE STRING "Compiler flags that are added to the command line after all other flags added by the build system.") +set(SECP256K1_APPEND_CFLAGS "" CACHE STRING "Compiler flags that are added to the command line after all other flags added by the build system.") include(AllTargetsCompileOptions) add_subdirectory(src) -all_targets_compile_options(src "${SECP256K1_LATE_CFLAGS}") +all_targets_compile_options(src "${SECP256K1_APPEND_CFLAGS}") if(SECP256K1_BUILD_EXAMPLES) add_subdirectory(examples) - all_targets_compile_options(examples "${SECP256K1_LATE_CFLAGS}") + all_targets_compile_options(examples "${SECP256K1_APPEND_CFLAGS}") endif() message("\n") @@ -365,8 +365,8 @@ else() message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}") message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") endif() -if(SECP256K1_LATE_CFLAGS) - message("SECP256K1_LATE_CFLAGS ................. ${SECP256K1_LATE_CFLAGS}") +if(SECP256K1_APPEND_CFLAGS) + message("SECP256K1_APPEND_CFLAGS ............... ${SECP256K1_APPEND_CFLAGS}") endif() message("") if(print_msan_notice) From 4706be2cd0bcac97da10ed3b98790f1ac6f04efb Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:45:07 +0100 Subject: [PATCH 062/383] cmake: Reimplement `SECP256K1_APPEND_CFLAGS` using Bitcoin Core approach --- CMakeLists.txt | 10 ++++++---- cmake/AllTargetsCompileOptions.cmake | 12 ------------ 2 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 cmake/AllTargetsCompileOptions.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 26ca2e8f..d91c50d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -284,14 +284,16 @@ if(SECP256K1_BUILD_BENCHMARK OR SECP256K1_BUILD_TESTS OR SECP256K1_BUILD_EXHAUST enable_testing() endif() -set(SECP256K1_APPEND_CFLAGS "" CACHE STRING "Compiler flags that are added to the command line after all other flags added by the build system.") -include(AllTargetsCompileOptions) +set(SECP256K1_APPEND_CFLAGS "" CACHE STRING "Compiler flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.") +if(SECP256K1_APPEND_CFLAGS) + # Appending to this low-level rule variable is the only way to + # guarantee that the flags appear at the end of the command line. + string(APPEND CMAKE_C_COMPILE_OBJECT " ${SECP256K1_APPEND_CFLAGS}") +endif() add_subdirectory(src) -all_targets_compile_options(src "${SECP256K1_APPEND_CFLAGS}") if(SECP256K1_BUILD_EXAMPLES) add_subdirectory(examples) - all_targets_compile_options(examples "${SECP256K1_APPEND_CFLAGS}") endif() message("\n") diff --git a/cmake/AllTargetsCompileOptions.cmake b/cmake/AllTargetsCompileOptions.cmake deleted file mode 100644 index 6e420e0f..00000000 --- a/cmake/AllTargetsCompileOptions.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# Add compile options to all targets added in the subdirectory. -function(all_targets_compile_options dir options) - get_directory_property(targets DIRECTORY ${dir} BUILDSYSTEM_TARGETS) - separate_arguments(options) - set(compiled_target_types STATIC_LIBRARY SHARED_LIBRARY OBJECT_LIBRARY EXECUTABLE) - foreach(target ${targets}) - get_target_property(type ${target} TYPE) - if(type IN_LIST compiled_target_types) - target_compile_options(${target} PRIVATE ${options}) - endif() - endforeach() -endfunction() From 7454a537367609e617f0bc5e0a64738ed6fbf6e9 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 24 Jun 2024 00:55:56 +0200 Subject: [PATCH 063/383] README: mention ellswift module Co-authored-by: Tim Ruffing --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6e88eb4e..e8d4123a 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Features: * Optional module for public key recovery. * Optional module for ECDH key exchange. * Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). +* Optional module for ElligatorSwift key exchange according to [BIP-324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki). Implementation details ---------------------- From 0e2fadb20c241bdd6cbbed7fcb3b4715a6133cf6 Mon Sep 17 00:00:00 2001 From: Elliot Lee Date: Mon, 24 Jun 2024 14:24:48 -0700 Subject: [PATCH 064/383] fix: typos in secp256k1.c --- src/secp256k1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/secp256k1.c b/src/secp256k1.c index 7a327694..72d725a7 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -76,7 +76,7 @@ const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_stati /* Helper function that determines if a context is proper, i.e., is not the static context or a copy thereof. * - * This is intended for "context" functions such as secp256k1_context_clone. Function which need specific + * This is intended for "context" functions such as secp256k1_context_clone. Functions that need specific * features of a context should still check for these features directly. For example, a function that needs * ecmult_gen should directly check for the existence of the ecmult_gen context. */ static int secp256k1_context_is_proper(const secp256k1_context* ctx) { @@ -544,7 +544,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc break; } is_nonce_valid = secp256k1_scalar_set_b32_seckey(&non, nonce32); - /* The nonce is still secret here, but it being invalid is is less likely than 1:2^255. */ + /* The nonce is still secret here, but it being invalid is less likely than 1:2^255. */ secp256k1_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); if (is_nonce_valid) { ret = secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid); From fe4fbaa7f3eaa404f7ded669e611e28260839f9c Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 25 Jun 2024 16:52:38 +0200 Subject: [PATCH 065/383] examples: fix case typos in secret clearing paragraphs (s/, Or/, or/) --- examples/ecdh.c | 2 +- examples/ecdsa.c | 2 +- examples/schnorr.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ecdh.c b/examples/ecdh.c index 4b7b7d61..d71fd2f6 100644 --- a/examples/ecdh.c +++ b/examples/ecdh.c @@ -108,7 +108,7 @@ int main(void) { /* It's best practice to try to clear secrets from memory after using them. * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), Or the OS + * example through "out of bounds" array access (see Heartbleed), or the OS * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. * * Here we are preventing these writes from being optimized out, as any good compiler diff --git a/examples/ecdsa.c b/examples/ecdsa.c index d1d2b0e3..d5c4613d 100644 --- a/examples/ecdsa.c +++ b/examples/ecdsa.c @@ -128,7 +128,7 @@ int main(void) { /* It's best practice to try to clear secrets from memory after using them. * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), Or the OS + * example through "out of bounds" array access (see Heartbleed), or the OS * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. * * Here we are preventing these writes from being optimized out, as any good compiler diff --git a/examples/schnorr.c b/examples/schnorr.c index 4c0dd1c1..b0409b98 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -146,7 +146,7 @@ int main(void) { /* It's best practice to try to clear secrets from memory after using them. * This is done because some bugs can allow an attacker to leak memory, for - * example through "out of bounds" array access (see Heartbleed), Or the OS + * example through "out of bounds" array access (see Heartbleed), or the OS * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. * * Here we are preventing these writes from being optimized out, as any good compiler From 31f84595c4fa8fcc89021790257b85416aae44f6 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 25 Jun 2024 03:11:21 +0200 Subject: [PATCH 066/383] Add ellswift usage example This should hopefully be useful as orientation for users implementing the key exchange part of BIP324. Conceptually the example is not very different to the ECDH one, so a lot of code/comments are just copied (e.g. context creation, secret key generation, shared secret comparison, console output, cleanup with secret key clearing). --- .gitignore | 1 + CHANGELOG.md | 3 + Makefile.am | 11 ++++ README.md | 1 + examples/CMakeLists.txt | 4 ++ examples/ellswift.c | 123 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 143 insertions(+) create mode 100644 examples/ellswift.c diff --git a/.gitignore b/.gitignore index 574902b8..18e3259f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ ctime_tests ecdh_example ecdsa_example schnorr_example +ellswift_example *.exe *.so *.a diff --git a/CHANGELOG.md b/CHANGELOG.md index a2855912..200653eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Added + - Added usage example for an ElligatorSwift key exchange. + ## [0.5.0] - 2024-05-06 #### Added diff --git a/Makefile.am b/Makefile.am index 322e44ea..8723b53b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -184,6 +184,17 @@ schnorr_example_LDFLAGS += -lbcrypt endif TESTS += schnorr_example endif +if ENABLE_MODULE_ELLSWIFT +noinst_PROGRAMS += ellswift_example +ellswift_example_SOURCES = examples/ellswift.c +ellswift_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC +ellswift_example_LDADD = libsecp256k1.la +ellswift_example_LDFLAGS = -static +if BUILD_WINDOWS +ellswift_example_LDFLAGS += -lbcrypt +endif +TESTS += ellswift_example +endif endif ### Precomputed tables diff --git a/README.md b/README.md index e8d4123a..9b20dd79 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ Usage examples can be found in the [examples](examples) directory. To compile th * [ECDSA example](examples/ecdsa.c) * [Schnorr signatures example](examples/schnorr.c) * [Deriving a shared secret (ECDH) example](examples/ecdh.c) + * [ElligatorSwift key exchange example](examples/ellswift.c) To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 607bb677..fd1ebce3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -28,3 +28,7 @@ endif() if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) add_example(schnorr) endif() + +if(SECP256K1_ENABLE_MODULE_ELLSWIFT) + add_example(ellswift) +endif() diff --git a/examples/ellswift.c b/examples/ellswift.c new file mode 100644 index 00000000..52be7eeb --- /dev/null +++ b/examples/ellswift.c @@ -0,0 +1,123 @@ +/************************************************************************* + * Written in 2024 by Sebastian Falbesoner * + * To the extent possible under law, the author(s) have dedicated all * + * copyright and related and neighboring rights to the software in this * + * file to the public domain worldwide. This software is distributed * + * without any warranty. For the CC0 Public Domain Dedication, see * + * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * + *************************************************************************/ + +/** This file demonstrates how to use the ElligatorSwift module to perform + * a key exchange according to BIP 324. Additionally, see the documentation + * in include/secp256k1_ellswift.h and doc/ellswift.md. + */ + +#include +#include +#include + +#include +#include + +#include "examples_util.h" + +int main(void) { + secp256k1_context* ctx; + unsigned char randomize[32]; + unsigned char auxrand1[32]; + unsigned char auxrand2[32]; + unsigned char seckey1[32]; + unsigned char seckey2[32]; + unsigned char ellswift_pubkey1[64]; + unsigned char ellswift_pubkey2[64]; + unsigned char shared_secret1[32]; + unsigned char shared_secret2[32]; + int return_val; + + /* Create a secp256k1 context */ + ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + if (!fill_random(randomize, sizeof(randomize))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* Randomizing the context is recommended to protect against side-channel + * leakage. See `secp256k1_context_randomize` in secp256k1.h for more + * information about it. This should never fail. */ + return_val = secp256k1_context_randomize(ctx, randomize); + assert(return_val); + + /*** Generate secret keys ***/ + + /* If the secret key is zero or out of range (bigger than secp256k1's + * order), we try to sample a new key. Note that the probability of this + * happening is negligible. */ + while (1) { + if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { + printf("Failed to generate randomness\n"); + return 1; + } + if (secp256k1_ec_seckey_verify(ctx, seckey1) && secp256k1_ec_seckey_verify(ctx, seckey2)) { + break; + } + } + + /* Generate ElligatorSwift public keys. This should never fail with valid context and + verified secret keys. Note that providing additional randomness (fourth parameter) is + optional, but recommended. */ + if (!fill_random(auxrand1, sizeof(auxrand1)) || !fill_random(auxrand2, sizeof(auxrand2))) { + printf("Failed to generate randomness\n"); + return 1; + } + return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey1, seckey1, auxrand1); + assert(return_val); + return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey2, seckey2, auxrand2); + assert(return_val); + + /*** Create the shared secret on each side ***/ + + /* Perform x-only ECDH with seckey1 and ellswift_pubkey2. Should never fail + * with a verified seckey and valid pubkey. Note that both parties pass both + * EllSwift pubkeys in the same order; the pubkey of the calling party is + * determined by the "party" boolean (sixth parameter). */ + return_val = secp256k1_ellswift_xdh(ctx, shared_secret1, ellswift_pubkey1, ellswift_pubkey2, + seckey1, 0, secp256k1_ellswift_xdh_hash_function_bip324, NULL); + assert(return_val); + + /* Perform x-only ECDH with seckey2 and ellswift_pubkey1. Should never fail + * with a verified seckey and valid pubkey. */ + return_val = secp256k1_ellswift_xdh(ctx, shared_secret2, ellswift_pubkey1, ellswift_pubkey2, + seckey2, 1, secp256k1_ellswift_xdh_hash_function_bip324, NULL); + assert(return_val); + + /* Both parties should end up with the same shared secret */ + return_val = memcmp(shared_secret1, shared_secret2, sizeof(shared_secret1)); + assert(return_val == 0); + + printf( " Secret Key1: "); + print_hex(seckey1, sizeof(seckey1)); + printf( "EllSwift Pubkey1: "); + print_hex(ellswift_pubkey1, sizeof(ellswift_pubkey1)); + printf("\n Secret Key2: "); + print_hex(seckey2, sizeof(seckey2)); + printf( "EllSwift Pubkey2: "); + print_hex(ellswift_pubkey2, sizeof(ellswift_pubkey2)); + printf("\n Shared Secret: "); + print_hex(shared_secret1, sizeof(shared_secret1)); + + /* This will clear everything from the context and free the memory */ + secp256k1_context_destroy(ctx); + + /* It's best practice to try to clear secrets from memory after using them. + * This is done because some bugs can allow an attacker to leak memory, for + * example through "out of bounds" array access (see Heartbleed), or the OS + * swapping them to disk. Hence, we overwrite the secret key buffer with zeros. + * + * Here we are preventing these writes from being optimized out, as any good compiler + * will remove any writes that aren't used. */ + secure_erase(seckey1, sizeof(seckey1)); + secure_erase(seckey2, sizeof(seckey2)); + secure_erase(shared_secret1, sizeof(shared_secret1)); + secure_erase(shared_secret2, sizeof(shared_secret2)); + + return 0; +} From 6aa576515efed241a749bcd2042eee6a928320a1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 26 Jun 2024 23:31:26 +0100 Subject: [PATCH 067/383] cmake: Delete `CTest` module The `CTest` module handles `CDash` integration, which we do not use. It is not required for testing functionality. --- CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e3465a7..e016cbf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -269,9 +269,6 @@ if(SECP256K1_BUILD_CTIME_TESTS) unset(msan_enabled) endif() -include(CTest) -# We do not use CTest's BUILD_TESTING because a single toggle for all tests is too coarse for our needs. -mark_as_advanced(BUILD_TESTING) if(SECP256K1_BUILD_BENCHMARK OR SECP256K1_BUILD_TESTS OR SECP256K1_BUILD_EXHAUSTIVE_TESTS OR SECP256K1_BUILD_CTIME_TESTS OR SECP256K1_BUILD_EXAMPLES) enable_testing() endif() From 7c987ec89e6cbee5d087683ba29b97012e679484 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 26 Jun 2024 23:37:36 +0100 Subject: [PATCH 068/383] cmake: Call `enable_testing()` unconditionally This change simplifies the code. Also comments has been added to highlight the code structure. --- CMakeLists.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e016cbf5..e068e202 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15) cmake_policy(SET CMP0092 NEW) endif() +#============================= +# Project / Package metadata +#============================= project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as @@ -16,6 +19,8 @@ project(libsecp256k1 HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C ) +enable_testing() +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) if(CMAKE_VERSION VERSION_LESS 3.21) # Emulates CMake 3.21+ behavior. @@ -37,11 +42,15 @@ set(${PROJECT_NAME}_LIB_VERSION_CURRENT 4) set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) set(${PROJECT_NAME}_LIB_VERSION_AGE 2) +#============================= +# Language setup +#============================= set(CMAKE_C_STANDARD 90) set(CMAKE_C_EXTENSIONS OFF) -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) - +#============================= +# Configurable options +#============================= option(BUILD_SHARED_LIBS "Build shared libraries." ON) option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF) if(SECP256K1_DISABLE_SHARED) @@ -269,10 +278,6 @@ if(SECP256K1_BUILD_CTIME_TESTS) unset(msan_enabled) endif() -if(SECP256K1_BUILD_BENCHMARK OR SECP256K1_BUILD_TESTS OR SECP256K1_BUILD_EXHAUSTIVE_TESTS OR SECP256K1_BUILD_CTIME_TESTS OR SECP256K1_BUILD_EXAMPLES) - enable_testing() -endif() - set(SECP256K1_APPEND_CFLAGS "" CACHE STRING "Compiler flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.") if(SECP256K1_APPEND_CFLAGS) # Appending to this low-level rule variable is the only way to From b8fe33332b7c6a7700f74be20c022fcc49753cd2 Mon Sep 17 00:00:00 2001 From: Eduardo Menges Mattje Date: Thu, 27 Jun 2024 11:46:48 -0300 Subject: [PATCH 069/383] cmake: Fixed O3 replacement --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e3465a7..46abe062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,7 +185,7 @@ else() string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") # Prefer -O2 optimization level. (-O3 is CMake's default for Release for many compilers.) - string(REGEX REPLACE "-O3[ \t\r\n]*" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + string(REGEX REPLACE "-O3( |$)" "-O2\\1" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") endif() # Define custom "Coverage" build type. From 16685649d2a6e52f81659ec629bc4e603128c54c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 1 Jul 2024 18:40:24 +0200 Subject: [PATCH 070/383] doc: Add convention for defaults --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5fbf7332..a366d38b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,6 +49,7 @@ In addition, libsecp256k1 tries to maintain the following coding conventions: * Operations involving secret data should be tested for being constant time with respect to the secrets (see [src/ctime_tests.c](src/ctime_tests.c)). * Local variables containing secret data should be cleared explicitly to try to delete secrets from memory. * Use `secp256k1_memcmp_var` instead of `memcmp` (see [#823](https://github.com/bitcoin-core/secp256k1/issues/823)). +* As a rule of thumb, the default values for configuration options should target standard desktop machines and align with Bitcoin Core's defaults, and the tests should mostly exercise the default configuration (see [#1549](https://github.com/bitcoin-core/secp256k1/issues/1549#issuecomment-2200559257)). #### Style conventions From 9420eece24117fc55540ab6d8bbfaca6b834b761 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 1 Jul 2024 22:46:05 +0100 Subject: [PATCH 071/383] cmake: Bump CMake minimum required version up to 3.16 --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 9 +-------- README.md | 2 +- doc/release-process.md | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ade94e1e..ded5df36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -864,5 +864,5 @@ jobs: CI_BUILD: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/build CI_INSTALL: ${{ runner.temp }}/${{ github.run_id }}${{ github.action }}/install run: | - cmake -B ${{ env.CI_BUILD }} -DCMAKE_INSTALL_PREFIX=${{ env.CI_INSTALL }} && cmake --build ${{ env.CI_BUILD }} --target install && ls -RlAh ${{ env.CI_INSTALL }} + cmake -B ${{ env.CI_BUILD }} -DCMAKE_INSTALL_PREFIX=${{ env.CI_INSTALL }} && cmake --build ${{ env.CI_BUILD }} && cmake --install ${{ env.CI_BUILD }} && ls -RlAh ${{ env.CI_INSTALL }} gcc -o ecdsa examples/ecdsa.c -I ${{ env.CI_INSTALL }}/include -L ${{ env.CI_INSTALL }}/lib*/ -l secp256k1 -Wl,-rpath,"${{ env.CI_INSTALL }}/lib",-rpath,"${{ env.CI_INSTALL }}/lib64" && ./ecdsa diff --git a/CMakeLists.txt b/CMakeLists.txt index 46abe062..8d1e8e40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,4 @@ -cmake_minimum_required(VERSION 3.13) - -if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15) - # MSVC runtime library flags are selected by the CMAKE_MSVC_RUNTIME_LIBRARY abstraction. - cmake_policy(SET CMP0091 NEW) - # MSVC warning flags are not in CMAKE__FLAGS by default. - cmake_policy(SET CMP0092 NEW) -endif() +cmake_minimum_required(VERSION 3.16) project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of diff --git a/README.md b/README.md index e8d4123a..6a2ea438 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ To maintain a pristine source tree, CMake encourages to perform an out-of-source $ cmake .. $ cmake --build . $ ctest # run the test suite - $ sudo cmake --build . --target install # optional + $ sudo cmake --install . # optional To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake .. -LH` to see the full list of available flags. diff --git a/doc/release-process.md b/doc/release-process.md index cdf62430..c37f519d 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -31,7 +31,7 @@ Perform these checks when reviewing the release PR (see below): ```shell dir=$(mktemp -d) build=$(mktemp -d) - cmake -B $build -DCMAKE_INSTALL_PREFIX=$dir && cmake --build $build --target install && ls -RlAh $dir + cmake -B $build -DCMAKE_INSTALL_PREFIX=$dir && cmake --build $build && cmake --install $build && ls -RlAh $dir gcc -o ecdsa examples/ecdsa.c -I $dir/include -L $dir/lib*/ -l secp256k1 -Wl,-rpath,"$dir/lib",-rpath,"$dir/lib64" && ./ecdsa ``` 4. Use the [`check-abi.sh`](/tools/check-abi.sh) tool to verify that there are no unexpected ABI incompatibilities and that the version number and the release notes accurately reflect all potential ABI changes. To run this tool, the `abi-dumper` and `abi-compliance-checker` packages are required. From d94a9273f82aeb468f9c48f6da5ee9abc64c024a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:41:36 +0100 Subject: [PATCH 072/383] build: Adjust the default size of the precomputed table for signing The new default value of the precomputed table for signing is aligned with Bitcoin Core's default. See: https://github.com/bitcoin/bitcoin/commit/a057869aa3c42457570765966cb66accb2375b13 --- CMakeLists.txt | 2 +- configure.ac | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d1e8e40..7a876860 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ include(CheckStringOptionValue) check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE) add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE}) -set(SECP256K1_ECMULT_GEN_KB 22 CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. The default value is a reasonable setting for desktop machines (currently 22). [default=22]") +set(SECP256K1_ECMULT_GEN_KB 86 CACHE STRING "The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms). Larger values result in possibly better signing or key generation performance at the cost of a larger table. Valid choices are 2, 22, 86. The default value is a reasonable setting for desktop machines (currently 86). [default=86]") set_property(CACHE SECP256K1_ECMULT_GEN_KB PROPERTY STRINGS 2 22 86) check_string_option_value(SECP256K1_ECMULT_GEN_KB) if(SECP256K1_ECMULT_GEN_KB EQUAL 2) diff --git a/configure.ac b/configure.ac index adae1897..24918885 100644 --- a/configure.ac +++ b/configure.ac @@ -216,9 +216,9 @@ AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE], AC_ARG_WITH([ecmult-gen-kb], [AS_HELP_STRING([--with-ecmult-gen-kb=2|22|86], [The size of the precomputed table for signing in multiples of 1024 bytes (on typical platforms).] [Larger values result in possibly better signing/keygeneration performance at the cost of a larger table.] -[The default value is a reasonable setting for desktop machines (currently 22). [default=22]] +[The default value is a reasonable setting for desktop machines (currently 86). [default=86]] )], -[set_ecmult_gen_kb=$withval], [set_ecmult_gen_kb=22]) +[set_ecmult_gen_kb=$withval], [set_ecmult_gen_kb=86]) AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind=yes|no|auto], [Build with extra checks for running inside Valgrind [default=auto]] From e2af491263e2f7e086dc7f1925d86660ff265dc6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:44:23 +0100 Subject: [PATCH 073/383] ci: Switch to the new default value of the precomputed table for signing --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ded5df36..56a8c9f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ env: BUILD: 'check' ### secp256k1 config ECMULTWINDOW: 15 - ECMULTGENKB: 22 + ECMULTGENKB: 86 ASM: 'no' WIDEMUL: 'auto' WITH_VALGRIND: 'yes' From af551ab9db09a3e4f2d06f68cf3e140fb1acfc4b Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 22 Jul 2024 07:24:31 +0000 Subject: [PATCH 074/383] tests: do not use functions from extrakeys module This fixes a bug introduced in 7d2591ce12d8a9b85f210cf9d678e91cee125ee9 that prevented compiling the library without enabling the extrakeys module. --- CHANGELOG.md | 3 +++ src/tests.c | 14 +++----------- src/testutil.h | 6 ++++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 200653eb..4a02e3fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Added - Added usage example for an ElligatorSwift key exchange. +#### Fixed +- Fixed compilation when the extrakeys module is disabled. + ## [0.5.0] - 2024-05-06 #### Added diff --git a/src/tests.c b/src/tests.c index 6b401e52..70c15f87 100644 --- a/src/tests.c +++ b/src/tests.c @@ -6609,14 +6609,6 @@ static void permute(size_t *arr, size_t n) { } } -static void rand_pk(secp256k1_pubkey *pk) { - unsigned char seckey[32]; - secp256k1_keypair keypair; - testrand256(seckey); - CHECK(secp256k1_keypair_create(CTX, &keypair, seckey) == 1); - CHECK(secp256k1_keypair_pub(CTX, pk, &keypair) == 1); -} - static void test_sort_api(void) { secp256k1_pubkey pks[2]; const secp256k1_pubkey *pks_ptr[2]; @@ -6624,8 +6616,8 @@ static void test_sort_api(void) { pks_ptr[0] = &pks[0]; pks_ptr[1] = &pks[1]; - rand_pk(&pks[0]); - rand_pk(&pks[1]); + testutil_random_pubkey_test(&pks[0]); + testutil_random_pubkey_test(&pks[1]); CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_sort(CTX, NULL, 2)); @@ -6678,7 +6670,7 @@ static void test_sort(void) { int j; const secp256k1_pubkey *pk_ptr[5]; for (j = 0; j < 5; j++) { - rand_pk(&pk[j]); + testutil_random_pubkey_test(&pk[j]); pk_ptr[j] = &pk[j]; } secp256k1_ec_pubkey_sort(CTX, pk_ptr, 5); diff --git a/src/testutil.h b/src/testutil.h index 8296a5fb..fc56854d 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -107,6 +107,12 @@ static void testutil_random_gej_test(secp256k1_gej *gej) { testutil_random_ge_jacobian_test(gej, &ge); } +static void testutil_random_pubkey_test(secp256k1_pubkey *pk) { + secp256k1_ge ge; + testutil_random_ge_test(&ge); + secp256k1_pubkey_save(pk, &ge); +} + static void testutil_random_scalar_order_test(secp256k1_scalar *num) { do { unsigned char b32[32]; From 763d938cf0e68ef6dc52fda4f45cc03c5d2e31f0 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 22 Jul 2024 07:36:22 +0000 Subject: [PATCH 075/383] ci: only enable extrakeys module when schnorrsig is enabled --- .cirrus.yml | 3 +++ .github/workflows/ci.yml | 51 ++++++++++++++++++++++++---------------- ci/ci.sh | 3 ++- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 4bd15511..0c1e01dc 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -20,6 +20,7 @@ env: EXPERIMENTAL: no ECDH: no RECOVERY: no + EXTRAKEYS: no SCHNORRSIG: no ELLSWIFT: no ### test options @@ -66,6 +67,7 @@ task: env: ECDH: yes RECOVERY: yes + EXTRAKEYS: yes SCHNORRSIG: yes ELLSWIFT: yes matrix: @@ -82,6 +84,7 @@ task: env: ECDH: yes RECOVERY: yes + EXTRAKEYS: yes SCHNORRSIG: yes ELLSWIFT: yes WRAPPER_CMD: 'valgrind --error-exitcode=42' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56a8c9f6..e238f3b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ env: EXPERIMENTAL: 'no' ECDH: 'no' RECOVERY: 'no' + EXTRAKEYS: 'no' SCHNORRSIG: 'no' ELLSWIFT: 'no' ### test options @@ -71,18 +72,18 @@ jobs: matrix: configuration: - env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' } - - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { WIDEMUL: 'int128' } - - env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' } - - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes' } - - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' } - - env_vars: { RECOVERY: 'yes', SCHNORRSIG: 'yes' } - - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', CPPFLAGS: '-DVERIFY' } + - env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes' } + - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' } + - env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes' } + - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', CPPFLAGS: '-DVERIFY' } - env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' } - env_vars: { CPPFLAGS: '-DDETERMINISTIC' } - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' } - - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 } - env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 } cc: @@ -139,6 +140,7 @@ jobs: HOST: 'i686-linux-gnu' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CC: ${{ matrix.cc }} @@ -183,6 +185,7 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -234,6 +237,7 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -279,6 +283,7 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -334,6 +339,7 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -386,6 +392,7 @@ jobs: WRAPPER_CMD: 'valgrind --error-exitcode=42' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -437,6 +444,7 @@ jobs: env: ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -501,6 +509,7 @@ jobs: env: ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CC: 'clang' @@ -547,6 +556,7 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -605,15 +615,15 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } - BUILD: 'distcheck' steps: @@ -666,13 +676,13 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } - BUILD: 'distcheck' steps: @@ -778,6 +788,7 @@ jobs: WERROR_CFLAGS: ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' ELLSWIFT: 'yes' diff --git a/ci/ci.sh b/ci/ci.sh index c7d2e9e4..a6c608c2 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -13,7 +13,7 @@ print_environment() { # does not rely on bash. for var in WERROR_CFLAGS MAKEFLAGS BUILD \ ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ - EXPERIMENTAL ECDH RECOVERY SCHNORRSIG ELLSWIFT \ + EXPERIMENTAL ECDH RECOVERY EXTRAKEYS SCHNORRSIG ELLSWIFT \ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ EXAMPLES \ HOST WRAPPER_CMD \ @@ -77,6 +77,7 @@ esac --with-ecmult-gen-kb="$ECMULTGENKB" \ --enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \ --enable-module-ellswift="$ELLSWIFT" \ + --enable-module-extrakeys="$EXTRAKEYS" \ --enable-module-schnorrsig="$SCHNORRSIG" \ --enable-examples="$EXAMPLES" \ --enable-ctime-tests="$CTIMETESTS" \ From 759bd4bbc8285fc6b99dae058b03f43353ab282e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 1 Aug 2024 15:55:01 +0000 Subject: [PATCH 076/383] doc: mention `needs-changelog` github label in release process --- doc/release-process.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/release-process.md b/doc/release-process.md index c37f519d..a64bae0f 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -44,7 +44,8 @@ Perform these checks when reviewing the release PR (see below): 1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that * finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) by * adding a section for the release (make sure that the version number is a link to a diff between the previous and new version), - * removing the `[Unreleased]` section header, and + * removing the `[Unreleased]` section header, + * ensuring that the release notes are not missing entries (check the `needs-changelog` label on github), and * including an entry for `### ABI Compatibility` if it doesn't exist, * sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and, * if this is not a patch release, From 5770226176568a0c11a821c83921180c76d37028 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 1 Aug 2024 16:57:45 +0000 Subject: [PATCH 077/383] changelog: clarify CMake option --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a02e3fc..2baab9d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Changed - The implementation of the point multiplication algorithm used for signing and public key generation was changed, resulting in improved performance for those operations. - - The related configure option `--ecmult-gen-precision` was replaced with `--ecmult-gen-kb` (`ECMULT_GEN_KB` for CMake). + - The related configure option `--ecmult-gen-precision` was replaced with `--ecmult-gen-kb` (`SECP256K1_ECMULT_GEN_KB` for CMake). - This changes the supported precomputed table sizes for these operations. The new supported sizes are 2 KiB, 22 KiB, or 86 KiB (while the old supported sizes were 32 KiB, 64 KiB, or 512 KiB). #### ABI Compatibility From 40d87b8e458b6546dd307119f754df23ffdfd359 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 1 Aug 2024 15:28:52 +0000 Subject: [PATCH 078/383] release: prepare for 0.5.1 --- CHANGELOG.md | 13 ++++++++++--- configure.ac | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2baab9d5..0868e754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.5.1] - 2024-08-01 #### Added - Added usage example for an ElligatorSwift key exchange. +#### Changed + - The default size of the precomputed table for signing was changed from 22 KiB to 86 KiB. The size can be changed with the configure option `--ecmult-gen-kb` (`SECP256K1_ECMULT_GEN_KB` for CMake). + - "auto" is no longer an accepted value for the `--with-ecmult-window` and `--with-ecmult-gen-kb` configure options (this also applies to `SECP256K1_ECMULT_WINDOW_SIZE` and `SECP256K1_ECMULT_GEN_KB` in CMake). To achieve the same configuration as previously provided by the "auto" value, omit setting the configure option explicitly. + #### Fixed -- Fixed compilation when the extrakeys module is disabled. + - Fixed compilation when the extrakeys module is disabled. + +#### ABI Compatibility +The ABI is backward compatible with versions 0.5.0, 0.4.x and 0.3.x. ## [0.5.0] - 2024-05-06 @@ -134,7 +141,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. -[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...HEAD +[0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...v0.4.0 diff --git a/configure.ac b/configure.ac index 24918885..6c4c11dd 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ AC_PREREQ([2.60]) define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 5) define(_PKG_VERSION_PATCH, 1) -define(_PKG_VERSION_IS_RELEASE, false) +define(_PKG_VERSION_IS_RELEASE, true) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: From c3e40d75db5d028c954ab5f31e89d39c1ce3a12b Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 1 Aug 2024 19:23:27 +0000 Subject: [PATCH 079/383] release cleanup: bump version after 0.5.1 --- CHANGELOG.md | 3 +++ CMakeLists.txt | 4 ++-- configure.ac | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0868e754..fb829406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + ## [0.5.1] - 2024-08-01 #### Added @@ -141,6 +143,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. +[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...HEAD [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...v0.4.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a876860..4ca8cbe8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.5.1 + VERSION 0.5.2 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -27,7 +27,7 @@ endif() # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. set(${PROJECT_NAME}_LIB_VERSION_CURRENT 4) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 2) set(${PROJECT_NAME}_LIB_VERSION_AGE 2) set(CMAKE_C_STANDARD 90) diff --git a/configure.ac b/configure.ac index 6c4c11dd..6841543f 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,8 @@ AC_PREREQ([2.60]) # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 5) -define(_PKG_VERSION_PATCH, 1) -define(_PKG_VERSION_IS_RELEASE, true) +define(_PKG_VERSION_PATCH, 2) +define(_PKG_VERSION_IS_RELEASE, false) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. define(_LIB_VERSION_CURRENT, 4) -define(_LIB_VERSION_REVISION, 1) +define(_LIB_VERSION_REVISION, 2) define(_LIB_VERSION_AGE, 2) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From 7057d3c9af4c136f9bcbf74dce7fda30690b64f8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:03:44 +0100 Subject: [PATCH 080/383] ci: Silent Homebrew's noisy reinstall warnings --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e238f3b7..0fc104d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -632,7 +632,7 @@ jobs: - name: Install Homebrew packages run: | - brew install automake libtool gcc + brew install --quiet automake libtool gcc ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc - name: Install and cache Valgrind @@ -691,7 +691,7 @@ jobs: - name: Install Homebrew packages run: | - brew install automake libtool gcc + brew install --quiet automake libtool gcc ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc - name: CI script From e34b47673085208ea863aed26c4a777b3e0b11a4 Mon Sep 17 00:00:00 2001 From: maflcko <6399679+maflcko@users.noreply.github.com> Date: Mon, 12 Aug 2024 19:41:04 +0200 Subject: [PATCH 081/383] ci: Bump GCC_SNAPSHOT_MAJOR to 15 --- ci/linux-debian.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 5ce715b4..241bfa97 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -40,7 +40,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ apt-get clean && rm -rf /var/lib/apt/lists/* # Build and install gcc snapshot -ARG GCC_SNAPSHOT_MAJOR=14 +ARG GCC_SNAPSHOT_MAJOR=15 RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ mkdir gcc && cd gcc && \ wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \ From 9b0f37bff1befbdccec0c7199aae98c07611f974 Mon Sep 17 00:00:00 2001 From: Epic Curious <109078515+epiccurious@users.noreply.github.com> Date: Tue, 13 Aug 2024 16:06:24 -0400 Subject: [PATCH 082/383] fix: remove duplicate 'the' from header file comment --- include/secp256k1_ellswift.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/secp256k1_ellswift.h b/include/secp256k1_ellswift.h index ae37287f..0d1293e9 100644 --- a/include/secp256k1_ellswift.h +++ b/include/secp256k1_ellswift.h @@ -35,7 +35,7 @@ extern "C" { * * If the Y coordinate is relevant, it is given the same parity as t. * - * Changes w.r.t. the the paper: + * Changes w.r.t. the paper: * - The u=0, t=0, and u^3+t^2+7=0 conditions result in decoding to the point * at infinity in the paper. Here they are remapped to finite points. * - The paper uses an additional encoding bit for the parity of y. Here the From fa67b6752d8ba3e4c41f6c36b1c6b94a21770419 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 15 Aug 2024 17:43:29 +0200 Subject: [PATCH 083/383] refactor: Use array initialization for unterminated strings The previous code is correct and harmless to initialize an array with a non-terminated character sequence using a string literal. However, it requires exactly specifying the array size, which can be cumbersome. Also, GCC-15 may issue the -Wunterminated-string-initialization warning. [1] Fix both issues by using array initialization. This refactoring commit does not change behavior. [1] Example warning: src/modules/schnorrsig/main_impl.h:48:46: error: initializer-string for array of 'unsigned char' is too long [-Werror=unterminated-string-initialization] 48 | static const unsigned char bip340_algo[13] = "BIP0340/nonce"; | ^~~~~~~~~~~~~~~ --- examples/schnorr.c | 4 ++-- src/modules/ellswift/tests_impl.h | 6 +++--- src/modules/schnorrsig/main_impl.h | 2 +- src/modules/schnorrsig/tests_impl.h | 10 +++++----- src/testrand_impl.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/schnorr.c b/examples/schnorr.c index b0409b98..8d5d14bd 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -18,9 +18,9 @@ #include "examples_util.h" int main(void) { - unsigned char msg[12] = "Hello World!"; + unsigned char msg[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'}; unsigned char msg_hash[32]; - unsigned char tag[17] = "my_fancy_protocol"; + unsigned char tag[] = {'m', 'y', '_', 'f', 'a', 'n', 'c', 'y', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l'}; unsigned char seckey[32]; unsigned char randomize[32]; unsigned char auxiliary_rand[32]; diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index ed5658f3..3c314c9b 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -406,9 +406,9 @@ void run_ellswift_tests(void) { /* Test hash initializers. */ { secp256k1_sha256 sha, sha_optimized; - static const unsigned char encode_tag[25] = "secp256k1_ellswift_encode"; - static const unsigned char create_tag[25] = "secp256k1_ellswift_create"; - static const unsigned char bip324_tag[26] = "bip324_ellswift_xonly_ecdh"; + static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; + static const unsigned char create_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'c', 'r', 'e', 'a', 't', 'e'}; + static const unsigned char bip324_tag[] = {'b', 'i', 'p', '3', '2', '4', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'x', 'o', 'n', 'l', 'y', '_', 'e', 'c', 'd', 'h'}; /* Check that hash initialized by * secp256k1_ellswift_sha256_init_encode has the expected diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 26727e46..57f7eadd 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -45,7 +45,7 @@ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 * /* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 * by using the correct tagged hash function. */ -static const unsigned char bip340_algo[13] = "BIP0340/nonce"; +static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC; diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index aa4fc382..2d716a01 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -21,9 +21,9 @@ static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, s } static void run_nonce_function_bip340_tests(void) { - unsigned char tag[13] = "BIP0340/nonce"; - unsigned char aux_tag[11] = "BIP0340/aux"; - unsigned char algo[13] = "BIP0340/nonce"; + unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; + unsigned char aux_tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; + unsigned char algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; size_t algolen = sizeof(algo); secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; @@ -158,7 +158,7 @@ static void test_schnorrsig_api(void) { /* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the * expected state. */ static void test_schnorrsig_sha256_tagged(void) { - unsigned char tag[17] = "BIP0340/challenge"; + unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; @@ -806,7 +806,7 @@ static void test_schnorrsig_sign(void) { unsigned char sk[32]; secp256k1_xonly_pubkey pk; secp256k1_keypair keypair; - const unsigned char msg[32] = "this is a msg for a schnorrsig.."; + const unsigned char msg[] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'm', 's', 'g', ' ', 'f', 'o', 'r', ' ', 'a', ' ', 's', 'c', 'h', 'n', 'o', 'r', 'r', 's', 'i', 'g', '.', '.'}; unsigned char sig[64]; unsigned char sig2[64]; unsigned char zeros64[64] = { 0 }; diff --git a/src/testrand_impl.h b/src/testrand_impl.h index 07564f7f..b84f5730 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -18,7 +18,7 @@ static uint64_t secp256k1_test_state[4]; SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) { - static const unsigned char PREFIX[19] = "secp256k1 test init"; + static const unsigned char PREFIX[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', ' ', 't', 'e', 's', 't', ' ', 'i', 'n', 'i', 't'}; unsigned char out32[32]; secp256k1_sha256 hash; int i; From 85e224dd97f521d704e9a2e41e686e43d90db631 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jan 2024 15:53:30 +0000 Subject: [PATCH 084/383] group: add ge_to_bytes and ge_from_bytes --- src/group.h | 8 ++++++++ src/group_impl.h | 22 ++++++++++++++++++++++ src/secp256k1.c | 16 ++-------------- src/tests.c | 18 ++++++++++++++++++ 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/group.h b/src/group.h index d81deb42..0f5ec6fe 100644 --- a/src/group.h +++ b/src/group.h @@ -174,6 +174,14 @@ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_g /** Rescale a jacobian point by b which must be non-zero. Constant-time. */ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); +/** Convert a group element that is not infinity to a 64-byte array. The output + * array is platform-dependent. */ +static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a); + +/** Convert a 64-byte array into group element. This function assumes that the + * provided buffer correctly encodes a group element. */ +static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf); + /** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve. * * In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the diff --git a/src/group_impl.h b/src/group_impl.h index 537be32f..cb390ee8 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -7,6 +7,8 @@ #ifndef SECP256K1_GROUP_IMPL_H #define SECP256K1_GROUP_IMPL_H +#include + #include "field.h" #include "group.h" #include "util.h" @@ -941,4 +943,24 @@ static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp25 return secp256k1_fe_is_square_var(&r); } +static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a) { + secp256k1_ge_storage s; + + /* We require that the secp256k1_ge_storage type is exactly 64 bytes. + * This is formally not guaranteed by the C standard, but should hold on any + * sane compiler in the real world. */ + STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64); + VERIFY_CHECK(!secp256k1_ge_is_infinity(a)); + secp256k1_ge_to_storage(&s, a); + memcpy(buf, &s, 64); +} + +static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf) { + secp256k1_ge_storage s; + + STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64); + memcpy(&s, buf, 64); + secp256k1_ge_from_storage(r, &s); +} + #endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/src/secp256k1.c b/src/secp256k1.c index 72d725a7..8821718a 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -238,25 +238,13 @@ static SECP256K1_INLINE void secp256k1_declassify(const secp256k1_context* ctx, } static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { - secp256k1_ge_storage s; - - /* We require that the secp256k1_ge_storage type is exactly 64 bytes. - * This is formally not guaranteed by the C standard, but should hold on any - * sane compiler in the real world. */ - STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64); - memcpy(&s, &pubkey->data[0], 64); - secp256k1_ge_from_storage(ge, &s); + secp256k1_ge_from_bytes(ge, pubkey->data); ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); return 1; } static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { - secp256k1_ge_storage s; - - STATIC_ASSERT(sizeof(secp256k1_ge_storage) == 64); - VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); - secp256k1_ge_to_storage(&s, ge); - memcpy(&pubkey->data[0], &s, 64); + secp256k1_ge_to_bytes(pubkey->data, ge); } int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { diff --git a/src/tests.c b/src/tests.c index 70c15f87..502161e9 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3982,6 +3982,23 @@ static void test_add_neg_y_diff_x(void) { CHECK(secp256k1_gej_eq_ge_var(&sumj, &res)); } +static void test_ge_bytes(void) { + int i; + + for (i = 0; i < COUNT; i++) { + unsigned char buf[64]; + secp256k1_ge p, q; + + testutil_random_ge_test(&p); + + if (!secp256k1_ge_is_infinity(&p)) { + secp256k1_ge_to_bytes(buf, &p); + secp256k1_ge_from_bytes(&q, buf); + CHECK(secp256k1_ge_eq_var(&p, &q)); + } + } +} + static void run_ge(void) { int i; for (i = 0; i < COUNT * 32; i++) { @@ -3989,6 +4006,7 @@ static void run_ge(void) { } test_add_neg_y_diff_x(); test_intialized_inf(); + test_ge_bytes(); } static void test_gej_cmov(const secp256k1_gej *a, const secp256k1_gej *b) { From 421ed1b46ff018f33a497df913a11d20f8dd1acc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 2 Sep 2024 21:41:03 +0100 Subject: [PATCH 085/383] cmake: Introduce `SECP256K1_APPEND_LDFLAGS` variable Downstream projects may include libsecp test executables in their test suites. In such cases, if a `-fsanitize=...` flag is passed via the `SECP256K1_APPEND_CFLAGS` variable, the same flag must also be passed to the linker. --- CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ca8cbe8..d5a7a2de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,6 +276,14 @@ if(SECP256K1_APPEND_CFLAGS) string(APPEND CMAKE_C_COMPILE_OBJECT " ${SECP256K1_APPEND_CFLAGS}") endif() +set(SECP256K1_APPEND_LDFLAGS "" CACHE STRING "Linker flags that are appended to the command line after all other flags added by the build system. This variable is intended for debugging and special builds.") +if(SECP256K1_APPEND_LDFLAGS) + # Appending to this low-level rule variable is the only way to + # guarantee that the flags appear at the end of the command line. + string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " ${SECP256K1_APPEND_LDFLAGS}") + string(APPEND CMAKE_C_LINK_EXECUTABLE " ${SECP256K1_APPEND_LDFLAGS}") +endif() + add_subdirectory(src) if(SECP256K1_BUILD_EXAMPLES) add_subdirectory(examples) @@ -355,6 +363,9 @@ endif() if(SECP256K1_APPEND_CFLAGS) message("SECP256K1_APPEND_CFLAGS ............... ${SECP256K1_APPEND_CFLAGS}") endif() +if(SECP256K1_APPEND_LDFLAGS) + message("SECP256K1_APPEND_LDFLAGS .............. ${SECP256K1_APPEND_LDFLAGS}") +endif() message("") if(print_msan_notice) message( From 292310fbb24bba324fdf3c47c90e5e576a3cb89d Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 9 Sep 2024 12:07:21 +0200 Subject: [PATCH 086/383] doc: fix typos in `secp256k1_ecdsa_{recoverable_,}signature` API description --- include/secp256k1.h | 2 +- include/secp256k1_recovery.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index cfbdd528..94a9a7a3 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -75,7 +75,7 @@ typedef struct { unsigned char data[64]; } secp256k1_pubkey; -/** Opaque data structured that holds a parsed ECDSA signature. +/** Opaque data structure that holds a parsed ECDSA signature. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is diff --git a/include/secp256k1_recovery.h b/include/secp256k1_recovery.h index 341b8bac..78a3eee0 100644 --- a/include/secp256k1_recovery.h +++ b/include/secp256k1_recovery.h @@ -7,7 +7,7 @@ extern "C" { #endif -/** Opaque data structured that holds a parsed ECDSA signature, +/** Opaque data structure that holds a parsed ECDSA signature, * supporting pubkey recovery. * * The exact representation of data inside is implementation defined and not From 447334cb06de229024161021cc79b3af32ce8b5c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sat, 24 Aug 2024 23:28:52 +0200 Subject: [PATCH 087/383] include: Avoid visibility("default") on Windows Fixes #1421. --- include/secp256k1.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index cfbdd528..41420ccf 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -147,6 +147,15 @@ typedef int (*secp256k1_nonce_function)( * 1. If using Libtool, it defines DLL_EXPORT automatically. * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */ # define SECP256K1_API extern __declspec (dllexport) +# else + /* Building libsecp256k1 as a static library on Windows. + * No declspec is needed, and so we would want the non-Windows-specific + * logic below take care of this case. However, this may result in setting + * __attribute__ ((visibility("default"))), which is supposed to be a noop + * on Windows but may trigger warnings when compiling with -flto due to a + * bug in GCC, see + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */ +# define SECP256K1_API extern # endif /* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static * library on Windows. */ @@ -156,11 +165,12 @@ typedef int (*secp256k1_nonce_function)( # endif #endif #ifndef SECP256K1_API +/* All cases not captured by the Windows-specific logic. */ # if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD) - /* Building libsecp256k1 on non-Windows using GCC or compatible. */ + /* Building libsecp256k1 using GCC or compatible. */ # define SECP256K1_API extern __attribute__ ((visibility ("default"))) # else - /* All cases not captured above. */ + /* Fall back to standard C's extern. */ # define SECP256K1_API extern # endif #endif From 26e4a7c2146d581af47f02fc69e0728c7adb3bd8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:29:50 +0100 Subject: [PATCH 088/383] cmake: Set top-level target output locations This change: 1. Collects build artifacts in dedicated locations. 2. Allows to run individual examples with a shared library on Windows. 3. Is compatible with Wine when testing cross-compiled Windows binaries on Linux. 4. Is compatible with integration the project into a larger project hierarchy. --- .github/workflows/ci.yml | 8 ++++---- CMakeLists.txt | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fc104d2..71bb3e9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -751,14 +751,14 @@ jobs: # Use the bash shell included with Git for Windows. shell: bash run: | - cd build/src/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true + cd build/bin/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true - name: Check run: | ctest -C RelWithDebInfo --test-dir build -j ([int]$env:NUMBER_OF_PROCESSORS + 1) - build\src\RelWithDebInfo\bench_ecmult.exe - build\src\RelWithDebInfo\bench_internal.exe - build\src\RelWithDebInfo\bench.exe + build\bin\RelWithDebInfo\bench_ecmult.exe + build\bin\RelWithDebInfo\bench_internal.exe + build\bin\RelWithDebInfo\bench.exe win64-native-headers: name: "x64 (MSVC): C++ (public headers)" diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e2b779d..0c4798f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,6 +286,15 @@ if(SECP256K1_APPEND_LDFLAGS) string(APPEND CMAKE_C_LINK_EXECUTABLE " ${SECP256K1_APPEND_LDFLAGS}") endif() +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) +endif() +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +endif() +if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib) +endif() add_subdirectory(src) if(SECP256K1_BUILD_EXAMPLES) add_subdirectory(examples) From c232486d84e21ece78b6cc956cd233cdf1bf8eee Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:44:02 +0100 Subject: [PATCH 089/383] Revert "cmake: Set `ENVIRONMENT` property for examples on Windows" This reverts commit 116d2ab3df630455f23a7b21f50237689879ecc0. --- examples/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index fd1ebce3..a7a5adbf 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -10,13 +10,6 @@ function(add_example name) ) set(test_name ${name}_example) add_test(NAME ${test_name} COMMAND ${target_name}) - if(BUILD_SHARED_LIBS AND MSVC) - # The DLL must reside either in the same folder where the executable is - # or somewhere in PATH. Using the latter option. - set_tests_properties(${test_name} PROPERTIES - ENVIRONMENT "PATH=$;$ENV{PATH}" - ) - endif() endfunction() add_example(ecdsa) From ef7ff03407fa79e7eab1b6771b77f72828e63636 Mon Sep 17 00:00:00 2001 From: Russell O'Connor Date: Wed, 25 Sep 2024 11:05:23 -0400 Subject: [PATCH 090/383] f can never equal -m In fact, before reaching this particular VERIFY_CHECK, we had already successfully passed through VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ ensuring that f is not -m. --- src/modinv32_impl.h | 10 ++++------ src/modinv64_impl.h | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/modinv32_impl.h b/src/modinv32_impl.h index 75eb354f..981d2abc 100644 --- a/src/modinv32_impl.h +++ b/src/modinv32_impl.h @@ -565,13 +565,12 @@ static void secp256k1_modinv32(secp256k1_modinv32_signed30 *x, const secp256k1_m /* g == 0 */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, 9, &SECP256K1_SIGNED30_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, -1) == 0 || secp256k1_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, 1) == 0 || (secp256k1_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && secp256k1_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - (secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) == 0 || - secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) == 0))); + secp256k1_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ secp256k1_modinv32_normalize_30(&d, f.v[8], modinfo); @@ -643,13 +642,12 @@ static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256 /* g == 0 */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&g, len, &SECP256K1_SIGNED30_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ VERIFY_CHECK(secp256k1_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, -1) == 0 || secp256k1_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, 1) == 0 || (secp256k1_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && secp256k1_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - (secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) == 0 || - secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) == 0))); + secp256k1_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ secp256k1_modinv32_normalize_30(&d, f.v[len - 1], modinfo); diff --git a/src/modinv64_impl.h b/src/modinv64_impl.h index 0dc1e806..548787be 100644 --- a/src/modinv64_impl.h +++ b/src/modinv64_impl.h @@ -621,13 +621,12 @@ static void secp256k1_modinv64(secp256k1_modinv64_signed62 *x, const secp256k1_m /* g == 0 */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, 5, &SECP256K1_SIGNED62_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, -1) == 0 || secp256k1_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, 1) == 0 || (secp256k1_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && secp256k1_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - (secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) == 0 || - secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) == 0))); + secp256k1_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ secp256k1_modinv64_normalize_62(&d, f.v[4], modinfo); @@ -698,13 +697,12 @@ static void secp256k1_modinv64_var(secp256k1_modinv64_signed62 *x, const secp256 /* g == 0 */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&g, len, &SECP256K1_SIGNED62_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ VERIFY_CHECK(secp256k1_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, -1) == 0 || secp256k1_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, 1) == 0 || (secp256k1_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && secp256k1_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - (secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) == 0 || - secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) == 0))); + secp256k1_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ secp256k1_modinv64_normalize_62(&d, f.v[len - 1], modinfo); From c8fbdb1b9720bb78270319e34d6422587daf31b3 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 5 Jun 2024 13:48:21 +0000 Subject: [PATCH 091/383] group: add ge_to_bytes_ext and ge_from_bytes_ext --- src/group.h | 8 ++++++++ src/group_impl.h | 17 +++++++++++++++++ src/tests.c | 15 +++++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/group.h b/src/group.h index 0f5ec6fe..992ff5c9 100644 --- a/src/group.h +++ b/src/group.h @@ -182,6 +182,14 @@ static void secp256k1_ge_to_bytes(unsigned char *buf, const secp256k1_ge *a); * provided buffer correctly encodes a group element. */ static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf); +/** Convert a group element (that is allowed to be infinity) to a 64-byte + * array. The output array is platform-dependent. */ +static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge); + +/** Convert a 64-byte array into a group element. This function assumes that the + * provided buffer is the output of secp256k1_ge_to_bytes_ext. */ +static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data); + /** Determine if a point (which is assumed to be on the curve) is in the correct (sub)group of the curve. * * In normal mode, the used group is secp256k1, which has cofactor=1 meaning that every point on the curve is in the diff --git a/src/group_impl.h b/src/group_impl.h index cb390ee8..2e096f41 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -963,4 +963,21 @@ static void secp256k1_ge_from_bytes(secp256k1_ge *r, const unsigned char *buf) { secp256k1_ge_from_storage(r, &s); } +static void secp256k1_ge_to_bytes_ext(unsigned char *data, const secp256k1_ge *ge) { + if (secp256k1_ge_is_infinity(ge)) { + memset(data, 0, 64); + } else { + secp256k1_ge_to_bytes(data, ge); + } +} + +static void secp256k1_ge_from_bytes_ext(secp256k1_ge *ge, const unsigned char *data) { + static const unsigned char zeros[64] = { 0 }; + if (secp256k1_memcmp_var(data, zeros, sizeof(zeros)) == 0) { + secp256k1_ge_set_infinity(ge); + } else { + secp256k1_ge_from_bytes(ge, data); + } +} + #endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/src/tests.c b/src/tests.c index 502161e9..935a03eb 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3985,17 +3985,28 @@ static void test_add_neg_y_diff_x(void) { static void test_ge_bytes(void) { int i; - for (i = 0; i < COUNT; i++) { + for (i = 0; i < COUNT + 1; i++) { unsigned char buf[64]; secp256k1_ge p, q; - testutil_random_ge_test(&p); + if (i == 0) { + secp256k1_ge_set_infinity(&p); + } else { + testutil_random_ge_test(&p); + } if (!secp256k1_ge_is_infinity(&p)) { secp256k1_ge_to_bytes(buf, &p); + secp256k1_ge_from_bytes(&q, buf); CHECK(secp256k1_ge_eq_var(&p, &q)); + + secp256k1_ge_from_bytes_ext(&q, buf); + CHECK(secp256k1_ge_eq_var(&p, &q)); } + secp256k1_ge_to_bytes_ext(buf, &p); + secp256k1_ge_from_bytes_ext(&q, buf); + CHECK(secp256k1_ge_eq_var(&p, &q)); } } From 0be79660f388df612f2ddbf3f82122e9a35ec02f Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 25 Sep 2024 16:03:14 +0000 Subject: [PATCH 092/383] util: add constant-time is_zero_array function --- src/tests.c | 13 +++++++++++++ src/util.h | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/tests.c b/src/tests.c index 935a03eb..544ad763 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7467,6 +7467,18 @@ static void run_secp256k1_memczero_test(void) { CHECK(secp256k1_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); } + +static void run_secp256k1_is_zero_array_test(void) { + unsigned char buf1[3] = {0, 1}; + unsigned char buf2[3] = {1, 0}; + + CHECK(secp256k1_is_zero_array(buf1, 0) == 1); + CHECK(secp256k1_is_zero_array(buf1, 1) == 1); + CHECK(secp256k1_is_zero_array(buf1, 2) == 0); + CHECK(secp256k1_is_zero_array(buf2, 1) == 0); + CHECK(secp256k1_is_zero_array(buf2, 2) == 0); +} + static void run_secp256k1_byteorder_tests(void) { { const uint32_t x = 0xFF03AB45; @@ -7806,6 +7818,7 @@ int main(int argc, char **argv) { /* util tests */ run_secp256k1_memczero_test(); + run_secp256k1_is_zero_array_test(); run_secp256k1_byteorder_tests(); run_cmov_tests(); diff --git a/src/util.h b/src/util.h index ca73752c..49af867a 100644 --- a/src/util.h +++ b/src/util.h @@ -239,6 +239,22 @@ static SECP256K1_INLINE int secp256k1_memcmp_var(const void *s1, const void *s2, return 0; } +/* Return 1 if all elements of array s are 0 and otherwise return 0. + * Constant-time. */ +static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size_t len) { + unsigned char acc = 0; + int ret; + size_t i; + + for (i = 0; i < len; i++) { + acc |= s[i]; + } + ret = (acc == 0); + /* acc may contain secret values. Try to explicitly clear it. */ + acc = 0; + return ret; +} + /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) { unsigned int mask0, mask1, r_masked, a_masked; From f411841a46b15aac6e7c403fc740e9c056cfe0a2 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jan 2024 19:31:18 +0000 Subject: [PATCH 093/383] Add module "musig" that implements MuSig2 multi-signatures (BIP 327) --- .cirrus.yml | 3 + .github/workflows/ci.yml | 37 +- .gitignore | 1 + CHANGELOG.md | 6 + Makefile.am | 15 + README.md | 1 + ci/ci.sh | 3 +- configure.ac | 14 + doc/musig.md | 54 ++ examples/musig.c | 257 ++++++ include/secp256k1_musig.h | 588 +++++++++++++ src/ctime_tests.c | 57 ++ src/modules/musig/Makefile.am.include | 8 + src/modules/musig/keyagg.h | 32 + src/modules/musig/keyagg_impl.h | 291 +++++++ src/modules/musig/main_impl.h | 12 + src/modules/musig/session.h | 24 + src/modules/musig/session_impl.h | 815 ++++++++++++++++++ src/modules/musig/tests_impl.h | 1143 +++++++++++++++++++++++++ src/modules/musig/vectors.h | 346 ++++++++ src/secp256k1.c | 4 + src/tests.c | 8 + tools/test_vectors_musig2_generate.py | 656 ++++++++++++++ 23 files changed, 4361 insertions(+), 14 deletions(-) create mode 100644 doc/musig.md create mode 100644 examples/musig.c create mode 100644 include/secp256k1_musig.h create mode 100644 src/modules/musig/Makefile.am.include create mode 100644 src/modules/musig/keyagg.h create mode 100644 src/modules/musig/keyagg_impl.h create mode 100644 src/modules/musig/main_impl.h create mode 100644 src/modules/musig/session.h create mode 100644 src/modules/musig/session_impl.h create mode 100644 src/modules/musig/tests_impl.h create mode 100644 src/modules/musig/vectors.h create mode 100755 tools/test_vectors_musig2_generate.py diff --git a/.cirrus.yml b/.cirrus.yml index 0c1e01dc..ae4236e0 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -22,6 +22,7 @@ env: RECOVERY: no EXTRAKEYS: no SCHNORRSIG: no + MUSIG: no ELLSWIFT: no ### test options SECP256K1_TEST_ITERS: @@ -69,6 +70,7 @@ task: RECOVERY: yes EXTRAKEYS: yes SCHNORRSIG: yes + MUSIG: yes ELLSWIFT: yes matrix: # Currently only gcc-snapshot, the other compilers are tested on GHA with QEMU @@ -86,6 +88,7 @@ task: RECOVERY: yes EXTRAKEYS: yes SCHNORRSIG: yes + MUSIG: yes ELLSWIFT: yes WRAPPER_CMD: 'valgrind --error-exitcode=42' SECP256K1_TEST_ITERS: 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fc104d2..3d50b36d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,7 @@ env: RECOVERY: 'no' EXTRAKEYS: 'no' SCHNORRSIG: 'no' + MUSIG: 'no' ELLSWIFT: 'no' ### test options SECP256K1_TEST_ITERS: @@ -72,18 +73,18 @@ jobs: matrix: configuration: - env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' } - - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { WIDEMUL: 'int128' } - env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' } - - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes' } + - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' } - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' } - - env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes' } - - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', CPPFLAGS: '-DVERIFY' } + - env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' } + - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', CPPFLAGS: '-DVERIFY' } - env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' } - env_vars: { CPPFLAGS: '-DDETERMINISTIC' } - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' } - - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 } - env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 } cc: @@ -142,6 +143,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CC: ${{ matrix.cc }} @@ -187,6 +189,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -239,6 +242,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -285,6 +289,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -341,6 +346,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -394,6 +400,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' SECP256K1_TEST_ITERS: 2 @@ -446,6 +453,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' CFLAGS: '-fsanitize=undefined,address -g' @@ -511,6 +519,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CC: 'clang' SECP256K1_TEST_ITERS: 32 @@ -558,6 +567,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -615,15 +625,15 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { 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 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } - BUILD: 'distcheck' steps: @@ -790,6 +800,7 @@ jobs: RECOVERY: 'yes' EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' steps: diff --git a/.gitignore b/.gitignore index 18e3259f..bffba8cb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ ecdh_example ecdsa_example schnorr_example ellswift_example +musig_example *.exe *.so *.a diff --git a/CHANGELOG.md b/CHANGELOG.md index fb829406..2f2e0f53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Added + - New module `musig` implements the MuSig2 multisignature scheme according to the [BIP 327 specification](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). See: + - Header file `include/secp256k1_musig.h` which defines the new API. + - Document `doc/musig.md` for further notes on API usage. + - Usage example `examples/musig.c`. + ## [0.5.1] - 2024-08-01 #### Added diff --git a/Makefile.am b/Makefile.am index 8723b53b..a4c8d33d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -195,6 +195,17 @@ ellswift_example_LDFLAGS += -lbcrypt endif TESTS += ellswift_example endif +if ENABLE_MODULE_MUSIG +noinst_PROGRAMS += musig_example +musig_example_SOURCES = examples/musig.c +musig_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC +musig_example_LDADD = libsecp256k1.la +musig_example_LDFLAGS = -static +if BUILD_WINDOWS +musig_example_LDFLAGS += -lbcrypt +endif +TESTS += musig_example +endif endif ### Precomputed tables @@ -281,6 +292,10 @@ if ENABLE_MODULE_SCHNORRSIG include src/modules/schnorrsig/Makefile.am.include endif +if ENABLE_MODULE_MUSIG +include src/modules/musig/Makefile.am.include +endif + if ENABLE_MODULE_ELLSWIFT include src/modules/ellswift/Makefile.am.include endif diff --git a/README.md b/README.md index ed93e051..222e5fb7 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Features: * Optional module for ECDH key exchange. * Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). * Optional module for ElligatorSwift key exchange according to [BIP-324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki). +* Optional module for MuSig2 Schnorr multi-signatures according to [BIP-327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). Implementation details ---------------------- diff --git a/ci/ci.sh b/ci/ci.sh index a6c608c2..3636deaf 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -13,7 +13,7 @@ print_environment() { # does not rely on bash. for var in WERROR_CFLAGS MAKEFLAGS BUILD \ ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ - EXPERIMENTAL ECDH RECOVERY EXTRAKEYS SCHNORRSIG ELLSWIFT \ + EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ EXAMPLES \ HOST WRAPPER_CMD \ @@ -79,6 +79,7 @@ esac --enable-module-ellswift="$ELLSWIFT" \ --enable-module-extrakeys="$EXTRAKEYS" \ --enable-module-schnorrsig="$SCHNORRSIG" \ + --enable-module-musig="$MUSIG" \ --enable-examples="$EXAMPLES" \ --enable-ctime-tests="$CTIMETESTS" \ --with-valgrind="$WITH_VALGRIND" \ diff --git a/configure.ac b/configure.ac index 6841543f..dca1e662 100644 --- a/configure.ac +++ b/configure.ac @@ -184,6 +184,10 @@ AC_ARG_ENABLE(module_schnorrsig, AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module [default=yes]]), [], [SECP_SET_DEFAULT([enable_module_schnorrsig], [yes], [yes])]) +AC_ARG_ENABLE(module_musig, + AS_HELP_STRING([--enable-module-musig],[enable MuSig2 module [default=yes]]), [], + [SECP_SET_DEFAULT([enable_module_musig], [yes], [yes])]) + AC_ARG_ENABLE(module_ellswift, AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [], [SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])]) @@ -398,6 +402,14 @@ if test x"$enable_module_ellswift" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1" fi +if test x"$enable_module_musig" = x"yes"; then + if test x"$enable_module_schnorrsig" = x"no"; then + AC_MSG_ERROR([Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.]) + fi + enable_module_schnorrsig=yes + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_MUSIG=1" +fi + if test x"$enable_module_schnorrsig" = x"yes"; then if test x"$enable_module_extrakeys" = x"no"; then AC_MSG_ERROR([Module dependency error: You have disabled the extrakeys module explicitly, but it is required by the schnorrsig module.]) @@ -449,6 +461,7 @@ AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"]) AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"]) AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"]) @@ -471,6 +484,7 @@ echo " module ecdh = $enable_module_ecdh" echo " module recovery = $enable_module_recovery" echo " module extrakeys = $enable_module_extrakeys" echo " module schnorrsig = $enable_module_schnorrsig" +echo " module musig = $enable_module_musig" echo " module ellswift = $enable_module_ellswift" echo echo " asm = $set_asm" diff --git a/doc/musig.md b/doc/musig.md new file mode 100644 index 00000000..ae21f9b1 --- /dev/null +++ b/doc/musig.md @@ -0,0 +1,54 @@ +Notes on the musig module API +=========================== + +The following sections contain additional notes on the API of the musig module (`include/secp256k1_musig.h`). +A usage example can be found in `examples/musig.c`. + +## API misuse + +The musig API is designed with a focus on misuse resistance. +However, due to the interactive nature of the MuSig protocol, there are additional failure modes that are not present in regular (single-party) Schnorr signature creation. +While the results can be catastrophic (e.g. leaking of the secret key), it is unfortunately not possible for the musig implementation to prevent all such failure modes. + +Therefore, users of the musig module must take great care to make sure of the following: + +1. A unique nonce per signing session is generated in `secp256k1_musig_nonce_gen`. + See the corresponding comment in `include/secp256k1_musig.h` for how to ensure that. +2. The `secp256k1_musig_secnonce` structure is never copied or serialized. + See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`. +3. Opaque data structures are never written to or read from directly. + Instead, only the provided accessor functions are used. + +## Key Aggregation and (Taproot) Tweaking + +Given a set of public keys, the aggregate public key is computed with `secp256k1_musig_pubkey_agg`. +A plain tweak can be added to the resulting public key with `secp256k1_ec_pubkey_tweak_add` by setting the `tweak32` argument to the hash defined in BIP 32. Similarly, a Taproot tweak can be added with `secp256k1_xonly_pubkey_tweak_add` by setting the `tweak32` argument to the TapTweak hash defined in BIP 341. +Both types of tweaking can be combined and invoked multiple times if the specific application requires it. + +## Signing + +This is covered by `examples/musig.c`. +Essentially, the protocol proceeds in the following steps: + +1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key with `secp256k1_keypair_pub`. +2. Call `secp256k1_musig_pubkey_agg` with the pubkeys of all participants. +3. Optionally add a (Taproot) tweak with `secp256k1_musig_pubkey_xonly_tweak_add` and a plain tweak with `secp256k1_musig_pubkey_ec_tweak_add`. +4. Generate a pair of secret and public nonce with `secp256k1_musig_nonce_gen` and send the public nonce to the other signers. +5. Someone (not necessarily the signer) aggregates the public nonces with `secp256k1_musig_nonce_agg` and sends it to the signers. +6. Process the aggregate nonce with `secp256k1_musig_nonce_process`. +7. Create a partial signature with `secp256k1_musig_partial_sign`. +8. Verify the partial signatures (optional in some scenarios) with `secp256k1_musig_partial_sig_verify`. +9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_musig_partial_sig_agg`. + +The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. + +Steps 1 through 5 above can occur before or after the signers are aware of the message to be signed. +Whenever possible, it is recommended to generate the nonces only after the message is known. +This provides enhanced defense-in-depth measures, protecting against potential API misuse in certain scenarios. +However, it does require two rounds of communication during the signing process. +The alternative, generating the nonces in a pre-processing step before the message is known, eliminates these additional protective measures but allows for non-interactive signing. +Similarly, the API supports an alternative protocol flow where generating the aggregate key (steps 1 to 3) is allowed to happen after exchanging nonces (steps 4 to 5). + +## Verification + +A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. diff --git a/examples/musig.c b/examples/musig.c new file mode 100644 index 00000000..396dbb9f --- /dev/null +++ b/examples/musig.c @@ -0,0 +1,257 @@ +/************************************************************************* + * To the extent possible under law, the author(s) have dedicated all * + * copyright and related and neighboring rights to the software in this * + * file to the public domain worldwide. This software is distributed * + * without any warranty. For the CC0 Public Domain Dedication, see * + * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * + *************************************************************************/ + +/** This file demonstrates how to use the MuSig module to create a + * 3-of-3 multisignature. Additionally, see the documentation in + * include/secp256k1_musig.h and doc/musig.md. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "examples_util.h" + +struct signer_secrets { + secp256k1_keypair keypair; + secp256k1_musig_secnonce secnonce; +}; + +struct signer { + secp256k1_pubkey pubkey; + secp256k1_musig_pubnonce pubnonce; + secp256k1_musig_partial_sig partial_sig; +}; + + /* Number of public keys involved in creating the aggregate signature */ +#define N_SIGNERS 3 +/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */ +static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { + unsigned char seckey[32]; + while (1) { + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 0; + } + if (secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) { + break; + } + } + if (!secp256k1_keypair_pub(ctx, &signer->pubkey, &signer_secrets->keypair)) { + return 0; + } + + secure_erase(seckey, sizeof(seckey)); + return 1; +} + +/* Tweak the pubkey corresponding to the provided keyagg cache, update the cache + * and return the tweaked aggregate pk. */ +static int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) { + secp256k1_pubkey output_pk; + /* For BIP 32 tweaking the plain_tweak is set to a hash as defined in BIP + * 32. */ + unsigned char plain_tweak[32] = "this could be a BIP32 tweak...."; + /* For Taproot tweaking the xonly_tweak is set to the TapTweak hash as + * defined in BIP 341 */ + unsigned char xonly_tweak[32] = "this could be a Taproot tweak.."; + + + /* Plain tweaking which, for example, allows deriving multiple child + * public keys from a single aggregate key using BIP32 */ + if (!secp256k1_musig_pubkey_ec_tweak_add(ctx, NULL, cache, plain_tweak)) { + return 0; + } + /* Note that we did not provide an output_pk argument, because the + * resulting pk is also saved in the cache and so if one is just interested + * in signing, the output_pk argument is unnecessary. On the other hand, if + * one is not interested in signing, the same output_pk can be obtained by + * calling `secp256k1_musig_pubkey_get` right after key aggregation to get + * the full pubkey and then call `secp256k1_ec_pubkey_tweak_add`. */ + + /* Xonly tweaking which, for example, allows creating Taproot commitments */ + if (!secp256k1_musig_pubkey_xonly_tweak_add(ctx, &output_pk, cache, xonly_tweak)) { + return 0; + } + /* Note that if we wouldn't care about signing, we can arrive at the same + * output_pk by providing the untweaked public key to + * `secp256k1_xonly_pubkey_tweak_add` (after converting it to an xonly pubkey + * if necessary with `secp256k1_xonly_pubkey_from_pubkey`). */ + + /* Now we convert the output_pk to an xonly pubkey to allow to later verify + * the Schnorr signature against it. For this purpose we can ignore the + * `pk_parity` output argument; we would need it if we would have to open + * the Taproot commitment. */ + if (!secp256k1_xonly_pubkey_from_pubkey(ctx, agg_pk, NULL, &output_pk)) { + return 0; + } + return 1; +} + +/* Sign a message hash with the given key pairs and store the result in sig */ +static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) { + int i; + const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS]; + const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS]; + /* The same for all signers */ + secp256k1_musig_session session; + secp256k1_musig_aggnonce agg_pubnonce; + + for (i = 0; i < N_SIGNERS; i++) { + unsigned char seckey[32]; + unsigned char session_secrand[32]; + /* Create random session ID. It is absolutely necessary that the session ID + * is unique for every call of secp256k1_musig_nonce_gen. Otherwise + * it's trivial for an attacker to extract the secret key! */ + if (!fill_random(session_secrand, sizeof(session_secrand))) { + return 0; + } + if (!secp256k1_keypair_sec(ctx, seckey, &signer_secrets[i].keypair)) { + return 0; + } + /* Initialize session and create secret nonce for signing and public + * nonce to send to the other signers. */ + if (!secp256k1_musig_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_secrand, seckey, &signer[i].pubkey, msg32, NULL, NULL)) { + return 0; + } + pubnonces[i] = &signer[i].pubnonce; + + secure_erase(seckey, sizeof(seckey)); + } + + /* Communication round 1: Every signer sends their pubnonce to the + * coordinator. The coordinator runs secp256k1_musig_nonce_agg and sends + * agg_pubnonce to each signer */ + if (!secp256k1_musig_nonce_agg(ctx, &agg_pubnonce, pubnonces, N_SIGNERS)) { + return 0; + } + + /* Every signer creates a partial signature */ + for (i = 0; i < N_SIGNERS; i++) { + /* Initialize the signing session by processing the aggregate nonce */ + if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache)) { + return 0; + } + /* partial_sign will clear the secnonce by setting it to 0. That's because + * you must _never_ reuse the secnonce (or use the same session_secrand to + * create a secnonce). If you do, you effectively reuse the nonce and + * leak the secret key. */ + if (!secp256k1_musig_partial_sign(ctx, &signer[i].partial_sig, &signer_secrets[i].secnonce, &signer_secrets[i].keypair, cache, &session)) { + return 0; + } + partial_sigs[i] = &signer[i].partial_sig; + } + /* Communication round 2: Every signer sends their partial signature to the + * coordinator, who verifies the partial signatures and aggregates them. */ + for (i = 0; i < N_SIGNERS; i++) { + /* To check whether signing was successful, it suffices to either verify + * the aggregate signature with the aggregate public key using + * secp256k1_schnorrsig_verify, or verify all partial signatures of all + * signers individually. Verifying the aggregate signature is cheaper but + * verifying the individual partial signatures has the advantage that it + * can be used to determine which of the partial signatures are invalid + * (if any), i.e., which of the partial signatures cause the aggregate + * signature to be invalid and thus the protocol run to fail. It's also + * fine to first verify the aggregate sig, and only verify the individual + * sigs if it does not work. + */ + if (!secp256k1_musig_partial_sig_verify(ctx, &signer[i].partial_sig, &signer[i].pubnonce, &signer[i].pubkey, cache, &session)) { + return 0; + } + } + return secp256k1_musig_partial_sig_agg(ctx, sig64, &session, partial_sigs, N_SIGNERS); +} + +int main(void) { + secp256k1_context* ctx; + int i; + struct signer_secrets signer_secrets[N_SIGNERS]; + struct signer signers[N_SIGNERS]; + const secp256k1_pubkey *pubkeys_ptr[N_SIGNERS]; + secp256k1_xonly_pubkey agg_pk; + secp256k1_musig_keyagg_cache cache; + unsigned char msg[32] = "this_could_be_the_hash_of_a_msg"; + unsigned char sig[64]; + + /* Create a secp256k1 context */ + ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + printf("Creating key pairs......"); + fflush(stdout); + for (i = 0; i < N_SIGNERS; i++) { + if (!create_keypair(ctx, &signer_secrets[i], &signers[i])) { + printf("FAILED\n"); + return 1; + } + pubkeys_ptr[i] = &signers[i].pubkey; + } + printf("ok\n"); + + /* The aggregate public key produced by secp256k1_musig_pubkey_agg depends + * on the order of the provided public keys. If there is no canonical order + * of the signers, the individual public keys can optionally be sorted with + * secp256k1_ec_pubkey_sort to ensure that the aggregate public key is + * independent of the order of signers. */ + printf("Sorting public keys....."); + fflush(stdout); + if (!secp256k1_ec_pubkey_sort(ctx, pubkeys_ptr, N_SIGNERS)) { + printf("FAILED\n"); + return 1; + } + printf("ok\n"); + + printf("Combining public keys..."); + fflush(stdout); + /* If you just want to aggregate and not sign, you can call + * secp256k1_musig_pubkey_agg with the keyagg_cache argument set to NULL + * while providing a non-NULL agg_pk argument. */ + if (!secp256k1_musig_pubkey_agg(ctx, NULL, &cache, pubkeys_ptr, N_SIGNERS)) { + printf("FAILED\n"); + return 1; + } + printf("ok\n"); + printf("Tweaking................"); + fflush(stdout); + /* Optionally tweak the aggregate key */ + if (!tweak(ctx, &agg_pk, &cache)) { + printf("FAILED\n"); + return 1; + } + printf("ok\n"); + printf("Signing message........."); + fflush(stdout); + if (!sign(ctx, signer_secrets, signers, &cache, msg, sig)) { + printf("FAILED\n"); + return 1; + } + printf("ok\n"); + printf("Verifying signature....."); + fflush(stdout); + if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) { + printf("FAILED\n"); + return 1; + } + printf("ok\n"); + + /* It's best practice to try to clear secrets from memory after using them. + * This is done because some bugs can allow an attacker to leak memory, for + * example through "out of bounds" array access (see Heartbleed), or the OS + * swapping them to disk. Hence, we overwrite secret key material with zeros. + * + * Here we are preventing these writes from being optimized out, as any good compiler + * will remove any writes that aren't used. */ + for (i = 0; i < N_SIGNERS; i++) { + secure_erase(&signer_secrets[i], sizeof(signer_secrets[i])); + } + secp256k1_context_destroy(ctx); + return 0; +} diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h new file mode 100644 index 00000000..53501814 --- /dev/null +++ b/include/secp256k1_musig.h @@ -0,0 +1,588 @@ +#ifndef SECP256K1_MUSIG_H +#define SECP256K1_MUSIG_H + +#include "secp256k1_extrakeys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** This module implements BIP 327 "MuSig2 for BIP340-compatible + * Multi-Signatures" + * (https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki) + * v1.0.0. You can find an example demonstrating the musig module in + * examples/musig.c. + * + * The module also supports BIP 341 ("Taproot") public key tweaking. + * + * It is recommended to read the documentation in this include file carefully. + * Further notes on API usage can be found in doc/musig.md + * + * Since the first version of MuSig is essentially replaced by MuSig2, we use + * MuSig, musig and MuSig2 synonymously unless noted otherwise. + */ + +/** Opaque data structures + * + * The exact representation of data inside the opaque data structures is + * implementation defined and not guaranteed to be portable between different + * platforms or versions. With the exception of `secp256k1_musig_secnonce`, the + * data structures can be safely copied/moved. If you need to convert to a + * format suitable for storage, transmission, or comparison, use the + * corresponding serialization and parsing functions. + */ + +/** Opaque data structure that caches information about public key aggregation. + * + * Guaranteed to be 197 bytes in size. No serialization and parsing functions + * (yet). + */ +typedef struct { + unsigned char data[197]; +} secp256k1_musig_keyagg_cache; + +/** Opaque data structure that holds a signer's _secret_ nonce. + * + * Guaranteed to be 132 bytes in size. + * + * WARNING: This structure MUST NOT be copied or read or written to directly. A + * signer who is online throughout the whole process and can keep this + * structure in memory can use the provided API functions for a safe standard + * workflow. + * + * Copying this data structure can result in nonce reuse which will leak the + * secret signing key. + */ +typedef struct { + unsigned char data[132]; +} secp256k1_musig_secnonce; + +/** Opaque data structure that holds a signer's public nonce. + * + * Guaranteed to be 132 bytes in size. Serialized and parsed with + * `musig_pubnonce_serialize` and `musig_pubnonce_parse`. + */ +typedef struct { + unsigned char data[132]; +} secp256k1_musig_pubnonce; + +/** Opaque data structure that holds an aggregate public nonce. + * + * Guaranteed to be 132 bytes in size. Serialized and parsed with + * `musig_aggnonce_serialize` and `musig_aggnonce_parse`. + */ +typedef struct { + unsigned char data[132]; +} secp256k1_musig_aggnonce; + +/** Opaque data structure that holds a MuSig session. + * + * This structure is not required to be kept secret for the signing protocol to + * be secure. Guaranteed to be 133 bytes in size. No serialization and parsing + * functions (yet). + */ +typedef struct { + unsigned char data[133]; +} secp256k1_musig_session; + +/** Opaque data structure that holds a partial MuSig signature. + * + * Guaranteed to be 36 bytes in size. Serialized and parsed with + * `musig_partial_sig_serialize` and `musig_partial_sig_parse`. + */ +typedef struct { + unsigned char data[36]; +} secp256k1_musig_partial_sig; + +/** Parse a signer's public nonce. + * + * Returns: 1 when the nonce could be parsed, 0 otherwise. + * Args: ctx: pointer to a context object + * Out: nonce: pointer to a nonce object + * In: in66: pointer to the 66-byte nonce to be parsed + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubnonce_parse( + const secp256k1_context *ctx, + secp256k1_musig_pubnonce *nonce, + const unsigned char *in66 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a signer's public nonce + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * Out: out66: pointer to a 66-byte array to store the serialized nonce + * In: nonce: pointer to the nonce + */ +SECP256K1_API int secp256k1_musig_pubnonce_serialize( + const secp256k1_context *ctx, + unsigned char *out66, + const secp256k1_musig_pubnonce *nonce +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse an aggregate public nonce. + * + * Returns: 1 when the nonce could be parsed, 0 otherwise. + * Args: ctx: pointer to a context object + * Out: nonce: pointer to a nonce object + * In: in66: pointer to the 66-byte nonce to be parsed + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_aggnonce_parse( + const secp256k1_context *ctx, + secp256k1_musig_aggnonce *nonce, + const unsigned char *in66 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an aggregate public nonce + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * Out: out66: pointer to a 66-byte array to store the serialized nonce + * In: nonce: pointer to the nonce + */ +SECP256K1_API int secp256k1_musig_aggnonce_serialize( + const secp256k1_context *ctx, + unsigned char *out66, + const secp256k1_musig_aggnonce *nonce +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a MuSig partial signature. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: in32: pointer to the 32-byte signature to be parsed + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_parse( + const secp256k1_context *ctx, + secp256k1_musig_partial_sig *sig, + const unsigned char *in32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a MuSig partial signature + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * Out: out32: pointer to a 32-byte array to store the serialized signature + * In: sig: pointer to the signature + */ +SECP256K1_API int secp256k1_musig_partial_sig_serialize( + const secp256k1_context *ctx, + unsigned char *out32, + const secp256k1_musig_partial_sig *sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Computes an aggregate public key and uses it to initialize a keyagg_cache + * + * Different orders of `pubkeys` result in different `agg_pk`s. + * + * Before aggregating, the pubkeys can be sorted with `secp256k1_ec_pubkey_sort` + * which ensures the same `agg_pk` result for the same multiset of pubkeys. + * This is useful to do before `pubkey_agg`, such that the order of pubkeys + * does not affect the aggregate public key. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: agg_pk: the MuSig-aggregated x-only public key. If you do not need it, + * this arg can be NULL. + * keyagg_cache: if non-NULL, pointer to a musig_keyagg_cache struct that + * is required for signing (or observing the signing session + * and verifying partial signatures). + * In: pubkeys: input array of pointers to public keys to aggregate. The order + * is important; a different order will result in a different + * aggregate public key. + * n_pubkeys: length of pubkeys array. Must be greater than 0. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_agg( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *agg_pk, + secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_pubkey * const *pubkeys, + size_t n_pubkeys +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(4); + +/** Obtain the aggregate public key from a keyagg_cache. + * + * This is only useful if you need the non-xonly public key, in particular for + * plain (non-xonly) tweaking or batch-verifying multiple key aggregations + * (not implemented). + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: agg_pk: the MuSig-aggregated public key. + * In: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by + * `musig_pubkey_agg` + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get( + const secp256k1_context *ctx, + secp256k1_pubkey *agg_pk, + const secp256k1_musig_keyagg_cache *keyagg_cache +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Apply plain "EC" tweaking to a public key in a given keyagg_cache by adding + * the generator multiplied with `tweak32` to it. This is useful for deriving + * child keys from an aggregate public key via BIP 32 where `tweak32` is set to + * a hash as defined in BIP 32. + * + * Callers are responsible for deriving `tweak32` in a way that does not reduce + * the security of MuSig (for example, by following BIP 32). + * + * The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after + * the following pseudocode buf and buf2 have identical contents (absent + * earlier failures). + * + * secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...) + * secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache) + * secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache) + * secp256k1_ec_pubkey_serialize(..., buf, ..., output_pk, ...) + * secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32) + * secp256k1_ec_pubkey_serialize(..., buf2, ..., agg_pk, ...) + * + * This function is required if you want to _sign_ for a tweaked aggregate key. + * If you are only computing a public key but not intending to create a + * signature for it, use `secp256k1_ec_pubkey_tweak_add` instead. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: output_pubkey: pointer to a public key to store the result. Will be set + * to an invalid value if this function returns 0. If you + * do not need it, this arg can be NULL. + * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by + * `musig_pubkey_agg` + * In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes + * `secp256k1_ec_seckey_verify` and is not equal to the + * secret key corresponding to the public key represented + * by keyagg_cache or its negation. For uniformly random + * 32-byte arrays the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_ec_tweak_add( + const secp256k1_context *ctx, + secp256k1_pubkey *output_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the + * generator multiplied with `tweak32` to it. This is useful for creating + * Taproot outputs where `tweak32` is set to a TapTweak hash as defined in BIP + * 341. + * + * Callers are responsible for deriving `tweak32` in a way that does not reduce + * the security of MuSig (for example, by following Taproot BIP 341). + * + * The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in + * the following pseudocode xonly_pubkey_tweak_add_check (absent earlier + * failures) returns 1. + * + * secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...) + * secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, keyagg_cache, tweak32) + * secp256k1_xonly_pubkey_serialize(..., buf, output_pk) + * secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32) + * + * This function is required if you want to _sign_ for a tweaked aggregate key. + * If you are only computing a public key but not intending to create a + * signature for it, use `secp256k1_xonly_pubkey_tweak_add` instead. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: output_pubkey: pointer to a public key to store the result. Will be set + * to an invalid value if this function returns 0. If you + * do not need it, this arg can be NULL. + * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by + * `musig_pubkey_agg` + * In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes + * `secp256k1_ec_seckey_verify` and is not equal to the + * secret key corresponding to the public key represented + * by keyagg_cache or its negation. For uniformly random + * 32-byte arrays the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add( + const secp256k1_context *ctx, + secp256k1_pubkey *output_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Starts a signing session by generating a nonce + * + * This function outputs a secret nonce that will be required for signing and a + * corresponding public nonce that is intended to be sent to other signers. + * + * MuSig differs from regular Schnorr signing in that implementers _must_ take + * special care to not reuse a nonce. This can be ensured by following these rules: + * + * 1. Each call to this function must have a UNIQUE session_secrand32 that must + * NOT BE REUSED in subsequent calls to this function and must be KEPT + * SECRET (even from other signers). + * 2. If you already know the seckey, message or aggregate public key + * cache, they can be optionally provided to derive the nonce and increase + * misuse-resistance. The extra_input32 argument can be used to provide + * additional data that does not repeat in normal scenarios, such as the + * current time. + * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility + * that it is used more than once for signing. + * + * If you don't have access to good randomness for session_secrand32, but you + * have access to a non-repeating counter, then see + * secp256k1_musig_nonce_gen_counter. + * + * Remember that nonce reuse will leak the secret key! + * Note that using the same seckey for multiple MuSig sessions is fine. + * + * Returns: 0 if the arguments are invalid and 1 otherwise + * Args: ctx: pointer to a context object (not secp256k1_context_static) + * Out: secnonce: pointer to a structure to store the secret nonce + * pubnonce: pointer to a structure to store the public nonce + * In/Out: + * session_secrand32: a 32-byte session_secrand32 as explained above. Must be unique to this + * call to secp256k1_musig_nonce_gen and must be uniformly + * random. If the function call is successful, the + * session_secrand32 buffer is invalidated to prevent reuse. + * In: + * seckey: the 32-byte secret key that will later be used for signing, if + * already known (can be NULL) + * pubkey: public key of the signer creating the nonce. The secnonce + * output of this function cannot be used to sign for any + * other public key. While the public key should correspond + * to the provided seckey, a mismatch will not cause the + * function to return 0. + * msg32: the 32-byte message that will later be signed, if already known + * (can be NULL) + * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate + * (and potentially tweaked) public key if already known + * (can be NULL) + * extra_input32: an optional 32-byte array that is input to the nonce + * derivation function (can be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen( + const secp256k1_context *ctx, + secp256k1_musig_secnonce *secnonce, + secp256k1_musig_pubnonce *pubnonce, + unsigned char *session_secrand32, + const unsigned char *seckey, + const secp256k1_pubkey *pubkey, + const unsigned char *msg32, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *extra_input32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6); + + +/** Alternative way to generate a nonce and start a signing session + * + * This function outputs a secret nonce that will be required for signing and a + * corresponding public nonce that is intended to be sent to other signers. + * + * This function differs from `secp256k1_musig_nonce_gen` by accepting a + * non-repeating counter value instead of a secret random value. This requires + * that a secret key is provided to `secp256k1_musig_nonce_gen_counter` + * (through the keypair argument), as opposed to `secp256k1_musig_nonce_gen` + * where the seckey argument is optional. + * + * MuSig differs from regular Schnorr signing in that implementers _must_ take + * special care to not reuse a nonce. This can be ensured by following these rules: + * + * 1. The nonrepeating_cnt argument must be a counter value that never repeats, + * i.e., you must never call `secp256k1_musig_nonce_gen_counter` twice with + * the same keypair and nonrepeating_cnt value. For example, this implies + * that if the same keypair is used with `secp256k1_musig_nonce_gen_counter` + * on multiple devices, none of the devices should have the same counter + * value as any other device. + * 2. If the seckey, message or aggregate public key cache is already available + * at this stage, any of these can be optionally provided, in which case + * they will be used in the derivation of the nonce and increase + * misuse-resistance. The extra_input32 argument can be used to provide + * additional data that does not repeat in normal scenarios, such as the + * current time. + * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility + * that it is used more than once for signing. + * + * Remember that nonce reuse will leak the secret key! + * Note that using the same keypair for multiple MuSig sessions is fine. + * + * Returns: 0 if the arguments are invalid and 1 otherwise + * Args: ctx: pointer to a context object (not secp256k1_context_static) + * Out: secnonce: pointer to a structure to store the secret nonce + * pubnonce: pointer to a structure to store the public nonce + * In: + * nonrepeating_cnt: the value of a counter as explained above. Must be + * unique to this call to secp256k1_musig_nonce_gen. + * keypair: keypair of the signer creating the nonce. The secnonce + * output of this function cannot be used to sign for any + * other keypair. + * msg32: the 32-byte message that will later be signed, if already known + * (can be NULL) + * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate + * (and potentially tweaked) public key if already known + * (can be NULL) + * extra_input32: an optional 32-byte array that is input to the nonce + * derivation function (can be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen_counter( + const secp256k1_context *ctx, + secp256k1_musig_secnonce *secnonce, + secp256k1_musig_pubnonce *pubnonce, + uint64_t nonrepeating_cnt, + const secp256k1_keypair *keypair, + const unsigned char *msg32, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *extra_input32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); + +/** Aggregates the nonces of all signers into a single nonce + * + * This can be done by an untrusted party to reduce the communication + * between signers. Instead of everyone sending nonces to everyone else, there + * can be one party receiving all nonces, aggregating the nonces with this + * function and then sending only the aggregate nonce back to the signers. + * + * If the aggregator does not compute the aggregate nonce correctly, the final + * signature will be invalid. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: aggnonce: pointer to an aggregate public nonce object for + * musig_nonce_process + * In: pubnonces: array of pointers to public nonces sent by the + * signers + * n_pubnonces: number of elements in the pubnonces array. Must be + * greater than 0. + */ +SECP256K1_API int secp256k1_musig_nonce_agg( + const secp256k1_context *ctx, + secp256k1_musig_aggnonce *aggnonce, + const secp256k1_musig_pubnonce * const *pubnonces, + size_t n_pubnonces +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Takes the aggregate nonce and creates a session that is required for signing + * and verification of partial signatures. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: session: pointer to a struct to store the session + * In: aggnonce: pointer to an aggregate public nonce object that is the + * output of musig_nonce_agg + * msg32: the 32-byte message to sign + * keyagg_cache: pointer to the keyagg_cache that was used to create the + * aggregate (and potentially tweaked) pubkey + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process( + const secp256k1_context *ctx, + secp256k1_musig_session *session, + const secp256k1_musig_aggnonce *aggnonce, + const unsigned char *msg32, + const secp256k1_musig_keyagg_cache *keyagg_cache +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); + +/** Produces a partial signature + * + * This function overwrites the given secnonce with zeros and will abort if given a + * secnonce that is all zeros. This is a best effort attempt to protect against nonce + * reuse. However, this is of course easily defeated if the secnonce has been + * copied (or serialized). Remember that nonce reuse will leak the secret key! + * + * For signing to succeed, the secnonce provided to this function must have + * been generated for the provided keypair. This means that when signing for a + * keypair consisting of a seckey and pubkey, the secnonce must have been + * created by calling musig_nonce_gen with that pubkey. Otherwise, the + * illegal_callback is called. + * + * This function does not verify the output partial signature, deviating from + * the BIP 327 specification. It is recommended to verify the output partial + * signature with `secp256k1_musig_partial_sig_verify` to prevent random or + * adversarially provoked computation errors. + * + * Returns: 0 if the arguments are invalid or the provided secnonce has already + * been used for signing, 1 otherwise + * Args: ctx: pointer to a context object + * Out: partial_sig: pointer to struct to store the partial signature + * In/Out: secnonce: pointer to the secnonce struct created in + * musig_nonce_gen that has been never used in a + * partial_sign call before and has been created for the + * keypair + * In: keypair: pointer to keypair to sign the message with + * keyagg_cache: pointer to the keyagg_cache that was output when the + * aggregate public key for this session + * session: pointer to the session that was created with + * musig_nonce_process + */ +SECP256K1_API int secp256k1_musig_partial_sign( + const secp256k1_context *ctx, + secp256k1_musig_partial_sig *partial_sig, + secp256k1_musig_secnonce *secnonce, + const secp256k1_keypair *keypair, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_musig_session *session +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); + +/** Verifies an individual signer's partial signature + * + * The signature is verified for a specific signing session. In order to avoid + * accidentally verifying a signature from a different or non-existing signing + * session, you must ensure the following: + * 1. The `keyagg_cache` argument is identical to the one used to create the + * `session` with `musig_nonce_process`. + * 2. The `pubkey` argument must be identical to the one sent by the signer + * before aggregating it with `musig_pubkey_agg` to create the + * `keyagg_cache`. + * 3. The `pubnonce` argument must be identical to the one sent by the signer + * before aggregating it with `musig_nonce_agg` and using the result to + * create the `session` with `musig_nonce_process`. + * + * It is not required to call this function in regular MuSig sessions, because + * if any partial signature does not verify, the final signature will not + * verify either, so the problem will be caught. However, this function + * provides the ability to identify which specific partial signature fails + * verification. + * + * Returns: 0 if the arguments are invalid or the partial signature does not + * verify, 1 otherwise + * Args ctx: pointer to a context object + * In: partial_sig: pointer to partial signature to verify, sent by + * the signer associated with `pubnonce` and `pubkey` + * pubnonce: public nonce of the signer in the signing session + * pubkey: public key of the signer in the signing session + * keyagg_cache: pointer to the keyagg_cache that was output when the + * aggregate public key for this signing session + * session: pointer to the session that was created with + * `musig_nonce_process` + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify( + const secp256k1_context *ctx, + const secp256k1_musig_partial_sig *partial_sig, + const secp256k1_musig_pubnonce *pubnonce, + const secp256k1_pubkey *pubkey, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_musig_session *session +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); + +/** Aggregates partial signatures + * + * Returns: 0 if the arguments are invalid, 1 otherwise (which does NOT mean + * the resulting signature verifies). + * Args: ctx: pointer to a context object + * Out: sig64: complete (but possibly invalid) Schnorr signature + * In: session: pointer to the session that was created with + * musig_nonce_process + * partial_sigs: array of pointers to partial signatures to aggregate + * n_sigs: number of elements in the partial_sigs array. Must be + * greater than 0. + */ +SECP256K1_API int secp256k1_musig_partial_sig_agg( + const secp256k1_context *ctx, + unsigned char *sig64, + const secp256k1_musig_session *session, + const secp256k1_musig_partial_sig * const *partial_sigs, + size_t n_sigs +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/ctime_tests.c b/src/ctime_tests.c index a384e831..bbde863d 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -5,6 +5,7 @@ ***********************************************************************/ #include +#include #include "../include/secp256k1.h" #include "assumptions.h" @@ -30,6 +31,10 @@ #include "../include/secp256k1_schnorrsig.h" #endif +#ifdef ENABLE_MODULE_MUSIG +#include "../include/secp256k1_musig.h" +#endif + #ifdef ENABLE_MODULE_ELLSWIFT #include "../include/secp256k1_ellswift.h" #endif @@ -180,6 +185,58 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { CHECK(ret == 1); #endif +#ifdef ENABLE_MODULE_MUSIG + { + secp256k1_pubkey pk; + const secp256k1_pubkey *pk_ptr[1]; + secp256k1_xonly_pubkey agg_pk; + unsigned char session_secrand[32]; + uint64_t nonrepeating_cnt = 0; + secp256k1_musig_secnonce secnonce; + secp256k1_musig_pubnonce pubnonce; + const secp256k1_musig_pubnonce *pubnonce_ptr[1]; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_keyagg_cache cache; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig; + unsigned char extra_input[32]; + + pk_ptr[0] = &pk; + pubnonce_ptr[0] = &pubnonce; + SECP256K1_CHECKMEM_DEFINE(key, 32); + memcpy(session_secrand, key, sizeof(session_secrand)); + session_secrand[0] = session_secrand[0] + 1; + memcpy(extra_input, key, sizeof(extra_input)); + extra_input[0] = extra_input[0] + 2; + + CHECK(secp256k1_keypair_create(ctx, &keypair, key)); + CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair)); + CHECK(secp256k1_musig_pubkey_agg(ctx, &agg_pk, &cache, pk_ptr, 1)); + + SECP256K1_CHECKMEM_UNDEFINE(key, 32); + SECP256K1_CHECKMEM_UNDEFINE(session_secrand, sizeof(session_secrand)); + SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input)); + ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_secrand, key, &pk, msg, &cache, extra_input); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + ret = secp256k1_musig_nonce_gen_counter(ctx, &secnonce, &pubnonce, nonrepeating_cnt, &keypair, msg, &cache, extra_input); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + + CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1)); + /* Make sure that previous tests don't undefine msg. It's not used as a secret here. */ + SECP256K1_CHECKMEM_DEFINE(msg, sizeof(msg)); + CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache) == 1); + + ret = secp256k1_keypair_create(ctx, &keypair, key); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + ret = secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &cache, &session); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + } +#endif + #ifdef ENABLE_MODULE_ELLSWIFT SECP256K1_CHECKMEM_UNDEFINE(key, 32); ret = secp256k1_ellswift_create(ctx, ellswift, key, NULL); diff --git a/src/modules/musig/Makefile.am.include b/src/modules/musig/Makefile.am.include new file mode 100644 index 00000000..796443c9 --- /dev/null +++ b/src/modules/musig/Makefile.am.include @@ -0,0 +1,8 @@ +include_HEADERS += include/secp256k1_musig.h +noinst_HEADERS += src/modules/musig/main_impl.h +noinst_HEADERS += src/modules/musig/keyagg.h +noinst_HEADERS += src/modules/musig/keyagg_impl.h +noinst_HEADERS += src/modules/musig/session.h +noinst_HEADERS += src/modules/musig/session_impl.h +noinst_HEADERS += src/modules/musig/tests_impl.h +noinst_HEADERS += src/modules/musig/vectors.h diff --git a/src/modules/musig/keyagg.h b/src/modules/musig/keyagg.h new file mode 100644 index 00000000..a0b37252 --- /dev/null +++ b/src/modules/musig/keyagg.h @@ -0,0 +1,32 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_KEYAGG_H +#define SECP256K1_MODULE_MUSIG_KEYAGG_H + +#include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_musig.h" + +#include "../../group.h" +#include "../../scalar.h" + +typedef struct { + secp256k1_ge pk; + /* If there is no "second" public key, second_pk is set to the point at + * infinity */ + secp256k1_ge second_pk; + unsigned char pks_hash[32]; + /* tweak is identical to value tacc[v] in the specification. */ + secp256k1_scalar tweak; + /* parity_acc corresponds to (1 - gacc[v])/2 in the spec. So if gacc[v] is + * -1, parity_acc is 1. Otherwise, parity_acc is 0. */ + int parity_acc; +} secp256k1_keyagg_cache_internal; + +static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); + +static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); + +#endif diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h new file mode 100644 index 00000000..0db4fce8 --- /dev/null +++ b/src/modules/musig/keyagg_impl.h @@ -0,0 +1,291 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H +#define SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H + +#include + +#include "keyagg.h" +#include "../../eckey.h" +#include "../../ecmult.h" +#include "../../field.h" +#include "../../group.h" +#include "../../hash.h" +#include "../../util.h" + +static const unsigned char secp256k1_musig_keyagg_cache_magic[4] = { 0xf4, 0xad, 0xbb, 0xdf }; + +/* A keyagg cache consists of + * - 4 byte magic set during initialization to allow detecting an uninitialized + * object. + * - 64 byte aggregate (and potentially tweaked) public key + * - 64 byte "second" public key (set to the point at infinity if not present) + * - 32 byte hash of all public keys + * - 1 byte the parity of the internal key (if tweaked, otherwise 0) + * - 32 byte tweak + */ +/* Requires that cache_i->pk is not infinity. */ +static void secp256k1_keyagg_cache_save(secp256k1_musig_keyagg_cache *cache, const secp256k1_keyagg_cache_internal *cache_i) { + unsigned char *ptr = cache->data; + memcpy(ptr, secp256k1_musig_keyagg_cache_magic, 4); + ptr += 4; + secp256k1_ge_to_bytes(ptr, &cache_i->pk); + ptr += 64; + secp256k1_ge_to_bytes_ext(ptr, &cache_i->second_pk); + ptr += 64; + memcpy(ptr, cache_i->pks_hash, 32); + ptr += 32; + *ptr = cache_i->parity_acc; + ptr += 1; + secp256k1_scalar_get_b32(ptr, &cache_i->tweak); +} + +static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache) { + const unsigned char *ptr = cache->data; + ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_keyagg_cache_magic, 4) == 0); + ptr += 4; + secp256k1_ge_from_bytes(&cache_i->pk, ptr); + ptr += 64; + secp256k1_ge_from_bytes_ext(&cache_i->second_pk, ptr); + ptr += 64; + memcpy(cache_i->pks_hash, ptr, 32); + ptr += 32; + cache_i->parity_acc = *ptr & 1; + ptr += 1; + secp256k1_scalar_set_b32(&cache_i->tweak, ptr, NULL); + return 1; +} + +/* Initializes SHA256 with fixed midstate. This midstate was computed by applying + * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */ +static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha); + + sha->s[0] = 0xb399d5e0ul; + sha->s[1] = 0xc8fff302ul; + sha->s[2] = 0x6badac71ul; + sha->s[3] = 0x07c5b7f1ul; + sha->s[4] = 0x9701e2eful; + sha->s[5] = 0x2a72ecf8ul; + sha->s[6] = 0x201a4c7bul; + sha->s[7] = 0xab148a38ul; + sha->bytes = 64; +} + +/* Computes pks_hash = tagged_hash(pk[0], ..., pk[np-1]) */ +static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsigned char *pks_hash, const secp256k1_pubkey * const* pks, size_t np) { + secp256k1_sha256 sha; + size_t i; + + secp256k1_musig_keyagglist_sha256(&sha); + for (i = 0; i < np; i++) { + unsigned char ser[33]; + size_t ser_len = sizeof(ser); + if (!secp256k1_ec_pubkey_serialize(ctx, ser, &ser_len, pks[i], SECP256K1_EC_COMPRESSED)) { + return 0; + } + VERIFY_CHECK(ser_len == sizeof(ser)); + secp256k1_sha256_write(&sha, ser, sizeof(ser)); + } + secp256k1_sha256_finalize(&sha, pks_hash); + return 1; +} + +/* Initializes SHA256 with fixed midstate. This midstate was computed by applying + * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */ +static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha); + + sha->s[0] = 0x6ef02c5aul; + sha->s[1] = 0x06a480deul; + sha->s[2] = 0x1f298665ul; + sha->s[3] = 0x1d1134f2ul; + sha->s[4] = 0x56a0b063ul; + sha->s[5] = 0x52da4147ul; + sha->s[6] = 0xf280d9d4ul; + sha->s[7] = 0x4484be15ul; + sha->bytes = 64; +} + +/* Compute KeyAgg coefficient which is constant 1 for the second pubkey and + * otherwise tagged_hash(pks_hash, pk) where pks_hash is the hash of public keys. + * second_pk is the point at infinity in case there is no second_pk. Assumes + * that pk is not the point at infinity and that the Y-coordinates of pk and + * second_pk are normalized. */ +static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { + VERIFY_CHECK(!secp256k1_ge_is_infinity(pk)); + + if (!secp256k1_ge_is_infinity(second_pk) + && secp256k1_ge_eq_var(pk, second_pk)) { + secp256k1_scalar_set_int(r, 1); + } else { + secp256k1_sha256 sha; + unsigned char buf[33]; + size_t buflen = sizeof(buf); + int ret; + secp256k1_musig_keyaggcoef_sha256(&sha); + secp256k1_sha256_write(&sha, pks_hash, 32); + ret = secp256k1_eckey_pubkey_serialize(pk, buf, &buflen, 1); +#ifdef VERIFY + /* Serialization does not fail since the pk is not the point at infinity + * (according to this function's precondition). */ + VERIFY_CHECK(ret && buflen == sizeof(buf)); +#else + (void) ret; +#endif + secp256k1_sha256_write(&sha, buf, sizeof(buf)); + secp256k1_sha256_finalize(&sha, buf); + secp256k1_scalar_set_b32(r, buf, NULL); + } +} + +/* Assumes that pk is not the point at infinity and that the Y-coordinates of pk + * and cache_i->second_pk are normalized. */ +static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { + secp256k1_musig_keyaggcoef_internal(r, cache_i->pks_hash, pk, &cache_i->second_pk); +} + +typedef struct { + const secp256k1_context *ctx; + /* pks_hash is the hash of the public keys */ + unsigned char pks_hash[32]; + const secp256k1_pubkey * const* pks; + secp256k1_ge second_pk; +} secp256k1_musig_pubkey_agg_ecmult_data; + +/* Callback for batch EC multiplication to compute keyaggcoef_0*P0 + keyaggcoef_1*P1 + ... */ +static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) { + secp256k1_musig_pubkey_agg_ecmult_data *ctx = (secp256k1_musig_pubkey_agg_ecmult_data *) data; + int ret; + ret = secp256k1_pubkey_load(ctx->ctx, pt, ctx->pks[idx]); +#ifdef VERIFY + /* pubkey_load can't fail because the same pks have already been loaded in + * `musig_compute_pks_hash` (and we test this). */ + VERIFY_CHECK(ret); +#else + (void) ret; +#endif + secp256k1_musig_keyaggcoef_internal(sc, ctx->pks_hash, pt, &ctx->second_pk); + return 1; +} + +int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey * const* pubkeys, size_t n_pubkeys) { + secp256k1_musig_pubkey_agg_ecmult_data ecmult_data; + secp256k1_gej pkj; + secp256k1_ge pkp; + size_t i; + + VERIFY_CHECK(ctx != NULL); + if (agg_pk != NULL) { + memset(agg_pk, 0, sizeof(*agg_pk)); + } + ARG_CHECK(pubkeys != NULL); + ARG_CHECK(n_pubkeys > 0); + + ecmult_data.ctx = ctx; + ecmult_data.pks = pubkeys; + + secp256k1_ge_set_infinity(&ecmult_data.second_pk); + for (i = 1; i < n_pubkeys; i++) { + if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) { + secp256k1_ge pk; + if (!secp256k1_pubkey_load(ctx, &pk, pubkeys[i])) { + return 0; + } + ecmult_data.second_pk = pk; + break; + } + } + + if (!secp256k1_musig_compute_pks_hash(ctx, ecmult_data.pks_hash, pubkeys, n_pubkeys)) { + return 0; + } + /* TODO: actually use optimized ecmult_multi algorithms by providing a + * scratch space */ + if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_musig_pubkey_agg_callback, (void *) &ecmult_data, n_pubkeys)) { + /* In order to reach this line with the current implementation of + * ecmult_multi_var one would need to provide a callback that can + * fail. */ + return 0; + } + secp256k1_ge_set_gej(&pkp, &pkj); + secp256k1_fe_normalize_var(&pkp.y); + /* The resulting public key is infinity with negligible probability */ + VERIFY_CHECK(!secp256k1_ge_is_infinity(&pkp)); + if (keyagg_cache != NULL) { + secp256k1_keyagg_cache_internal cache_i = { 0 }; + cache_i.pk = pkp; + cache_i.second_pk = ecmult_data.second_pk; + memcpy(cache_i.pks_hash, ecmult_data.pks_hash, sizeof(cache_i.pks_hash)); + secp256k1_keyagg_cache_save(keyagg_cache, &cache_i); + } + + if (agg_pk != NULL) { + secp256k1_extrakeys_ge_even_y(&pkp); + secp256k1_xonly_pubkey_save(agg_pk, &pkp); + } + return 1; +} + +int secp256k1_musig_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *agg_pk, const secp256k1_musig_keyagg_cache *keyagg_cache) { + secp256k1_keyagg_cache_internal cache_i; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(agg_pk != NULL); + memset(agg_pk, 0, sizeof(*agg_pk)); + ARG_CHECK(keyagg_cache != NULL); + + if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + secp256k1_pubkey_save(agg_pk, &cache_i.pk); + return 1; +} + +static int secp256k1_musig_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32, int xonly) { + secp256k1_keyagg_cache_internal cache_i; + int overflow = 0; + secp256k1_scalar tweak; + + VERIFY_CHECK(ctx != NULL); + if (output_pubkey != NULL) { + memset(output_pubkey, 0, sizeof(*output_pubkey)); + } + ARG_CHECK(keyagg_cache != NULL); + ARG_CHECK(tweak32 != NULL); + + if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + secp256k1_scalar_set_b32(&tweak, tweak32, &overflow); + if (overflow) { + return 0; + } + if (xonly && secp256k1_extrakeys_ge_even_y(&cache_i.pk)) { + cache_i.parity_acc ^= 1; + secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak); + } + secp256k1_scalar_add(&cache_i.tweak, &cache_i.tweak, &tweak); + if (!secp256k1_eckey_pubkey_tweak_add(&cache_i.pk, &tweak)) { + return 0; + } + /* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */ + VERIFY_CHECK(!secp256k1_ge_is_infinity(&cache_i.pk)); + secp256k1_keyagg_cache_save(keyagg_cache, &cache_i); + if (output_pubkey != NULL) { + secp256k1_pubkey_save(output_pubkey, &cache_i.pk); + } + return 1; +} + +int secp256k1_musig_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { + return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0); +} + +int secp256k1_musig_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { + return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1); +} + +#endif diff --git a/src/modules/musig/main_impl.h b/src/modules/musig/main_impl.h new file mode 100644 index 00000000..a1311e41 --- /dev/null +++ b/src/modules/musig/main_impl.h @@ -0,0 +1,12 @@ +/********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_MAIN_H +#define SECP256K1_MODULE_MUSIG_MAIN_H + +#include "keyagg_impl.h" +#include "session_impl.h" + +#endif diff --git a/src/modules/musig/session.h b/src/modules/musig/session.h new file mode 100644 index 00000000..d6d76bc6 --- /dev/null +++ b/src/modules/musig/session.h @@ -0,0 +1,24 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_SESSION_H +#define SECP256K1_MODULE_MUSIG_SESSION_H + +#include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_musig.h" + +#include "../../scalar.h" + +typedef struct { + int fin_nonce_parity; + unsigned char fin_nonce[32]; + secp256k1_scalar noncecoef; + secp256k1_scalar challenge; + secp256k1_scalar s_part; +} secp256k1_musig_session_internal; + +static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session); + +#endif diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h new file mode 100644 index 00000000..2715b09d --- /dev/null +++ b/src/modules/musig/session_impl.h @@ -0,0 +1,815 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_SESSION_IMPL_H +#define SECP256K1_MODULE_MUSIG_SESSION_IMPL_H + +#include + +#include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_extrakeys.h" +#include "../../../include/secp256k1_musig.h" + +#include "keyagg.h" +#include "session.h" +#include "../../eckey.h" +#include "../../hash.h" +#include "../../scalar.h" +#include "../../util.h" + +/* Outputs 33 zero bytes if the given group element is the point at infinity and + * otherwise outputs the compressed serialization */ +static void secp256k1_musig_ge_serialize_ext(unsigned char *out33, secp256k1_ge* ge) { + if (secp256k1_ge_is_infinity(ge)) { + memset(out33, 0, 33); + } else { + int ret; + size_t size = 33; + ret = secp256k1_eckey_pubkey_serialize(ge, out33, &size, 1); +#ifdef VERIFY + /* Serialize must succeed because the point is not at infinity */ + VERIFY_CHECK(ret && size == 33); +#else + (void) ret; +#endif + } +} + +/* Outputs the point at infinity if the given byte array is all zero, otherwise + * attempts to parse compressed point serialization. */ +static int secp256k1_musig_ge_parse_ext(secp256k1_ge* ge, const unsigned char *in33) { + unsigned char zeros[33] = { 0 }; + + if (secp256k1_memcmp_var(in33, zeros, sizeof(zeros)) == 0) { + secp256k1_ge_set_infinity(ge); + return 1; + } + if (!secp256k1_eckey_pubkey_parse(ge, in33, 33)) { + return 0; + } + return secp256k1_ge_is_in_correct_subgroup(ge); +} + +static const unsigned char secp256k1_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 }; + +static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, const secp256k1_scalar *k, const secp256k1_ge *pk) { + memcpy(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4); + secp256k1_scalar_get_b32(&secnonce->data[4], &k[0]); + secp256k1_scalar_get_b32(&secnonce->data[36], &k[1]); + secp256k1_ge_to_bytes(&secnonce->data[68], pk); +} + +static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, secp256k1_ge *pk, const secp256k1_musig_secnonce *secnonce) { + int is_zero; + ARG_CHECK(secp256k1_memcmp_var(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4) == 0); + /* We make very sure that the nonce isn't invalidated by checking the values + * in addition to the magic. */ + is_zero = secp256k1_is_zero_array(&secnonce->data[4], 2 * 32); + secp256k1_declassify(ctx, &is_zero, sizeof(is_zero)); + ARG_CHECK(!is_zero); + + secp256k1_scalar_set_b32(&k[0], &secnonce->data[4], NULL); + secp256k1_scalar_set_b32(&k[1], &secnonce->data[36], NULL); + secp256k1_ge_from_bytes(pk, &secnonce->data[68]); + return 1; +} + +/* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */ +static void secp256k1_musig_secnonce_invalidate(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, int flag) { + secp256k1_memczero(secnonce->data, sizeof(secnonce->data), flag); + /* The flag argument is usually classified. So, the line above makes the + * magic and public key classified. However, we need both to be + * declassified. Note that we don't declassify the entire object, because if + * flag is 0, then k[0] and k[1] have not been zeroed. */ + secp256k1_declassify(ctx, secnonce->data, sizeof(secp256k1_musig_secnonce_magic)); + secp256k1_declassify(ctx, &secnonce->data[68], 64); +} + +static const unsigned char secp256k1_musig_pubnonce_magic[4] = { 0xf5, 0x7a, 0x3d, 0xa0 }; + +/* Saves two group elements into a pubnonce. Requires that none of the provided + * group elements is infinity. */ +static void secp256k1_musig_pubnonce_save(secp256k1_musig_pubnonce* nonce, const secp256k1_ge* ges) { + int i; + memcpy(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4); + for (i = 0; i < 2; i++) { + secp256k1_ge_to_bytes(nonce->data + 4+64*i, &ges[i]); + } +} + +/* Loads two group elements from a pubnonce. Returns 1 unless the nonce wasn't + * properly initialized */ +static int secp256k1_musig_pubnonce_load(const secp256k1_context* ctx, secp256k1_ge* ges, const secp256k1_musig_pubnonce* nonce) { + int i; + + ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4) == 0); + for (i = 0; i < 2; i++) { + secp256k1_ge_from_bytes(&ges[i], nonce->data + 4 + 64*i); + } + return 1; +} + +static const unsigned char secp256k1_musig_aggnonce_magic[4] = { 0xa8, 0xb7, 0xe4, 0x67 }; + +static void secp256k1_musig_aggnonce_save(secp256k1_musig_aggnonce* nonce, const secp256k1_ge* ges) { + int i; + memcpy(&nonce->data[0], secp256k1_musig_aggnonce_magic, 4); + for (i = 0; i < 2; i++) { + secp256k1_ge_to_bytes_ext(&nonce->data[4 + 64*i], &ges[i]); + } +} + +static int secp256k1_musig_aggnonce_load(const secp256k1_context* ctx, secp256k1_ge* ges, const secp256k1_musig_aggnonce* nonce) { + int i; + + ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_aggnonce_magic, 4) == 0); + for (i = 0; i < 2; i++) { + secp256k1_ge_from_bytes_ext(&ges[i], &nonce->data[4 + 64*i]); + } + return 1; +} + +static const unsigned char secp256k1_musig_session_cache_magic[4] = { 0x9d, 0xed, 0xe9, 0x17 }; + +/* A session consists of + * - 4 byte session cache magic + * - 1 byte the parity of the final nonce + * - 32 byte serialized x-only final nonce + * - 32 byte nonce coefficient b + * - 32 byte signature challenge hash e + * - 32 byte scalar s that is added to the partial signatures of the signers + */ +static void secp256k1_musig_session_save(secp256k1_musig_session *session, const secp256k1_musig_session_internal *session_i) { + unsigned char *ptr = session->data; + + memcpy(ptr, secp256k1_musig_session_cache_magic, 4); + ptr += 4; + *ptr = session_i->fin_nonce_parity; + ptr += 1; + memcpy(ptr, session_i->fin_nonce, 32); + ptr += 32; + secp256k1_scalar_get_b32(ptr, &session_i->noncecoef); + ptr += 32; + secp256k1_scalar_get_b32(ptr, &session_i->challenge); + ptr += 32; + secp256k1_scalar_get_b32(ptr, &session_i->s_part); +} + +static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session) { + const unsigned char *ptr = session->data; + + ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_session_cache_magic, 4) == 0); + ptr += 4; + session_i->fin_nonce_parity = *ptr; + ptr += 1; + memcpy(session_i->fin_nonce, ptr, 32); + ptr += 32; + secp256k1_scalar_set_b32(&session_i->noncecoef, ptr, NULL); + ptr += 32; + secp256k1_scalar_set_b32(&session_i->challenge, ptr, NULL); + ptr += 32; + secp256k1_scalar_set_b32(&session_i->s_part, ptr, NULL); + return 1; +} + +static const unsigned char secp256k1_musig_partial_sig_magic[4] = { 0xeb, 0xfb, 0x1a, 0x32 }; + +static void secp256k1_musig_partial_sig_save(secp256k1_musig_partial_sig* sig, secp256k1_scalar *s) { + memcpy(&sig->data[0], secp256k1_musig_partial_sig_magic, 4); + secp256k1_scalar_get_b32(&sig->data[4], s); +} + +static int secp256k1_musig_partial_sig_load(const secp256k1_context* ctx, secp256k1_scalar *s, const secp256k1_musig_partial_sig* sig) { + int overflow; + + ARG_CHECK(secp256k1_memcmp_var(&sig->data[0], secp256k1_musig_partial_sig_magic, 4) == 0); + secp256k1_scalar_set_b32(s, &sig->data[4], &overflow); + /* Parsed signatures can not overflow */ + VERIFY_CHECK(!overflow); + return 1; +} + +int secp256k1_musig_pubnonce_parse(const secp256k1_context* ctx, secp256k1_musig_pubnonce* nonce, const unsigned char *in66) { + secp256k1_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(nonce != NULL); + ARG_CHECK(in66 != NULL); + + for (i = 0; i < 2; i++) { + if (!secp256k1_eckey_pubkey_parse(&ges[i], &in66[33*i], 33)) { + return 0; + } + if (!secp256k1_ge_is_in_correct_subgroup(&ges[i])) { + return 0; + } + } + secp256k1_musig_pubnonce_save(nonce, ges); + return 1; +} + +int secp256k1_musig_pubnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_pubnonce* nonce) { + secp256k1_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(out66 != NULL); + memset(out66, 0, 66); + ARG_CHECK(nonce != NULL); + + if (!secp256k1_musig_pubnonce_load(ctx, ges, nonce)) { + return 0; + } + for (i = 0; i < 2; i++) { + int ret; + size_t size = 33; + ret = secp256k1_eckey_pubkey_serialize(&ges[i], &out66[33*i], &size, 1); +#ifdef VERIFY + /* serialize must succeed because the point was just loaded */ + VERIFY_CHECK(ret && size == 33); +#else + (void) ret; +#endif + } + return 1; +} + +int secp256k1_musig_aggnonce_parse(const secp256k1_context* ctx, secp256k1_musig_aggnonce* nonce, const unsigned char *in66) { + secp256k1_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(nonce != NULL); + ARG_CHECK(in66 != NULL); + + for (i = 0; i < 2; i++) { + if (!secp256k1_musig_ge_parse_ext(&ges[i], &in66[33*i])) { + return 0; + } + } + secp256k1_musig_aggnonce_save(nonce, ges); + return 1; +} + +int secp256k1_musig_aggnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_aggnonce* nonce) { + secp256k1_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(out66 != NULL); + memset(out66, 0, 66); + ARG_CHECK(nonce != NULL); + + if (!secp256k1_musig_aggnonce_load(ctx, ges, nonce)) { + return 0; + } + for (i = 0; i < 2; i++) { + secp256k1_musig_ge_serialize_ext(&out66[33*i], &ges[i]); + } + return 1; +} + +int secp256k1_musig_partial_sig_parse(const secp256k1_context* ctx, secp256k1_musig_partial_sig* sig, const unsigned char *in32) { + secp256k1_scalar tmp; + int overflow; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(in32 != NULL); + + /* Ensure that using the signature will fail if parsing fails (and the user + * doesn't check the return value). */ + memset(sig, 0, sizeof(*sig)); + + secp256k1_scalar_set_b32(&tmp, in32, &overflow); + if (overflow) { + return 0; + } + secp256k1_musig_partial_sig_save(sig, &tmp); + return 1; +} + +int secp256k1_musig_partial_sig_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_sig* sig) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(out32 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(secp256k1_memcmp_var(&sig->data[0], secp256k1_musig_partial_sig_magic, 4) == 0); + + memcpy(out32, &sig->data[4], 32); + return 1; +} + +/* Write optional inputs into the hash */ +static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigned int prefix_size, const unsigned char *data, unsigned char len) { + unsigned char zero[7] = { 0 }; + /* The spec requires length prefixes to be between 1 and 8 bytes + * (inclusive) */ + VERIFY_CHECK(prefix_size >= 1 && prefix_size <= 8); + /* Since the length of all input data fits in a byte, we can always pad the + * length prefix with prefix_size - 1 zero bytes. */ + secp256k1_sha256_write(sha, zero, prefix_size - 1); + if (data != NULL) { + secp256k1_sha256_write(sha, &len, 1); + secp256k1_sha256_write(sha, data, len); + } else { + len = 0; + secp256k1_sha256_write(sha, &len, 1); + } +} + +/* Initializes SHA256 with fixed midstate. This midstate was computed by applying + * SHA256 to SHA256("MuSig/aux")||SHA256("MuSig/aux"). */ +static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha); + sha->s[0] = 0xa19e884bul; + sha->s[1] = 0xf463fe7eul; + sha->s[2] = 0x2f18f9a2ul; + sha->s[3] = 0xbeb0f9fful; + sha->s[4] = 0x0f37e8b0ul; + sha->s[5] = 0x06ebd26ful; + sha->s[6] = 0xe3b243d2ul; + sha->s[7] = 0x522fb150ul; + sha->bytes = 64; +} + +/* Initializes SHA256 with fixed midstate. This midstate was computed by applying + * SHA256 to SHA256("MuSig/nonce")||SHA256("MuSig/nonce"). */ +static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha); + sha->s[0] = 0x07101b64ul; + sha->s[1] = 0x18003414ul; + sha->s[2] = 0x0391bc43ul; + sha->s[3] = 0x0e6258eeul; + sha->s[4] = 0x29d26b72ul; + sha->s[5] = 0x8343937eul; + sha->s[6] = 0xb7a0a4fbul; + sha->s[7] = 0xff568a30ul; + sha->bytes = 64; +} + +static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { + secp256k1_sha256 sha; + unsigned char rand[32]; + unsigned char i; + unsigned char msg_present; + + if (seckey32 != NULL) { + secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); + secp256k1_sha256_write(&sha, session_secrand, 32); + secp256k1_sha256_finalize(&sha, rand); + for (i = 0; i < 32; i++) { + rand[i] ^= seckey32[i]; + } + } else { + memcpy(rand, session_secrand, sizeof(rand)); + } + + secp256k1_nonce_function_musig_sha256_tagged(&sha); + secp256k1_sha256_write(&sha, rand, sizeof(rand)); + secp256k1_nonce_function_musig_helper(&sha, 1, pk33, 33); + secp256k1_nonce_function_musig_helper(&sha, 1, agg_pk32, 32); + msg_present = msg32 != NULL; + secp256k1_sha256_write(&sha, &msg_present, 1); + if (msg_present) { + secp256k1_nonce_function_musig_helper(&sha, 8, msg32, 32); + } + secp256k1_nonce_function_musig_helper(&sha, 4, extra_input32, 32); + + for (i = 0; i < 2; i++) { + unsigned char buf[32]; + secp256k1_sha256 sha_tmp = sha; + secp256k1_sha256_write(&sha_tmp, &i, 1); + secp256k1_sha256_finalize(&sha_tmp, buf); + secp256k1_scalar_set_b32(&k[i], buf, NULL); + + /* Attempt to erase secret data */ + memset(buf, 0, sizeof(buf)); + memset(&sha_tmp, 0, sizeof(sha_tmp)); + } + memset(rand, 0, sizeof(rand)); + memset(&sha, 0, sizeof(sha)); +} + +int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { + secp256k1_scalar k[2]; + secp256k1_ge nonce_pts[2]; + int i; + unsigned char pk_ser[33]; + size_t pk_ser_len = sizeof(pk_ser); + unsigned char aggpk_ser[32]; + unsigned char *aggpk_ser_ptr = NULL; + secp256k1_ge pk; + int pk_serialize_success; + int ret = 1; + + ARG_CHECK(pubnonce != NULL); + memset(pubnonce, 0, sizeof(*pubnonce)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + + /* Check that the seckey is valid to be able to sign for it later. */ + if (seckey != NULL) { + secp256k1_scalar sk; + ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey); + secp256k1_scalar_clear(&sk); + } + + if (keyagg_cache != NULL) { + secp256k1_keyagg_cache_internal cache_i; + if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + /* The loaded point cache_i.pk can not be the point at infinity. */ + secp256k1_fe_get_b32(aggpk_ser, &cache_i.pk.x); + aggpk_ser_ptr = aggpk_ser; + } + if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { + return 0; + } + pk_serialize_success = secp256k1_eckey_pubkey_serialize(&pk, pk_ser, &pk_ser_len, 1); + +#ifdef VERIFY + /* A pubkey cannot be the point at infinity */ + VERIFY_CHECK(pk_serialize_success); + VERIFY_CHECK(pk_ser_len == sizeof(pk_ser)); +#else + (void) pk_serialize_success; +#endif + + secp256k1_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); + VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); + VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); + secp256k1_musig_secnonce_save(secnonce, k, &pk); + secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); + + for (i = 0; i < 2; i++) { + secp256k1_gej nonce_ptj; + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); + secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj); + secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts)); + secp256k1_scalar_clear(&k[i]); + } + /* None of the nonce_pts will be infinity because k != 0 with overwhelming + * probability */ + secp256k1_musig_pubnonce_save(pubnonce, nonce_pts); + return ret; +} + +int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, unsigned char *session_secrand32, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { + int ret = 1; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secnonce != NULL); + memset(secnonce, 0, sizeof(*secnonce)); + ARG_CHECK(session_secrand32 != NULL); + + /* Check in constant time that the session_secrand32 is not 0 as a + * defense-in-depth measure that may protect against a faulty RNG. */ + ret &= !secp256k1_is_zero_array(session_secrand32, 32); + + /* We can declassify because branching on ret is only relevant when this + * function called with an invalid session_secrand32 argument */ + secp256k1_declassify(ctx, &ret, sizeof(ret)); + if (ret == 0) { + secp256k1_musig_secnonce_invalidate(ctx, secnonce, 1); + return 0; + } + + ret &= secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, session_secrand32, seckey, pubkey, msg32, keyagg_cache, extra_input32); + + /* Set the session_secrand32 buffer to zero to prevent the caller from using + * nonce_gen multiple times with the same buffer. */ + secp256k1_memczero(session_secrand32, 32, ret); + return ret; +} + +int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, uint64_t nonrepeating_cnt, const secp256k1_keypair *keypair, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { + unsigned char buf[32] = { 0 }; + unsigned char seckey[32]; + secp256k1_pubkey pubkey; + int ret; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secnonce != NULL); + memset(secnonce, 0, sizeof(*secnonce)); + ARG_CHECK(keypair != NULL); + + secp256k1_write_be64(buf, nonrepeating_cnt); + /* keypair_sec and keypair_pub do not fail if the arguments are not NULL */ + ret = secp256k1_keypair_sec(ctx, seckey, keypair); + VERIFY_CHECK(ret); + ret = secp256k1_keypair_pub(ctx, &pubkey, keypair); + VERIFY_CHECK(ret); +#ifndef VERIFY + (void) ret; +#endif + + if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) { + return 0; + } + memset(seckey, 0, sizeof(seckey)); + return 1; +} + +static int secp256k1_musig_sum_pubnonces(const secp256k1_context* ctx, secp256k1_gej *summed_pubnonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { + size_t i; + int j; + + secp256k1_gej_set_infinity(&summed_pubnonces[0]); + secp256k1_gej_set_infinity(&summed_pubnonces[1]); + + for (i = 0; i < n_pubnonces; i++) { + secp256k1_ge nonce_pts[2]; + if (!secp256k1_musig_pubnonce_load(ctx, nonce_pts, pubnonces[i])) { + return 0; + } + for (j = 0; j < 2; j++) { + secp256k1_gej_add_ge_var(&summed_pubnonces[j], &summed_pubnonces[j], &nonce_pts[j], NULL); + } + } + return 1; +} + +int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggnonce *aggnonce, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { + secp256k1_gej aggnonce_ptsj[2]; + secp256k1_ge aggnonce_pts[2]; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(aggnonce != NULL); + ARG_CHECK(pubnonces != NULL); + ARG_CHECK(n_pubnonces > 0); + + if (!secp256k1_musig_sum_pubnonces(ctx, aggnonce_ptsj, pubnonces, n_pubnonces)) { + return 0; + } + secp256k1_ge_set_all_gej_var(aggnonce_pts, aggnonce_ptsj, 2); + secp256k1_musig_aggnonce_save(aggnonce, aggnonce_pts); + return 1; +} + +/* Initializes SHA256 with fixed midstate. This midstate was computed by applying + * SHA256 to SHA256("MuSig/noncecoef")||SHA256("MuSig/noncecoef"). */ +static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sha) { + secp256k1_sha256_initialize(sha); + sha->s[0] = 0x2c7d5a45ul; + sha->s[1] = 0x06bf7e53ul; + sha->s[2] = 0x89be68a6ul; + sha->s[3] = 0x971254c0ul; + sha->s[4] = 0x60ac12d2ul; + sha->s[5] = 0x72846dcdul; + sha->s[6] = 0x6c81212ful; + sha->s[7] = 0xde7a2500ul; + sha->bytes = 64; +} + +/* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ +static void secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { + unsigned char buf[33]; + secp256k1_sha256 sha; + int i; + + secp256k1_musig_compute_noncehash_sha256_tagged(&sha); + for (i = 0; i < 2; i++) { + secp256k1_musig_ge_serialize_ext(buf, &aggnonce[i]); + secp256k1_sha256_write(&sha, buf, sizeof(buf)); + } + secp256k1_sha256_write(&sha, agg_pk32, 32); + secp256k1_sha256_write(&sha, msg, 32); + secp256k1_sha256_finalize(&sha, noncehash); +} + +/* out_nonce = nonce_pts[0] + b*nonce_pts[1] */ +static void secp256k1_effective_nonce(secp256k1_gej *out_nonce, const secp256k1_ge *nonce_pts, const secp256k1_scalar *b) { + secp256k1_gej tmp; + + secp256k1_gej_set_ge(&tmp, &nonce_pts[1]); + secp256k1_ecmult(out_nonce, &tmp, b, NULL); + secp256k1_gej_add_ge_var(out_nonce, out_nonce, &nonce_pts[0], NULL); +} + +static void secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { + unsigned char noncehash[32]; + secp256k1_ge fin_nonce_pt; + secp256k1_gej fin_nonce_ptj; + + secp256k1_musig_compute_noncehash(noncehash, aggnonce_pts, agg_pk32, msg); + secp256k1_scalar_set_b32(b, noncehash, NULL); + /* fin_nonce = aggnonce_pts[0] + b*aggnonce_pts[1] */ + secp256k1_effective_nonce(&fin_nonce_ptj, aggnonce_pts, b); + secp256k1_ge_set_gej(&fin_nonce_pt, &fin_nonce_ptj); + if (secp256k1_ge_is_infinity(&fin_nonce_pt)) { + fin_nonce_pt = secp256k1_ge_const_g; + } + /* fin_nonce_pt is not the point at infinity */ + secp256k1_fe_normalize_var(&fin_nonce_pt.x); + secp256k1_fe_get_b32(fin_nonce, &fin_nonce_pt.x); + secp256k1_fe_normalize_var(&fin_nonce_pt.y); + *fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y); +} + +int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache) { + secp256k1_keyagg_cache_internal cache_i; + secp256k1_ge aggnonce_pts[2]; + unsigned char fin_nonce[32]; + secp256k1_musig_session_internal session_i; + unsigned char agg_pk32[32]; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(session != NULL); + ARG_CHECK(aggnonce != NULL); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(keyagg_cache != NULL); + + if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + secp256k1_fe_get_b32(agg_pk32, &cache_i.pk.x); + + if (!secp256k1_musig_aggnonce_load(ctx, aggnonce_pts, aggnonce)) { + return 0; + } + + secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); + secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32); + + /* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/ + secp256k1_scalar_set_int(&session_i.s_part, 0); + if (!secp256k1_scalar_is_zero(&cache_i.tweak)) { + secp256k1_scalar e_tmp; + secp256k1_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak); + if (secp256k1_fe_is_odd(&cache_i.pk.y)) { + secp256k1_scalar_negate(&e_tmp, &e_tmp); + } + session_i.s_part = e_tmp; + } + memcpy(session_i.fin_nonce, fin_nonce, sizeof(session_i.fin_nonce)); + secp256k1_musig_session_save(session, &session_i); + return 1; +} + +static void secp256k1_musig_partial_sign_clear(secp256k1_scalar *sk, secp256k1_scalar *k) { + secp256k1_scalar_clear(sk); + secp256k1_scalar_clear(&k[0]); + secp256k1_scalar_clear(&k[1]); +} + +int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_partial_sig *partial_sig, secp256k1_musig_secnonce *secnonce, const secp256k1_keypair *keypair, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { + secp256k1_scalar sk; + secp256k1_ge pk, keypair_pk; + secp256k1_scalar k[2]; + secp256k1_scalar mu, s; + secp256k1_keyagg_cache_internal cache_i; + secp256k1_musig_session_internal session_i; + int ret; + + VERIFY_CHECK(ctx != NULL); + + ARG_CHECK(secnonce != NULL); + /* Fails if the magic doesn't match */ + ret = secp256k1_musig_secnonce_load(ctx, k, &pk, secnonce); + /* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls + * of this function to fail */ + memset(secnonce, 0, sizeof(*secnonce)); + if (!ret) { + secp256k1_musig_partial_sign_clear(&sk, k); + return 0; + } + + ARG_CHECK(partial_sig != NULL); + ARG_CHECK(keypair != NULL); + ARG_CHECK(keyagg_cache != NULL); + ARG_CHECK(session != NULL); + + if (!secp256k1_keypair_load(ctx, &sk, &keypair_pk, keypair)) { + secp256k1_musig_partial_sign_clear(&sk, k); + return 0; + } + ARG_CHECK(secp256k1_fe_equal(&pk.x, &keypair_pk.x) + && secp256k1_fe_equal(&pk.y, &keypair_pk.y)); + if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + secp256k1_musig_partial_sign_clear(&sk, k); + return 0; + } + + /* Negate sk if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. + * This corresponds to the line "Let d = g⋅gacc⋅d' mod n" in the + * specification. */ + if ((secp256k1_fe_is_odd(&cache_i.pk.y) + != cache_i.parity_acc)) { + secp256k1_scalar_negate(&sk, &sk); + } + + /* Multiply KeyAgg coefficient */ + secp256k1_musig_keyaggcoef(&mu, &cache_i, &pk); + secp256k1_scalar_mul(&sk, &sk, &mu); + + if (!secp256k1_musig_session_load(ctx, &session_i, session)) { + secp256k1_musig_partial_sign_clear(&sk, k); + return 0; + } + + if (session_i.fin_nonce_parity) { + secp256k1_scalar_negate(&k[0], &k[0]); + secp256k1_scalar_negate(&k[1], &k[1]); + } + + /* Sign */ + secp256k1_scalar_mul(&s, &session_i.challenge, &sk); + secp256k1_scalar_mul(&k[1], &session_i.noncecoef, &k[1]); + secp256k1_scalar_add(&k[0], &k[0], &k[1]); + secp256k1_scalar_add(&s, &s, &k[0]); + secp256k1_musig_partial_sig_save(partial_sig, &s); + secp256k1_musig_partial_sign_clear(&sk, k); + return 1; +} + +int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp256k1_musig_partial_sig *partial_sig, const secp256k1_musig_pubnonce *pubnonce, const secp256k1_pubkey *pubkey, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { + secp256k1_keyagg_cache_internal cache_i; + secp256k1_musig_session_internal session_i; + secp256k1_scalar mu, e, s; + secp256k1_gej pkj; + secp256k1_ge nonce_pts[2]; + secp256k1_gej rj; + secp256k1_gej tmp; + secp256k1_ge pkp; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(partial_sig != NULL); + ARG_CHECK(pubnonce != NULL); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(keyagg_cache != NULL); + ARG_CHECK(session != NULL); + + if (!secp256k1_musig_session_load(ctx, &session_i, session)) { + return 0; + } + + if (!secp256k1_musig_pubnonce_load(ctx, nonce_pts, pubnonce)) { + return 0; + } + /* Compute "effective" nonce rj = nonce_pts[0] + b*nonce_pts[1] */ + /* TODO: use multiexp to compute -s*G + e*mu*pubkey + nonce_pts[0] + b*nonce_pts[1] */ + secp256k1_effective_nonce(&rj, nonce_pts, &session_i.noncecoef); + + if (!secp256k1_pubkey_load(ctx, &pkp, pubkey)) { + return 0; + } + if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + /* Multiplying the challenge by the KeyAgg coefficient is equivalent + * to multiplying the signer's public key by the coefficient, except + * much easier to do. */ + secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp); + secp256k1_scalar_mul(&e, &session_i.challenge, &mu); + + /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. + * This corresponds to the line "Let g' = g⋅gacc mod n" and the multiplication "g'⋅e" + * in the specification. */ + if (secp256k1_fe_is_odd(&cache_i.pk.y) + != cache_i.parity_acc) { + secp256k1_scalar_negate(&e, &e); + } + + if (!secp256k1_musig_partial_sig_load(ctx, &s, partial_sig)) { + return 0; + } + /* Compute -s*G + e*pkj + rj (e already includes the keyagg coefficient mu) */ + secp256k1_scalar_negate(&s, &s); + secp256k1_gej_set_ge(&pkj, &pkp); + secp256k1_ecmult(&tmp, &pkj, &e, &s); + if (session_i.fin_nonce_parity) { + secp256k1_gej_neg(&rj, &rj); + } + secp256k1_gej_add_var(&tmp, &tmp, &rj, NULL); + + return secp256k1_gej_is_infinity(&tmp); +} + +int secp256k1_musig_partial_sig_agg(const secp256k1_context* ctx, unsigned char *sig64, const secp256k1_musig_session *session, const secp256k1_musig_partial_sig * const* partial_sigs, size_t n_sigs) { + size_t i; + secp256k1_musig_session_internal session_i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig64 != NULL); + ARG_CHECK(session != NULL); + ARG_CHECK(partial_sigs != NULL); + ARG_CHECK(n_sigs > 0); + + if (!secp256k1_musig_session_load(ctx, &session_i, session)) { + return 0; + } + for (i = 0; i < n_sigs; i++) { + secp256k1_scalar term; + if (!secp256k1_musig_partial_sig_load(ctx, &term, partial_sigs[i])) { + return 0; + } + secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &term); + } + secp256k1_scalar_get_b32(&sig64[32], &session_i.s_part); + memcpy(&sig64[0], session_i.fin_nonce, 32); + return 1; +} + +#endif diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h new file mode 100644 index 00000000..ce6ae178 --- /dev/null +++ b/src/modules/musig/tests_impl.h @@ -0,0 +1,1143 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_TESTS_IMPL_H +#define SECP256K1_MODULE_MUSIG_TESTS_IMPL_H + +#include +#include + +#include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_extrakeys.h" +#include "../../../include/secp256k1_musig.h" + +#include "session.h" +#include "keyagg.h" +#include "../../scalar.h" +#include "../../field.h" +#include "../../group.h" +#include "../../hash.h" +#include "../../util.h" + +#include "vectors.h" + +static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *pk, const unsigned char *sk) { + int ret; + secp256k1_keypair keypair_tmp; + ret = secp256k1_keypair_create(CTX, &keypair_tmp, sk); + ret &= secp256k1_keypair_pub(CTX, pk, &keypair_tmp); + if (keypair != NULL) { + *keypair = keypair_tmp; + } + return ret; +} + +/* Just a simple (non-tweaked) 2-of-2 MuSig aggregate, sign, verify + * test. */ +static void musig_simple_test(void) { + unsigned char sk[2][32]; + secp256k1_keypair keypair[2]; + secp256k1_musig_pubnonce pubnonce[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr[2]; + secp256k1_musig_aggnonce aggnonce; + unsigned char msg[32]; + secp256k1_xonly_pubkey agg_pk; + secp256k1_musig_keyagg_cache keyagg_cache; + unsigned char session_secrand[2][32]; + secp256k1_musig_secnonce secnonce[2]; + secp256k1_pubkey pk[2]; + const secp256k1_pubkey *pk_ptr[2]; + secp256k1_musig_partial_sig partial_sig[2]; + const secp256k1_musig_partial_sig *partial_sig_ptr[2]; + unsigned char final_sig[64]; + secp256k1_musig_session session; + int i; + + testrand256(msg); + for (i = 0; i < 2; i++) { + testrand256(sk[i]); + pk_ptr[i] = &pk[i]; + pubnonce_ptr[i] = &pubnonce[i]; + partial_sig_ptr[i] = &partial_sig[i]; + + CHECK(create_keypair_and_pk(&keypair[i], &pk[i], sk[i])); + if (i == 0) { + testrand256(session_secrand[i]); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[i], &pubnonce[i], session_secrand[i], sk[i], &pk[i], NULL, NULL, NULL) == 1); + } else { + uint64_t nonrepeating_cnt = 0; + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[i], &pubnonce[i], nonrepeating_cnt, &keypair[i], NULL, NULL, NULL) == 1); + } + } + + CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + + for (i = 0; i < 2; i++) { + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[i], &secnonce[i], &keypair[i], &keyagg_cache, &session) == 1); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[i], &pubnonce[i], &pk[i], &keyagg_cache, &session) == 1); + } + + CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); +} + +/* Generate two pubnonces such that both group elements of their sum (calculated + * with secp256k1_musig_sum_pubnonces) are infinity. */ +static void pubnonce_summing_to_inf(secp256k1_musig_pubnonce *pubnonce) { + secp256k1_ge ge[2]; + int i; + secp256k1_gej summed_pubnonces[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr[2]; + + testutil_random_ge_test(&ge[0]); + testutil_random_ge_test(&ge[1]); + + for (i = 0; i < 2; i++) { + secp256k1_musig_pubnonce_save(&pubnonce[i], ge); + pubnonce_ptr[i] = &pubnonce[i]; + secp256k1_ge_neg(&ge[0], &ge[0]); + secp256k1_ge_neg(&ge[1], &ge[1]); + } + + secp256k1_musig_sum_pubnonces(CTX, summed_pubnonces, pubnonce_ptr, 2); + CHECK(secp256k1_gej_is_infinity(&summed_pubnonces[0])); + CHECK(secp256k1_gej_is_infinity(&summed_pubnonces[1])); +} + +int memcmp_and_randomize(unsigned char *value, const unsigned char *expected, size_t len) { + int ret; + size_t i; + ret = secp256k1_memcmp_var(value, expected, len); + for (i = 0; i < len; i++) { + value[i] = testrand_bits(8); + } + return ret; +} + +static void musig_api_tests(void) { + secp256k1_musig_partial_sig partial_sig[2]; + const secp256k1_musig_partial_sig *partial_sig_ptr[2]; + secp256k1_musig_partial_sig invalid_partial_sig; + const secp256k1_musig_partial_sig *invalid_partial_sig_ptr[2]; + unsigned char pre_sig[64]; + unsigned char buf[32]; + unsigned char sk[2][32]; + secp256k1_keypair keypair[2]; + secp256k1_keypair invalid_keypair; + unsigned char max64[64]; + unsigned char zeros132[132] = { 0 }; + unsigned char session_secrand[2][32]; + unsigned char nonrepeating_cnt = 0; + secp256k1_musig_secnonce secnonce[2]; + secp256k1_musig_secnonce secnonce_tmp; + secp256k1_musig_secnonce invalid_secnonce; + secp256k1_musig_pubnonce pubnonce[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr[2]; + unsigned char pubnonce_ser[66]; + secp256k1_musig_pubnonce inf_pubnonce[2]; + const secp256k1_musig_pubnonce *inf_pubnonce_ptr[2]; + secp256k1_musig_pubnonce invalid_pubnonce; + const secp256k1_musig_pubnonce *invalid_pubnonce_ptr[1]; + secp256k1_musig_aggnonce aggnonce; + unsigned char aggnonce_ser[66]; + unsigned char msg[32]; + secp256k1_xonly_pubkey agg_pk; + secp256k1_pubkey full_agg_pk; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_musig_keyagg_cache invalid_keyagg_cache; + secp256k1_musig_session session; + secp256k1_musig_session invalid_session; + secp256k1_pubkey pk[2]; + const secp256k1_pubkey *pk_ptr[2]; + secp256k1_pubkey invalid_pk; + const secp256k1_pubkey *invalid_pk_ptr2[2]; + const secp256k1_pubkey *invalid_pk_ptr3[3]; + unsigned char tweak[32]; + int i; + + /** setup **/ + memset(max64, 0xff, sizeof(max64)); + memset(&invalid_keypair, 0, sizeof(invalid_keypair)); + memset(&invalid_pk, 0, sizeof(invalid_pk)); + memset(&invalid_secnonce, 0, sizeof(invalid_secnonce)); + memset(&invalid_partial_sig, 0, sizeof(invalid_partial_sig)); + pubnonce_summing_to_inf(inf_pubnonce); + /* Simulate structs being uninitialized by setting it to 0s. We don't want + * to produce undefined behavior by actually providing uninitialized + * structs. */ + memset(&invalid_keyagg_cache, 0, sizeof(invalid_keyagg_cache)); + memset(&invalid_pk, 0, sizeof(invalid_pk)); + memset(&invalid_pubnonce, 0, sizeof(invalid_pubnonce)); + memset(&invalid_session, 0, sizeof(invalid_session)); + + testrand256(msg); + testrand256(tweak); + for (i = 0; i < 2; i++) { + pk_ptr[i] = &pk[i]; + invalid_pk_ptr2[i] = &invalid_pk; + invalid_pk_ptr3[i] = &pk[i]; + pubnonce_ptr[i] = &pubnonce[i]; + inf_pubnonce_ptr[i] = &inf_pubnonce[i]; + partial_sig_ptr[i] = &partial_sig[i]; + invalid_partial_sig_ptr[i] = &partial_sig[i]; + testrand256(session_secrand[i]); + testrand256(sk[i]); + CHECK(create_keypair_and_pk(&keypair[i], &pk[i], sk[i])); + } + invalid_pubnonce_ptr[0] = &invalid_pubnonce; + invalid_partial_sig_ptr[0] = &invalid_partial_sig; + /* invalid_pk_ptr3 has two valid, one invalid pk, which is important to test + * musig_pubkey_agg */ + invalid_pk_ptr3[2] = &invalid_pk; + + /** main test body **/ + + /** Key aggregation **/ + CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); + CHECK(secp256k1_musig_pubkey_agg(CTX, NULL, &keyagg_cache, pk_ptr, 2) == 1); + CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, NULL, pk_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, NULL, 2)); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, invalid_pk_ptr2, 2)); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, invalid_pk_ptr3, 3)); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 0)); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, NULL, 0)); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); + + CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); + + /* pubkey_get */ + CHECK(secp256k1_musig_pubkey_get(CTX, &full_agg_pk, &keyagg_cache) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_get(CTX, NULL, &keyagg_cache)); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_get(CTX, &full_agg_pk, NULL)); + CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros132, sizeof(full_agg_pk)) == 0); + + /** Tweaking **/ + { + int (*tweak_func[2]) (const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32); + tweak_func[0] = secp256k1_musig_pubkey_ec_tweak_add; + tweak_func[1] = secp256k1_musig_pubkey_xonly_tweak_add; + for (i = 0; i < 2; i++) { + secp256k1_pubkey tmp_output_pk; + secp256k1_musig_keyagg_cache tmp_keyagg_cache = keyagg_cache; + CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1); + /* Reset keyagg_cache */ + tmp_keyagg_cache = keyagg_cache; + CHECK((*tweak_func[i])(CTX, NULL, &tmp_keyagg_cache, tweak) == 1); + tmp_keyagg_cache = keyagg_cache; + CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, NULL, tweak)); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); + tmp_keyagg_cache = keyagg_cache; + CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, NULL)); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); + tmp_keyagg_cache = keyagg_cache; + CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, max64) == 0); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); + tmp_keyagg_cache = keyagg_cache; + /* Uninitialized keyagg_cache */ + CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &invalid_keyagg_cache, tweak)); + CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); + } + } + + /** Session creation with nonce_gen **/ + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64) == 1); + /* nonce_gen, if successful, sets session_secrand to the zero array, which + * makes subsequent nonce_gen calls with the same session_secrand fail. So + * check that session_secrand is indeed the zero array and fill it with + * random values again. */ + CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); + + CHECK_ILLEGAL(STATIC_CTX, secp256k1_musig_nonce_gen(STATIC_CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, NULL, &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); + + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], NULL, session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], NULL, sk[0], &pk[0], msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + /* session_secrand = 0 is disallowed because it indicates a faulty RNG */ + memcpy(&session_secrand[0], zeros132, sizeof(session_secrand[0])); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros132, sk[0], &pk[0], msg, &keyagg_cache, max64) == 0); + CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], NULL, &pk[0], msg, &keyagg_cache, max64) == 1); + CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); + + /* invalid seckey */ + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], max64, &pk[0], msg, &keyagg_cache, max64) == 0); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], NULL, msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &invalid_pk, msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], NULL, &keyagg_cache, max64) == 1); + CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); + + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, NULL, max64) == 1); + CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); + + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &invalid_keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, NULL) == 1); + CHECK(memcmp_and_randomize(session_secrand[0], zeros132, sizeof(session_secrand[0])) == 0); + + /* Every in-argument except session_secrand and pubkey can be NULL */ + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], NULL, &pk[0], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk[1], &pk[1], NULL, NULL, NULL) == 1); + + /** Session creation with nonce_gen_counter **/ + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64) == 1); + CHECK_ILLEGAL(STATIC_CTX, secp256k1_musig_nonce_gen_counter(STATIC_CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, NULL, &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], NULL, nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + /* using nonce_gen_counter requires keypair */ + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, NULL, msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + /* invalid keypair */ + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &invalid_keypair, msg, &keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], NULL, &keyagg_cache, max64) == 1); + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, NULL, max64) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &invalid_keyagg_cache, max64)); + CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt,&keypair[0], msg, &keyagg_cache, NULL) == 1); + + /* Every in-argument except nonrepeating_cnt and keypair can be NULL */ + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce[1], &pubnonce[1], nonrepeating_cnt, &keypair[1], NULL, NULL, NULL) == 1); + + + /** Serialize and parse public nonces **/ + CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, NULL, &pubnonce[0])); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, NULL)); + CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &invalid_pubnonce)); + CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); + CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); + + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_parse(CTX, NULL, pubnonce_ser)); + CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], NULL)); + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], zeros132) == 0); + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); + + { + /* Check that serialize and parse results in the same value */ + secp256k1_musig_pubnonce tmp; + CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); + CHECK(secp256k1_musig_pubnonce_parse(CTX, &tmp, pubnonce_ser) == 1); + CHECK(secp256k1_memcmp_var(&tmp, &pubnonce[0], sizeof(tmp)) == 0); + } + + /** Receive nonces and aggregate **/ + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, NULL, pubnonce_ptr, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, NULL, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 0)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, invalid_pubnonce_ptr, 1)); + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, inf_pubnonce_ptr, 2) == 1); + { + /* Check that the aggnonce encodes two points at infinity */ + secp256k1_ge aggnonce_pt[2]; + secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce); + for (i = 0; i < 2; i++) { + secp256k1_ge_is_infinity(&aggnonce_pt[i]); + } + } + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + + /** Serialize and parse aggregate nonces **/ + CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, NULL, &aggnonce)); + CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, NULL)); + CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, (secp256k1_musig_aggnonce*) &invalid_pubnonce)); + CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); + CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); + + CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_parse(CTX, NULL, aggnonce_ser)); + CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_parse(CTX, &aggnonce, NULL)); + CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, zeros132) == 1); + CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); + + { + /* Check that serialize and parse results in the same value */ + secp256k1_musig_aggnonce tmp; + CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); + CHECK(secp256k1_musig_aggnonce_parse(CTX, &tmp, aggnonce_ser) == 1); + CHECK(secp256k1_memcmp_var(&tmp, &aggnonce, sizeof(tmp)) == 0); + } + + /** Process nonces **/ + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache)); + + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 1); + /* The secnonce is set to 0 and subsequent signing attempts fail */ + CHECK(secp256k1_memcmp_var(&secnonce_tmp, zeros132, sizeof(secnonce_tmp)) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, NULL, &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], NULL, &keypair[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &invalid_secnonce, &keypair[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, NULL, &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &invalid_keypair, &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + { + unsigned char sk_tmp[32]; + secp256k1_keypair keypair_tmp; + testrand256(sk_tmp); + CHECK(secp256k1_keypair_create(CTX, &keypair_tmp, sk_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair_tmp, &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + } + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], NULL, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &invalid_keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, NULL)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &invalid_session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], &keyagg_cache, &session) == 1); + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], &keyagg_cache, &session) == 1); + + CHECK(secp256k1_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, NULL, &partial_sig[0])); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, buf, NULL)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, buf, &invalid_partial_sig)); + CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], buf) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_parse(CTX, NULL, buf)); + { + /* Check that parsing failure results in an invalid sig */ + secp256k1_musig_partial_sig tmp; + CHECK(secp256k1_musig_partial_sig_parse(CTX, &tmp, max64) == 0); + CHECK(secp256k1_memcmp_var(&tmp, zeros132, sizeof(partial_sig[0])) == 0); + } + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], NULL)); + + { + /* Check that serialize and parse results in the same value */ + secp256k1_musig_partial_sig tmp; + CHECK(secp256k1_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); + CHECK(secp256k1_musig_partial_sig_parse(CTX, &tmp, buf) == 1); + CHECK(secp256k1_memcmp_var(&tmp, &partial_sig[0], sizeof(tmp)) == 0); + } + + /** Partial signature verification */ + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, NULL, &pubnonce[0], &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &invalid_partial_sig, &pubnonce[0], &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], NULL, &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &invalid_pubnonce, &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], NULL, &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &invalid_pk, &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], NULL, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &invalid_keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, NULL)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &invalid_session)); + + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], &keyagg_cache, &session) == 1); + + /** Signature aggregation and verification */ + CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, NULL, &session, partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, NULL, partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &invalid_session, partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, NULL, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, invalid_partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 0)); + CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 1) == 1); + CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); +} + +static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { + secp256k1_scalar k1[2], k2[2]; + + secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); + testrand_flip(args[n_flip], n_bytes); + secp256k1_nonce_function_musig(k2, args[0], args[1], args[2], args[3], args[4], args[5]); + CHECK(secp256k1_scalar_eq(&k1[0], &k2[0]) == 0); + CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0); +} + +static void musig_nonce_test(void) { + unsigned char *args[6]; + unsigned char session_secrand[32]; + unsigned char sk[32]; + unsigned char pk[33]; + unsigned char msg[32]; + unsigned char agg_pk[32]; + unsigned char extra_input[32]; + int i, j; + secp256k1_scalar k[6][2]; + + testrand_bytes_test(session_secrand, sizeof(session_secrand)); + testrand_bytes_test(sk, sizeof(sk)); + testrand_bytes_test(pk, sizeof(pk)); + testrand_bytes_test(msg, sizeof(msg)); + testrand_bytes_test(agg_pk, sizeof(agg_pk)); + testrand_bytes_test(extra_input, sizeof(extra_input)); + + /* Check that a bitflip in an argument results in different nonces. */ + args[0] = session_secrand; + args[1] = msg; + args[2] = sk; + args[3] = pk; + args[4] = agg_pk; + args[5] = extra_input; + for (i = 0; i < COUNT; i++) { + musig_nonce_bitflip(args, 0, sizeof(session_secrand)); + musig_nonce_bitflip(args, 1, sizeof(msg)); + musig_nonce_bitflip(args, 2, sizeof(sk)); + musig_nonce_bitflip(args, 3, sizeof(pk)); + musig_nonce_bitflip(args, 4, sizeof(agg_pk)); + musig_nonce_bitflip(args, 5, sizeof(extra_input)); + } + /* Check that if any argument is NULL, a different nonce is produced than if + * any other argument is NULL. */ + memcpy(msg, session_secrand, sizeof(msg)); + memcpy(sk, session_secrand, sizeof(sk)); + memcpy(pk, session_secrand, sizeof(session_secrand)); + memcpy(agg_pk, session_secrand, sizeof(agg_pk)); + memcpy(extra_input, session_secrand, sizeof(extra_input)); + secp256k1_nonce_function_musig(k[0], args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(k[1], args[0], NULL, args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(k[2], args[0], args[1], NULL, args[3], args[4], args[5]); + secp256k1_nonce_function_musig(k[3], args[0], args[1], args[2], NULL, args[4], args[5]); + secp256k1_nonce_function_musig(k[4], args[0], args[1], args[2], args[3], NULL, args[5]); + secp256k1_nonce_function_musig(k[5], args[0], args[1], args[2], args[3], args[4], NULL); + for (i = 0; i < 6; i++) { + CHECK(!secp256k1_scalar_eq(&k[i][0], &k[i][1])); + for (j = i+1; j < 6; j++) { + CHECK(!secp256k1_scalar_eq(&k[i][0], &k[j][0])); + CHECK(!secp256k1_scalar_eq(&k[i][1], &k[j][1])); + } + } +} + +static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { + secp256k1_sha256 sha; + secp256k1_sha256_initialize_tagged(&sha, tag, taglen); + test_sha256_eq(&sha, sha_tagged); +} + +/* Checks that the initialized tagged hashes have the expected + * state. */ +static void sha256_tag_test(void) { + secp256k1_sha256 sha; + { + char tag[] = "KeyAgg list"; + secp256k1_musig_keyagglist_sha256(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + char tag[] = "KeyAgg coefficient"; + secp256k1_musig_keyaggcoef_sha256(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + unsigned char tag[] = "MuSig/aux"; + secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + unsigned char tag[] = "MuSig/nonce"; + secp256k1_nonce_function_musig_sha256_tagged(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + unsigned char tag[] = "MuSig/noncecoef"; + secp256k1_musig_compute_noncehash_sha256_tagged(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } +} + +/* Attempts to create a signature for the aggregate public key using given secret + * keys and keyagg_cache. */ +static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigned char *sk0, const unsigned char *sk1, secp256k1_musig_keyagg_cache *keyagg_cache) { + secp256k1_pubkey pk[2]; + unsigned char session_secrand[2][32]; + unsigned char msg[32]; + secp256k1_musig_secnonce secnonce[2]; + secp256k1_musig_pubnonce pubnonce[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr[2]; + secp256k1_musig_aggnonce aggnonce; + secp256k1_keypair keypair[2]; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig[2]; + const secp256k1_musig_partial_sig *partial_sig_ptr[2]; + unsigned char final_sig[64]; + int i; + + for (i = 0; i < 2; i++) { + pubnonce_ptr[i] = &pubnonce[i]; + partial_sig_ptr[i] = &partial_sig[i]; + + testrand256(session_secrand[i]); + } + CHECK(create_keypair_and_pk(&keypair[0], &pk[0], sk0) == 1); + CHECK(create_keypair_and_pk(&keypair[1], &pk[1], sk1) == 1); + testrand256(msg); + + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk0, &pk[0], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk1, &pk[1], NULL, NULL, NULL) == 1); + + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache) == 1); + + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], keyagg_cache, &session) == 1); + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], keyagg_cache, &session) == 1); + + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], keyagg_cache, &session) == 1); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], keyagg_cache, &session) == 1); + + CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), agg_pk) == 1); +} + +/* Create aggregate public key P[0], tweak multiple times (using xonly and + * plain tweaking) and test signing. */ +static void musig_tweak_test(void) { + unsigned char sk[2][32]; + secp256k1_pubkey pk[2]; + const secp256k1_pubkey *pk_ptr[2]; + secp256k1_musig_keyagg_cache keyagg_cache; + enum { N_TWEAKS = 8 }; + secp256k1_pubkey P[N_TWEAKS + 1]; + secp256k1_xonly_pubkey P_xonly[N_TWEAKS + 1]; + int i; + + /* Key Setup */ + for (i = 0; i < 2; i++) { + pk_ptr[i] = &pk[i]; + testrand256(sk[i]); + CHECK(create_keypair_and_pk(NULL, &pk[i], sk[i]) == 1); + } + /* Compute P0 = keyagg(pk0, pk1) and test signing for it */ + CHECK(secp256k1_musig_pubkey_agg(CTX, &P_xonly[0], &keyagg_cache, pk_ptr, 2) == 1); + musig_tweak_test_helper(&P_xonly[0], sk[0], sk[1], &keyagg_cache); + CHECK(secp256k1_musig_pubkey_get(CTX, &P[0], &keyagg_cache)); + + /* Compute Pi = f(Pj) + tweaki*G where where j = i-1 and try signing for + * that key. If xonly is set to true, the function f normalizes the input + * point to have an even X-coordinate ("xonly-tweaking"). + * Otherwise, the function f is the identity function. */ + for (i = 1; i <= N_TWEAKS; i++) { + unsigned char tweak[32]; + int P_parity; + int xonly = testrand_bits(1); + + testrand256(tweak); + if (xonly) { + CHECK(secp256k1_musig_pubkey_xonly_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); + } else { + CHECK(secp256k1_musig_pubkey_ec_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); + } + CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &P_xonly[i], &P_parity, &P[i])); + /* Check that musig_pubkey_tweak_add produces same result as + * xonly_pubkey_tweak_add or ec_pubkey_tweak_add. */ + if (xonly) { + unsigned char P_serialized[32]; + CHECK(secp256k1_xonly_pubkey_serialize(CTX, P_serialized, &P_xonly[i])); + CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, P_serialized, P_parity, &P_xonly[i-1], tweak) == 1); + } else { + secp256k1_pubkey tmp_key = P[i-1]; + CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &tmp_key, tweak)); + CHECK(secp256k1_memcmp_var(&tmp_key, &P[i], sizeof(tmp_key)) == 0); + } + /* Test signing for P[i] */ + musig_tweak_test_helper(&P_xonly[i], sk[0], sk[1], &keyagg_cache); + } +} + +int musig_vectors_keyagg_and_tweak(enum MUSIG_ERROR *error, + secp256k1_musig_keyagg_cache *keyagg_cache, + unsigned char *agg_pk_ser, + const unsigned char pubkeys33[][33], + const unsigned char tweaks32[][32], + size_t key_indices_len, + const size_t *key_indices, + size_t tweak_indices_len, + const size_t *tweak_indices, + const int *is_xonly) { + secp256k1_pubkey pubkeys[MUSIG_VECTORS_MAX_PUBKEYS]; + const secp256k1_pubkey *pk_ptr[MUSIG_VECTORS_MAX_PUBKEYS]; + int i; + secp256k1_pubkey agg_pk; + secp256k1_xonly_pubkey agg_pk_xonly; + + for (i = 0; i < (int)key_indices_len; i++) { + if (!secp256k1_ec_pubkey_parse(CTX, &pubkeys[i], pubkeys33[key_indices[i]], 33)) { + *error = MUSIG_PUBKEY; + return 0; + } + pk_ptr[i] = &pubkeys[i]; + } + if (!secp256k1_musig_pubkey_agg(CTX, NULL, keyagg_cache, pk_ptr, key_indices_len)) { + *error = MUSIG_OTHER; + return 0; + } + + for (i = 0; i < (int)tweak_indices_len; i++) { + if (is_xonly[i]) { + if (!secp256k1_musig_pubkey_xonly_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { + *error = MUSIG_TWEAK; + return 0; + } + } else { + if (!secp256k1_musig_pubkey_ec_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { + *error = MUSIG_TWEAK; + return 0; + } + } + } + if (!secp256k1_musig_pubkey_get(CTX, &agg_pk, keyagg_cache)) { + *error = MUSIG_OTHER; + return 0; + } + + if (!secp256k1_xonly_pubkey_from_pubkey(CTX, &agg_pk_xonly, NULL, &agg_pk)) { + *error = MUSIG_OTHER; + return 0; + } + + if (agg_pk_ser != NULL) { + if (!secp256k1_xonly_pubkey_serialize(CTX, agg_pk_ser, &agg_pk_xonly)) { + *error = MUSIG_OTHER; + return 0; + } + } + + return 1; +} + +static void musig_test_vectors_keyagg(void) { + size_t i; + const struct musig_key_agg_vector *vector = &musig_key_agg_vector; + + for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + const struct musig_key_agg_valid_test_case *c = &vector->valid_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + unsigned char agg_pk[32]; + + CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, 0, NULL, NULL)); + CHECK(secp256k1_memcmp_var(agg_pk, c->expected, sizeof(agg_pk)) == 0); + } + + for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + const struct musig_key_agg_error_test_case *c = &vector->error_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + + CHECK(!musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); + CHECK(c->error == error); + } +} + +static void musig_test_vectors_noncegen(void) { + size_t i; + const struct musig_nonce_gen_vector *vector = &musig_nonce_gen_vector; + + for (i = 0; i < sizeof(vector->test_case)/sizeof(vector->test_case[0]); i++) { + const struct musig_nonce_gen_test_case *c = &vector->test_case[i]; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_musig_keyagg_cache *keyagg_cache_ptr = NULL; + unsigned char session_secrand32[32]; + secp256k1_musig_secnonce secnonce; + secp256k1_musig_pubnonce pubnonce; + const unsigned char *sk = NULL; + const unsigned char *msg = NULL; + const unsigned char *extra_in = NULL; + secp256k1_pubkey pk; + unsigned char pubnonce66[66]; + + memcpy(session_secrand32, c->rand_, 32); + if (c->has_sk) { + sk = c->sk; + } + if (c->has_aggpk) { + /* Create keyagg_cache from aggpk */ + secp256k1_keyagg_cache_internal cache_i; + secp256k1_xonly_pubkey aggpk; + memset(&cache_i, 0, sizeof(cache_i)); + CHECK(secp256k1_xonly_pubkey_parse(CTX, &aggpk, c->aggpk)); + CHECK(secp256k1_xonly_pubkey_load(CTX, &cache_i.pk, &aggpk)); + secp256k1_keyagg_cache_save(&keyagg_cache, &cache_i); + keyagg_cache_ptr = &keyagg_cache; + } + if (c->has_msg) { + msg = c->msg; + } + if (c->has_extra_in) { + extra_in = c->extra_in; + } + + CHECK(secp256k1_ec_pubkey_parse(CTX, &pk, c->pk, sizeof(c->pk))); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce, &pubnonce, session_secrand32, sk, &pk, msg, keyagg_cache_ptr, extra_in) == 1); + CHECK(secp256k1_memcmp_var(&secnonce.data[4], c->expected_secnonce, 2*32) == 0); + /* The last element of the secnonce is the public key (uncompressed in + * secp256k1_musig_secnonce, compressed in the test vector secnonce). */ + CHECK(secp256k1_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); + CHECK(secp256k1_memcmp_var(&c->expected_secnonce[2*32], c->pk, sizeof(c->pk)) == 0); + + CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); + CHECK(sizeof(c->expected_pubnonce) == sizeof(pubnonce66)); + CHECK(secp256k1_memcmp_var(pubnonce66, c->expected_pubnonce, sizeof(pubnonce66)) == 0); + } +} + + +static void musig_test_vectors_nonceagg(void) { + size_t i; + int j; + const struct musig_nonce_agg_vector *vector = &musig_nonce_agg_vector; + + for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + const struct musig_nonce_agg_test_case *c = &vector->valid_case[i]; + secp256k1_musig_pubnonce pubnonce[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr[2]; + secp256k1_musig_aggnonce aggnonce; + unsigned char aggnonce66[66]; + + for (j = 0; j < 2; j++) { + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]]) == 1); + pubnonce_ptr[j] = &pubnonce[j]; + } + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2)); + CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce)); + CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, 33) == 0); + } + for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + const struct musig_nonce_agg_test_case *c = &vector->error_case[i]; + secp256k1_musig_pubnonce pubnonce[2]; + for (j = 0; j < 2; j++) { + int expected = c->invalid_nonce_idx != j; + CHECK(expected == secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]])); + } + } +} + +static void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned char *secnonce64, const secp256k1_pubkey *pubkey) { + secp256k1_ge pk; + secp256k1_scalar k[2]; + + secp256k1_scalar_set_b32(&k[0], &secnonce64[0], NULL); + secp256k1_scalar_set_b32(&k[1], &secnonce64[32], NULL); + CHECK(secp256k1_pubkey_load(CTX, &pk, pubkey)); + secp256k1_musig_secnonce_save(secnonce, k, &pk); +} + +static void musig_test_vectors_signverify(void) { + size_t i; + const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector; + + for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + const struct musig_valid_case *c = &vector->valid_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_pubkey pubkey; + secp256k1_musig_pubnonce pubnonce; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig; + secp256k1_musig_secnonce secnonce; + secp256k1_keypair keypair; + unsigned char partial_sig32[32]; + + CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); + CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); + + CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey); + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); + CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); + + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[0])); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); + } + for (i = 0; i < sizeof(vector->sign_error_case)/sizeof(vector->sign_error_case[0]); i++) { + const struct musig_sign_error_case *c = &vector->sign_error_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_pubkey pubkey; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig; + secp256k1_musig_secnonce secnonce; + secp256k1_keypair keypair; + int expected; + + if (i == 0) { + /* Skip this vector since the implementation does not error out when + * the signing key does not belong to any pubkey. */ + continue; + } + expected = c->error != MUSIG_PUBKEY; + CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); + CHECK(expected || c->error == error); + if (!expected) { + continue; + } + + expected = c->error != MUSIG_AGGNONCE; + CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); + if (!expected) { + continue; + } + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); + expected = c->error != MUSIG_SECNONCE; + if (expected) { + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + } else { + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + } + } + for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) { + const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig; + enum { NUM_PUBNONCES = 3 }; + secp256k1_musig_pubnonce pubnonce[NUM_PUBNONCES]; + const secp256k1_musig_pubnonce *pubnonce_ptr[NUM_PUBNONCES]; + secp256k1_pubkey pubkey; + int expected; + size_t j; + + CHECK(NUM_PUBNONCES <= c->nonce_indices_len); + for (j = 0; j < c->nonce_indices_len; j++) { + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pubnonces[c->nonce_indices[j]])); + pubnonce_ptr[j] = &pubnonce[j]; + } + + CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, c->nonce_indices_len) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[c->signer_index], sizeof(vector->pubkeys[0]))); + + expected = c->error != MUSIG_SIG; + CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig, c->sig)); + if (!expected) { + continue; + } + expected = c->error != MUSIG_SIG_VERIFY; + CHECK(expected == secp256k1_musig_partial_sig_verify(CTX, &partial_sig, pubnonce, &pubkey, &keyagg_cache, &session)); + } + for (i = 0; i < sizeof(vector->verify_error_case)/sizeof(vector->verify_error_case[0]); i++) { + const struct musig_verify_fail_error_case *c = &vector->verify_error_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_musig_pubnonce pubnonce; + int expected; + + expected = c->error != MUSIG_PUBKEY; + CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); + CHECK(expected || c->error == error); + if (!expected) { + continue; + } + expected = c->error != MUSIG_PUBNONCE; + CHECK(expected == secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); + } +} + +static void musig_test_vectors_tweak(void) { + size_t i; + const struct musig_tweak_vector *vector = &musig_tweak_vector; + secp256k1_pubkey pubkey; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_secnonce secnonce; + + CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonce)); + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + + for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + const struct musig_tweak_case *c = &vector->valid_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + secp256k1_musig_pubnonce pubnonce; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig; + secp256k1_keypair keypair; + unsigned char partial_sig32[32]; + + musig_test_set_secnonce(&secnonce, vector->secnonce, &pubkey); + + CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); + CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); + + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); + + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); + CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); + + CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); + } + for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + const struct musig_tweak_case *c = &vector->error_case[i]; + enum MUSIG_ERROR error; + secp256k1_musig_keyagg_cache keyagg_cache; + CHECK(!musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); + CHECK(error == MUSIG_TWEAK); + } +} + +static void musig_test_vectors_sigagg(void) { + size_t i, j; + const struct musig_sig_agg_vector *vector = &musig_sig_agg_vector; + + for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + const struct musig_sig_agg_case *c = &vector->valid_case[i]; + enum MUSIG_ERROR error; + unsigned char final_sig[64]; + secp256k1_musig_keyagg_cache keyagg_cache; + unsigned char agg_pk32[32]; + secp256k1_xonly_pubkey agg_pk; + secp256k1_musig_aggnonce aggnonce; + secp256k1_musig_session session; + secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; + const secp256k1_musig_partial_sig *partial_sig_ptr[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; + + CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk32, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); + CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); + for (j = 0; j < c->psig_indices_len; j++) { + CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); + partial_sig_ptr[j] = &partial_sig[j]; + } + + CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, c->psig_indices_len) == 1); + CHECK(secp256k1_memcmp_var(final_sig, c->expected, sizeof(final_sig)) == 0); + + CHECK(secp256k1_xonly_pubkey_parse(CTX, &agg_pk, agg_pk32)); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, vector->msg, sizeof(vector->msg), &agg_pk) == 1); + } + for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + const struct musig_sig_agg_case *c = &vector->error_case[i]; + secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; + for (j = 0; j < c->psig_indices_len; j++) { + int expected = c->invalid_sig_idx != (int)j; + CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); + } + } +} + +/* Since the BIP doesn't provide static test vectors for nonce_gen_counter, we + * define a static test here */ +static void musig_test_static_nonce_gen_counter(void) { + secp256k1_musig_secnonce secnonce; + secp256k1_musig_pubnonce pubnonce; + unsigned char pubnonce66[66]; + secp256k1_pubkey pk; + secp256k1_keypair keypair; + uint64_t nonrepeating_cnt = 0; + unsigned char sk[32] = { + 0xEE, 0xC1, 0xCB, 0x7D, 0x1B, 0x72, 0x54, 0xC5, + 0xCA, 0xB0, 0xD9, 0xC6, 0x1A, 0xB0, 0x2E, 0x64, + 0x3D, 0x46, 0x4A, 0x59, 0xFE, 0x6C, 0x96, 0xA7, + 0xEF, 0xE8, 0x71, 0xF0, 0x7C, 0x5A, 0xEF, 0x54, + }; + unsigned char expected_secnonce[64] = { + 0x84, 0x2F, 0x13, 0x80, 0xCD, 0x17, 0xA1, 0x98, + 0xFC, 0x3D, 0xAD, 0x3B, 0x7D, 0xA7, 0x49, 0x29, + 0x41, 0xF4, 0x69, 0x76, 0xF2, 0x70, 0x2F, 0xF7, + 0xC6, 0x6F, 0x24, 0xF4, 0x72, 0x03, 0x6A, 0xF1, + 0xDA, 0x3F, 0x95, 0x2D, 0xDE, 0x4A, 0x2D, 0xA6, + 0xB6, 0x32, 0x57, 0x07, 0xCE, 0x87, 0xA4, 0xE3, + 0x61, 0x6D, 0x06, 0xFC, 0x5F, 0x81, 0xA9, 0xC9, + 0x93, 0x86, 0xD2, 0x0A, 0x99, 0xCE, 0xCF, 0x99, + }; + unsigned char expected_pubnonce[66] = { + 0x03, 0xA5, 0xB9, 0xB6, 0x90, 0x79, 0x42, 0xEA, + 0xCD, 0xDA, 0x49, 0xA3, 0x66, 0x01, 0x6E, 0xC2, + 0xE6, 0x24, 0x04, 0xA1, 0xBF, 0x4A, 0xB6, 0xD4, + 0xDB, 0x82, 0x06, 0x7B, 0xC3, 0xAD, 0xF0, 0x86, + 0xD7, 0x03, 0x32, 0x05, 0xDB, 0x9E, 0xB3, 0x4D, + 0x5C, 0x7C, 0xE0, 0x28, 0x48, 0xCA, 0xC6, 0x8A, + 0x83, 0xED, 0x73, 0xE3, 0x88, 0x34, 0x77, 0xF5, + 0x63, 0xF2, 0x3C, 0xE9, 0xA1, 0x1A, 0x77, 0x21, + 0xEC, 0x64, + }; + + CHECK(secp256k1_keypair_create(CTX, &keypair, sk)); + CHECK(secp256k1_keypair_pub(CTX, &pk, &keypair)); + CHECK(secp256k1_musig_nonce_gen_counter(CTX, &secnonce, &pubnonce, nonrepeating_cnt, &keypair, NULL, NULL, NULL) == 1); + + CHECK(secp256k1_memcmp_var(&secnonce.data[4], expected_secnonce, 2*32) == 0); + CHECK(secp256k1_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); + + CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); + CHECK(secp256k1_memcmp_var(pubnonce66, expected_pubnonce, sizeof(pubnonce66)) == 0); +} + +static void run_musig_tests(void) { + int i; + + for (i = 0; i < COUNT; i++) { + musig_simple_test(); + } + musig_api_tests(); + musig_nonce_test(); + for (i = 0; i < COUNT; i++) { + /* Run multiple times to ensure that pk and nonce have different y + * parities */ + musig_tweak_test(); + } + sha256_tag_test(); + musig_test_vectors_keyagg(); + musig_test_vectors_noncegen(); + musig_test_vectors_nonceagg(); + musig_test_vectors_signverify(); + musig_test_vectors_tweak(); + musig_test_vectors_sigagg(); + + musig_test_static_nonce_gen_counter(); +} + +#endif diff --git a/src/modules/musig/vectors.h b/src/modules/musig/vectors.h new file mode 100644 index 00000000..8407c2a6 --- /dev/null +++ b/src/modules/musig/vectors.h @@ -0,0 +1,346 @@ +/** + * Automatically generated by ./tools/test_vectors_musig2_generate.py. + * + * The test vectors for the KeySort function are included in this file. They can + * be found in src/modules/extrakeys/tests_impl.h. */ + +enum MUSIG_ERROR { + MUSIG_PUBKEY, + MUSIG_TWEAK, + MUSIG_PUBNONCE, + MUSIG_AGGNONCE, + MUSIG_SECNONCE, + MUSIG_SIG, + MUSIG_SIG_VERIFY, + MUSIG_OTHER +}; + +struct musig_key_agg_valid_test_case { + size_t key_indices_len; + size_t key_indices[4]; + unsigned char expected[32]; +}; + +struct musig_key_agg_error_test_case { + size_t key_indices_len; + size_t key_indices[4]; + size_t tweak_indices_len; + size_t tweak_indices[1]; + int is_xonly[1]; + enum MUSIG_ERROR error; +}; + +struct musig_key_agg_vector { + unsigned char pubkeys[7][33]; + unsigned char tweaks[2][32]; + struct musig_key_agg_valid_test_case valid_case[4]; + struct musig_key_agg_error_test_case error_case[5]; +}; + +static const struct musig_key_agg_vector musig_key_agg_vector = { + { + { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, + { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }, + { 0x02, 0x35, 0x90, 0xA9, 0x4E, 0x76, 0x8F, 0x8E, 0x18, 0x15, 0xC2, 0xF2, 0x4B, 0x4D, 0x80, 0xA8, 0xE3, 0x14, 0x93, 0x16, 0xC3, 0x51, 0x8C, 0xE7, 0xB7, 0xAD, 0x33, 0x83, 0x68, 0xD0, 0x38, 0xCA, 0x66 }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 }, + { 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 }, + { 0x04, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, + { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 } + }, + { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }, + { 0x25, 0x2E, 0x4B, 0xD6, 0x74, 0x10, 0xA7, 0x6C, 0xDF, 0x93, 0x3D, 0x30, 0xEA, 0xA1, 0x60, 0x82, 0x14, 0x03, 0x7F, 0x1B, 0x10, 0x5A, 0x01, 0x3E, 0xCC, 0xD3, 0xC5, 0xC1, 0x84, 0xA6, 0x11, 0x0B } + }, + { + { 3, { 0, 1, 2 }, { 0x90, 0x53, 0x9E, 0xED, 0xE5, 0x65, 0xF5, 0xD0, 0x54, 0xF3, 0x2C, 0xC0, 0xC2, 0x20, 0x12, 0x68, 0x89, 0xED, 0x1E, 0x5D, 0x19, 0x3B, 0xAF, 0x15, 0xAE, 0xF3, 0x44, 0xFE, 0x59, 0xD4, 0x61, 0x0C }}, + { 3, { 2, 1, 0 }, { 0x62, 0x04, 0xDE, 0x8B, 0x08, 0x34, 0x26, 0xDC, 0x6E, 0xAF, 0x95, 0x02, 0xD2, 0x70, 0x24, 0xD5, 0x3F, 0xC8, 0x26, 0xBF, 0x7D, 0x20, 0x12, 0x14, 0x8A, 0x05, 0x75, 0x43, 0x5D, 0xF5, 0x4B, 0x2B }}, + { 3, { 0, 0, 0 }, { 0xB4, 0x36, 0xE3, 0xBA, 0xD6, 0x2B, 0x8C, 0xD4, 0x09, 0x96, 0x9A, 0x22, 0x47, 0x31, 0xC1, 0x93, 0xD0, 0x51, 0x16, 0x2D, 0x8C, 0x5A, 0xE8, 0xB1, 0x09, 0x30, 0x61, 0x27, 0xDA, 0x3A, 0xA9, 0x35 }}, + { 4, { 0, 0, 1, 1 }, { 0x69, 0xBC, 0x22, 0xBF, 0xA5, 0xD1, 0x06, 0x30, 0x6E, 0x48, 0xA2, 0x06, 0x79, 0xDE, 0x1D, 0x73, 0x89, 0x38, 0x61, 0x24, 0xD0, 0x75, 0x71, 0xD0, 0xD8, 0x72, 0x68, 0x60, 0x28, 0xC2, 0x6A, 0x3E }}, + }, + { + { 2, { 0, 3 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, + { 2, { 0, 4 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, + { 2, { 5, 0 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, + { 2, { 0, 1 }, 1, { 0 }, { 1 }, MUSIG_TWEAK }, + { 1, { 6 }, 1, { 1 }, { 0 }, MUSIG_TWEAK }, + }, +}; + +struct musig_nonce_gen_test_case { + unsigned char rand_[32]; + int has_sk; + unsigned char sk[32]; + unsigned char pk[33]; + int has_aggpk; + unsigned char aggpk[32]; + int has_msg; + unsigned char msg[32]; + int has_extra_in; + unsigned char extra_in[32]; + unsigned char expected_secnonce[97]; + unsigned char expected_pubnonce[66]; +}; + +struct musig_nonce_gen_vector { + struct musig_nonce_gen_test_case test_case[2]; +}; + +static const struct musig_nonce_gen_vector musig_nonce_gen_vector = { + { + { { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }, 1 , { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, { 0x02, 0x4D, 0x4B, 0x6C, 0xD1, 0x36, 0x10, 0x32, 0xCA, 0x9B, 0xD2, 0xAE, 0xB9, 0xD9, 0x00, 0xAA, 0x4D, 0x45, 0xD9, 0xEA, 0xD8, 0x0A, 0xC9, 0x42, 0x33, 0x74, 0xC4, 0x51, 0xA7, 0x25, 0x4D, 0x07, 0x66 }, 1 , { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }, 1 , { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, 1 , { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0xB1, 0x14, 0xE5, 0x02, 0xBE, 0xAA, 0x4E, 0x30, 0x1D, 0xD0, 0x8A, 0x50, 0x26, 0x41, 0x72, 0xC8, 0x4E, 0x41, 0x65, 0x0E, 0x6C, 0xB7, 0x26, 0xB4, 0x10, 0xC0, 0x69, 0x4D, 0x59, 0xEF, 0xFB, 0x64, 0x95, 0xB5, 0xCA, 0xF2, 0x8D, 0x04, 0x5B, 0x97, 0x3D, 0x63, 0xE3, 0xC9, 0x9A, 0x44, 0xB8, 0x07, 0xBD, 0xE3, 0x75, 0xFD, 0x6C, 0xB3, 0x9E, 0x46, 0xDC, 0x4A, 0x51, 0x17, 0x08, 0xD0, 0xE9, 0xD2, 0x02, 0x4D, 0x4B, 0x6C, 0xD1, 0x36, 0x10, 0x32, 0xCA, 0x9B, 0xD2, 0xAE, 0xB9, 0xD9, 0x00, 0xAA, 0x4D, 0x45, 0xD9, 0xEA, 0xD8, 0x0A, 0xC9, 0x42, 0x33, 0x74, 0xC4, 0x51, 0xA7, 0x25, 0x4D, 0x07, 0x66 }, { 0x02, 0xF7, 0xBE, 0x70, 0x89, 0xE8, 0x37, 0x6E, 0xB3, 0x55, 0x27, 0x23, 0x68, 0x76, 0x6B, 0x17, 0xE8, 0x8E, 0x7D, 0xB7, 0x20, 0x47, 0xD0, 0x5E, 0x56, 0xAA, 0x88, 0x1E, 0xA5, 0x2B, 0x3B, 0x35, 0xDF, 0x02, 0xC2, 0x9C, 0x80, 0x46, 0xFD, 0xD0, 0xDE, 0xD4, 0xC7, 0xE5, 0x58, 0x69, 0x13, 0x72, 0x00, 0xFB, 0xDB, 0xFE, 0x2E, 0xB6, 0x54, 0x26, 0x7B, 0x6D, 0x70, 0x13, 0x60, 0x2C, 0xAE, 0xD3, 0x11, 0x5A } }, + { { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }, 0 , { 0 }, { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, 0 , { 0 }, 0 , { 0 }, 0 , { 0 }, { 0x89, 0xBD, 0xD7, 0x87, 0xD0, 0x28, 0x4E, 0x5E, 0x4D, 0x5F, 0xC5, 0x72, 0xE4, 0x9E, 0x31, 0x6B, 0xAB, 0x7E, 0x21, 0xE3, 0xB1, 0x83, 0x0D, 0xE3, 0x7D, 0xFE, 0x80, 0x15, 0x6F, 0xA4, 0x1A, 0x6D, 0x0B, 0x17, 0xAE, 0x8D, 0x02, 0x4C, 0x53, 0x67, 0x96, 0x99, 0xA6, 0xFD, 0x79, 0x44, 0xD9, 0xC4, 0xA3, 0x66, 0xB5, 0x14, 0xBA, 0xF4, 0x30, 0x88, 0xE0, 0x70, 0x8B, 0x10, 0x23, 0xDD, 0x28, 0x97, 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, { 0x02, 0xC9, 0x6E, 0x7C, 0xB1, 0xE8, 0xAA, 0x5D, 0xAC, 0x64, 0xD8, 0x72, 0x94, 0x79, 0x14, 0x19, 0x8F, 0x60, 0x7D, 0x90, 0xEC, 0xDE, 0x52, 0x00, 0xDE, 0x52, 0x97, 0x8A, 0xD5, 0xDE, 0xD6, 0x3C, 0x00, 0x02, 0x99, 0xEC, 0x51, 0x17, 0xC2, 0xD2, 0x9E, 0xDE, 0xE8, 0xA2, 0x09, 0x25, 0x87, 0xC3, 0x90, 0x9B, 0xE6, 0x94, 0xD5, 0xCF, 0xF0, 0x66, 0x7D, 0x6C, 0x02, 0xEA, 0x40, 0x59, 0xF7, 0xCD, 0x97, 0x86 } }, + }, +}; + +struct musig_nonce_agg_test_case { + size_t pnonce_indices[2]; + /* if valid case */ + unsigned char expected[66]; + /* if error case */ + int invalid_nonce_idx; +}; + +struct musig_nonce_agg_vector { + unsigned char pnonces[7][66]; + struct musig_nonce_agg_test_case valid_case[2]; + struct musig_nonce_agg_test_case error_case[3]; +}; + +static const struct musig_nonce_agg_vector musig_nonce_agg_vector = { + { + { 0x02, 0x01, 0x51, 0xC8, 0x0F, 0x43, 0x56, 0x48, 0xDF, 0x67, 0xA2, 0x2B, 0x74, 0x9C, 0xD7, 0x98, 0xCE, 0x54, 0xE0, 0x32, 0x1D, 0x03, 0x4B, 0x92, 0xB7, 0x09, 0xB5, 0x67, 0xD6, 0x0A, 0x42, 0xE6, 0x66, 0x03, 0xBA, 0x47, 0xFB, 0xC1, 0x83, 0x44, 0x37, 0xB3, 0x21, 0x2E, 0x89, 0xA8, 0x4D, 0x84, 0x25, 0xE7, 0xBF, 0x12, 0xE0, 0x24, 0x5D, 0x98, 0x26, 0x22, 0x68, 0xEB, 0xDC, 0xB3, 0x85, 0xD5, 0x06, 0x41 }, + { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x33 }, + { 0x02, 0x01, 0x51, 0xC8, 0x0F, 0x43, 0x56, 0x48, 0xDF, 0x67, 0xA2, 0x2B, 0x74, 0x9C, 0xD7, 0x98, 0xCE, 0x54, 0xE0, 0x32, 0x1D, 0x03, 0x4B, 0x92, 0xB7, 0x09, 0xB5, 0x67, 0xD6, 0x0A, 0x42, 0xE6, 0x66, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, + { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x03, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, + { 0x04, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x33 }, + { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x31 }, + { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 } + }, + { + { { 0, 1 }, { 0x03, 0x5F, 0xE1, 0x87, 0x3B, 0x4F, 0x29, 0x67, 0xF5, 0x2F, 0xEA, 0x4A, 0x06, 0xAD, 0x5A, 0x8E, 0xCC, 0xBE, 0x9D, 0x0F, 0xD7, 0x30, 0x68, 0x01, 0x2C, 0x89, 0x4E, 0x2E, 0x87, 0xCC, 0xB5, 0x80, 0x4B, 0x02, 0x47, 0x25, 0x37, 0x73, 0x45, 0xBD, 0xE0, 0xE9, 0xC3, 0x3A, 0xF3, 0xC4, 0x3C, 0x0A, 0x29, 0xA9, 0x24, 0x9F, 0x2F, 0x29, 0x56, 0xFA, 0x8C, 0xFE, 0xB5, 0x5C, 0x85, 0x73, 0xD0, 0x26, 0x2D, 0xC8 }, 0 }, + { { 2, 3 }, { 0x03, 0x5F, 0xE1, 0x87, 0x3B, 0x4F, 0x29, 0x67, 0xF5, 0x2F, 0xEA, 0x4A, 0x06, 0xAD, 0x5A, 0x8E, 0xCC, 0xBE, 0x9D, 0x0F, 0xD7, 0x30, 0x68, 0x01, 0x2C, 0x89, 0x4E, 0x2E, 0x87, 0xCC, 0xB5, 0x80, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0 }, + }, + { + { { 0, 4 }, { 0 }, 1 }, + { { 5, 1 }, { 0 }, 0 }, + { { 6, 1 }, { 0 }, 0 }, + }, +}; + +/* Omit pubnonces in the test vectors because our partial signature verification + * implementation is able to accept the aggnonce directly. */ +struct musig_valid_case { + size_t key_indices_len; + size_t key_indices[3]; + size_t aggnonce_index; + size_t msg_index; + size_t signer_index; + unsigned char expected[32]; +}; + +struct musig_sign_error_case { + size_t key_indices_len; + size_t key_indices[3]; + size_t aggnonce_index; + size_t msg_index; + size_t secnonce_index; + enum MUSIG_ERROR error; +}; + +struct musig_verify_fail_error_case { + unsigned char sig[32]; + size_t key_indices_len; + size_t key_indices[3]; + size_t nonce_indices_len; + size_t nonce_indices[3]; + size_t msg_index; + size_t signer_index; + enum MUSIG_ERROR error; +}; + +struct musig_sign_verify_vector { + unsigned char sk[32]; + unsigned char pubkeys[4][33]; + unsigned char secnonces[2][194]; + unsigned char pubnonces[5][194]; + unsigned char aggnonces[5][66]; + unsigned char msgs[1][32]; + struct musig_valid_case valid_case[4]; + struct musig_sign_error_case sign_error_case[6]; + struct musig_verify_fail_error_case verify_fail_case[3]; + struct musig_verify_fail_error_case verify_error_case[2]; +}; + +static const struct musig_sign_verify_vector musig_sign_verify_vector = { + { 0x7F, 0xB9, 0xE0, 0xE6, 0x87, 0xAD, 0xA1, 0xEE, 0xBF, 0x7E, 0xCF, 0xE2, 0xF2, 0x1E, 0x73, 0xEB, 0xDB, 0x51, 0xA7, 0xD4, 0x50, 0x94, 0x8D, 0xFE, 0x8D, 0x76, 0xD7, 0xF2, 0xD1, 0x00, 0x76, 0x71 }, + { + { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, + { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, + { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x61 }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 } + }, + { + { 0x50, 0x8B, 0x81, 0xA6, 0x11, 0xF1, 0x00, 0xA6, 0xB2, 0xB6, 0xB2, 0x96, 0x56, 0x59, 0x08, 0x98, 0xAF, 0x48, 0x8B, 0xCF, 0x2E, 0x1F, 0x55, 0xCF, 0x22, 0xE5, 0xCF, 0xB8, 0x44, 0x21, 0xFE, 0x61, 0xFA, 0x27, 0xFD, 0x49, 0xB1, 0xD5, 0x00, 0x85, 0xB4, 0x81, 0x28, 0x5E, 0x1C, 0xA2, 0x05, 0xD5, 0x5C, 0x82, 0xCC, 0x1B, 0x31, 0xFF, 0x5C, 0xD5, 0x4A, 0x48, 0x98, 0x29, 0x35, 0x59, 0x01, 0xF7, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 } + }, + { + { 0x03, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, + { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, + { 0x03, 0x2D, 0xE2, 0x66, 0x26, 0x28, 0xC9, 0x0B, 0x03, 0xF5, 0xE7, 0x20, 0x28, 0x4E, 0xB5, 0x2F, 0xF7, 0xD7, 0x1F, 0x42, 0x84, 0xF6, 0x27, 0xB6, 0x8A, 0x85, 0x3D, 0x78, 0xC7, 0x8E, 0x1F, 0xFE, 0x93, 0x03, 0xE4, 0xC5, 0x52, 0x4E, 0x83, 0xFF, 0xE1, 0x49, 0x3B, 0x90, 0x77, 0xCF, 0x1C, 0xA6, 0xBE, 0xB2, 0x09, 0x0C, 0x93, 0xD9, 0x30, 0x32, 0x10, 0x71, 0xAD, 0x40, 0xB2, 0xF4, 0x4E, 0x59, 0x90, 0x46 }, + { 0x02, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x03, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 } + }, + { + { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x04, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, + { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }, + { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 } + }, + { + { 0xF9, 0x54, 0x66, 0xD0, 0x86, 0x77, 0x0E, 0x68, 0x99, 0x64, 0x66, 0x42, 0x19, 0x26, 0x6F, 0xE5, 0xED, 0x21, 0x5C, 0x92, 0xAE, 0x20, 0xBA, 0xB5, 0xC9, 0xD7, 0x9A, 0xDD, 0xDD, 0xF3, 0xC0, 0xCF } + }, + { + { 3, { 0, 1, 2 }, 0, 0, 0, { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }}, + { 3, { 1, 0, 2 }, 0, 0, 1, { 0x9F, 0xF2, 0xF7, 0xAA, 0xA8, 0x56, 0x15, 0x0C, 0xC8, 0x81, 0x92, 0x54, 0x21, 0x8D, 0x3A, 0xDE, 0xEB, 0x05, 0x35, 0x26, 0x90, 0x51, 0x89, 0x77, 0x24, 0xF9, 0xDB, 0x37, 0x89, 0x51, 0x3A, 0x52 }}, + { 3, { 1, 2, 0 }, 0, 0, 2, { 0xFA, 0x23, 0xC3, 0x59, 0xF6, 0xFA, 0xC4, 0xE7, 0x79, 0x6B, 0xB9, 0x3B, 0xC9, 0xF0, 0x53, 0x2A, 0x95, 0x46, 0x8C, 0x53, 0x9B, 0xA2, 0x0F, 0xF8, 0x6D, 0x7C, 0x76, 0xED, 0x92, 0x22, 0x79, 0x00 }}, + { 2, { 0, 1 }, 1, 0, 0, { 0xAE, 0x38, 0x60, 0x64, 0xB2, 0x61, 0x05, 0x40, 0x47, 0x98, 0xF7, 0x5D, 0xE2, 0xEB, 0x9A, 0xF5, 0xED, 0xA5, 0x38, 0x7B, 0x06, 0x4B, 0x83, 0xD0, 0x49, 0xCB, 0x7C, 0x5E, 0x08, 0x87, 0x95, 0x31 }}, + }, + { + { 2, { 1, 2 }, 0, 0, 0, MUSIG_PUBKEY }, + { 3, { 1, 0, 3 }, 0, 0, 0, MUSIG_PUBKEY }, + { 3, { 1, 2, 0 }, 2, 0, 0, MUSIG_AGGNONCE }, + { 3, { 1, 2, 0 }, 3, 0, 0, MUSIG_AGGNONCE }, + { 3, { 1, 2, 0 }, 4, 0, 0, MUSIG_AGGNONCE }, + { 3, { 0, 1, 2 }, 0, 0, 1, MUSIG_SECNONCE }, + }, + { + { { 0xFE, 0xD5, 0x44, 0x34, 0xAD, 0x4C, 0xFE, 0x95, 0x3F, 0xC5, 0x27, 0xDC, 0x6A, 0x5E, 0x5B, 0xE8, 0xF6, 0x23, 0x49, 0x07, 0xB7, 0xC1, 0x87, 0x55, 0x95, 0x57, 0xCE, 0x87, 0xA0, 0x54, 0x1C, 0x46 }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_SIG_VERIFY }, + { { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 1, MUSIG_SIG_VERIFY }, + { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_SIG }, + }, + { + { { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }, 3, { 0, 1, 2 }, 3, { 4, 1, 2 }, 0, 0, MUSIG_PUBNONCE }, + { { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }, 3, { 3, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_PUBKEY }, + }, +}; + +struct musig_tweak_case { + size_t key_indices_len; + size_t key_indices[3]; + size_t nonce_indices_len; + size_t nonce_indices[3]; + size_t tweak_indices_len; + size_t tweak_indices[4]; + int is_xonly[4]; + size_t signer_index; + unsigned char expected[32]; +}; + +struct musig_tweak_vector { + unsigned char sk[32]; + unsigned char secnonce[97]; + unsigned char aggnonce[66]; + unsigned char msg[32]; + unsigned char pubkeys[3][33]; + unsigned char pubnonces[3][194]; + unsigned char tweaks[5][32]; + struct musig_tweak_case valid_case[5]; + struct musig_tweak_case error_case[1]; +}; + +static const struct musig_tweak_vector musig_tweak_vector = { + { 0x7F, 0xB9, 0xE0, 0xE6, 0x87, 0xAD, 0xA1, 0xEE, 0xBF, 0x7E, 0xCF, 0xE2, 0xF2, 0x1E, 0x73, 0xEB, 0xDB, 0x51, 0xA7, 0xD4, 0x50, 0x94, 0x8D, 0xFE, 0x8D, 0x76, 0xD7, 0xF2, 0xD1, 0x00, 0x76, 0x71 }, + { 0x50, 0x8B, 0x81, 0xA6, 0x11, 0xF1, 0x00, 0xA6, 0xB2, 0xB6, 0xB2, 0x96, 0x56, 0x59, 0x08, 0x98, 0xAF, 0x48, 0x8B, 0xCF, 0x2E, 0x1F, 0x55, 0xCF, 0x22, 0xE5, 0xCF, 0xB8, 0x44, 0x21, 0xFE, 0x61, 0xFA, 0x27, 0xFD, 0x49, 0xB1, 0xD5, 0x00, 0x85, 0xB4, 0x81, 0x28, 0x5E, 0x1C, 0xA2, 0x05, 0xD5, 0x5C, 0x82, 0xCC, 0x1B, 0x31, 0xFF, 0x5C, 0xD5, 0x4A, 0x48, 0x98, 0x29, 0x35, 0x59, 0x01, 0xF7, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, + { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, + { 0xF9, 0x54, 0x66, 0xD0, 0x86, 0x77, 0x0E, 0x68, 0x99, 0x64, 0x66, 0x42, 0x19, 0x26, 0x6F, 0xE5, 0xED, 0x21, 0x5C, 0x92, 0xAE, 0x20, 0xBA, 0xB5, 0xC9, 0xD7, 0x9A, 0xDD, 0xDD, 0xF3, 0xC0, 0xCF }, + { + { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, + { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, + { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 } + }, + { + { 0x03, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, + { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, + { 0x03, 0x2D, 0xE2, 0x66, 0x26, 0x28, 0xC9, 0x0B, 0x03, 0xF5, 0xE7, 0x20, 0x28, 0x4E, 0xB5, 0x2F, 0xF7, 0xD7, 0x1F, 0x42, 0x84, 0xF6, 0x27, 0xB6, 0x8A, 0x85, 0x3D, 0x78, 0xC7, 0x8E, 0x1F, 0xFE, 0x93, 0x03, 0xE4, 0xC5, 0x52, 0x4E, 0x83, 0xFF, 0xE1, 0x49, 0x3B, 0x90, 0x77, 0xCF, 0x1C, 0xA6, 0xBE, 0xB2, 0x09, 0x0C, 0x93, 0xD9, 0x30, 0x32, 0x10, 0x71, 0xAD, 0x40, 0xB2, 0xF4, 0x4E, 0x59, 0x90, 0x46 } + }, + { + { 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB }, + { 0xAE, 0x2E, 0xA7, 0x97, 0xCC, 0x0F, 0xE7, 0x2A, 0xC5, 0xB9, 0x7B, 0x97, 0xF3, 0xC6, 0x95, 0x7D, 0x7E, 0x41, 0x99, 0xA1, 0x67, 0xA5, 0x8E, 0xB0, 0x8B, 0xCA, 0xFF, 0xDA, 0x70, 0xAC, 0x04, 0x55 }, + { 0xF5, 0x2E, 0xCB, 0xC5, 0x65, 0xB3, 0xD8, 0xBE, 0xA2, 0xDF, 0xD5, 0xB7, 0x5A, 0x4F, 0x45, 0x7E, 0x54, 0x36, 0x98, 0x09, 0x32, 0x2E, 0x41, 0x20, 0x83, 0x16, 0x26, 0xF2, 0x90, 0xFA, 0x87, 0xE0 }, + { 0x19, 0x69, 0xAD, 0x73, 0xCC, 0x17, 0x7F, 0xA0, 0xB4, 0xFC, 0xED, 0x6D, 0xF1, 0xF7, 0xBF, 0x99, 0x07, 0xE6, 0x65, 0xFD, 0xE9, 0xBA, 0x19, 0x6A, 0x74, 0xFE, 0xD0, 0xA3, 0xCF, 0x5A, 0xEF, 0x9D }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 } + }, + { + { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 0 }, { 1 }, 2, { 0xE2, 0x8A, 0x5C, 0x66, 0xE6, 0x1E, 0x17, 0x8C, 0x2B, 0xA1, 0x9D, 0xB7, 0x7B, 0x6C, 0xF9, 0xF7, 0xE2, 0xF0, 0xF5, 0x6C, 0x17, 0x91, 0x8C, 0xD1, 0x31, 0x35, 0xE6, 0x0C, 0xC8, 0x48, 0xFE, 0x91 }}, + { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 0 }, { 0 }, 2, { 0x38, 0xB0, 0x76, 0x77, 0x98, 0x25, 0x2F, 0x21, 0xBF, 0x57, 0x02, 0xC4, 0x80, 0x28, 0xB0, 0x95, 0x42, 0x83, 0x20, 0xF7, 0x3A, 0x4B, 0x14, 0xDB, 0x1E, 0x25, 0xDE, 0x58, 0x54, 0x3D, 0x2D, 0x2D }}, + { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 2, { 0, 1 }, { 0, 1 }, 2, { 0x40, 0x8A, 0x0A, 0x21, 0xC4, 0xA0, 0xF5, 0xDA, 0xCA, 0xF9, 0x64, 0x6A, 0xD6, 0xEB, 0x6F, 0xEC, 0xD7, 0xF7, 0xA1, 0x1F, 0x03, 0xED, 0x1F, 0x48, 0xDF, 0xFF, 0x21, 0x85, 0xBC, 0x2C, 0x24, 0x08 }}, + { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 4, { 0, 1, 2, 3 }, { 0, 0, 1, 1 }, 2, { 0x45, 0xAB, 0xD2, 0x06, 0xE6, 0x1E, 0x3D, 0xF2, 0xEC, 0x9E, 0x26, 0x4A, 0x6F, 0xEC, 0x82, 0x92, 0x14, 0x1A, 0x63, 0x3C, 0x28, 0x58, 0x63, 0x88, 0x23, 0x55, 0x41, 0xF9, 0xAD, 0xE7, 0x54, 0x35 }}, + { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 4, { 0, 1, 2, 3 }, { 1, 0, 1, 0 }, 2, { 0xB2, 0x55, 0xFD, 0xCA, 0xC2, 0x7B, 0x40, 0xC7, 0xCE, 0x78, 0x48, 0xE2, 0xD3, 0xB7, 0xBF, 0x5E, 0xA0, 0xED, 0x75, 0x6D, 0xA8, 0x15, 0x65, 0xAC, 0x80, 0x4C, 0xCC, 0xA3, 0xE1, 0xD5, 0xD2, 0x39 }}, + }, + { + { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 4 }, { 0 }, 2, { 0 }}, + }, +}; + +/* Omit pubnonces in the test vectors because they're only needed for + * implementations that do not directly accept an aggnonce. */ +struct musig_sig_agg_case { + size_t key_indices_len; + size_t key_indices[2]; + size_t tweak_indices_len; + size_t tweak_indices[3]; + int is_xonly[3]; + unsigned char aggnonce[66]; + size_t psig_indices_len; + size_t psig_indices[2]; + /* if valid case */ + unsigned char expected[64]; + /* if error case */ + int invalid_sig_idx; +}; + +struct musig_sig_agg_vector { + unsigned char pubkeys[4][33]; + unsigned char tweaks[3][32]; + unsigned char psigs[9][32]; + unsigned char msg[32]; + struct musig_sig_agg_case valid_case[4]; + struct musig_sig_agg_case error_case[1]; +}; + +static const struct musig_sig_agg_vector musig_sig_agg_vector = { + { + { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, + { 0x02, 0xD2, 0xDC, 0x6F, 0x5D, 0xF7, 0xC5, 0x6A, 0xCF, 0x38, 0xC7, 0xFA, 0x0A, 0xE7, 0xA7, 0x59, 0xAE, 0x30, 0xE1, 0x9B, 0x37, 0x35, 0x9D, 0xFD, 0xE0, 0x15, 0x87, 0x23, 0x24, 0xC7, 0xEF, 0x6E, 0x05 }, + { 0x03, 0xC7, 0xFB, 0x10, 0x1D, 0x97, 0xFF, 0x93, 0x0A, 0xCD, 0x0C, 0x67, 0x60, 0x85, 0x2E, 0xF6, 0x4E, 0x69, 0x08, 0x3D, 0xE0, 0xB0, 0x6A, 0xC6, 0x33, 0x57, 0x24, 0x75, 0x4B, 0xB4, 0xB0, 0x52, 0x2C }, + { 0x02, 0x35, 0x24, 0x33, 0xB2, 0x1E, 0x7E, 0x05, 0xD3, 0xB4, 0x52, 0xB8, 0x1C, 0xAE, 0x56, 0x6E, 0x06, 0xD2, 0xE0, 0x03, 0xEC, 0xE1, 0x6D, 0x10, 0x74, 0xAA, 0xBA, 0x42, 0x89, 0xE0, 0xE3, 0xD5, 0x81 } + }, + { + { 0xB5, 0x11, 0xDA, 0x49, 0x21, 0x82, 0xA9, 0x1B, 0x0F, 0xFB, 0x9A, 0x98, 0x02, 0x0D, 0x55, 0xF2, 0x60, 0xAE, 0x86, 0xD7, 0xEC, 0xBD, 0x03, 0x99, 0xC7, 0x38, 0x3D, 0x59, 0xA5, 0xF2, 0xAF, 0x7C }, + { 0xA8, 0x15, 0xFE, 0x04, 0x9E, 0xE3, 0xC5, 0xAA, 0xB6, 0x63, 0x10, 0x47, 0x7F, 0xBC, 0x8B, 0xCC, 0xCA, 0xC2, 0xF3, 0x39, 0x5F, 0x59, 0xF9, 0x21, 0xC3, 0x64, 0xAC, 0xD7, 0x8A, 0x2F, 0x48, 0xDC }, + { 0x75, 0x44, 0x8A, 0x87, 0x27, 0x4B, 0x05, 0x64, 0x68, 0xB9, 0x77, 0xBE, 0x06, 0xEB, 0x1E, 0x9F, 0x65, 0x75, 0x77, 0xB7, 0x32, 0x0B, 0x0A, 0x33, 0x76, 0xEA, 0x51, 0xFD, 0x42, 0x0D, 0x18, 0xA8 } + }, + { + { 0xB1, 0x5D, 0x2C, 0xD3, 0xC3, 0xD2, 0x2B, 0x04, 0xDA, 0xE4, 0x38, 0xCE, 0x65, 0x3F, 0x6B, 0x4E, 0xCF, 0x04, 0x2F, 0x42, 0xCF, 0xDE, 0xD7, 0xC4, 0x1B, 0x64, 0xAA, 0xF9, 0xB4, 0xAF, 0x53, 0xFB }, + { 0x61, 0x93, 0xD6, 0xAC, 0x61, 0xB3, 0x54, 0xE9, 0x10, 0x5B, 0xBD, 0xC8, 0x93, 0x7A, 0x34, 0x54, 0xA6, 0xD7, 0x05, 0xB6, 0xD5, 0x73, 0x22, 0xA5, 0xA4, 0x72, 0xA0, 0x2C, 0xE9, 0x9F, 0xCB, 0x64 }, + { 0x9A, 0x87, 0xD3, 0xB7, 0x9E, 0xC6, 0x72, 0x28, 0xCB, 0x97, 0x87, 0x8B, 0x76, 0x04, 0x9B, 0x15, 0xDB, 0xD0, 0x5B, 0x81, 0x58, 0xD1, 0x7B, 0x5B, 0x91, 0x14, 0xD3, 0xC2, 0x26, 0x88, 0x75, 0x05 }, + { 0x66, 0xF8, 0x2E, 0xA9, 0x09, 0x23, 0x68, 0x9B, 0x85, 0x5D, 0x36, 0xC6, 0xB7, 0xE0, 0x32, 0xFB, 0x99, 0x70, 0x30, 0x14, 0x81, 0xB9, 0x9E, 0x01, 0xCD, 0xB4, 0xD6, 0xAC, 0x7C, 0x34, 0x7A, 0x15 }, + { 0x4F, 0x5A, 0xEE, 0x41, 0x51, 0x08, 0x48, 0xA6, 0x44, 0x7D, 0xCD, 0x1B, 0xBC, 0x78, 0x45, 0x7E, 0xF6, 0x90, 0x24, 0x94, 0x4C, 0x87, 0xF4, 0x02, 0x50, 0xD3, 0xEF, 0x2C, 0x25, 0xD3, 0x3E, 0xFE }, + { 0xDD, 0xEF, 0x42, 0x7B, 0xBB, 0x84, 0x7C, 0xC0, 0x27, 0xBE, 0xFF, 0x4E, 0xDB, 0x01, 0x03, 0x81, 0x48, 0x91, 0x78, 0x32, 0x25, 0x3E, 0xBC, 0x35, 0x5F, 0xC3, 0x3F, 0x4A, 0x8E, 0x2F, 0xCC, 0xE4 }, + { 0x97, 0xB8, 0x90, 0xA2, 0x6C, 0x98, 0x1D, 0xA8, 0x10, 0x2D, 0x3B, 0xC2, 0x94, 0x15, 0x9D, 0x17, 0x1D, 0x72, 0x81, 0x0F, 0xDF, 0x7C, 0x6A, 0x69, 0x1D, 0xEF, 0x02, 0xF0, 0xF7, 0xAF, 0x3F, 0xDC }, + { 0x53, 0xFA, 0x9E, 0x08, 0xBA, 0x52, 0x43, 0xCB, 0xCB, 0x0D, 0x79, 0x7C, 0x5E, 0xE8, 0x3B, 0xC6, 0x72, 0x8E, 0x53, 0x9E, 0xB7, 0x6C, 0x2D, 0x0B, 0xF0, 0xF9, 0x71, 0xEE, 0x4E, 0x90, 0x99, 0x71 }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 } + }, + { 0x59, 0x9C, 0x67, 0xEA, 0x41, 0x0D, 0x00, 0x5B, 0x9D, 0xA9, 0x08, 0x17, 0xCF, 0x03, 0xED, 0x3B, 0x1C, 0x86, 0x8E, 0x4D, 0xA4, 0xED, 0xF0, 0x0A, 0x58, 0x80, 0xB0, 0x08, 0x2C, 0x23, 0x78, 0x69 }, + { + { 2, { 0, 1 }, 0, { 0 }, { 0 }, { 0x03, 0x41, 0x43, 0x27, 0x22, 0xC5, 0xCD, 0x02, 0x68, 0xD8, 0x29, 0xC7, 0x02, 0xCF, 0x0D, 0x1C, 0xBC, 0xE5, 0x70, 0x33, 0xEE, 0xD2, 0x01, 0xFD, 0x33, 0x51, 0x91, 0x38, 0x52, 0x27, 0xC3, 0x21, 0x0C, 0x03, 0xD3, 0x77, 0xF2, 0xD2, 0x58, 0xB6, 0x4A, 0xAD, 0xC0, 0xE1, 0x6F, 0x26, 0x46, 0x23, 0x23, 0xD7, 0x01, 0xD2, 0x86, 0x04, 0x6A, 0x2E, 0xA9, 0x33, 0x65, 0x65, 0x6A, 0xFD, 0x98, 0x75, 0x98, 0x2B }, 2, { 0, 1 }, { 0x04, 0x1D, 0xA2, 0x22, 0x23, 0xCE, 0x65, 0xC9, 0x2C, 0x9A, 0x0D, 0x6C, 0x2C, 0xAC, 0x82, 0x8A, 0xAF, 0x1E, 0xEE, 0x56, 0x30, 0x4F, 0xEC, 0x37, 0x1D, 0xDF, 0x91, 0xEB, 0xB2, 0xB9, 0xEF, 0x09, 0x12, 0xF1, 0x03, 0x80, 0x25, 0x85, 0x7F, 0xED, 0xEB, 0x3F, 0xF6, 0x96, 0xF8, 0xB9, 0x9F, 0xA4, 0xBB, 0x2C, 0x58, 0x12, 0xF6, 0x09, 0x5A, 0x2E, 0x00, 0x04, 0xEC, 0x99, 0xCE, 0x18, 0xDE, 0x1E }, 0 }, + { 2, { 0, 2 }, 0, { 0 }, { 0 }, { 0x02, 0x24, 0xAF, 0xD3, 0x6C, 0x90, 0x20, 0x84, 0x05, 0x8B, 0x51, 0xB5, 0xD3, 0x66, 0x76, 0xBB, 0xA4, 0xDC, 0x97, 0xC7, 0x75, 0x87, 0x37, 0x68, 0xE5, 0x88, 0x22, 0xF8, 0x7F, 0xE4, 0x37, 0xD7, 0x92, 0x02, 0x8C, 0xB1, 0x59, 0x29, 0x09, 0x9E, 0xEE, 0x2F, 0x5D, 0xAE, 0x40, 0x4C, 0xD3, 0x93, 0x57, 0x59, 0x1B, 0xA3, 0x2E, 0x9A, 0xF4, 0xE1, 0x62, 0xB8, 0xD3, 0xE7, 0xCB, 0x5E, 0xFE, 0x31, 0xCB, 0x20 }, 2, { 2, 3 }, { 0x10, 0x69, 0xB6, 0x7E, 0xC3, 0xD2, 0xF3, 0xC7, 0xC0, 0x82, 0x91, 0xAC, 0xCB, 0x17, 0xA9, 0xC9, 0xB8, 0xF2, 0x81, 0x9A, 0x52, 0xEB, 0x5D, 0xF8, 0x72, 0x6E, 0x17, 0xE7, 0xD6, 0xB5, 0x2E, 0x9F, 0x01, 0x80, 0x02, 0x60, 0xA7, 0xE9, 0xDA, 0xC4, 0x50, 0xF4, 0xBE, 0x52, 0x2D, 0xE4, 0xCE, 0x12, 0xBA, 0x91, 0xAE, 0xAF, 0x2B, 0x42, 0x79, 0x21, 0x9E, 0xF7, 0x4B, 0xE1, 0xD2, 0x86, 0xAD, 0xD9 }, 0 }, + { 2, { 0, 2 }, 1, { 0 }, { 0 }, { 0x02, 0x08, 0xC5, 0xC4, 0x38, 0xC7, 0x10, 0xF4, 0xF9, 0x6A, 0x61, 0xE9, 0xFF, 0x3C, 0x37, 0x75, 0x88, 0x14, 0xB8, 0xC3, 0xAE, 0x12, 0xBF, 0xEA, 0x0E, 0xD2, 0xC8, 0x7F, 0xF6, 0x95, 0x4F, 0xF1, 0x86, 0x02, 0x0B, 0x18, 0x16, 0xEA, 0x10, 0x4B, 0x4F, 0xCA, 0x2D, 0x30, 0x4D, 0x73, 0x3E, 0x0E, 0x19, 0xCE, 0xAD, 0x51, 0x30, 0x3F, 0xF6, 0x42, 0x0B, 0xFD, 0x22, 0x23, 0x35, 0xCA, 0xA4, 0x02, 0x91, 0x6D }, 2, { 4, 5 }, { 0x5C, 0x55, 0x8E, 0x1D, 0xCA, 0xDE, 0x86, 0xDA, 0x0B, 0x2F, 0x02, 0x62, 0x6A, 0x51, 0x2E, 0x30, 0xA2, 0x2C, 0xF5, 0x25, 0x5C, 0xAE, 0xA7, 0xEE, 0x32, 0xC3, 0x8E, 0x9A, 0x71, 0xA0, 0xE9, 0x14, 0x8B, 0xA6, 0xC0, 0xE6, 0xEC, 0x76, 0x83, 0xB6, 0x42, 0x20, 0xF0, 0x29, 0x86, 0x96, 0xF1, 0xB8, 0x78, 0xCD, 0x47, 0xB1, 0x07, 0xB8, 0x1F, 0x71, 0x88, 0x81, 0x2D, 0x59, 0x39, 0x71, 0xE0, 0xCC }, 0 }, + { 2, { 0, 3 }, 3, { 0, 1, 2 }, { 1, 0, 1 }, { 0x02, 0xB5, 0xAD, 0x07, 0xAF, 0xCD, 0x99, 0xB6, 0xD9, 0x2C, 0xB4, 0x33, 0xFB, 0xD2, 0xA2, 0x8F, 0xDE, 0xB9, 0x8E, 0xAE, 0x2E, 0xB0, 0x9B, 0x60, 0x14, 0xEF, 0x0F, 0x81, 0x97, 0xCD, 0x58, 0x40, 0x33, 0x02, 0xE8, 0x61, 0x69, 0x10, 0xF9, 0x29, 0x3C, 0xF6, 0x92, 0xC4, 0x9F, 0x35, 0x1D, 0xB8, 0x6B, 0x25, 0xE3, 0x52, 0x90, 0x1F, 0x0E, 0x23, 0x7B, 0xAF, 0xDA, 0x11, 0xF1, 0xC1, 0xCE, 0xF2, 0x9F, 0xFD }, 2, { 6, 7 }, { 0x83, 0x9B, 0x08, 0x82, 0x0B, 0x68, 0x1D, 0xBA, 0x8D, 0xAF, 0x4C, 0xC7, 0xB1, 0x04, 0xE8, 0xF2, 0x63, 0x8F, 0x93, 0x88, 0xF8, 0xD7, 0xA5, 0x55, 0xDC, 0x17, 0xB6, 0xE6, 0x97, 0x1D, 0x74, 0x26, 0xCE, 0x07, 0xBF, 0x6A, 0xB0, 0x1F, 0x1D, 0xB5, 0x0E, 0x4E, 0x33, 0x71, 0x92, 0x95, 0xF4, 0x09, 0x45, 0x72, 0xB7, 0x98, 0x68, 0xE4, 0x40, 0xFB, 0x3D, 0xEF, 0xD3, 0xFA, 0xC1, 0xDB, 0x58, 0x9E }, 0 }, + }, + { + { 2, { 0, 3 }, 3, { 0, 1, 2 }, { 1, 0, 1 }, { 0x02, 0xB5, 0xAD, 0x07, 0xAF, 0xCD, 0x99, 0xB6, 0xD9, 0x2C, 0xB4, 0x33, 0xFB, 0xD2, 0xA2, 0x8F, 0xDE, 0xB9, 0x8E, 0xAE, 0x2E, 0xB0, 0x9B, 0x60, 0x14, 0xEF, 0x0F, 0x81, 0x97, 0xCD, 0x58, 0x40, 0x33, 0x02, 0xE8, 0x61, 0x69, 0x10, 0xF9, 0x29, 0x3C, 0xF6, 0x92, 0xC4, 0x9F, 0x35, 0x1D, 0xB8, 0x6B, 0x25, 0xE3, 0x52, 0x90, 0x1F, 0x0E, 0x23, 0x7B, 0xAF, 0xDA, 0x11, 0xF1, 0xC1, 0xCE, 0xF2, 0x9F, 0xFD }, 2, { 7, 8 }, { 0 }, 1 }, + }, +}; +enum { MUSIG_VECTORS_MAX_PUBKEYS = 7 }; diff --git a/src/secp256k1.c b/src/secp256k1.c index 8821718a..a8c249ad 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -818,6 +818,10 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, # include "modules/schnorrsig/main_impl.h" #endif +#ifdef ENABLE_MODULE_MUSIG +# include "modules/musig/main_impl.h" +#endif + #ifdef ENABLE_MODULE_ELLSWIFT # include "modules/ellswift/main_impl.h" #endif diff --git a/src/tests.c b/src/tests.c index 544ad763..dba4097b 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7448,6 +7448,10 @@ static void run_ecdsa_wycheproof(void) { # include "modules/schnorrsig/tests_impl.h" #endif +#ifdef ENABLE_MODULE_MUSIG +# include "modules/musig/tests_impl.h" +#endif + #ifdef ENABLE_MODULE_ELLSWIFT # include "modules/ellswift/tests_impl.h" #endif @@ -7812,6 +7816,10 @@ int main(int argc, char **argv) { run_schnorrsig_tests(); #endif +#ifdef ENABLE_MODULE_MUSIG + run_musig_tests(); +#endif + #ifdef ENABLE_MODULE_ELLSWIFT run_ellswift_tests(); #endif diff --git a/tools/test_vectors_musig2_generate.py b/tools/test_vectors_musig2_generate.py new file mode 100755 index 00000000..97424419 --- /dev/null +++ b/tools/test_vectors_musig2_generate.py @@ -0,0 +1,656 @@ +#!/usr/bin/env python3 + +import sys +import json +import textwrap + +max_pubkeys = 0 + +if len(sys.argv) < 2: + print( + "This script converts BIP MuSig2 test vectors in a given directory to a C file that can be used in the test framework." + ) + print("Usage: %s " % sys.argv[0]) + sys.exit(1) + + +def hexstr_to_intarray(str): + return ", ".join([f"0x{b:02X}" for b in bytes.fromhex(str)]) + + +def create_init(name): + return """ +static const struct musig_%s_vector musig_%s_vector = { +""" % ( + name, + name, + ) + + +def init_array(key): + return textwrap.indent("{ %s },\n" % hexstr_to_intarray(data[key]), 4 * " ") + + +def init_arrays(key): + s = textwrap.indent("{\n", 4 * " ") + s += textwrap.indent( + ",\n".join(["{ %s }" % hexstr_to_intarray(x) for x in data[key]]), 8 * " " + ) + s += textwrap.indent("\n},\n", 4 * " ") + return s + + +def init_indices(array): + return " %d, { %s }" % ( + len(array), + ", ".join(map(str, array) if len(array) > 0 else "0"), + ) + + +def init_is_xonly(case): + if len(case["tweak_indices"]) > 0: + return ", ".join(map(lambda x: "1" if x else "0", case["is_xonly"])) + return "0" + + +def init_optional_expected(case): + return hexstr_to_intarray(case["expected"]) if "expected" in case else 0 + + +def init_cases(cases, f): + s = textwrap.indent("{\n", 4 * " ") + for (i, case) in enumerate(cases): + s += textwrap.indent("%s\n" % f(case), 8 * " ") + s += textwrap.indent("},\n", 4 * " ") + return s + + +def finish_init(): + return "};\n" + + +s = ( + """/** + * Automatically generated by %s. + * + * The test vectors for the KeySort function are included in this file. They can + * be found in src/modules/extrakeys/tests_impl.h. */ +""" + % sys.argv[0] +) + + +s += """ +enum MUSIG_ERROR { + MUSIG_PUBKEY, + MUSIG_TWEAK, + MUSIG_PUBNONCE, + MUSIG_AGGNONCE, + MUSIG_SECNONCE, + MUSIG_SIG, + MUSIG_SIG_VERIFY, + MUSIG_OTHER +}; +""" + +# key agg vectors +with open(sys.argv[1] + "/key_agg_vectors.json", "r") as f: + data = json.load(f) + + max_key_indices = max( + len(test_case["key_indices"]) for test_case in data["valid_test_cases"] + ) + max_tweak_indices = max( + len(test_case["tweak_indices"]) for test_case in data["error_test_cases"] + ) + num_pubkeys = len(data["pubkeys"]) + max_pubkeys = max(num_pubkeys, max_pubkeys) + num_tweaks = len(data["tweaks"]) + num_valid_cases = len(data["valid_test_cases"]) + num_error_cases = len(data["error_test_cases"]) + + # Add structures for valid and error cases + s += ( + """ +struct musig_key_agg_valid_test_case { + size_t key_indices_len; + size_t key_indices[%d]; + unsigned char expected[32]; +}; +""" + % max_key_indices + ) + s += """ +struct musig_key_agg_error_test_case { + size_t key_indices_len; + size_t key_indices[%d]; + size_t tweak_indices_len; + size_t tweak_indices[%d]; + int is_xonly[%d]; + enum MUSIG_ERROR error; +}; +""" % ( + max_key_indices, + max_tweak_indices, + max_tweak_indices, + ) + + # Add structure for entire vector + s += """ +struct musig_key_agg_vector { + unsigned char pubkeys[%d][33]; + unsigned char tweaks[%d][32]; + struct musig_key_agg_valid_test_case valid_case[%d]; + struct musig_key_agg_error_test_case error_case[%d]; +}; +""" % ( + num_pubkeys, + num_tweaks, + num_valid_cases, + num_error_cases, + ) + + s += create_init("key_agg") + # Add pubkeys and tweaks to the vector + s += init_arrays("pubkeys") + s += init_arrays("tweaks") + + # Add valid cases to the vector + s += init_cases( + data["valid_test_cases"], + lambda case: "{ %s, { %s }}," + % (init_indices(case["key_indices"]), hexstr_to_intarray(case["expected"])), + ) + + def comment_to_error(case): + comment = case["comment"] + if "public key" in comment.lower(): + return "MUSIG_PUBKEY" + elif "tweak" in comment.lower(): + return "MUSIG_TWEAK" + else: + sys.exit("Unknown error") + + # Add error cases to the vector + s += init_cases( + data["error_test_cases"], + lambda case: "{ %s, %s, { %s }, %s }," + % ( + init_indices(case["key_indices"]), + init_indices(case["tweak_indices"]), + init_is_xonly(case), + comment_to_error(case), + ), + ) + + s += finish_init() + +# nonce gen vectors +with open(sys.argv[1] + "/nonce_gen_vectors.json", "r") as f: + data = json.load(f) + + # The MuSig2 implementation only allows messages of length 32 + data["test_cases"] = list( + filter(lambda c: c["msg"] is None or len(c["msg"]) == 64, data["test_cases"]) + ) + + num_tests = len(data["test_cases"]) + + s += """ +struct musig_nonce_gen_test_case { + unsigned char rand_[32]; + int has_sk; + unsigned char sk[32]; + unsigned char pk[33]; + int has_aggpk; + unsigned char aggpk[32]; + int has_msg; + unsigned char msg[32]; + int has_extra_in; + unsigned char extra_in[32]; + unsigned char expected_secnonce[97]; + unsigned char expected_pubnonce[66]; +}; +""" + + s += ( + """ +struct musig_nonce_gen_vector { + struct musig_nonce_gen_test_case test_case[%d]; +}; +""" + % num_tests + ) + + s += create_init("nonce_gen") + + def init_array_maybe(array): + return "%d , { %s }" % ( + 0 if array is None else 1, + hexstr_to_intarray(array) if array is not None else 0, + ) + + s += init_cases( + data["test_cases"], + lambda case: "{ { %s }, %s, { %s }, %s, %s, %s, { %s }, { %s } }," + % ( + hexstr_to_intarray(case["rand_"]), + init_array_maybe(case["sk"]), + hexstr_to_intarray(case["pk"]), + init_array_maybe(case["aggpk"]), + init_array_maybe(case["msg"]), + init_array_maybe(case["extra_in"]), + hexstr_to_intarray(case["expected_secnonce"]), + hexstr_to_intarray(case["expected_pubnonce"]), + ), + ) + + s += finish_init() + +# nonce agg vectors +with open(sys.argv[1] + "/nonce_agg_vectors.json", "r") as f: + data = json.load(f) + + num_pnonces = len(data["pnonces"]) + num_valid_cases = len(data["valid_test_cases"]) + num_error_cases = len(data["error_test_cases"]) + + pnonce_indices_len = 2 + for case in data["valid_test_cases"] + data["error_test_cases"]: + assert len(case["pnonce_indices"]) == pnonce_indices_len + + # Add structures for valid and error cases + s += """ +struct musig_nonce_agg_test_case { + size_t pnonce_indices[2]; + /* if valid case */ + unsigned char expected[66]; + /* if error case */ + int invalid_nonce_idx; +}; +""" + # Add structure for entire vector + s += """ +struct musig_nonce_agg_vector { + unsigned char pnonces[%d][66]; + struct musig_nonce_agg_test_case valid_case[%d]; + struct musig_nonce_agg_test_case error_case[%d]; +}; +""" % ( + num_pnonces, + num_valid_cases, + num_error_cases, + ) + + s += create_init("nonce_agg") + s += init_arrays("pnonces") + + for cases in (data["valid_test_cases"], data["error_test_cases"]): + s += init_cases( + cases, + lambda case: "{ { %s }, { %s }, %d }," + % ( + ", ".join(map(str, case["pnonce_indices"])), + init_optional_expected(case), + case["error"]["signer"] if "error" in case else 0, + ), + ) + s += finish_init() + +# sign/verify vectors +with open(sys.argv[1] + "/sign_verify_vectors.json", "r") as f: + data = json.load(f) + + # The MuSig2 implementation only allows messages of length 32 + assert list(filter(lambda x: len(x) == 64, data["msgs"]))[0] == data["msgs"][0] + data["msgs"] = [data["msgs"][0]] + + def filter_msg32(k): + return list(filter(lambda x: x["msg_index"] == 0, data[k])) + + data["valid_test_cases"] = filter_msg32("valid_test_cases") + data["sign_error_test_cases"] = filter_msg32("sign_error_test_cases") + data["verify_error_test_cases"] = filter_msg32("verify_error_test_cases") + data["verify_fail_test_cases"] = filter_msg32("verify_fail_test_cases") + + num_pubkeys = len(data["pubkeys"]) + max_pubkeys = max(num_pubkeys, max_pubkeys) + num_secnonces = len(data["secnonces"]) + num_pubnonces = len(data["pnonces"]) + num_aggnonces = len(data["aggnonces"]) + num_msgs = len(data["msgs"]) + num_valid_cases = len(data["valid_test_cases"]) + num_sign_error_cases = len(data["sign_error_test_cases"]) + num_verify_fail_cases = len(data["verify_fail_test_cases"]) + num_verify_error_cases = len(data["verify_error_test_cases"]) + + all_cases = ( + data["valid_test_cases"] + + data["sign_error_test_cases"] + + data["verify_error_test_cases"] + + data["verify_fail_test_cases"] + ) + max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) + max_nonce_indices = max( + len(test_case["nonce_indices"]) if "nonce_indices" in test_case else 0 + for test_case in all_cases + ) + # Add structures for valid and error cases + s += ( + """ +/* Omit pubnonces in the test vectors because our partial signature verification + * implementation is able to accept the aggnonce directly. */ +struct musig_valid_case { + size_t key_indices_len; + size_t key_indices[%d]; + size_t aggnonce_index; + size_t msg_index; + size_t signer_index; + unsigned char expected[32]; +}; +""" + % max_key_indices + ) + + s += ( + """ +struct musig_sign_error_case { + size_t key_indices_len; + size_t key_indices[%d]; + size_t aggnonce_index; + size_t msg_index; + size_t secnonce_index; + enum MUSIG_ERROR error; +}; +""" + % max_key_indices + ) + + s += """ +struct musig_verify_fail_error_case { + unsigned char sig[32]; + size_t key_indices_len; + size_t key_indices[%d]; + size_t nonce_indices_len; + size_t nonce_indices[%d]; + size_t msg_index; + size_t signer_index; + enum MUSIG_ERROR error; +}; +""" % ( + max_key_indices, + max_nonce_indices, + ) + + # Add structure for entire vector + s += """ +struct musig_sign_verify_vector { + unsigned char sk[32]; + unsigned char pubkeys[%d][33]; + unsigned char secnonces[%d][194]; + unsigned char pubnonces[%d][194]; + unsigned char aggnonces[%d][66]; + unsigned char msgs[%d][32]; + struct musig_valid_case valid_case[%d]; + struct musig_sign_error_case sign_error_case[%d]; + struct musig_verify_fail_error_case verify_fail_case[%d]; + struct musig_verify_fail_error_case verify_error_case[%d]; +}; +""" % ( + num_pubkeys, + num_secnonces, + num_pubnonces, + num_aggnonces, + num_msgs, + num_valid_cases, + num_sign_error_cases, + num_verify_fail_cases, + num_verify_error_cases, + ) + + s += create_init("sign_verify") + s += init_array("sk") + s += init_arrays("pubkeys") + s += init_arrays("secnonces") + s += init_arrays("pnonces") + s += init_arrays("aggnonces") + s += init_arrays("msgs") + + s += init_cases( + data["valid_test_cases"], + lambda case: "{ %s, %d, %d, %d, { %s }}," + % ( + init_indices(case["key_indices"]), + case["aggnonce_index"], + case["msg_index"], + case["signer_index"], + init_optional_expected(case), + ), + ) + + def sign_error(case): + comment = case["comment"] + if "pubkey" in comment or "public key" in comment: + return "MUSIG_PUBKEY" + elif "Aggregate nonce" in comment: + return "MUSIG_AGGNONCE" + elif "Secnonce" in comment: + return "MUSIG_SECNONCE" + else: + sys.exit("Unknown sign error") + + s += init_cases( + data["sign_error_test_cases"], + lambda case: "{ %s, %d, %d, %d, %s }," + % ( + init_indices(case["key_indices"]), + case["aggnonce_index"], + case["msg_index"], + case["secnonce_index"], + sign_error(case), + ), + ) + + def verify_error(case): + comment = case["comment"] + if "exceeds" in comment: + return "MUSIG_SIG" + elif "Wrong signer" in comment or "Wrong signature" in comment: + return "MUSIG_SIG_VERIFY" + elif "pubnonce" in comment: + return "MUSIG_PUBNONCE" + elif "pubkey" in comment: + return "MUSIG_PUBKEY" + else: + sys.exit("Unknown verify error") + + for cases in ("verify_fail_test_cases", "verify_error_test_cases"): + s += init_cases( + data[cases], + lambda case: "{ { %s }, %s, %s, %d, %d, %s }," + % ( + hexstr_to_intarray(case["sig"]), + init_indices(case["key_indices"]), + init_indices(case["nonce_indices"]), + case["msg_index"], + case["signer_index"], + verify_error(case), + ), + ) + + s += finish_init() + +# tweak vectors +with open(sys.argv[1] + "/tweak_vectors.json", "r") as f: + data = json.load(f) + + num_pubkeys = len(data["pubkeys"]) + max_pubkeys = max(num_pubkeys, max_pubkeys) + num_pubnonces = len(data["pnonces"]) + num_tweaks = len(data["tweaks"]) + num_valid_cases = len(data["valid_test_cases"]) + num_error_cases = len(data["error_test_cases"]) + + all_cases = data["valid_test_cases"] + data["error_test_cases"] + max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) + max_tweak_indices = max(len(test_case["tweak_indices"]) for test_case in all_cases) + max_nonce_indices = max(len(test_case["nonce_indices"]) for test_case in all_cases) + # Add structures for valid and error cases + s += """ +struct musig_tweak_case { + size_t key_indices_len; + size_t key_indices[%d]; + size_t nonce_indices_len; + size_t nonce_indices[%d]; + size_t tweak_indices_len; + size_t tweak_indices[%d]; + int is_xonly[%d]; + size_t signer_index; + unsigned char expected[32]; +}; +""" % ( + max_key_indices, + max_nonce_indices, + max_tweak_indices, + max_tweak_indices, + ) + + # Add structure for entire vector + s += """ +struct musig_tweak_vector { + unsigned char sk[32]; + unsigned char secnonce[97]; + unsigned char aggnonce[66]; + unsigned char msg[32]; + unsigned char pubkeys[%d][33]; + unsigned char pubnonces[%d][194]; + unsigned char tweaks[%d][32]; + struct musig_tweak_case valid_case[%d]; + struct musig_tweak_case error_case[%d]; +}; +""" % ( + num_pubkeys, + num_pubnonces, + num_tweaks, + num_valid_cases, + num_error_cases, + ) + s += create_init("tweak") + s += init_array("sk") + s += init_array("secnonce") + s += init_array("aggnonce") + s += init_array("msg") + s += init_arrays("pubkeys") + s += init_arrays("pnonces") + s += init_arrays("tweaks") + + s += init_cases( + data["valid_test_cases"], + lambda case: "{ %s, %s, %s, { %s }, %d, { %s }}," + % ( + init_indices(case["key_indices"]), + init_indices(case["nonce_indices"]), + init_indices(case["tweak_indices"]), + init_is_xonly(case), + case["signer_index"], + init_optional_expected(case), + ), + ) + + s += init_cases( + data["error_test_cases"], + lambda case: "{ %s, %s, %s, { %s }, %d, { %s }}," + % ( + init_indices(case["key_indices"]), + init_indices(case["nonce_indices"]), + init_indices(case["tweak_indices"]), + init_is_xonly(case), + case["signer_index"], + init_optional_expected(case), + ), + ) + + s += finish_init() + +# sigagg vectors +with open(sys.argv[1] + "/sig_agg_vectors.json", "r") as f: + data = json.load(f) + + num_pubkeys = len(data["pubkeys"]) + max_pubkeys = max(num_pubkeys, max_pubkeys) + num_tweaks = len(data["tweaks"]) + num_psigs = len(data["psigs"]) + num_valid_cases = len(data["valid_test_cases"]) + num_error_cases = len(data["error_test_cases"]) + + all_cases = data["valid_test_cases"] + data["error_test_cases"] + max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) + max_tweak_indices = max(len(test_case["tweak_indices"]) for test_case in all_cases) + max_psig_indices = max(len(test_case["psig_indices"]) for test_case in all_cases) + + # Add structures for valid and error cases + s += """ +/* Omit pubnonces in the test vectors because they're only needed for + * implementations that do not directly accept an aggnonce. */ +struct musig_sig_agg_case { + size_t key_indices_len; + size_t key_indices[%d]; + size_t tweak_indices_len; + size_t tweak_indices[%d]; + int is_xonly[%d]; + unsigned char aggnonce[66]; + size_t psig_indices_len; + size_t psig_indices[%d]; + /* if valid case */ + unsigned char expected[64]; + /* if error case */ + int invalid_sig_idx; +}; +""" % ( + max_key_indices, + max_tweak_indices, + max_tweak_indices, + max_psig_indices, + ) + + # Add structure for entire vector + s += """ +struct musig_sig_agg_vector { + unsigned char pubkeys[%d][33]; + unsigned char tweaks[%d][32]; + unsigned char psigs[%d][32]; + unsigned char msg[32]; + struct musig_sig_agg_case valid_case[%d]; + struct musig_sig_agg_case error_case[%d]; +}; +""" % ( + num_pubkeys, + num_tweaks, + num_psigs, + num_valid_cases, + num_error_cases, + ) + + s += create_init("sig_agg") + s += init_arrays("pubkeys") + s += init_arrays("tweaks") + s += init_arrays("psigs") + s += init_array("msg") + + for cases in (data["valid_test_cases"], data["error_test_cases"]): + s += init_cases( + cases, + lambda case: "{ %s, %s, { %s }, { %s }, %s, { %s }, %d }," + % ( + init_indices(case["key_indices"]), + init_indices(case["tweak_indices"]), + init_is_xonly(case), + hexstr_to_intarray(case["aggnonce"]), + init_indices(case["psig_indices"]), + init_optional_expected(case), + case["error"]["signer"] if "error" in case else 0, + ), + ) + s += finish_init() +s += "enum { MUSIG_VECTORS_MAX_PUBKEYS = %d };" % max_pubkeys +print(s) From 168c92011f5ddae8d7fe28d166b68f126459548a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sat, 6 Jan 2024 20:17:27 +0000 Subject: [PATCH 094/383] build: allow enabling the musig module in cmake --- CMakeLists.txt | 10 ++++++++++ examples/CMakeLists.txt | 4 ++++ src/CMakeLists.txt | 3 +++ 3 files changed, 17 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ca8cbe8..d136d43c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON) option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF) option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON) option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON) +option(SECP256K1_ENABLE_MODULE_MUSIG "Enable musig module." ON) option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON) # Processing must be done in a topological sorting of the dependency graph @@ -59,6 +60,14 @@ if(SECP256K1_ENABLE_MODULE_ELLSWIFT) add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) endif() +if(SECP256K1_ENABLE_MODULE_MUSIG) + if(DEFINED SECP256K1_ENABLE_MODULE_SCHNORRSIG AND NOT SECP256K1_ENABLE_MODULE_SCHNORRSIG) + message(FATAL_ERROR "Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.") + endif() + set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) + add_compile_definitions(ENABLE_MODULE_MUSIG=1) +endif() + if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) if(DEFINED SECP256K1_ENABLE_MODULE_EXTRAKEYS AND NOT SECP256K1_ENABLE_MODULE_EXTRAKEYS) message(FATAL_ERROR "Module dependency error: You have disabled the extrakeys module explicitly, but it is required by the schnorrsig module.") @@ -297,6 +306,7 @@ message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH} message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}") message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRAKEYS}") message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}") +message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}") message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}") message("Parameters:") message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index fd1ebce3..f844d4a0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -32,3 +32,7 @@ endif() if(SECP256K1_ENABLE_MODULE_ELLSWIFT) add_example(ellswift) endif() + +if(SECP256K1_ENABLE_MODULE_MUSIG) + add_example(musig) +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4cbaeb91..cc042b6e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,6 +132,9 @@ if(SECP256K1_INSTALL) if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h") endif() + if(SECP256K1_ENABLE_MODULE_MUSIG) + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_musig.h") + endif() if(SECP256K1_ENABLE_MODULE_ELLSWIFT) list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ellswift.h") endif() From cd4f84f3ba8de37726274f61d5a34477c88433cf Mon Sep 17 00:00:00 2001 From: cheapshot003 Date: Thu, 29 Aug 2024 22:24:20 +0200 Subject: [PATCH 095/383] Improve examples/documentation: remove key generation loops Co-Authored by: Sebastian Falbesoner --- examples/ecdh.c | 22 ++++++++++------------ examples/ecdsa.c | 22 ++++++++++------------ examples/ellswift.c | 21 ++++++++++----------- examples/schnorr.c | 26 ++++++++++++-------------- include/secp256k1.h | 6 ++++-- 5 files changed, 46 insertions(+), 51 deletions(-) diff --git a/examples/ecdh.c b/examples/ecdh.c index d71fd2f6..ef9e8b89 100644 --- a/examples/ecdh.c +++ b/examples/ecdh.c @@ -42,18 +42,16 @@ int main(void) { assert(return_val); /*** Key Generation ***/ - - /* If the secret key is zero or out of range (bigger than secp256k1's - * order), we try to sample a new key. Note that the probability of this - * happening is negligible. */ - while (1) { - if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { - printf("Failed to generate randomness\n"); - return 1; - } - if (secp256k1_ec_seckey_verify(ctx, seckey1) && secp256k1_ec_seckey_verify(ctx, seckey2)) { - break; - } + if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* If the secret key is zero or out of range (greater than secp256k1's + * order), we fail. Note that the probability of this occurring + * is negligible with a properly functioning random number generator. */ + if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { + printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); + return 1; } /* Public key creation using a valid context with a verified secret key should never fail */ diff --git a/examples/ecdsa.c b/examples/ecdsa.c index d5c4613d..433c58ff 100644 --- a/examples/ecdsa.c +++ b/examples/ecdsa.c @@ -49,18 +49,16 @@ int main(void) { assert(return_val); /*** Key Generation ***/ - - /* If the secret key is zero or out of range (bigger than secp256k1's - * order), we try to sample a new key. Note that the probability of this - * happening is negligible. */ - while (1) { - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 1; - } - if (secp256k1_ec_seckey_verify(ctx, seckey)) { - break; - } + /* If the secret key is zero or out of range (greater than secp256k1's + * order), we return 1. Note that the probability of this occurring + * is negligible with a properly functioning random number generator. */ + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 1; + } + if (!secp256k1_ec_seckey_verify(ctx, seckey)) { + printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); + return 1; } /* Public key creation using a valid context with a verified secret key should never fail */ diff --git a/examples/ellswift.c b/examples/ellswift.c index 52be7eeb..e6159f36 100644 --- a/examples/ellswift.c +++ b/examples/ellswift.c @@ -48,17 +48,16 @@ int main(void) { /*** Generate secret keys ***/ - /* If the secret key is zero or out of range (bigger than secp256k1's - * order), we try to sample a new key. Note that the probability of this - * happening is negligible. */ - while (1) { - if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { - printf("Failed to generate randomness\n"); - return 1; - } - if (secp256k1_ec_seckey_verify(ctx, seckey1) && secp256k1_ec_seckey_verify(ctx, seckey2)) { - break; - } + /* If the secret key is zero or out of range (greater than secp256k1's + * order), we return 1. Note that the probability of this occurring + * is negligible with a properly functioning random number generator. */ + if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { + printf("Failed to generate randomness\n"); + return 1; + } + if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { + printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); + return 1; } /* Generate ElligatorSwift public keys. This should never fail with valid context and diff --git a/examples/schnorr.c b/examples/schnorr.c index 8d5d14bd..adced235 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -43,20 +43,18 @@ int main(void) { assert(return_val); /*** Key Generation ***/ - - /* If the secret key is zero or out of range (bigger than secp256k1's - * order), we try to sample a new key. Note that the probability of this - * happening is negligible. */ - while (1) { - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 1; - } - /* Try to create a keypair with a valid context, it should only fail if - * the secret key is zero or out of range. */ - if (secp256k1_keypair_create(ctx, &keypair, seckey)) { - break; - } + /* If the secret key is zero or out of range (greater than secp256k1's + * order), we return 1. Note that the probability of this occurring + * is negligible with a properly functioning random number generator. */ + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* Try to create a keypair with a valid context, it should only fail if + * the secret key is zero or out of range. */ + if (!secp256k1_keypair_create(ctx, &keypair, seckey)) { + printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); + return 1; } /* Extract the X-only public key from the keypair. We pass NULL for diff --git a/include/secp256k1.h b/include/secp256k1.h index cfbdd528..88928111 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -679,12 +679,14 @@ SECP256K1_API int secp256k1_ecdsa_sign( const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -/** Verify an ECDSA secret key. +/** Verify an elliptic curve secret key. * * A secret key is valid if it is not 0 and less than the secp256k1 curve order * when interpreted as an integer (most significant byte first). The * probability of choosing a 32-byte string uniformly at random which is an - * invalid secret key is negligible. + * invalid secret key is negligible. However, if it does happen it should + * be assumed that the randomness source is severely broken and there should + * be no retry. * * Returns: 1: secret key is valid * 0: secret key is invalid From 70b6be1834e2ece8d9cfcf2ad12e4452c87cdc20 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sun, 13 Oct 2024 19:08:02 +0000 Subject: [PATCH 096/383] extrakeys: improve doc of keypair_create (don't suggest retry) --- include/secp256k1.h | 2 +- include/secp256k1_extrakeys.h | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 6e96778d..25196fb7 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -684,7 +684,7 @@ SECP256K1_API int secp256k1_ecdsa_sign( * A secret key is valid if it is not 0 and less than the secp256k1 curve order * when interpreted as an integer (most significant byte first). The * probability of choosing a 32-byte string uniformly at random which is an - * invalid secret key is negligible. However, if it does happen it should + * invalid secret key is negligible. However, if it does happen it should * be assumed that the randomness source is severely broken and there should * be no retry. * diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h index ad70b92f..13acb032 100644 --- a/include/secp256k1_extrakeys.h +++ b/include/secp256k1_extrakeys.h @@ -155,10 +155,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_ const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); -/** Compute the keypair for a secret key. +/** Compute the keypair for a valid secret key. * - * Returns: 1: secret was valid, keypair is ready to use - * 0: secret was invalid, try again with a different secret + * See the documentation of `secp256k1_ec_seckey_verify` for more information + * about the validity of secret keys. + * + * Returns: 1: secret key is valid + * 0: secret key is invalid * Args: ctx: pointer to a context object (not secp256k1_context_static). * Out: keypair: pointer to the created keypair. * In: seckey: pointer to a 32-byte secret key. From e8908221a45a368c2c8ae0fed0e2310968d4815a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sun, 13 Oct 2024 19:10:45 +0000 Subject: [PATCH 097/383] examples: do not retry generating seckey randomness in musig --- examples/musig.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/musig.c b/examples/musig.c index 396dbb9f..0352dc40 100644 --- a/examples/musig.c +++ b/examples/musig.c @@ -38,14 +38,17 @@ struct signer { /* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */ static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { unsigned char seckey[32]; - while (1) { - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 0; - } - if (secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) { - break; - } + + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 0; + } + /* Try to create a keypair with a valid context. This only fails if the + * secret key is zero or out of range (greater than secp256k1's order). Note + * that the probability of this occurring is negligible with a properly + * functioning random number generator. */ + if (!secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) { + return 0; } if (!secp256k1_keypair_pub(ctx, &signer->pubkey, &signer_secrets->keypair)) { return 0; From 5bab8f6d3c4946f32bebd2a99b9975aa160ff794 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Sun, 13 Oct 2024 19:11:02 +0000 Subject: [PATCH 098/383] examples: make key generation doc consistent --- examples/ecdh.c | 4 ++-- examples/ecdsa.c | 6 +++--- examples/ellswift.c | 7 +++---- examples/schnorr.c | 11 +++++------ 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/examples/ecdh.c b/examples/ecdh.c index ef9e8b89..13aa760b 100644 --- a/examples/ecdh.c +++ b/examples/ecdh.c @@ -47,8 +47,8 @@ int main(void) { return 1; } /* If the secret key is zero or out of range (greater than secp256k1's - * order), we fail. Note that the probability of this occurring - * is negligible with a properly functioning random number generator. */ + * order), we fail. Note that the probability of this occurring is negligible + * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); return 1; diff --git a/examples/ecdsa.c b/examples/ecdsa.c index 433c58ff..80ae9d46 100644 --- a/examples/ecdsa.c +++ b/examples/ecdsa.c @@ -49,13 +49,13 @@ int main(void) { assert(return_val); /*** Key Generation ***/ - /* If the secret key is zero or out of range (greater than secp256k1's - * order), we return 1. Note that the probability of this occurring - * is negligible with a properly functioning random number generator. */ if (!fill_random(seckey, sizeof(seckey))) { printf("Failed to generate randomness\n"); return 1; } + /* If the secret key is zero or out of range (greater than secp256k1's + * order), we fail. Note that the probability of this occurring is negligible + * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); return 1; diff --git a/examples/ellswift.c b/examples/ellswift.c index e6159f36..afb2fee4 100644 --- a/examples/ellswift.c +++ b/examples/ellswift.c @@ -47,14 +47,13 @@ int main(void) { assert(return_val); /*** Generate secret keys ***/ - - /* If the secret key is zero or out of range (greater than secp256k1's - * order), we return 1. Note that the probability of this occurring - * is negligible with a properly functioning random number generator. */ if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { printf("Failed to generate randomness\n"); return 1; } + /* If the secret key is zero or out of range (greater than secp256k1's + * order), we fail. Note that the probability of this occurring is negligible + * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); return 1; diff --git a/examples/schnorr.c b/examples/schnorr.c index adced235..909fcaa1 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -43,18 +43,17 @@ int main(void) { assert(return_val); /*** Key Generation ***/ - /* If the secret key is zero or out of range (greater than secp256k1's - * order), we return 1. Note that the probability of this occurring - * is negligible with a properly functioning random number generator. */ if (!fill_random(seckey, sizeof(seckey))) { printf("Failed to generate randomness\n"); return 1; } - /* Try to create a keypair with a valid context, it should only fail if - * the secret key is zero or out of range. */ + /* Try to create a keypair with a valid context. This only fails if the + * secret key is zero or out of range (greater than secp256k1's order). Note + * that the probability of this occurring is negligible with a properly + * functioning random number generator. */ if (!secp256k1_keypair_create(ctx, &keypair, seckey)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return 1; } /* Extract the X-only public key from the keypair. We pass NULL for From 87384f5c0f2bdf2b500858a18f5397e8dcffa8ec Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 12 Aug 2024 12:07:45 +0100 Subject: [PATCH 099/383] cmake, test: Add `secp256k1_` prefix to test names This change improves regex matching options when using `ctest` in downstream projects. --- examples/CMakeLists.txt | 2 +- src/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 675f4c8c..c9da9de6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -9,7 +9,7 @@ function(add_example name) $<$:bcrypt> ) set(test_name ${name}_example) - add_test(NAME ${test_name} COMMAND ${target_name}) + add_test(NAME secp256k1_${test_name} COMMAND ${target_name}) endfunction() add_example(ecdsa) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc042b6e..f31b8c8f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,12 +87,12 @@ endif() if(SECP256K1_BUILD_TESTS) add_executable(noverify_tests tests.c) target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm) - add_test(NAME noverify_tests COMMAND noverify_tests) + add_test(NAME secp256k1_noverify_tests COMMAND noverify_tests) if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage") add_executable(tests tests.c) target_compile_definitions(tests PRIVATE VERIFY) target_link_libraries(tests secp256k1_precomputed secp256k1_asm) - add_test(NAME tests COMMAND tests) + add_test(NAME secp256k1_tests COMMAND tests) endif() endif() @@ -101,7 +101,7 @@ if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) add_executable(exhaustive_tests tests_exhaustive.c) target_link_libraries(exhaustive_tests secp256k1_asm) target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) - add_test(NAME exhaustive_tests COMMAND exhaustive_tests) + add_test(NAME secp256k1_exhaustive_tests COMMAND exhaustive_tests) endif() if(SECP256K1_BUILD_CTIME_TESTS) From 57eda3ba300acb2e54f26a8ad00fbdd5750867ed Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 20 Oct 2024 02:25:06 +0200 Subject: [PATCH 100/383] musig: ctimetests: fix _declassify range for generated nonce points The area marked as non-secret exceeds the nonce_pts array in the second iteration of the for loop. Fix that by passing the correct size to the _declassify call. --- src/modules/musig/session_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 2715b09d..fbdfd635 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -448,7 +448,7 @@ int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_m secp256k1_gej nonce_ptj; secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj); - secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts)); + secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); secp256k1_scalar_clear(&k[i]); } /* None of the nonce_pts will be infinity because k != 0 with overwhelming From 8be3839fb2e1e501ef82c5b341e5a7f88587997a Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 11 May 2023 13:24:37 +0000 Subject: [PATCH 101/383] Remove unused scratch space from API --- CHANGELOG.md | 3 +++ include/secp256k1.h | 36 ------------------------------------ src/scratch.h | 2 ++ src/secp256k1.c | 4 ++-- 4 files changed, 7 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f2e0f53..5026aab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Document `doc/musig.md` for further notes on API usage. - Usage example `examples/musig.c`. +#### Removed + - Removed the `secp256k1_scratch_space` struct and its associated functions `secp256k1_scratch_space_create` `secp256k1_scratch_space_destroy` because the scratch space was unused in the API. + ## [0.5.1] - 2024-08-01 #### Added diff --git a/include/secp256k1.h b/include/secp256k1.h index 25196fb7..a28615a7 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -49,19 +49,6 @@ extern "C" { */ typedef struct secp256k1_context_struct secp256k1_context; -/** Opaque data structure that holds rewritable "scratch space" - * - * The purpose of this structure is to replace dynamic memory allocations, - * because we target architectures where this may not be available. It is - * essentially a resizable (within specified parameters) block of bytes, - * which is initially created either by memory allocation or TODO as a pointer - * into some fixed rewritable space. - * - * Unlike the context object, this cannot safely be shared between threads - * without additional synchronization logic. - */ -typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; - /** Opaque data structure that holds a parsed and valid public key. * * The exact representation of data inside is implementation defined and not @@ -392,29 +379,6 @@ SECP256K1_API void secp256k1_context_set_error_callback( const void *data ) SECP256K1_ARG_NONNULL(1); -/** Create a secp256k1 scratch space object. - * - * Returns: a newly created scratch space. - * Args: ctx: pointer to a context object. - * In: size: amount of memory to be available as scratch space. Some extra - * (<100 bytes) will be allocated for extra accounting. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space *secp256k1_scratch_space_create( - const secp256k1_context *ctx, - size_t size -) SECP256K1_ARG_NONNULL(1); - -/** Destroy a secp256k1 scratch space. - * - * The pointer may not be used afterwards. - * Args: ctx: pointer to a context object. - * scratch: space to destroy - */ -SECP256K1_API void secp256k1_scratch_space_destroy( - const secp256k1_context *ctx, - secp256k1_scratch_space *scratch -) SECP256K1_ARG_NONNULL(1); - /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. diff --git a/src/scratch.h b/src/scratch.h index 9dcb7581..6164330b 100644 --- a/src/scratch.h +++ b/src/scratch.h @@ -21,6 +21,8 @@ typedef struct secp256k1_scratch_space_struct { size_t max_size; } secp256k1_scratch; +typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; + static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size); static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch); diff --git a/src/secp256k1.c b/src/secp256k1.c index a8c249ad..93b7b459 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -220,12 +220,12 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } -secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { +static secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { VERIFY_CHECK(ctx != NULL); return secp256k1_scratch_create(&ctx->error_callback, max_size); } -void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scratch_space* scratch) { +static void secp256k1_scratch_space_destroy(const secp256k1_context *ctx, secp256k1_scratch_space* scratch) { VERIFY_CHECK(ctx != NULL); secp256k1_scratch_destroy(&ctx->error_callback, scratch); } From e7d384488e85650cd2a29493bc55fa5e68bf59c3 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 6 Jun 2019 16:51:33 +0200 Subject: [PATCH 102/383] Don't clear secrets in pippenger implementation This code is not supposed to handle secret data. --- src/ecmult_impl.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 07d8477e..8f584552 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -660,7 +660,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call struct secp256k1_pippenger_state *state_space; size_t idx = 0; size_t point_idx = 0; - int i, j; int bucket_window; secp256k1_gej_set_infinity(r); @@ -708,18 +707,6 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call } secp256k1_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx); - - /* Clear data */ - for(i = 0; (size_t)i < idx; i++) { - secp256k1_scalar_clear(&scalars[i]); - state_space->ps[i].skew_na = 0; - for(j = 0; j < WNAF_SIZE(bucket_window+1); j++) { - state_space->wnaf_na[i * WNAF_SIZE(bucket_window+1) + j] = 0; - } - } - for(i = 0; i < 1< Date: Fri, 25 Oct 2024 08:18:02 +0100 Subject: [PATCH 103/383] ci: Update macOS image The macOS 12 GHA image has been deprecated since 2024-10-07. See: https://github.com/actions/runner-images/issues/10721 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0dd19b5..9550c7a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -612,9 +612,9 @@ jobs: if: ${{ always() }} x86_64-macos-native: - name: "x86_64: macOS Monterey, Valgrind" + name: "x86_64: macOS Ventura, Valgrind" # See: https://github.com/actions/runner-images#available-images. - runs-on: macos-12 + runs-on: macos-13 env: CC: 'clang' From 980c08df80aa1698bf7e8f1f4f8ecf20078535a8 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 25 Oct 2024 16:00:25 +0200 Subject: [PATCH 104/383] util: Remove unused (u)int64_t formatting macros We should anyway prefer to use the predefined macros from . If I haven't missed anything, this removes the last OS-specific #if, leaving us only with compiler-specific #if(def)s. --- src/util.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/util.h b/src/util.h index 49af867a..ff9271ed 100644 --- a/src/util.h +++ b/src/util.h @@ -192,14 +192,6 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ # endif #endif -#if defined(_WIN32) -# define I64FORMAT "I64d" -# define I64uFORMAT "I64u" -#else -# define I64FORMAT "lld" -# define I64uFORMAT "llu" -#endif - #if defined(__GNUC__) # define SECP256K1_GNUC_EXT __extension__ #else From 1c0812622277b85123c751b76f68f10f0f93b3c0 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 6 Jun 2019 21:22:28 +0200 Subject: [PATCH 105/383] Add secp256k1_memclear() for clearing secret data We rely on memset() and an __asm__ memory barrier where it's available or on SecureZeroMemory() on Windows. The fallback implementation uses a volatile function pointer to memset which the compiler is not clever enough to optimize. --- src/util.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/util.h b/src/util.h index 49af867a..c2add8ac 100644 --- a/src/util.h +++ b/src/util.h @@ -8,11 +8,17 @@ #define SECP256K1_UTIL_H #include "../include/secp256k1.h" +#include "checkmem.h" +#include #include #include #include #include +#if defined(_MSC_VER) +/* For SecureZeroMemory */ +#include +#endif #define STR_(x) #x #define STR(x) STR_(x) @@ -221,6 +227,34 @@ static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) { } } +/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ +static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { +#if defined(_MSC_VER) + /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */ + SecureZeroMemory(ptr, len); +#elif defined(__GNUC__) + /* We use a memory barrier that scares the compiler away from optimizing out the memset. + * + * Quoting Adam Langley in commit ad1907fe73334d6c696c8539646c21b11178f20f + * in BoringSSL (ISC License): + * As best as we can tell, this is sufficient to break any optimisations that + * might try to eliminate "superfluous" memsets. + * This method is used in memzero_explicit() the Linux kernel, too. Its advantage is that it + * is pretty efficient, because the compiler can still implement the memset() efficently, + * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by + * Yang et al. (USENIX Security 2017) for more background. + */ + memset(ptr, 0, len); + __asm__ __volatile__("" : : "r"(ptr) : "memory"); +#else + void *(*volatile const volatile_memset)(void *, int, size_t) = memset; + volatile_memset(ptr, 0, len); +#endif +#ifdef VERIFY + SECP256K1_CHECKMEM_UNDEFINE(ptr, len); +#endif +} + /** Semantics like memcmp. Variable-time. * * We use this to avoid possible compiler bugs with memcmp, e.g. From d79a6ccd43ae1681280e5e27d9cd181285bf8540 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 12 Jun 2019 16:05:06 +0200 Subject: [PATCH 106/383] Separate secp256k1_fe_set_int( . , 0 ) from secp256k1_fe_clear() There are two uses of the secp256k1_fe_clear() function that are now separated into these two functions in order to reflect the intent: 1) initializing the memory prior to being used -> converted to fe_set_int( . , 0 ) 2) zeroing the memory after being used such that no sensitive data remains. -> remains as fe_clear() In the latter case, 'magnitude' and 'normalized' need to be overwritten when VERIFY is enabled. Co-Authored-By: isle2983 --- src/field.h | 6 +----- src/field_impl.h | 2 +- src/group_impl.h | 10 +++++----- src/testutil.h | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/field.h b/src/field.h index 8c65a3af..95990309 100644 --- a/src/field.h +++ b/src/field.h @@ -144,11 +144,7 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r); */ static void secp256k1_fe_set_int(secp256k1_fe *r, int a); -/** Set a field element to 0. - * - * On input, a does not need to be initialized. - * On output, a represents 0, is normalized and has magnitude 0. - */ +/** Clear a field element to prevent leaking sensitive information. */ static void secp256k1_fe_clear(secp256k1_fe *a); /** Determine whether a represents field element 0. diff --git a/src/field_impl.h b/src/field_impl.h index 989e9cdb..8cf6f22c 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -235,7 +235,7 @@ SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { static void secp256k1_fe_impl_clear(secp256k1_fe *a); SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { a->magnitude = 0; - a->normalized = 1; + a->normalized = 0; secp256k1_fe_impl_clear(a); SECP256K1_FE_VERIFY(a); diff --git a/src/group_impl.h b/src/group_impl.h index 2e096f41..10aff433 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -283,17 +283,17 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se static void secp256k1_gej_set_infinity(secp256k1_gej *r) { r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); + secp256k1_fe_set_int(&r->x, 0); + secp256k1_fe_set_int(&r->y, 0); + secp256k1_fe_set_int(&r->z, 0); SECP256K1_GEJ_VERIFY(r); } static void secp256k1_ge_set_infinity(secp256k1_ge *r) { r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); + secp256k1_fe_set_int(&r->x, 0); + secp256k1_fe_set_int(&r->y, 0); SECP256K1_GE_VERIFY(r); } diff --git a/src/testutil.h b/src/testutil.h index fc56854d..64b3bb41 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -34,7 +34,7 @@ static void testutil_random_fe_magnitude(secp256k1_fe *fe, int m) { if (n == 0) { return; } - secp256k1_fe_clear(&zero); + secp256k1_fe_set_int(&zero, 0); secp256k1_fe_negate(&zero, &zero, 0); secp256k1_fe_mul_int_unchecked(&zero, n - 1); secp256k1_fe_add(fe, &zero); From e3497bbf001f8e06dcc21d27fed173be77ef7136 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sat, 8 Jun 2019 11:56:15 +0200 Subject: [PATCH 107/383] Separate between clearing memory and setting to zero in tests Co-Authored-By: isle2983 Co-Authored-By: Pieter Wuille --- src/bench_ecmult.c | 2 +- src/tests.c | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 7dc52ad8..3974af75 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -71,7 +71,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset secp256k1_scalar sum_scalars; secp256k1_gej_set_infinity(&sum_output); - secp256k1_scalar_clear(&sum_scalars); + secp256k1_scalar_set_int(&sum_scalars, 0); for (i = 0; i < iters; ++i) { secp256k1_gej_add_var(&sum_output, &sum_output, &data->output[i], NULL); if (scalar_gen_offset != NULL) { diff --git a/src/tests.c b/src/tests.c index dba4097b..270b1c83 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3671,8 +3671,7 @@ static void test_ge(void) { secp256k1_fe zfi2, zfi3; secp256k1_gej_set_infinity(&gej[0]); - secp256k1_ge_clear(&ge[0]); - secp256k1_ge_set_gej_var(&ge[0], &gej[0]); + secp256k1_ge_set_infinity(&ge[0]); for (i = 0; i < runs; i++) { int j, k; secp256k1_ge g; @@ -4797,12 +4796,12 @@ static void test_ecmult_multi(secp256k1_scratch *scratch, secp256k1_ecmult_multi testutil_random_ge_test(&pt[ncount]); } - secp256k1_scalar_clear(&sc[0]); + secp256k1_scalar_set_int(&sc[0], 0); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 20)); - secp256k1_scalar_clear(&sc[1]); - secp256k1_scalar_clear(&sc[2]); - secp256k1_scalar_clear(&sc[3]); - secp256k1_scalar_clear(&sc[4]); + secp256k1_scalar_set_int(&sc[1], 0); + secp256k1_scalar_set_int(&sc[2], 0); + secp256k1_scalar_set_int(&sc[3], 0); + secp256k1_scalar_set_int(&sc[4], 0); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 6)); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &secp256k1_scalar_zero, ecmult_multi_callback, &data, 5)); CHECK(secp256k1_gej_is_infinity(&r)); From 9bb368d146683aa9b44645f1b75a0ed230df97e9 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sat, 8 Jun 2019 13:54:14 +0200 Subject: [PATCH 108/383] Use secp256k1_memclear() to clear stack memory instead of memset() All of the invocations of secp256k1_memclear() operate on stack memory and happen after the function is done with the memory object. This commit replaces existing memset() invocations and also adds secp256k1_memclear() to code locations where clearing was missing; there is no guarantee that this commit covers all code locations where clearing is necessary. Co-Authored-By: isle2983 --- src/ecmult_gen_impl.h | 8 ++++---- src/hash_impl.h | 11 ++++++----- src/modules/ecdh/main_impl.h | 5 +++-- src/modules/ellswift/main_impl.h | 2 +- src/modules/musig/session_impl.h | 10 +++++----- src/modules/schnorrsig/main_impl.h | 2 +- src/secp256k1.c | 4 ++-- src/util.h | 2 +- 8 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 2fbf623c..6903cd1b 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -277,8 +277,8 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Cleanup. */ secp256k1_fe_clear(&neg); secp256k1_ge_clear(&add); - memset(&adds, 0, sizeof(adds)); - memset(&recoded, 0, sizeof(recoded)); + secp256k1_memclear(&adds, sizeof(adds)); + secp256k1_memclear(&recoded, sizeof(recoded)); } /* Setup blinding values for secp256k1_ecmult_gen. */ @@ -310,7 +310,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const VERIFY_CHECK(seed32 != NULL); memcpy(keydata + 32, seed32, 32); secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); - memset(keydata, 0, sizeof(keydata)); + secp256k1_memclear(keydata, sizeof(keydata)); /* Compute projective blinding factor (cannot be 0). */ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); @@ -325,13 +325,13 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const * which secp256k1_gej_add_ge cannot handle. */ secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b)); secp256k1_rfc6979_hmac_sha256_finalize(&rng); - memset(nonce32, 0, 32); secp256k1_ecmult_gen(ctx, &gb, &b); secp256k1_scalar_negate(&b, &b); secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff); secp256k1_ge_set_gej(&ctx->ge_offset, &gb); /* Clean up. */ + secp256k1_memclear(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&b); secp256k1_gej_clear(&gb); secp256k1_fe_clear(&f); diff --git a/src/hash_impl.h b/src/hash_impl.h index 89f75ace..49393c67 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -156,6 +156,9 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out secp256k1_write_be32(&out32[4*i], hash->s[i]); hash->s[i] = 0; } + + secp256k1_memclear(sizedesc, sizeof(sizedesc)); + secp256k1_memclear(hash, sizeof(secp256k1_sha256)); } /* Initializes a sha256 struct and writes the 64 byte string @@ -196,7 +199,7 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const rkey[n] ^= 0x5c ^ 0x36; } secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); - memset(rkey, 0, sizeof(rkey)); + secp256k1_memclear(rkey, sizeof(rkey)); } static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { @@ -207,7 +210,7 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned unsigned char temp[32]; secp256k1_sha256_finalize(&hash->inner, temp); secp256k1_sha256_write(&hash->outer, temp, 32); - memset(temp, 0, 32); + secp256k1_memclear(temp, sizeof(temp)); secp256k1_sha256_finalize(&hash->outer, out32); } @@ -274,9 +277,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 } static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { - memset(rng->k, 0, 32); - memset(rng->v, 0, 32); - rng->retry = 0; + secp256k1_memclear(rng, sizeof(secp256k1_rfc6979_hmac_sha256)); } #undef Round diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 82b082a9..9286f70f 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -61,9 +61,10 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se ret = hashfp(output, x, y, data); - memset(x, 0, 32); - memset(y, 0, 32); + secp256k1_memclear(x, sizeof(x)); + secp256k1_memclear(y, sizeof(y)); secp256k1_scalar_clear(&s); + secp256k1_ge_clear(&pt); return !!ret & !overflow; } diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index b54ec08a..78e85004 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -580,7 +580,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, /* Invoke hasher */ ret = hashfp(output, sx, ell_a64, ell_b64, data); - memset(sx, 0, 32); + secp256k1_memclear(sx, sizeof(sx)); secp256k1_fe_clear(&px); secp256k1_scalar_clear(&s); diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 2715b09d..e22d1a54 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -385,11 +385,11 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c secp256k1_scalar_set_b32(&k[i], buf, NULL); /* Attempt to erase secret data */ - memset(buf, 0, sizeof(buf)); - memset(&sha_tmp, 0, sizeof(sha_tmp)); + secp256k1_memclear(buf, sizeof(buf)); + secp256k1_memclear(&sha_tmp, sizeof(sha_tmp)); } - memset(rand, 0, sizeof(rand)); - memset(&sha, 0, sizeof(sha)); + secp256k1_memclear(rand, sizeof(rand)); + secp256k1_memclear(&sha, sizeof(sha)); } int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { @@ -509,7 +509,7 @@ int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_mu if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) { return 0; } - memset(seckey, 0, sizeof(seckey)); + secp256k1_memclear(seckey, sizeof(seckey)); return 1; } diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 57f7eadd..783714fe 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -187,7 +187,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_memczero(sig64, 64, !ret); secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); - memset(seckey, 0, sizeof(seckey)); + secp256k1_memclear(seckey, sizeof(seckey)); return ret; } diff --git a/src/secp256k1.c b/src/secp256k1.c index 93b7b459..f4e83dc2 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -494,7 +494,7 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m buffer_append(keydata, &offset, algo16, 16); } secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); - memset(keydata, 0, sizeof(keydata)); + secp256k1_memclear(keydata, sizeof(keydata)); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); } @@ -548,7 +548,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc * seckey. As a result is_sec_valid is included in ret only after ret was * used as a branching variable. */ ret &= is_sec_valid; - memset(nonce32, 0, 32); + secp256k1_memclear(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); secp256k1_scalar_clear(&sec); diff --git a/src/util.h b/src/util.h index c2add8ac..2605141d 100644 --- a/src/util.h +++ b/src/util.h @@ -285,7 +285,7 @@ static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size } ret = (acc == 0); /* acc may contain secret values. Try to explicitly clear it. */ - acc = 0; + secp256k1_memclear(&acc, sizeof(acc)); return ret; } From 97c57f42ba8aca51479d23874b7608b9500a5bc9 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sat, 8 Jun 2019 11:29:49 +0200 Subject: [PATCH 109/383] Implement various _clear() functions with secp256k1_memclear() --- src/field.h | 1 - src/field_10x26_impl.h | 7 ------- src/field_5x52_impl.h | 7 ------- src/field_impl.h | 13 ++++--------- src/group_impl.h | 13 ++----------- src/scalar_4x64_impl.h | 7 ------- src/scalar_8x32_impl.h | 11 ----------- src/scalar_impl.h | 4 ++++ src/scalar_low_impl.h | 2 -- 9 files changed, 10 insertions(+), 55 deletions(-) diff --git a/src/field.h b/src/field.h index 95990309..1f6ba746 100644 --- a/src/field.h +++ b/src/field.h @@ -81,7 +81,6 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST( # define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero # define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var # define secp256k1_fe_set_int secp256k1_fe_impl_set_int -# define secp256k1_fe_clear secp256k1_fe_impl_clear # define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero # define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd # define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index 666068c7..ea14c273 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -270,13 +270,6 @@ SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) { return a->n[0] & 1; } -SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) { - int i; - for (i=0; i<10; i++) { - a->n[i] = 0; - } -} - static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { int i; for (i = 9; i >= 0; i--) { diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 76031f75..46dca6b9 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -212,13 +212,6 @@ SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) { return a->n[0] & 1; } -SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) { - int i; - for (i=0; i<5; i++) { - a->n[i] = 0; - } -} - static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { int i; for (i = 4; i >= 0; i--) { diff --git a/src/field_impl.h b/src/field_impl.h index 8cf6f22c..896507a3 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -18,6 +18,10 @@ #error "Please select wide multiplication implementation" #endif +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { + secp256k1_memclear(a, sizeof(secp256k1_fe)); +} + SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { secp256k1_fe na; SECP256K1_FE_VERIFY(a); @@ -232,15 +236,6 @@ SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) { SECP256K1_FE_VERIFY(r); } -static void secp256k1_fe_impl_clear(secp256k1_fe *a); -SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - a->magnitude = 0; - a->normalized = 0; - secp256k1_fe_impl_clear(a); - - SECP256K1_FE_VERIFY(a); -} - static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a); SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { SECP256K1_FE_VERIFY(a); diff --git a/src/group_impl.h b/src/group_impl.h index 10aff433..c668fb24 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -299,20 +299,11 @@ static void secp256k1_ge_set_infinity(secp256k1_ge *r) { } static void secp256k1_gej_clear(secp256k1_gej *r) { - r->infinity = 0; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - secp256k1_fe_clear(&r->z); - - SECP256K1_GEJ_VERIFY(r); + secp256k1_memclear(r, sizeof(secp256k1_gej)); } static void secp256k1_ge_clear(secp256k1_ge *r) { - r->infinity = 0; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); - - SECP256K1_GE_VERIFY(r); + secp256k1_memclear(r, sizeof(secp256k1_ge)); } static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 4aaec85b..807b9b70 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -29,13 +29,6 @@ #define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) #define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; -} - SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index c7d87b17..26104960 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -38,17 +38,6 @@ #define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; - r->d[4] = 0; - r->d[5] = 0; - r->d[6] = 0; - r->d[7] = 0; -} - SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 972d8041..dbb5b0a0 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -27,6 +27,10 @@ static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { + secp256k1_memclear(r, sizeof(secp256k1_scalar)); +} + static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin) { int overflow; secp256k1_scalar_set_b32(r, bin, &overflow); diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 45d2f3e4..84e1a380 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -19,8 +19,6 @@ SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) return !(*a & 1); } -SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } - SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v % EXHAUSTIVE_TEST_ORDER; From 99cc9fd6d01db1165d08b88d45c0de85a59b70cf Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Sat, 8 Jun 2019 13:21:52 +0200 Subject: [PATCH 110/383] Don't rely on memset to set signed integers to 0 --- src/ecmult_impl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 8f584552..0b53b3fc 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -171,7 +171,9 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, VERIFY_CHECK(a != NULL); VERIFY_CHECK(2 <= w && w <= 31); - memset(wnaf, 0, len * sizeof(wnaf[0])); + for (bit = 0; bit < len; bit++) { + wnaf[bit] = 0; + } s = *a; if (secp256k1_scalar_get_bits_limb32(&s, 255, 1)) { @@ -179,6 +181,7 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, sign = -1; } + bit = 0; while (bit < len) { int now; int word; From 349e6ab916b3dd106fea9b56dacec065df5fa457 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 27 Apr 2020 18:55:36 +0200 Subject: [PATCH 111/383] Introduce separate _clear functions for hash module This gives the caller more control about whether the state should be cleaned (= should be considered secret). Moreover, it gives the caller the possibility to clean a hash struct without finalizing it. --- src/ecmult_gen_impl.h | 1 + src/hash.h | 3 +++ src/hash_impl.h | 16 ++++++++++++---- src/modules/ecdh/main_impl.h | 1 + src/modules/ellswift/main_impl.h | 2 ++ src/modules/musig/session_impl.h | 4 ++-- src/modules/schnorrsig/main_impl.h | 1 + src/secp256k1.c | 5 ++++- 8 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 6903cd1b..070a1213 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -335,6 +335,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_scalar_clear(&b); secp256k1_gej_clear(&gb); secp256k1_fe_clear(&f); + secp256k1_rfc6979_hmac_sha256_clear(&rng); } #endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/src/hash.h b/src/hash.h index 4e0384cf..6d903ca7 100644 --- a/src/hash.h +++ b/src/hash.h @@ -19,6 +19,7 @@ typedef struct { static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); +static void secp256k1_sha256_clear(secp256k1_sha256 *hash); typedef struct { secp256k1_sha256 inner, outer; @@ -27,6 +28,7 @@ typedef struct { static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); +static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash); typedef struct { unsigned char v[32]; @@ -37,5 +39,6 @@ typedef struct { static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); +static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng); #endif /* SECP256K1_HASH_H */ diff --git a/src/hash_impl.h b/src/hash_impl.h index 49393c67..956e0ea4 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -156,9 +156,6 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out secp256k1_write_be32(&out32[4*i], hash->s[i]); hash->s[i] = 0; } - - secp256k1_memclear(sizedesc, sizeof(sizedesc)); - secp256k1_memclear(hash, sizeof(secp256k1_sha256)); } /* Initializes a sha256 struct and writes the 64 byte string @@ -174,6 +171,10 @@ static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const uns secp256k1_sha256_write(hash, buf, 32); } +static void secp256k1_sha256_clear(secp256k1_sha256 *hash) { + secp256k1_memclear(hash, sizeof(*hash)); +} + static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { size_t n; unsigned char rkey[64]; @@ -214,6 +215,9 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned secp256k1_sha256_finalize(&hash->outer, out32); } +static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) { + secp256k1_memclear(hash, sizeof(*hash)); +} static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { secp256k1_hmac_sha256 hmac; @@ -277,7 +281,11 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 } static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { - secp256k1_memclear(rng, sizeof(secp256k1_rfc6979_hmac_sha256)); + (void) rng; +} + +static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng) { + secp256k1_memclear(rng, sizeof(*rng)); } #undef Round diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 9286f70f..a3dc1833 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -19,6 +19,7 @@ static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char secp256k1_sha256_write(&sha, &version, 1); secp256k1_sha256_write(&sha, x32, 32); secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 78e85004..745a9691 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -510,6 +510,7 @@ static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsign secp256k1_sha256_write(&sha, ell_b64, 64); secp256k1_sha256_write(&sha, x32, 32); secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_clear(&sha); return 1; } @@ -539,6 +540,7 @@ static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsign secp256k1_sha256_write(&sha, ell_b64, 64); secp256k1_sha256_write(&sha, x32, 32); secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index e22d1a54..d646ec11 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -386,10 +386,10 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c /* Attempt to erase secret data */ secp256k1_memclear(buf, sizeof(buf)); - secp256k1_memclear(&sha_tmp, sizeof(sha_tmp)); + secp256k1_sha256_clear(&sha_tmp); } secp256k1_memclear(rand, sizeof(rand)); - secp256k1_memclear(&sha, sizeof(sha)); + secp256k1_sha256_clear(&sha); } int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 783714fe..261f4e4e 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -93,6 +93,7 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms secp256k1_sha256_write(&sha, xonly_pk32, 32); secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, nonce32); + secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/secp256k1.c b/src/secp256k1.c index f4e83dc2..00c7285a 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -494,11 +494,13 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m buffer_append(keydata, &offset, algo16, 16); } secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); - secp256k1_memclear(keydata, sizeof(keydata)); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_memclear(keydata, sizeof(keydata)); + secp256k1_rfc6979_hmac_sha256_clear(&rng); return 1; } @@ -799,6 +801,7 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, secp256k1_sha256_initialize_tagged(&sha, tag, taglen); secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, hash32); + secp256k1_sha256_clear(&sha); return 1; } From 765ef53335a3e0fafdafe1e757f6fe0789f2797f Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 11 Oct 2024 18:00:59 +0200 Subject: [PATCH 112/383] Clear _gej instances after point multiplication to avoid potential leaks Quoting sipa (see https://github.com/bitcoin-core/secp256k1/pull/1479#discussion_r1790079414): "When performing an EC multiplication A = aG for secret a, the resulting _affine_ coordinates of A are presumed to not leak information about a (ECDLP), but the same is not necessarily true for the Jacobian coordinates that come out of our multiplication algorithm." For the ECDH point multiplication result, the result in Jacobi coordinates should be cleared not only to avoid leaking the scalar, but even more so as it's a representation of the resulting shared secret. --- src/modules/ecdh/main_impl.h | 1 + src/modules/musig/session_impl.h | 1 + src/modules/schnorrsig/main_impl.h | 1 + src/secp256k1.c | 1 + 4 files changed, 4 insertions(+) diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index a3dc1833..842b5359 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -66,6 +66,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se secp256k1_memclear(y, sizeof(y)); secp256k1_scalar_clear(&s); secp256k1_ge_clear(&pt); + secp256k1_gej_clear(&res); return !!ret & !overflow; } diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index d646ec11..2733e47d 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -450,6 +450,7 @@ int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_m secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj); secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts)); secp256k1_scalar_clear(&k[i]); + secp256k1_gej_clear(&nonce_ptj); } /* None of the nonce_pts will be infinity because k != 0 with overwhelming * probability */ diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 261f4e4e..82bba2f5 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -189,6 +189,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); secp256k1_memclear(seckey, sizeof(seckey)); + secp256k1_gej_clear(&rj); return ret; } diff --git a/src/secp256k1.c b/src/secp256k1.c index 00c7285a..a248519d 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -597,6 +597,7 @@ static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); secp256k1_ge_set_gej(p, &pj); + secp256k1_gej_clear(&pj); return ret; } From 0f73caf7c62564dd4a28cdf682ea9644d1be0ef4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:30:55 +0000 Subject: [PATCH 113/383] test, ci: Lower default iteration count to 16 The number of test iterations in the CI remains unchanged. Additionally, the minimum iteration counts to enable the `test_ecmult_constants_2bit` test is adjusted from 35 to 16, so it is run by default. --- .cirrus.yml | 2 +- .github/workflows/ci.yml | 2 +- src/tests.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 0c1e01dc..9a9ca8e7 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -24,7 +24,7 @@ env: SCHNORRSIG: no ELLSWIFT: no ### test options - SECP256K1_TEST_ITERS: + SECP256K1_TEST_ITERS: 64 BENCH: yes SECP256K1_BENCH_ITERS: 2 CTIMETESTS: yes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fc104d2..77815ceb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ env: SCHNORRSIG: 'no' ELLSWIFT: 'no' ### test options - SECP256K1_TEST_ITERS: + SECP256K1_TEST_ITERS: 64 BENCH: 'yes' SECP256K1_BENCH_ITERS: 2 CTIMETESTS: 'yes' diff --git a/src/tests.c b/src/tests.c index 70c15f87..bde10161 100644 --- a/src/tests.c +++ b/src/tests.c @@ -37,7 +37,7 @@ #define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else -static int COUNT = 64; +static int COUNT = 16; static secp256k1_context *CTX = NULL; static secp256k1_context *STATIC_CTX = NULL; @@ -5515,7 +5515,7 @@ static void run_ecmult_constants(void) { test_ecmult_constants_sha(1607366309u, 2048, expected32_8bit8); } - CONDITIONAL_TEST(35, "test_ecmult_constants_2bit") { + CONDITIONAL_TEST(16, "test_ecmult_constants_2bit") { test_ecmult_constants_2bit(); } } From 694342fdb71722b31dd4b6bc7241b992fdf6f492 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Thu, 31 Oct 2024 13:55:52 -0400 Subject: [PATCH 114/383] Name public API structs --- include/secp256k1.h | 4 ++-- include/secp256k1_extrakeys.h | 4 ++-- include/secp256k1_musig.h | 12 ++++++------ include/secp256k1_recovery.h | 2 +- include/secp256k1_schnorrsig.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index b0c5e634..c6e9417f 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -58,7 +58,7 @@ typedef struct secp256k1_context_struct secp256k1_context; * use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. To * compare keys, use secp256k1_ec_pubkey_cmp. */ -typedef struct { +typedef struct secp256k1_pubkey { unsigned char data[64]; } secp256k1_pubkey; @@ -71,7 +71,7 @@ typedef struct { * comparison, use the secp256k1_ecdsa_signature_serialize_* and * secp256k1_ecdsa_signature_parse_* functions. */ -typedef struct { +typedef struct secp256k1_ecdsa_signature { unsigned char data[64]; } secp256k1_ecdsa_signature; diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h index 13acb032..48c98693 100644 --- a/include/secp256k1_extrakeys.h +++ b/include/secp256k1_extrakeys.h @@ -19,7 +19,7 @@ extern "C" { * use secp256k1_xonly_pubkey_serialize and secp256k1_xonly_pubkey_parse. To * compare keys, use secp256k1_xonly_pubkey_cmp. */ -typedef struct { +typedef struct secp256k1_xonly_pubkey { unsigned char data[64]; } secp256k1_xonly_pubkey; @@ -30,7 +30,7 @@ typedef struct { * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 96 bytes in size, and can be safely copied/moved. */ -typedef struct { +typedef struct secp256k1_keypair { unsigned char data[96]; } secp256k1_keypair; diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index 53501814..11b8f08c 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -40,7 +40,7 @@ extern "C" { * Guaranteed to be 197 bytes in size. No serialization and parsing functions * (yet). */ -typedef struct { +typedef struct secp256k1_musig_keyagg_cache { unsigned char data[197]; } secp256k1_musig_keyagg_cache; @@ -56,7 +56,7 @@ typedef struct { * Copying this data structure can result in nonce reuse which will leak the * secret signing key. */ -typedef struct { +typedef struct secp256k1_musig_secnonce { unsigned char data[132]; } secp256k1_musig_secnonce; @@ -65,7 +65,7 @@ typedef struct { * Guaranteed to be 132 bytes in size. Serialized and parsed with * `musig_pubnonce_serialize` and `musig_pubnonce_parse`. */ -typedef struct { +typedef struct secp256k1_musig_pubnonce { unsigned char data[132]; } secp256k1_musig_pubnonce; @@ -74,7 +74,7 @@ typedef struct { * Guaranteed to be 132 bytes in size. Serialized and parsed with * `musig_aggnonce_serialize` and `musig_aggnonce_parse`. */ -typedef struct { +typedef struct secp256k1_musig_aggnonce { unsigned char data[132]; } secp256k1_musig_aggnonce; @@ -84,7 +84,7 @@ typedef struct { * be secure. Guaranteed to be 133 bytes in size. No serialization and parsing * functions (yet). */ -typedef struct { +typedef struct secp256k1_musig_session { unsigned char data[133]; } secp256k1_musig_session; @@ -93,7 +93,7 @@ typedef struct { * Guaranteed to be 36 bytes in size. Serialized and parsed with * `musig_partial_sig_serialize` and `musig_partial_sig_parse`. */ -typedef struct { +typedef struct secp256k1_musig_partial_sig { unsigned char data[36]; } secp256k1_musig_partial_sig; diff --git a/include/secp256k1_recovery.h b/include/secp256k1_recovery.h index 78a3eee0..93a2e4cc 100644 --- a/include/secp256k1_recovery.h +++ b/include/secp256k1_recovery.h @@ -21,7 +21,7 @@ extern "C" { * recoverability) will have identical representation, so they can be * memcmp'ed. */ -typedef struct { +typedef struct secp256k1_ecdsa_recoverable_signature { unsigned char data[65]; } secp256k1_ecdsa_recoverable_signature; diff --git a/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h index 23163de2..013d4ee7 100644 --- a/include/secp256k1_schnorrsig.h +++ b/include/secp256k1_schnorrsig.h @@ -79,7 +79,7 @@ SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_b * secp256k1_nonce_function_bip340 is used, then ndata must be a * pointer to 32-byte auxiliary randomness as per BIP-340. */ -typedef struct { +typedef struct secp256k1_schnorrsig_extraparams { unsigned char magic[4]; secp256k1_nonce_function_hardened noncefp; void *ndata; From d3082ddeadef755d24523b2d4ae6b792138e847b Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 8 Oct 2024 13:42:32 +0200 Subject: [PATCH 115/383] group: Add constant-time secp256k1_ge_set_all_gej This is a dump mechanical translation of secp256k1_ge_set_all_gej_var that assumes that inputs are not infinity. --- src/group.h | 6 +++++- src/group_impl.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/tests.c | 17 +++++++++++++++-- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/group.h b/src/group.h index 992ff5c9..05ae0d20 100644 --- a/src/group.h +++ b/src/group.h @@ -80,7 +80,11 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); /** Set a group element equal to another which is given in jacobian coordinates. */ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a); -/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ +/** Set group elements r[0:len] (affine) equal to group elements a[0:len] (jacobian). + * None of the group elements in a[0:len] may be infinity. Constant time. */ +static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len); + +/** Set group elements r[0:len] (affine) equal to group elements a[0:len] (jacobian). */ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len); /** Bring a batch of inputs to the same global z "denominator", based on ratios between diff --git a/src/group_impl.h b/src/group_impl.h index 2e096f41..2e612dfb 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -195,6 +195,52 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { SECP256K1_GE_VERIFY(r); } +static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { + secp256k1_fe u; + size_t i; + size_t last_i = SIZE_MAX; +#ifdef VERIFY + for (i = 0; i < len; i++) { + SECP256K1_GEJ_VERIFY(&a[i]); + VERIFY_CHECK(!secp256k1_gej_is_infinity(&a[i])); + } +#endif + + for (i = 0; i < len; i++) { + /* Use destination's x coordinates as scratch space */ + if (last_i == SIZE_MAX) { + r[i].x = a[i].z; + } else { + secp256k1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); + } + last_i = i; + } + if (last_i == SIZE_MAX) { + return; + } + secp256k1_fe_inv(&u, &r[last_i].x); + + i = last_i; + while (i > 0) { + i--; + secp256k1_fe_mul(&r[last_i].x, &r[i].x, &u); + secp256k1_fe_mul(&u, &u, &a[last_i].z); + last_i = i; + } + VERIFY_CHECK(!a[last_i].infinity); + r[last_i].x = u; + + for (i = 0; i < len; i++) { + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); + } + +#ifdef VERIFY + for (i = 0; i < len; i++) { + SECP256K1_GE_VERIFY(&r[i]); + } +#endif +} + static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { secp256k1_fe u; size_t i; diff --git a/src/tests.c b/src/tests.c index dba4097b..61e75815 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3822,14 +3822,27 @@ static void test_ge(void) { /* Test batch gej -> ge conversion without known z ratios. */ { + secp256k1_ge *ge_set_all_var = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); + secp256k1_ge_set_all_gej_var(&ge_set_all_var[0], &gej[0], 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; testutil_random_fe_non_zero(&s); secp256k1_gej_rescale(&gej[i], &s); - CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all[i])); + CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all_var[i])); } + + /* Skip infinity at &gej[0]. */ + secp256k1_ge_set_all_gej(&ge_set_all[1], &gej[1], 4 * runs); + for (i = 1; i < 4 * runs + 1; i++) { + secp256k1_fe s; + testutil_random_fe_non_zero(&s); + secp256k1_gej_rescale(&gej[i], &s); + CHECK(secp256k1_gej_eq_ge_var(&gej[i], &ge_set_all[i])); + CHECK(secp256k1_ge_eq_var(&ge_set_all_var[i], &ge_set_all[i])); + } + + free(ge_set_all_var); free(ge_set_all); } From 365f274ce3a18a876765e2a360685f6c35c347c2 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 8 Oct 2024 13:54:41 +0200 Subject: [PATCH 116/383] group: Simplify secp256k1_ge_set_all_gej No semantic changes. --- src/group_impl.h | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/group_impl.h b/src/group_impl.h index 2e612dfb..7035cafb 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -198,7 +198,6 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, size_t len) { secp256k1_fe u; size_t i; - size_t last_i = SIZE_MAX; #ifdef VERIFY for (i = 0; i < len; i++) { SECP256K1_GEJ_VERIFY(&a[i]); @@ -206,29 +205,22 @@ static void secp256k1_ge_set_all_gej(secp256k1_ge *r, const secp256k1_gej *a, si } #endif - for (i = 0; i < len; i++) { - /* Use destination's x coordinates as scratch space */ - if (last_i == SIZE_MAX) { - r[i].x = a[i].z; - } else { - secp256k1_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); - } - last_i = i; - } - if (last_i == SIZE_MAX) { + if (len == 0) { return; } - secp256k1_fe_inv(&u, &r[last_i].x); - i = last_i; - while (i > 0) { - i--; - secp256k1_fe_mul(&r[last_i].x, &r[i].x, &u); - secp256k1_fe_mul(&u, &u, &a[last_i].z); - last_i = i; + /* Use destination's x coordinates as scratch space */ + r[0].x = a[0].z; + for (i = 1; i < len; i++) { + secp256k1_fe_mul(&r[i].x, &r[i - 1].x, &a[i].z); } - VERIFY_CHECK(!a[last_i].infinity); - r[last_i].x = u; + secp256k1_fe_inv(&u, &r[len - 1].x); + + for (i = len - 1; i > 0; i--) { + secp256k1_fe_mul(&r[i].x, &r[i - 1].x, &u); + secp256k1_fe_mul(&u, &u, &a[i].z); + } + r[0].x = u; for (i = 0; i < len; i++) { secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); From 300aab1c056a05b2b4e289c0b9ac7a07c38cde5d Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 8 Oct 2024 13:57:27 +0200 Subject: [PATCH 117/383] tests: Improve _ge_set_all_gej(_var) tests --- src/tests.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tests.c b/src/tests.c index 61e75815..2d2c8e6e 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3842,6 +3842,17 @@ static void test_ge(void) { CHECK(secp256k1_ge_eq_var(&ge_set_all_var[i], &ge_set_all[i])); } + /* Test with an array of length 1. */ + secp256k1_ge_set_all_gej_var(ge_set_all_var, &gej[1], 1); + secp256k1_ge_set_all_gej(ge_set_all, &gej[1], 1); + CHECK(secp256k1_gej_eq_ge_var(&gej[1], &ge_set_all_var[1])); + CHECK(secp256k1_gej_eq_ge_var(&gej[1], &ge_set_all[1])); + CHECK(secp256k1_ge_eq_var(&ge_set_all_var[1], &ge_set_all[1])); + + /* Test with an array of length 0. */ + secp256k1_ge_set_all_gej_var(NULL, NULL, 0); + secp256k1_ge_set_all_gej(NULL, NULL, 0); + free(ge_set_all_var); free(ge_set_all); } From 64228a648fa137723e73c6e019378f58add18a1a Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 8 Oct 2024 13:59:05 +0200 Subject: [PATCH 118/383] musig: Use _ge_set_all_gej for own public nonces --- src/modules/musig/session_impl.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index fbdfd635..b5d7c221 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -395,6 +395,7 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { secp256k1_scalar k[2]; secp256k1_ge nonce_pts[2]; + secp256k1_gej nonce_ptj[2]; int i; unsigned char pk_ser[33]; size_t pk_ser_len = sizeof(pk_ser); @@ -445,12 +446,13 @@ int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_m secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); for (i = 0; i < 2; i++) { - secp256k1_gej nonce_ptj; - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); - secp256k1_ge_set_gej(&nonce_pts[i], &nonce_ptj); - secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]); secp256k1_scalar_clear(&k[i]); } + secp256k1_ge_set_all_gej(nonce_pts, nonce_ptj, 2); + for (i = 0; i < 2; i++) { + secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); + } /* None of the nonce_pts will be infinity because k != 0 with overwhelming * probability */ secp256k1_musig_pubnonce_save(pubnonce, nonce_pts); From 145868a84d28512fe0b3af83c1474b288261e720 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 1 Nov 2024 20:24:49 +0000 Subject: [PATCH 119/383] Do not export `secp256k1_musig_nonce_gen_internal` --- src/modules/musig/session_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 1251b378..dde38085 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -392,7 +392,7 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c secp256k1_sha256_clear(&sha); } -int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { +static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { secp256k1_scalar k[2]; secp256k1_ge nonce_pts[2]; int i; From a306bb7e903fef32bc7a5ea0f8144955168c7fca Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 4 Nov 2024 14:08:27 +0000 Subject: [PATCH 120/383] tools: fix check-abi.sh after cmake out locations were changed --- tools/check-abi.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/check-abi.sh b/tools/check-abi.sh index 94a98831..601a64ba 100755 --- a/tools/check-abi.sh +++ b/tools/check-abi.sh @@ -49,7 +49,14 @@ checkout_and_build() { -DSECP256K1_BUILD_CTIME_TESTS=OFF \ -DSECP256K1_BUILD_EXAMPLES=OFF cmake --build . -j "$(nproc)" - abi-dumper src/libsecp256k1.so -o ABI.dump -lver "$2" -public-headers ../include/ + # FIXME: Just set LIBPATH to lib/libsecp256k1.so once version 0.6.0 is + # released. + if [ -f "src/libsecp256k1.so" ]; then + LIBPATH="src/libsecp256k1.so" + else + LIBPATH="lib/libsecp256k1.so" + fi + abi-dumper $LIBPATH -o ABI.dump -lver "$2" -public-headers ../include/ cd "$_orig_dir" } From df2eceb2790fb63812955c1bd0ab9fe11c930584 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 4 Nov 2024 15:58:36 +0000 Subject: [PATCH 121/383] build: add ellswift.md and musig.md to release tarball --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index a4c8d33d..a95b4809 100644 --- a/Makefile.am +++ b/Makefile.am @@ -265,6 +265,7 @@ maintainer-clean-local: clean-testvectors ### Additional files to distribute EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md +EXTRA_DIST += doc/ellswift.md doc/musig.md EXTRA_DIST += examples/EXAMPLES_COPYING EXTRA_DIST += sage/gen_exhaustive_groups.sage EXTRA_DIST += sage/gen_split_lambda_constants.sage From 39d5dfd542a12bb1ad236c78e9fcc1f044998385 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 4 Nov 2024 13:45:03 +0000 Subject: [PATCH 122/383] release: prepare for 0.6.0 --- CHANGELOG.md | 16 +++++++++++++--- CMakeLists.txt | 8 ++++---- configure.ac | 12 ++++++------ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5026aab1..ee447c0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,16 +5,26 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.6.0] - 2024-11-04 #### Added - New module `musig` implements the MuSig2 multisignature scheme according to the [BIP 327 specification](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). See: - Header file `include/secp256k1_musig.h` which defines the new API. - Document `doc/musig.md` for further notes on API usage. - Usage example `examples/musig.c`. + - New CMake variable `SECP256K1_APPEND_LDFLAGS` for appending linker flags to the build command. + +#### Changed + - API functions now use a significantly more robust method to clear secrets from the stack before returning. However, secret clearing remains a best-effort security measure and cannot guarantee complete removal. + - Any type `secp256k1_foo` can now be forward-declared using `typedef struct secp256k1_foo secp256k1_foo;` (or also `struct secp256k1_foo;` in C++). + - Organized CMake build artifacts into dedicated directories (`bin/` for executables, `lib/` for libraries) to improve build output structure and Windows shared library compatibility. #### Removed - - Removed the `secp256k1_scratch_space` struct and its associated functions `secp256k1_scratch_space_create` `secp256k1_scratch_space_destroy` because the scratch space was unused in the API. + - Removed the `secp256k1_scratch_space` struct and its associated functions `secp256k1_scratch_space_create` and `secp256k1_scratch_space_destroy` because the scratch space was unused in the API. + +#### ABI Compatibility +The symbols `secp256k1_scratch_space_create` and `secp256k1_scratch_space_destroy` were removed. +Otherwise, the library maintains backward compatibility with versions 0.3.x through 0.5.x. ## [0.5.1] - 2024-08-01 @@ -152,7 +162,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. -[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...HEAD +[0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.0...v0.4.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 84078101..041bfa3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.5.2 + VERSION 0.6.0 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -31,9 +31,9 @@ endif() # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -set(${PROJECT_NAME}_LIB_VERSION_CURRENT 4) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 2) -set(${PROJECT_NAME}_LIB_VERSION_AGE 2) +set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_AGE 0) #============================= # Language setup diff --git a/configure.ac b/configure.ac index dca1e662..f880a357 100644 --- a/configure.ac +++ b/configure.ac @@ -4,18 +4,18 @@ AC_PREREQ([2.60]) # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) -define(_PKG_VERSION_MINOR, 5) -define(_PKG_VERSION_PATCH, 2) -define(_PKG_VERSION_IS_RELEASE, false) +define(_PKG_VERSION_MINOR, 6) +define(_PKG_VERSION_PATCH, 0) +define(_PKG_VERSION_IS_RELEASE, true) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -define(_LIB_VERSION_CURRENT, 4) -define(_LIB_VERSION_REVISION, 2) -define(_LIB_VERSION_AGE, 2) +define(_LIB_VERSION_CURRENT, 5) +define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From c97059f5948a2d4070e0f19922e451079c749d78 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 4 Nov 2024 17:17:39 +0000 Subject: [PATCH 123/383] release cleanup: bump version after 0.6.0 --- CHANGELOG.md | 3 +++ CMakeLists.txt | 4 ++-- configure.ac | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee447c0c..05222e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + ## [0.6.0] - 2024-11-04 #### Added @@ -162,6 +164,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. +[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...HEAD [0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 041bfa3d..5d3c9061 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.6.0 + VERSION 0.6.1 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -32,7 +32,7 @@ endif() # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) set(${PROJECT_NAME}_LIB_VERSION_AGE 0) #============================= diff --git a/configure.ac b/configure.ac index f880a357..22a7ac0d 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,8 @@ AC_PREREQ([2.60]) # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 6) -define(_PKG_VERSION_PATCH, 0) -define(_PKG_VERSION_IS_RELEASE, true) +define(_PKG_VERSION_PATCH, 1) +define(_PKG_VERSION_IS_RELEASE, false) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. define(_LIB_VERSION_CURRENT, 5) -define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_REVISION, 1) define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From 39705450ebcfc7a2a8be540c868da9d2c44900cb Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Tue, 5 Nov 2024 16:44:29 +0100 Subject: [PATCH 124/383] Fix some misspellings Some files contained English misspellings or math issues (`lamba` instead of `lambda`). --- CMakeLists.txt | 2 +- configure.ac | 4 ++-- src/scalar_impl.h | 4 ++-- src/util.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d3c9061..aba6e512 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,7 @@ option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL}) ## Modules # We declare all options before processing them, to make sure we can express -# dependendencies while processing. +# dependencies while processing. option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON) option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF) option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON) diff --git a/configure.ac b/configure.ac index 22a7ac0d..c62a391d 100644 --- a/configure.ac +++ b/configure.ac @@ -254,8 +254,8 @@ fi print_msan_notice=no if test x"$enable_ctime_tests" = x"yes"; then SECP_MSAN_CHECK - # MSan on Clang >=16 reports unitialized memory in function parameters and return values, even if - # the uninitalized variable is never actually "used". This is called "eager" checking, and it's + # MSan on Clang >=16 reports uninitialized memory in function parameters and return values, even if + # the uninitialized variable is never actually "used". This is called "eager" checking, and it's # sounds like good idea for normal use of MSan. However, it yields many false positives in the # ctime_tests because many return values depend on secret (i.e., "uninitialized") values, and # we're only interested in detecting branches (which count as "uses") on secret data. diff --git a/src/scalar_impl.h b/src/scalar_impl.h index dbb5b0a0..0232a8c2 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -90,11 +90,11 @@ static void secp256k1_scalar_split_lambda_verify(const secp256k1_scalar *r1, con #endif /* - * Both lambda and beta are primitive cube roots of unity. That is lamba^3 == 1 mod n and + * Both lambda and beta are primitive cube roots of unity. That is lambda^3 == 1 mod n and * beta^3 == 1 mod p, where n is the curve order and p is the field order. * * Furthermore, because (X^3 - 1) = (X - 1)(X^2 + X + 1), the primitive cube roots of unity are - * roots of X^2 + X + 1. Therefore lambda^2 + lamba == -1 mod n and beta^2 + beta == -1 mod p. + * roots of X^2 + X + 1. Therefore lambda^2 + lambda == -1 mod n and beta^2 + beta == -1 mod p. * (The other primitive cube roots of unity are lambda^2 and beta^2 respectively.) * * Let l = -1/2 + i*sqrt(3)/2, the complex root of X^2 + X + 1. We can define a ring diff --git a/src/util.h b/src/util.h index 88a41494..5f29f407 100644 --- a/src/util.h +++ b/src/util.h @@ -232,7 +232,7 @@ static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { * As best as we can tell, this is sufficient to break any optimisations that * might try to eliminate "superfluous" memsets. * This method is used in memzero_explicit() the Linux kernel, too. Its advantage is that it - * is pretty efficient, because the compiler can still implement the memset() efficently, + * is pretty efficient, because the compiler can still implement the memset() efficiently, * just not remove it entirely. See "Dead Store Elimination (Still) Considered Harmful" by * Yang et al. (USENIX Security 2017) for more background. */ From 1823594761046ae38e002781d65e9538dd211d27 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 2 Dec 2024 18:20:18 +0100 Subject: [PATCH 125/383] Verify `compressed` argument in `secp256k1_eckey_pubkey_serialize` Due to similarity to the public API function `secp256k1_ec_pubkey_serialize`, public API flags like `SECP256K1_EC_COMPRESSED` are sometimes mistakingly passed to newly proposed code (this is currently the case for several modules in secp256k1-zkp, see https://github.com/BlockstreamResearch/secp256k1-zkp/pull/300). which is currently not detected. To avoid this in the future, a VERIFY_CHECK is added to check that the `compressed` argument is either 0 or 1. --- src/eckey_impl.h | 3 +++ src/secp256k1.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 121966f8..a88a5964 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -9,6 +9,7 @@ #include "eckey.h" +#include "util.h" #include "scalar.h" #include "field.h" #include "group.h" @@ -35,6 +36,8 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char } static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { + VERIFY_CHECK(compressed == 0 || compressed == 1); + if (secp256k1_ge_is_infinity(elem)) { return 0; } diff --git a/src/secp256k1.c b/src/secp256k1.c index a248519d..8b6f9937 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -280,7 +280,7 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o ARG_CHECK(pubkey != NULL); ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, !!(flags & SECP256K1_FLAGS_BIT_COMPRESSION)); if (ret) { *outputlen = len; } From 2ac9f558c43b5ef11f0d6e1088a8295a6d162659 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Tue, 26 Nov 2024 22:35:25 +0100 Subject: [PATCH 126/383] doc: Improve cmake instructions in README --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 222e5fb7..6a311aa6 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,11 @@ Implementation details Building with Autotools ----------------------- - $ ./autogen.sh - $ ./configure - $ make - $ make check # run the test suite - $ sudo make install # optional + $ ./autogen.sh # Generate a ./configure script + $ ./configure # Generate a build system + $ make # Run the actual build process + $ make check # Run the test suite + $ sudo make install # Install the library into the system (optional) To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. @@ -79,24 +79,23 @@ To maintain a pristine source tree, CMake encourages to perform an out-of-source ### Building on POSIX systems - $ mkdir build && cd build - $ cmake .. - $ cmake --build . - $ ctest # run the test suite - $ sudo cmake --install . # optional + $ cmake -B build # Generate a build system in subdirectory "build" + $ cmake --build build # Run the actual build process + $ ctest --test-dir build # Run the test suite + $ sudo cmake --install build # Install the library into the system (optional) -To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake .. -LH` to see the full list of available flags. +To compile optional modules (such as Schnorr signatures), you need to run `cmake` with additional flags (such as `-DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON`). Run `cmake -B build -LH` or `ccmake -B build` to see the full list of available flags. ### Cross compiling To alleviate issues with cross compiling, preconfigured toolchain files are available in the `cmake` directory. For example, to cross compile for Windows: - $ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-w64-mingw32.toolchain.cmake + $ cmake -B build -DCMAKE_TOOLCHAIN_FILE=cmake/x86_64-w64-mingw32.toolchain.cmake To cross compile for Android with [NDK](https://developer.android.com/ndk/guides/cmake) (using NDK's toolchain file, and assuming the `ANDROID_NDK_ROOT` environment variable has been set): - $ cmake .. -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 + $ cmake -B build -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 ### Building on Windows @@ -106,7 +105,7 @@ The following example assumes using of Visual Studio 2022 and CMake v3.21+. In "Developer Command Prompt for VS 2022": - >cmake -G "Visual Studio 17 2022" -A x64 -S . -B build + >cmake -G "Visual Studio 17 2022" -A x64 -B build >cmake --build build --config RelWithDebInfo Usage examples From 84c0bd1f7276c163cf0e34a5dfe6e307cd2bbd4a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 13 Dec 2024 09:19:40 +0000 Subject: [PATCH 127/383] cmake: Adjust diagnostic flags for clang-cl --- CMakeLists.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aba6e512..520a96ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,17 +242,21 @@ endif() include(TryAppendCFlags) if(MSVC) - # Keep the following commands ordered lexicographically. + # For both cl and clang-cl compilers. try_append_c_flags(/W3) # Production quality warning level. - try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". - try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". - try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". # Eliminate deprecation warnings for the older, less secure functions. add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +else() + try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers. +endif() +if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + # Keep the following commands ordered lexicographically. + try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned". + try_append_c_flags(/wd4244) # Disable warning C4244 "'conversion' conversion from 'type1' to 'type2', possible loss of data". + try_append_c_flags(/wd4267) # Disable warning C4267 "'var' : conversion from 'size_t' to 'type', possible loss of data". else() # Keep the following commands ordered lexicographically. try_append_c_flags(-pedantic) - try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers. try_append_c_flags(-Wcast-align) # GCC >= 2.95. try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0. try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only. From 4c50d73dd98edc0b968525a291cf14b708bbdbf1 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 13 Dec 2024 09:35:55 +0000 Subject: [PATCH 128/383] ci: Add new "Windows (clang-cl)" job --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54b2fab1..c87de301 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -746,6 +746,8 @@ jobs: cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' - job_name: 'x86 (MSVC): Windows (VS 2022)' cmake_options: '-A Win32' + - job_name: 'x64 (MSVC): Windows (clang-cl)' + cmake_options: '-T ClangCL' steps: - name: Checkout From a82287fb85746e0f7ea142a68a859e56ee86ee10 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Wed, 29 Jan 2025 03:59:32 +0100 Subject: [PATCH 129/383] schnorrsig: clear out masked secret key in BIP-340 nonce function --- src/modules/schnorrsig/main_impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 82bba2f5..2ed7be67 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -94,6 +94,8 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, nonce32); secp256k1_sha256_clear(&sha); + secp256k1_memclear(masked_key, sizeof(masked_key)); + return 1; } From b682dbcf845d80f69c4e2d8243c90dd48006a4c1 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Wed, 11 Dec 2024 09:15:26 -0500 Subject: [PATCH 130/383] README: add instructions for verifying GPG signatures --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index 6a311aa6..f7a59b2b 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,42 @@ Implementation details * Optional runtime blinding which attempts to frustrate differential power analysis. * The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally. +Obtaining and verifying +----------------------- + +The git tag for each release (e.g. `v0.6.0`) is GPG-signed by one of the maintainers. +For a fully verified build of this project, it is recommended to obtain this repository +via git, obtain the GPG keys of the signing maintainer(s), and then verify the release +tag's signature using git. + +This can be done with the following steps: + +1. Obtain the GPG keys listed in [SECURITY.md](./SECURITY.md). +2. If possible, cross-reference these key IDs with another source controlled by its owner (e.g. + social media, personal website). This is to mitigate the unlikely case that incorrect + content is being presented by this repository. +3. Clone the repository: + ``` + git clone https://github.com/bitcoin-core/secp256k1 + ``` +4. Check out the latest release tag, e.g. + ``` + git checkout v0.6.0 + ``` +5. Use git to verify the GPG signature: + ``` + % git tag -v v0.6.0 | grep -C 3 'Good signature' + + gpg: Signature made Mon 04 Nov 2024 12:14:44 PM EST + gpg: using RSA key 4BBB845A6F5A65A69DFAEC234861DBF262123605 + gpg: Good signature from "Jonas Nick " [unknown] + gpg: aka "Jonas Nick " [unknown] + gpg: WARNING: This key is not certified with a trusted signature! + gpg: There is no indication that the signature belongs to the owner. + Primary key fingerprint: 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 + Subkey fingerprint: 4BBB 845A 6F5A 65A6 9DFA EC23 4861 DBF2 6212 3605 + ``` + Building with Autotools ----------------------- From 965393fceadf8024c6b60dff59b2c30b61af28d2 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 14 Feb 2025 13:43:10 +0100 Subject: [PATCH 131/383] examples: use `EXIT_...` constants for `main` return values Fixes issue #1609. --- examples/ecdh.c | 9 +++++---- examples/ecdsa.c | 13 +++++++------ examples/ellswift.c | 11 ++++++----- examples/musig.c | 15 ++++++++------- examples/schnorr.c | 13 +++++++------ 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/examples/ecdh.c b/examples/ecdh.c index 13aa760b..67b8c204 100644 --- a/examples/ecdh.c +++ b/examples/ecdh.c @@ -8,6 +8,7 @@ *************************************************************************/ #include +#include #include #include @@ -33,7 +34,7 @@ int main(void) { secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage See `secp256k1_context_randomize` in secp256k1.h for more @@ -44,14 +45,14 @@ int main(void) { /*** Key Generation ***/ if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* If the secret key is zero or out of range (greater than secp256k1's * order), we fail. Note that the probability of this occurring is negligible * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Public key creation using a valid context with a verified secret key should never fail */ @@ -116,5 +117,5 @@ int main(void) { secure_erase(shared_secret1, sizeof(shared_secret1)); secure_erase(shared_secret2, sizeof(shared_secret2)); - return 0; + return EXIT_SUCCESS; } diff --git a/examples/ecdsa.c b/examples/ecdsa.c index 80ae9d46..ae16c180 100644 --- a/examples/ecdsa.c +++ b/examples/ecdsa.c @@ -8,6 +8,7 @@ *************************************************************************/ #include +#include #include #include @@ -40,7 +41,7 @@ int main(void) { secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage See `secp256k1_context_randomize` in secp256k1.h for more @@ -51,14 +52,14 @@ int main(void) { /*** Key Generation ***/ if (!fill_random(seckey, sizeof(seckey))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* If the secret key is zero or out of range (greater than secp256k1's * order), we fail. Note that the probability of this occurring is negligible * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Public key creation using a valid context with a verified secret key should never fail */ @@ -92,13 +93,13 @@ int main(void) { /* Deserialize the signature. This will return 0 if the signature can't be parsed correctly. */ if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) { printf("Failed parsing the signature\n"); - return 1; + return EXIT_FAILURE; } /* Deserialize the public key. This will return 0 if the public key can't be parsed correctly. */ if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) { printf("Failed parsing the public key\n"); - return 1; + return EXIT_FAILURE; } /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ @@ -133,5 +134,5 @@ int main(void) { * will remove any writes that aren't used. */ secure_erase(seckey, sizeof(seckey)); - return 0; + return EXIT_SUCCESS; } diff --git a/examples/ellswift.c b/examples/ellswift.c index afb2fee4..d58e96b0 100644 --- a/examples/ellswift.c +++ b/examples/ellswift.c @@ -13,6 +13,7 @@ */ #include +#include #include #include @@ -38,7 +39,7 @@ int main(void) { ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage. See `secp256k1_context_randomize` in secp256k1.h for more @@ -49,14 +50,14 @@ int main(void) { /*** Generate secret keys ***/ if (!fill_random(seckey1, sizeof(seckey1)) || !fill_random(seckey2, sizeof(seckey2))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* If the secret key is zero or out of range (greater than secp256k1's * order), we fail. Note that the probability of this occurring is negligible * with a properly functioning random number generator. */ if (!secp256k1_ec_seckey_verify(ctx, seckey1) || !secp256k1_ec_seckey_verify(ctx, seckey2)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Generate ElligatorSwift public keys. This should never fail with valid context and @@ -64,7 +65,7 @@ int main(void) { optional, but recommended. */ if (!fill_random(auxrand1, sizeof(auxrand1)) || !fill_random(auxrand2, sizeof(auxrand2))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } return_val = secp256k1_ellswift_create(ctx, ellswift_pubkey1, seckey1, auxrand1); assert(return_val); @@ -117,5 +118,5 @@ int main(void) { secure_erase(shared_secret1, sizeof(shared_secret1)); secure_erase(shared_secret2, sizeof(shared_secret2)); - return 0; + return EXIT_SUCCESS; } diff --git a/examples/musig.c b/examples/musig.c index 0352dc40..bdb8fced 100644 --- a/examples/musig.c +++ b/examples/musig.c @@ -12,6 +12,7 @@ */ #include +#include #include #include @@ -193,7 +194,7 @@ int main(void) { for (i = 0; i < N_SIGNERS; i++) { if (!create_keypair(ctx, &signer_secrets[i], &signers[i])) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } pubkeys_ptr[i] = &signers[i].pubkey; } @@ -208,7 +209,7 @@ int main(void) { fflush(stdout); if (!secp256k1_ec_pubkey_sort(ctx, pubkeys_ptr, N_SIGNERS)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); @@ -219,7 +220,7 @@ int main(void) { * while providing a non-NULL agg_pk argument. */ if (!secp256k1_musig_pubkey_agg(ctx, NULL, &cache, pubkeys_ptr, N_SIGNERS)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); printf("Tweaking................"); @@ -227,21 +228,21 @@ int main(void) { /* Optionally tweak the aggregate key */ if (!tweak(ctx, &agg_pk, &cache)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); printf("Signing message........."); fflush(stdout); if (!sign(ctx, signer_secrets, signers, &cache, msg, sig)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); printf("Verifying signature....."); fflush(stdout); if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) { printf("FAILED\n"); - return 1; + return EXIT_FAILURE; } printf("ok\n"); @@ -256,5 +257,5 @@ int main(void) { secure_erase(&signer_secrets[i], sizeof(signer_secrets[i])); } secp256k1_context_destroy(ctx); - return 0; + return EXIT_SUCCESS; } diff --git a/examples/schnorr.c b/examples/schnorr.c index 909fcaa1..49baed24 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -8,6 +8,7 @@ *************************************************************************/ #include +#include #include #include @@ -34,7 +35,7 @@ int main(void) { secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); if (!fill_random(randomize, sizeof(randomize))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Randomizing the context is recommended to protect against side-channel * leakage See `secp256k1_context_randomize` in secp256k1.h for more @@ -45,7 +46,7 @@ int main(void) { /*** Key Generation ***/ if (!fill_random(seckey, sizeof(seckey))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Try to create a keypair with a valid context. This only fails if the * secret key is zero or out of range (greater than secp256k1's order). Note @@ -53,7 +54,7 @@ int main(void) { * functioning random number generator. */ if (!secp256k1_keypair_create(ctx, &keypair, seckey)) { printf("Generated secret key is invalid. This indicates an issue with the random number generator.\n"); - return 1; + return EXIT_FAILURE; } /* Extract the X-only public key from the keypair. We pass NULL for @@ -90,7 +91,7 @@ int main(void) { /* Generate 32 bytes of randomness to use with BIP-340 schnorr signing. */ if (!fill_random(auxiliary_rand, sizeof(auxiliary_rand))) { printf("Failed to generate randomness\n"); - return 1; + return EXIT_FAILURE; } /* Generate a Schnorr signature. @@ -110,7 +111,7 @@ int main(void) { * be parsed correctly */ if (!secp256k1_xonly_pubkey_parse(ctx, &pubkey, serialized_pubkey)) { printf("Failed parsing the public key\n"); - return 1; + return EXIT_FAILURE; } /* Compute the tagged hash on the received messages using the same tag as the signer. */ @@ -149,5 +150,5 @@ int main(void) { * Here we are preventing these writes from being optimized out, as any good compiler * will remove any writes that aren't used. */ secure_erase(seckey, sizeof(seckey)); - return 0; + return EXIT_SUCCESS; } From c8555817280d106a9f860462a4499f0eb1acd001 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 14 Feb 2025 13:43:29 +0100 Subject: [PATCH 132/383] test, bench, precompute_ecmult: use `EXIT_...` constants for `main` return values --- src/bench.c | 15 ++++++++------- src/bench.h | 2 +- src/bench_ecmult.c | 7 ++++--- src/bench_internal.c | 5 +++-- src/ctime_tests.c | 5 +++-- src/precompute_ecmult.c | 5 +++-- src/precompute_ecmult_gen.c | 5 +++-- src/tests.c | 2 +- src/tests_exhaustive.c | 4 ++-- 9 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/bench.c b/src/bench.c index 1127df67..149f25fc 100644 --- a/src/bench.c +++ b/src/bench.c @@ -5,6 +5,7 @@ ***********************************************************************/ #include +#include #include #include "../include/secp256k1.h" @@ -188,11 +189,11 @@ int main(int argc, char** argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(default_iters); - return 0; + return EXIT_SUCCESS; } else if (invalid_args) { fprintf(stderr, "./bench: unrecognized argument.\n\n"); help(default_iters); - return 1; + return EXIT_FAILURE; } } @@ -201,7 +202,7 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "ecdh")) { fprintf(stderr, "./bench: ECDH module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -209,7 +210,7 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) { fprintf(stderr, "./bench: Public key recovery module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -217,7 +218,7 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) { fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -227,7 +228,7 @@ int main(int argc, char** argv) { have_flag(argc, argv, "ellswift_ecdh")) { fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n"); fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n"); - return 1; + return EXIT_FAILURE; } #endif @@ -275,5 +276,5 @@ int main(int argc, char** argv) { run_ellswift_bench(iters, argc, argv); #endif - return 0; + return EXIT_SUCCESS; } diff --git a/src/bench.h b/src/bench.h index 1564b1a1..232fb35f 100644 --- a/src/bench.h +++ b/src/bench.h @@ -24,7 +24,7 @@ static int64_t gettime_i64(void) { struct timespec tv; if (!timespec_get(&tv, TIME_UTC)) { fputs("timespec_get failed!", stderr); - exit(1); + exit(EXIT_FAILURE); } return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL; #else diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 3974af75..172292d5 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -4,6 +4,7 @@ * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ #include +#include #include "secp256k1.c" #include "../include/secp256k1.h" @@ -287,7 +288,7 @@ int main(int argc, char **argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(argv); - return 0; + return EXIT_SUCCESS; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); data.ecmult_multi = secp256k1_ecmult_pippenger_batch_single; @@ -299,7 +300,7 @@ int main(int argc, char **argv) { } else { fprintf(stderr, "%s: unrecognized argument '%s'.\n\n", argv[0], argv[1]); help(argv); - return 1; + return EXIT_FAILURE; } } @@ -363,5 +364,5 @@ int main(int argc, char **argv) { free(data.output); free(data.expected_output); - return(0); + return EXIT_SUCCESS; } diff --git a/src/bench_internal.c b/src/bench_internal.c index a7006849..8688a4dc 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -4,6 +4,7 @@ * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ #include +#include #include "secp256k1.c" #include "../include/secp256k1.h" @@ -393,7 +394,7 @@ int main(int argc, char **argv) { || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { help(default_iters); - return 0; + return EXIT_SUCCESS; } } @@ -432,5 +433,5 @@ int main(int argc, char **argv) { if (d || have_flag(argc, argv, "context")) run_benchmark("context_create", bench_context, bench_setup, NULL, &data, 10, iters); - return 0; + return EXIT_SUCCESS; } diff --git a/src/ctime_tests.c b/src/ctime_tests.c index bbde863d..f81bdb92 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -5,6 +5,7 @@ ***********************************************************************/ #include +#include #include #include "../include/secp256k1.h" @@ -49,7 +50,7 @@ int main(void) { if (!SECP256K1_CHECKMEM_RUNNING()) { fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n"); fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n"); - return 1; + return EXIT_FAILURE; } ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY); /** In theory, testing with a single secret input should be sufficient: @@ -69,7 +70,7 @@ int main(void) { CHECK(ret); secp256k1_context_destroy(ctx); - return 0; + return EXIT_SUCCESS; } static void run_tests(secp256k1_context *ctx, unsigned char *key) { diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c index 5ef198a7..021fe394 100644 --- a/src/precompute_ecmult.c +++ b/src/precompute_ecmult.c @@ -6,6 +6,7 @@ #include #include +#include #include "../include/secp256k1.h" @@ -62,7 +63,7 @@ int main(void) { fp = fopen(outfile, "w"); if (fp == NULL) { fprintf(stderr, "Could not open %s for writing!\n", outfile); - return -1; + return EXIT_FAILURE; } fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n"); @@ -86,5 +87,5 @@ int main(void) { fprintf(fp, "#undef S\n"); fclose(fp); - return 0; + return EXIT_SUCCESS; } diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index 4d153a65..cd0fe70f 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -6,6 +6,7 @@ #include #include +#include #include "../include/secp256k1.h" @@ -64,7 +65,7 @@ int main(int argc, char **argv) { fp = fopen(outfile, "w"); if (fp == NULL) { fprintf(stderr, "Could not open %s for writing!\n", outfile); - return -1; + return EXIT_FAILURE; } fprintf(fp, "/* This file was automatically generated by precompute_ecmult_gen. */\n"); @@ -96,5 +97,5 @@ int main(int argc, char **argv) { fprintf(fp, "#undef S\n"); fclose(fp); - return 0; + return EXIT_SUCCESS; } diff --git a/src/tests.c b/src/tests.c index 78533b11..88628a14 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7837,5 +7837,5 @@ int main(int argc, char **argv) { testrand_finish(); printf("no problems found\n"); - return 0; + return EXIT_SUCCESS; } diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 6efa8898..f8bbcaaf 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -383,7 +383,7 @@ int main(int argc, char** argv) { this_core = strtol(argv[4], NULL, 0); if (num_cores < 1 || this_core >= num_cores) { fprintf(stderr, "Usage: %s [count] [seed] [numcores] [thiscore]\n", argv[0]); - return 1; + return EXIT_FAILURE; } printf("running tests for core %lu (out of [0..%lu])\n", (unsigned long)this_core, (unsigned long)num_cores - 1); } @@ -462,5 +462,5 @@ int main(int argc, char** argv) { testrand_finish(); printf("no problems found\n"); - return 0; + return EXIT_SUCCESS; } From 13d389629aba2c686798a856332c00c6934cacd5 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 14 Feb 2025 13:42:28 +0100 Subject: [PATCH 133/383] CONTRIBUTING: mention that `EXIT_` codes should be used --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a366d38b..80890fb7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -74,6 +74,7 @@ In addition, libsecp256k1 tries to maintain the following coding conventions: * User-facing comment lines in headers should be limited to 80 chars if possible. * All identifiers in file scope should start with `secp256k1_`. * Avoid trailing whitespace. +* Use the constants `EXIT_SUCCESS`/`EXIT_FAILURE` (defined in `stdlib.h`) to indicate program execution status for examples and other binaries. ### Tests From 432ac57705b8e2f6a5874095214c443f1f8ea9bf Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Fri, 22 Nov 2024 22:28:30 +0100 Subject: [PATCH 134/383] Make static context const --- include/secp256k1.h | 4 ++-- src/secp256k1.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index c6e9417f..ccb7457e 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -230,10 +230,10 @@ typedef int (*secp256k1_nonce_function)( * * It is highly recommended to call secp256k1_selftest before using this context. */ -SECP256K1_API const secp256k1_context *secp256k1_context_static; +SECP256K1_API const secp256k1_context * const secp256k1_context_static; /** Deprecated alias for secp256k1_context_static. */ -SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp +SECP256K1_API const secp256k1_context * const secp256k1_context_no_precomp SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); /** Perform basic self tests (to be used in conjunction with secp256k1_context_static) diff --git a/src/secp256k1.c b/src/secp256k1.c index 8b6f9937..f047ca9e 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -71,8 +71,8 @@ static const secp256k1_context secp256k1_context_static_ = { { secp256k1_default_error_callback_fn, 0 }, 0 }; -const secp256k1_context *secp256k1_context_static = &secp256k1_context_static_; -const secp256k1_context *secp256k1_context_no_precomp = &secp256k1_context_static_; +const secp256k1_context * const secp256k1_context_static = &secp256k1_context_static_; +const secp256k1_context * const secp256k1_context_no_precomp = &secp256k1_context_static_; /* Helper function that determines if a context is proper, i.e., is not the static context or a copy thereof. * From 37d2c60beca394e8f4733c65f5d558eb302cac06 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Wed, 21 Aug 2024 00:57:38 +0200 Subject: [PATCH 135/383] Remove deprecated _ec_privkey_{negate,tweak_add,tweak_mul} aliases These function aliases have been described as DEPRECATED in the public API docs already many years ago (see #701, commit 41fc7856), and in addition explicit deprecation warnings are shown by the compiler at least since the first official release 0.2.0 (see PR #1089, commit fc94a2da), so it should be fine to just remove them by now. Co-authored-by: Tim Ruffing --- CHANGELOG.md | 5 +++++ include/secp256k1.h | 26 -------------------------- src/secp256k1.c | 12 ------------ src/tests.c | 19 ------------------- 4 files changed, 5 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05222e5e..70421711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Removed +- Removed previously deprecated function aliases `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add` and + `secp256k1_ec_privkey_tweak_mul`. Use `secp256k1_ec_seckey_negate`, `secp256k1_ec_seckey_tweak_add` and + `secp256k1_ec_seckey_tweak_mul` instead. + ## [0.6.0] - 2024-11-04 #### Added diff --git a/include/secp256k1.h b/include/secp256k1.h index c6e9417f..b7a099c7 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -701,14 +701,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate( unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); -/** Same as secp256k1_ec_seckey_negate, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( - const secp256k1_context *ctx, - unsigned char *seckey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) - SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_negate instead"); - /** Negates a public key in place. * * Returns: 1 always @@ -741,15 +733,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add( const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Same as secp256k1_ec_seckey_tweak_add, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( - const secp256k1_context *ctx, - unsigned char *seckey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) - SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_tweak_add instead"); - /** Tweak a public key by adding tweak times the generator to it. * * Returns: 0 if the arguments are invalid or the resulting public key would be @@ -788,15 +771,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul( const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Same as secp256k1_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in - * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context *ctx, - unsigned char *seckey, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) - SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_tweak_mul instead"); - /** Tweak a public key by multiplying it by a tweak value. * * Returns: 0 if the arguments are invalid. 1 otherwise. diff --git a/src/secp256k1.c b/src/secp256k1.c index 8b6f9937..b89ef36d 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -634,10 +634,6 @@ int secp256k1_ec_seckey_negate(const secp256k1_context* ctx, unsigned char *seck return ret; } -int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { - return secp256k1_ec_seckey_negate(ctx, seckey); -} - int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { int ret = 0; secp256k1_ge p; @@ -681,10 +677,6 @@ int secp256k1_ec_seckey_tweak_add(const secp256k1_context* ctx, unsigned char *s return ret; } -int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - return secp256k1_ec_seckey_tweak_add(ctx, seckey, tweak32); -} - static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *p, const unsigned char *tweak32) { secp256k1_scalar term; int overflow = 0; @@ -729,10 +721,6 @@ int secp256k1_ec_seckey_tweak_mul(const secp256k1_context* ctx, unsigned char *s return ret; } -int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - return secp256k1_ec_seckey_tweak_mul(ctx, seckey, tweak32); -} - int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak32) { secp256k1_ge p; secp256k1_scalar factor; diff --git a/src/tests.c b/src/tests.c index 88628a14..76583563 100644 --- a/src/tests.c +++ b/src/tests.c @@ -6248,11 +6248,6 @@ static void run_eckey_negate_test(void) { CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 1); CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); - /* Check that privkey alias gives same result */ - CHECK(secp256k1_ec_seckey_negate(CTX, seckey) == 1); - CHECK(secp256k1_ec_privkey_negate(CTX, seckey_tmp) == 1); - CHECK(secp256k1_memcmp_var(seckey, seckey_tmp, 32) == 0); - /* Negating all 0s fails */ memset(seckey, 0, 32); memset(seckey_tmp, 0, 32); @@ -6413,22 +6408,15 @@ static void test_ecdsa_end_to_end(void) { if (testrand_int(3) == 0) { int ret1; int ret2; - int ret3; unsigned char rnd[32]; - unsigned char privkey_tmp[32]; secp256k1_pubkey pubkey2; testrand256_test(rnd); - memcpy(privkey_tmp, privkey, 32); ret1 = secp256k1_ec_seckey_tweak_add(CTX, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_add(CTX, &pubkey, rnd); - /* Check that privkey alias gives same result */ - ret3 = secp256k1_ec_privkey_tweak_add(CTX, privkey_tmp, rnd); CHECK(ret1 == ret2); - CHECK(ret2 == ret3); if (ret1 == 0) { return; } - CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0); CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } @@ -6437,22 +6425,15 @@ static void test_ecdsa_end_to_end(void) { if (testrand_int(3) == 0) { int ret1; int ret2; - int ret3; unsigned char rnd[32]; - unsigned char privkey_tmp[32]; secp256k1_pubkey pubkey2; testrand256_test(rnd); - memcpy(privkey_tmp, privkey, 32); ret1 = secp256k1_ec_seckey_tweak_mul(CTX, privkey, rnd); ret2 = secp256k1_ec_pubkey_tweak_mul(CTX, &pubkey, rnd); - /* Check that privkey alias gives same result */ - ret3 = secp256k1_ec_privkey_tweak_mul(CTX, privkey_tmp, rnd); CHECK(ret1 == ret2); - CHECK(ret2 == ret3); if (ret1 == 0) { return; } - CHECK(secp256k1_memcmp_var(privkey, privkey_tmp, 32) == 0); CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); CHECK(secp256k1_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } From 961ec25a8392415f3e1d3e88a43e81c12d716e72 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 10 Mar 2025 15:10:29 +0100 Subject: [PATCH 136/383] musig: Fix clearing of pubnonces Fixes a silent merge conflict between #1614 and #1579. --- src/modules/musig/session_impl.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index fd09df6c..d8dcd00c 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -445,12 +445,18 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp secp256k1_musig_secnonce_save(secnonce, k, &pk); secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); + /* Compute pubnonce as two gejs */ for (i = 0; i < 2; i++) { secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]); secp256k1_scalar_clear(&k[i]); - secp256k1_gej_clear(&nonce_ptj); } + + /* Batch convert to two public ges */ secp256k1_ge_set_all_gej(nonce_pts, nonce_ptj, 2); + for (i = 0; i < 2; i++) { + secp256k1_gej_clear(&nonce_ptj[i]); + } + for (i = 0; i < 2; i++) { secp256k1_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); } From 59860bcc24814a4779be5688fce03bc6385faf87 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 10 Mar 2025 10:20:29 +0100 Subject: [PATCH 137/383] gha: Print all *.log files, in a separate action Before this commit, we didn't print *_example.log files and test_suite.log. Printing is now handled in a separate action, which avoids code duplication and makes the ci.yml file more readable. This changes the folding/grouping of the log output in the GitHub Actions CI, but I think the new variant is as good as the old one. Furthermore, the condition for printing the logs is changed from "always()" to "!cancelled()". This ensures that logs will still be printed if previous steps such as the CI script failed, but that they won't be printed if the entire run is cancelled (e.g., by clicking a button in the UI or through a force-push to the PR). This is in line with a recommendation in the GHA docs: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#always --- .github/actions/print-logs/action.yml | 34 ++++ .github/workflows/ci.yml | 264 +++++--------------------- 2 files changed, 77 insertions(+), 221 deletions(-) create mode 100644 .github/actions/print-logs/action.yml diff --git a/.github/actions/print-logs/action.yml b/.github/actions/print-logs/action.yml new file mode 100644 index 00000000..33de35cb --- /dev/null +++ b/.github/actions/print-logs/action.yml @@ -0,0 +1,34 @@ +name: "Print logs" +description: "Print the log files produced by ci/ci.sh" +runs: + using: "composite" + steps: + - shell: bash + run: | + # Print the log files produced by ci/ci.sh + + # Helper functions + group() { + title=$1 + echo "::group::$title" + } + endgroup() { + echo "::endgroup::" + } + cat_file() { + file=$1 + group "$file" + cat "$file" + endgroup + } + + # Print all *.log files + shopt -s nullglob + for file in *.log; do + cat_file "$file" + done + + # Print environment + group "CI env" + env + endgroup diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54b2fab1..3683ebb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,23 +107,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} i686_debian: name: "i686: Linux (Debian stable)" @@ -157,23 +143,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} s390x_debian: name: "s390x (big-endian): Linux (Debian stable, QEMU)" @@ -203,23 +175,10 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} + arm32_debian: name: "ARM32: Linux (Debian stable, QEMU)" @@ -257,23 +216,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} arm64_debian: name: "ARM64: Linux (Debian stable, QEMU)" @@ -314,23 +259,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} ppc64le_debian: name: "ppc64le: Linux (Debian stable, QEMU)" @@ -360,23 +291,10 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} + valgrind_debian: name: "Valgrind (memcheck)" @@ -416,23 +334,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} sanitizers_debian: name: "UBSan, ASan, LSan" @@ -473,23 +377,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} msan_debian: name: "MSan" @@ -537,23 +427,10 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} + mingw_debian: name: ${{ matrix.configuration.job_name }} @@ -593,23 +470,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} x86_64-macos-native: name: "x86_64: macOS Ventura, Valgrind" @@ -652,23 +515,9 @@ jobs: env: ${{ matrix.env_vars }} run: ./ci/ci.sh - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} arm64-macos-native: name: "ARM64: macOS Sonoma" @@ -708,23 +557,10 @@ jobs: env: ${{ matrix.env_vars }} run: ./ci/ci.sh - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} + win64-native: name: ${{ matrix.configuration.job_name }} @@ -813,23 +649,9 @@ jobs: dockerfile: ./ci/linux-debian.Dockerfile tag: linux-debian-image - - run: cat tests.log || true - if: ${{ always() }} - - run: cat noverify_tests.log || true - if: ${{ always() }} - - run: cat exhaustive_tests.log || true - if: ${{ always() }} - - run: cat ctime_tests.log || true - if: ${{ always() }} - - run: cat bench.log || true - if: ${{ always() }} - - run: cat config.log || true - if: ${{ always() }} - - run: cat test_env.log || true - if: ${{ always() }} - - name: CI env - run: env - if: ${{ always() }} + - name: Print logs + uses: ./.github/actions/print-logs + if: ${{ !cancelled() }} cxx_headers_debian: name: "C++ (public headers)" From 88548058b3e88f7f1ce7c1abbe12da8105a858cc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 10 Mar 2025 11:22:13 +0000 Subject: [PATCH 138/383] Introduce `SECP256K1_LOCAL_VAR` macro This change makes the `-fvisibility=hidden` compiler option unnecessary. --- Makefile.am | 1 + src/precomputed_ecmult.h | 6 ++++-- src/precomputed_ecmult_gen.h | 4 +++- src/util_local_visibility.h | 12 ++++++++++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 src/util_local_visibility.h diff --git a/Makefile.am b/Makefile.am index a95b4809..fb4a48aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,7 @@ noinst_HEADERS += src/assumptions.h noinst_HEADERS += src/checkmem.h noinst_HEADERS += src/testutil.h noinst_HEADERS += src/util.h +noinst_HEADERS += src/util_local_visibility.h noinst_HEADERS += src/int128.h noinst_HEADERS += src/int128_impl.h noinst_HEADERS += src/int128_native.h diff --git a/src/precomputed_ecmult.h b/src/precomputed_ecmult.h index 17df1029..e5a85f68 100644 --- a/src/precomputed_ecmult.h +++ b/src/precomputed_ecmult.h @@ -13,6 +13,8 @@ extern "C" { #include "ecmult.h" #include "group.h" +#include "util_local_visibility.h" + #if defined(EXHAUSTIVE_TEST_ORDER) # if EXHAUSTIVE_TEST_ORDER == 7 # define WINDOW_G 3 @@ -27,8 +29,8 @@ static secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; static secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ # define WINDOW_G ECMULT_WINDOW_SIZE -extern const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; -extern const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; +SECP256K1_LOCAL_VAR const secp256k1_ge_storage secp256k1_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; +SECP256K1_LOCAL_VAR const secp256k1_ge_storage secp256k1_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ #ifdef __cplusplus diff --git a/src/precomputed_ecmult_gen.h b/src/precomputed_ecmult_gen.h index 283738a5..00ddce10 100644 --- a/src/precomputed_ecmult_gen.h +++ b/src/precomputed_ecmult_gen.h @@ -13,10 +13,12 @@ extern "C" { #include "group.h" #include "ecmult_gen.h" +#include "util_local_visibility.h" + #ifdef EXHAUSTIVE_TEST_ORDER static secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; #else -extern const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; +SECP256K1_LOCAL_VAR const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ #ifdef __cplusplus diff --git a/src/util_local_visibility.h b/src/util_local_visibility.h new file mode 100644 index 00000000..8912a64d --- /dev/null +++ b/src/util_local_visibility.h @@ -0,0 +1,12 @@ +#ifndef SECP256K1_LOCAL_VISIBILITY_H +#define SECP256K1_LOCAL_VISIBILITY_H + +/* Global variable visibility */ +/* See: https://github.com/bitcoin-core/secp256k1/issues/1181 */ +#if !defined(_WIN32) && defined(__GNUC__) && (__GNUC__ >= 4) +# define SECP256K1_LOCAL_VAR extern __attribute__ ((visibility ("hidden"))) +#else +# define SECP256K1_LOCAL_VAR extern +#endif + +#endif /* SECP256K1_LOCAL_VISIBILITY_H */ From 41d32ab2de050e48f2854bf381cc86871aa59135 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 10 Mar 2025 11:22:25 +0000 Subject: [PATCH 139/383] test: Add `tools/symbol-check.py` Co-authored-by: Tim Ruffing --- tools/symbol-check.py | 72 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100755 tools/symbol-check.py diff --git a/tools/symbol-check.py b/tools/symbol-check.py new file mode 100755 index 00000000..e7f47808 --- /dev/null +++ b/tools/symbol-check.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Check that a libsecp256k1 shared library exports only expected symbols. + +Usage examples: + - When building with Autotools: + ./tools/symbol-check.py .libs/libsecp256k1.so + ./tools/symbol-check.py .libs/libsecp256k1-.dll + ./tools/symbol-check.py .libs/libsecp256k1.dylib + + - When building with CMake: + ./tools/symbol-check.py build/lib/libsecp256k1.so + ./tools/symbol-check.py build/bin/libsecp256k1-.dll + ./tools/symbol-check.py build/lib/libsecp256k1.dylib""" + +import re +import sys +import subprocess + +import lief + + +class UnexpectedExport(RuntimeError): + pass + + +def get_exported_exports(library) -> list[str]: + """Adapter function to get exported symbols based on the library format.""" + if library.format == lief.Binary.FORMATS.ELF: + return [symbol.name for symbol in library.exported_symbols] + elif library.format == lief.Binary.FORMATS.PE: + return [entry.name for entry in library.get_export().entries] + elif library.format == lief.Binary.FORMATS.MACHO: + return [symbol.name[1:] for symbol in library.exported_symbols] + raise NotImplementedError(f"Unsupported format: {library.format}") + + +def grep_expected_symbols() -> list[str]: + """Guess the list of expected exported symbols from the source code.""" + grep_output = subprocess.check_output( + ["git", "grep", r"^\s*SECP256K1_API", "--", "include"], + universal_newlines=True, + encoding="utf-8" + ) + lines = grep_output.split("\n") + pattern = re.compile(r'\bsecp256k1_\w+') + exported: list[str] = [pattern.findall(line)[-1] for line in lines if line.strip()] + return exported + + +def check_symbols(library, expected_exports) -> None: + """Check that the library exports only the expected symbols.""" + actual_exports = get_exported_exports(library) + unexpected_exports = set(actual_exports) - set(expected_exports) + if unexpected_exports != set(): + raise UnexpectedExport(f"Unexpected exported symbols: {unexpected_exports}") + +def main(): + if len(sys.argv) != 2: + print(__doc__) + return 1 + library = lief.parse(sys.argv[1]) + expected_exports = grep_expected_symbols() + try: + check_symbols(library, expected_exports) + except UnexpectedExport as e: + print(f"{sys.argv[0]}: In {sys.argv[1]}: {e}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 8ed1d83d92d19bd1c9ce5575e3858f881cc1674a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 10 Mar 2025 11:22:38 +0000 Subject: [PATCH 140/383] ci: Run `tools/symbol-check.py` --- .cirrus.yml | 3 +++ .github/workflows/ci.yml | 29 +++++++++++++++++++++++++++++ ci/ci.sh | 16 +++++++++++++++- ci/linux-debian.Dockerfile | 6 +++++- 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 81a4f043..023cd191 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -29,6 +29,8 @@ env: BENCH: yes SECP256K1_BENCH_ITERS: 2 CTIMETESTS: yes + SYMBOL_CHECK: yes + VIRTUAL_ENV: /root/venv # Compile and run the tests EXAMPLES: yes @@ -53,6 +55,7 @@ cat_logs_snippet: &CAT_LOGS linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER env_script: + - export PATH="$VIRTUAL_ENV/bin:$PATH" - env | tee /tmp/env build_script: - DOCKER_BUILDKIT=1 docker build --file "ci/linux-debian.Dockerfile" --tag="ci_secp256k1_arm" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a3f6dc2..a3108d6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,7 @@ env: BENCH: 'yes' SECP256K1_BENCH_ITERS: 2 CTIMETESTS: 'yes' + SYMBOL_CHECK: 'yes' # Compile and run the examples. EXAMPLES: 'yes' @@ -365,6 +366,7 @@ jobs: ASAN_OPTIONS: 'strict_string_checks=1:detect_stack_use_after_return=1:detect_leaks=1' LSAN_OPTIONS: 'use_unaligned=1' SECP256K1_TEST_ITERS: 32 + SYMBOL_CHECK: 'no' steps: - name: Checkout @@ -415,6 +417,7 @@ jobs: SECP256K1_TEST_ITERS: 32 ASM: 'no' WITH_VALGRIND: 'no' + SYMBOL_CHECK: 'no' steps: - name: Checkout @@ -483,6 +486,7 @@ jobs: CC: 'clang' HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1 + SYMBOL_CHECK: 'no' strategy: fail-fast: false @@ -515,6 +519,12 @@ jobs: env: ${{ matrix.env_vars }} run: ./ci/ci.sh + - name: Symbol check + run: | + python3 --version + python3 -m pip install lief + python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib + - name: Print logs uses: ./.github/actions/print-logs if: ${{ !cancelled() }} @@ -530,6 +540,7 @@ jobs: HOMEBREW_NO_INSTALL_CLEANUP: 1 WITH_VALGRIND: 'no' CTIMETESTS: 'no' + SYMBOL_CHECK: 'no' strategy: fail-fast: false @@ -557,6 +568,16 @@ jobs: env: ${{ matrix.env_vars }} run: ./ci/ci.sh + - name: Symbol check + env: + VIRTUAL_ENV: '${{ github.workspace }}/venv' + run: | + python3 --version + python3 -m venv $VIRTUAL_ENV + export PATH="$VIRTUAL_ENV/bin:$PATH" + python3 -m pip install lief + python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib + - name: Print logs uses: ./.github/actions/print-logs if: ${{ !cancelled() }} @@ -573,6 +594,7 @@ jobs: configuration: - job_name: 'x64 (MSVC): Windows (VS 2022, shared)' cmake_options: '-A x64 -DBUILD_SHARED_LIBS=ON' + symbol_check: 'true' - job_name: 'x64 (MSVC): Windows (VS 2022, static)' cmake_options: '-A x64 -DBUILD_SHARED_LIBS=OFF' - job_name: 'x64 (MSVC): Windows (VS 2022, int128_struct)' @@ -601,6 +623,13 @@ jobs: run: | cd build/bin/RelWithDebInfo && file *tests.exe bench*.exe libsecp256k1-*.dll || true + - name: Symbol check + if: ${{ matrix.configuration.symbol_check }} + run: | + py -3 --version + py -3 -m pip install lief + py -3 .\tools\symbol-check.py build\bin\RelWithDebInfo\libsecp256k1-5.dll + - name: Check run: | ctest -C RelWithDebInfo --test-dir build -j ([int]$env:NUMBER_OF_PROCESSORS + 1) diff --git a/ci/ci.sh b/ci/ci.sh index 3636deaf..f50a5f07 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -14,7 +14,7 @@ print_environment() { for var in WERROR_CFLAGS MAKEFLAGS BUILD \ ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \ - SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ + SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS SYMBOL_CHECK \ EXAMPLES \ HOST WRAPPER_CMD \ CC CFLAGS CPPFLAGS AR NM \ @@ -107,6 +107,20 @@ file *tests* || true file bench* || true file .libs/* || true +if [ "$SYMBOL_CHECK" = "yes" ] +then + python3 --version + case "$HOST" in + *mingw*) + ls -l .libs + python3 ./tools/symbol-check.py .libs/libsecp256k1-5.dll + ;; + *) + python3 ./tools/symbol-check.py .libs/libsecp256k1.so + ;; + esac +fi + # This tells `make check` to wrap test invocations. export LOG_COMPILER="$WRAPPER_CMD" diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 241bfa97..547b4022 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -32,7 +32,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross libc6-dbg:ppc64el \ gcc-mingw-w64-x86-64-win32 wine64 wine \ gcc-mingw-w64-i686-win32 wine32 \ - python3 && \ + python3-full && \ if ! ( dpkg --print-architecture | grep --quiet "arm64" ) ; then \ apt-get install --no-install-recommends -y \ gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 ;\ @@ -77,3 +77,7 @@ RUN \ apt-get autoremove -y wget && \ apt-get clean && rm -rf /var/lib/apt/lists/* +ENV VIRTUAL_ENV=/root/venv +RUN python3 -m venv $VIRTUAL_ENV +ENV PATH="$VIRTUAL_ENV/bin:$PATH" +RUN pip install lief From d1478763a5f400fafb42af5911db4a9460dd4a5d Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 10 Mar 2025 11:22:45 +0000 Subject: [PATCH 141/383] build: Drop no longer needed `-fvisibility=hidden` compiler option --- CMakeLists.txt | 2 -- configure.ac | 1 - 2 files changed, 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 520a96ef..2b773714 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,8 +271,6 @@ else() try_append_c_flags(-Wundef) endif() -set(CMAKE_C_VISIBILITY_PRESET hidden) - set(print_msan_notice) if(SECP256K1_BUILD_CTIME_TESTS) include(CheckMemorySanitizer) diff --git a/configure.ac b/configure.ac index c62a391d..8cb8006c 100644 --- a/configure.ac +++ b/configure.ac @@ -111,7 +111,6 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [ SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0 SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only SECP_TRY_APPEND_CFLAGS([-Wreserved-identifier], $1) # Clang >= 13.0 only - SECP_TRY_APPEND_CFLAGS([-fvisibility=hidden], $1) # GCC >= 4.0 CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS" fi From 51907fa91875b8fd34cb23ec6c23793f7ea92949 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 13 Mar 2025 08:01:08 +0000 Subject: [PATCH 142/383] tests: remove unused uncounting_illegal_callback_fn This callback function has been unused since a1d52e3e125bb46dac2cf6daa699e9f15167e8d4 --- src/tests.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/tests.c b/src/tests.c index 06bcc595..52614401 100644 --- a/src/tests.c +++ b/src/tests.c @@ -87,15 +87,6 @@ static void counting_callback_fn(const char* str, void* data) { (*p)++; } -static void uncounting_illegal_callback_fn(const char* str, void* data) { - /* Dummy callback function that just counts (backwards). */ - int32_t *p; - (void)str; - p = data; - CHECK(*p != INT32_MIN); - (*p)--; -} - static void run_xoshiro256pp_tests(void) { { size_t i; From 1b6e081538cc9a171157ec858c4aac19deb7d6cc Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 13 Mar 2025 09:31:02 +0000 Subject: [PATCH 143/383] include: remove WARN_UNUSED_RESULT for functions always returning 1 This makes the usage of the atribute consistent. In the musig and ellswift module, functions that return 1 always already don't have the WARN_UNUSED_RESULT attribute. In secp256k1.h and the extrakeys module, this has only been the case partially. In all cases where this was removed, the function only returns 0 if the illegal callback has been called. --- include/secp256k1.h | 4 ++-- include/secp256k1_extrakeys.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 2477de49..1d25a02a 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -707,7 +707,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate( * Args: ctx: pointer to a context object * In/Out: pubkey: pointer to the public key to be negated. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( +SECP256K1_API int secp256k1_ec_pubkey_negate( const secp256k1_context *ctx, secp256k1_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); @@ -857,7 +857,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( * msg: pointer to an array containing the message * msglen: length of the message array */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_tagged_sha256( +SECP256K1_API int secp256k1_tagged_sha256( const secp256k1_context *ctx, unsigned char *hash32, const unsigned char *tag, diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h index 48c98693..1a517ded 100644 --- a/include/secp256k1_extrakeys.h +++ b/include/secp256k1_extrakeys.h @@ -90,7 +90,7 @@ SECP256K1_API int secp256k1_xonly_pubkey_cmp( * the negation of the pubkey and set to 0 otherwise. * In: pubkey: pointer to a public key that is converted. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey( +SECP256K1_API int secp256k1_xonly_pubkey_from_pubkey( const secp256k1_context *ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, @@ -179,7 +179,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create( * Out: seckey: pointer to a 32-byte buffer for the secret key. * In: keypair: pointer to a keypair. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec( +SECP256K1_API int secp256k1_keypair_sec( const secp256k1_context *ctx, unsigned char *seckey, const secp256k1_keypair *keypair @@ -192,7 +192,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec( * Out: pubkey: pointer to a pubkey object, set to the keypair public key. * In: keypair: pointer to a keypair. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub( +SECP256K1_API int secp256k1_keypair_pub( const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair @@ -211,7 +211,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub( * pk_parity argument of secp256k1_xonly_pubkey_from_pubkey. * In: keypair: pointer to a keypair. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub( +SECP256K1_API int secp256k1_keypair_xonly_pub( const secp256k1_context *ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, From d87c3bc58f369a91fb07d0812eec8b0d77e8968b Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 13 Mar 2025 11:56:07 +0100 Subject: [PATCH 144/383] ci: Fix exiting from ci.sh on error Fixes the following bash error when make fails: ./ci/ci.sh: line 100: return: can only `return' from a function or sourced script --- ci/ci.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ci.sh b/ci/ci.sh index f50a5f07..3285ecc9 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -94,10 +94,10 @@ if [ $build_exit_code -ne 0 ]; then *snapshot*) # Ignore internal compiler errors in gcc-snapshot and clang-snapshot grep -e "internal compiler error:" -e "PLEASE submit a bug report" make.log - return $?; + exit $? ;; *) - return 1; + exit 1 ;; esac fi From 20b05c9d3f3376fa3719b3d455de93423167244c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 13 Mar 2025 12:56:21 +0100 Subject: [PATCH 145/383] configure: Show exhaustive tests in summary Fixes #1658. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 8cb8006c..406227fc 100644 --- a/configure.ac +++ b/configure.ac @@ -476,6 +476,7 @@ echo "Build Options:" echo " with external callbacks = $enable_external_default_callbacks" echo " with benchmarks = $enable_benchmark" echo " with tests = $enable_tests" +echo " with exhaustive tests = $enable_exhaustive_tests" echo " with ctime tests = $enable_ctime_tests" echo " with coverage = $enable_coverage" echo " with examples = $enable_examples" From 6b3fe51fb6c4f0bf38e49acc562a74c8a8b743d3 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 13 Mar 2025 14:51:17 +0000 Subject: [PATCH 146/383] bench: add ellswift to bench help output --- src/bench.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/bench.c b/src/bench.c index 149f25fc..8ba7623a 100644 --- a/src/bench.c +++ b/src/bench.c @@ -16,18 +16,22 @@ static void help(int default_iters) { printf("Benchmarks the following algorithms:\n"); printf(" - ECDSA signing/verification\n"); -#ifdef ENABLE_MODULE_ECDH - printf(" - ECDH key exchange (optional module)\n"); -#endif - #ifdef ENABLE_MODULE_RECOVERY printf(" - Public key recovery (optional module)\n"); #endif +#ifdef ENABLE_MODULE_ECDH + printf(" - ECDH key exchange (optional module)\n"); +#endif + #ifdef ENABLE_MODULE_SCHNORRSIG printf(" - Schnorr signatures (optional module)\n"); #endif +#ifdef ENABLE_MODULE_ELLSWIFT + printf(" - ElligatorSwift (optional module)\n"); +#endif + printf("\n"); printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); From c1bcb03276a0848102f26050334fc04a3081a77b Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 22 Apr 2025 12:13:44 +0200 Subject: [PATCH 147/383] gitignore: Add Python cache files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index bffba8cb..ce33a84a 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,7 @@ libsecp256k1.pc /CMakeUserPresets.json # Default CMake build directory. /build + +### Python +__pycache__/ +*.py[oc] From e266ba11ae9fd20f011ac303d82caf8017d8b627 Mon Sep 17 00:00:00 2001 From: RandomLattice <128569685+RandomLattice@users.noreply.github.com> Date: Sat, 3 Feb 2024 18:52:22 -0500 Subject: [PATCH 148/383] tests: Add Wycheproof ECDH vectors Adds a test for the ECDH module using the Wycheproof vectors. We use a python script to convert the JSON-formatted vectors into C code, in the same spirit as https://github.com/bitcoin-core/secp256k1/pull/1245 Co-authored-by: Sean Andersen <6730974+andozw@users.noreply.github.com> --- Makefile.am | 14 +- src/modules/ecdh/Makefile.am.include | 1 + src/modules/ecdh/tests_impl.h | 41 + src/wycheproof/WYCHEPROOF_COPYING | 11 +- src/wycheproof/ecdh_secp256k1_test.h | 2008 ++++ src/wycheproof/ecdh_secp256k1_test.json | 8441 +++++++++++++++++ .../ecdsa_secp256k1_sha256_bitcoin_test.h | 2 +- tools/tests_wycheproof_generate_ecdh.py | 166 + ....py => tests_wycheproof_generate_ecdsa.py} | 10 +- tools/wycheproof_utils.py | 12 + 10 files changed, 10695 insertions(+), 11 deletions(-) create mode 100644 src/wycheproof/ecdh_secp256k1_test.h create mode 100644 src/wycheproof/ecdh_secp256k1_test.json create mode 100755 tools/tests_wycheproof_generate_ecdh.py rename tools/{tests_wycheproof_generate.py => tests_wycheproof_generate_ecdsa.py} (95%) create mode 100644 tools/wycheproof_utils.py diff --git a/Makefile.am b/Makefile.am index 54986179..8123e4ba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -225,9 +225,17 @@ maintainer-clean-local: clean-precomp ### (see the comments in the previous section for detailed rationale) TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h +if ENABLE_MODULE_ECDH +TESTVECTORS += src/wycheproof/ecdh_secp256k1_test.h +endif + src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h: mkdir -p $(@D) - python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@ + python3 $(top_srcdir)/tools/tests_wycheproof_generate_ecdsa.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@ + +src/wycheproof/ecdh_secp256k1_test.h: + mkdir -p $(@D) + python3 $(top_srcdir)/tools/tests_wycheproof_generate_ecdh.py $(top_srcdir)/src/wycheproof/ecdh_secp256k1_test.json > $@ testvectors: $(TESTVECTORS) @@ -250,7 +258,9 @@ EXTRA_DIST += sage/secp256k1_params.sage EXTRA_DIST += sage/weierstrass_prover.sage EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json -EXTRA_DIST += tools/tests_wycheproof_generate.py +EXTRA_DIST += src/wycheproof/ecdh_secp256k1_test.json +EXTRA_DIST += tools/tests_wycheproof_generate_ecdsa.py +EXTRA_DIST += tools/tests_wycheproof_generate_ecdh.py if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include diff --git a/src/modules/ecdh/Makefile.am.include b/src/modules/ecdh/Makefile.am.include index 7f7f95f1..18660535 100644 --- a/src/modules/ecdh/Makefile.am.include +++ b/src/modules/ecdh/Makefile.am.include @@ -2,3 +2,4 @@ include_HEADERS += include/secp256k1_ecdh.h noinst_HEADERS += src/modules/ecdh/main_impl.h noinst_HEADERS += src/modules/ecdh/tests_impl.h noinst_HEADERS += src/modules/ecdh/bench_impl.h +noinst_HEADERS += src/wycheproof/ecdh_secp256k1_test.h diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index 6be96eac..5392eedb 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -7,6 +7,13 @@ #ifndef SECP256K1_MODULE_ECDH_TESTS_H #define SECP256K1_MODULE_ECDH_TESTS_H +static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { + (void)y; + (void)data; + memcpy(output, x, 32); + return 1; +} + static int ecdh_hash_function_test_fail(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { (void)output; (void)x; @@ -142,11 +149,45 @@ static void test_result_basepoint(void) { } } +static void test_ecdh_wycheproof(void) { +#include "../../wycheproof/ecdh_secp256k1_test.h" + int t; + for (t = 0; t < SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS; t++) { + int parsed_ok; + secp256k1_pubkey point; + const unsigned char *pk; + const unsigned char *sk; + const unsigned char *expected_shared_secret; + unsigned char output_ecdh[65] = { 0 }; + + int expected_result; + + memset(&point, 0, sizeof(point)); + pk = &wycheproof_ecdh_public_keys[testvectors[t].pk_offset]; + parsed_ok = secp256k1_ec_pubkey_parse(CTX, &point, pk, testvectors[t].pk_len); + + expected_result = testvectors[t].expected_result; + CHECK(parsed_ok == expected_result); + if (!parsed_ok) { + continue; + } + + sk = &wycheproof_ecdh_private_keys[testvectors[t].sk_offset]; + CHECK(testvectors[t].sk_len == 32); + + CHECK(secp256k1_ecdh(CTX, output_ecdh, &point, sk, ecdh_hash_function_test_xpassthru, NULL) == 1); + expected_shared_secret = &wycheproof_ecdh_shared_secrets[testvectors[t].shared_offset]; + + CHECK(secp256k1_memcmp_var(output_ecdh, expected_shared_secret, testvectors[t].shared_len) == 0); + } +} + static void run_ecdh_tests(void) { test_ecdh_api(); test_ecdh_generator_basepoint(); test_bad_scalar(); test_result_basepoint(); + test_ecdh_wycheproof(); } #endif /* SECP256K1_MODULE_ECDH_TESTS_H */ diff --git a/src/wycheproof/WYCHEPROOF_COPYING b/src/wycheproof/WYCHEPROOF_COPYING index cddf9d91..efe3e8bf 100644 --- a/src/wycheproof/WYCHEPROOF_COPYING +++ b/src/wycheproof/WYCHEPROOF_COPYING @@ -3,9 +3,18 @@ `b063b4aedae951c69df014cd25fa6d69ae9e8cb9`, see https://github.com/google/wycheproof/blob/b063b4aedae951c69df014cd25fa6d69ae9e8cb9/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json +* The file `ecdh_secp256k1_test.json` in this directory + comes from Google's project Wycheproof with git commit + `d9f6ec7d8bd8c96da05368999094e4a75ba5cb3d`, see + https://github.com/google/wycheproof/blob/d9f6ec7d8bd8c96da05368999094e4a75ba5cb3d/testvectors_v1/ecdh_secp256k1_test.json + * The file `ecdsa_secp256k1_sha256_bitcoin_test.h` is generated from `ecdsa_secp256k1_sha256_bitcoin_test.json` using the script - `tests_wycheproof_generate.py`. + `tests_wycheproof_generate_ecdsa.py`. + +* The file `ecdh_secp256k1_test.h` is generated from + `ecdh_secp256k1_test.json` using the script + `tests_wycheproof_generate_ecdh.py`. ------------------------------------------------------------------------------- diff --git a/src/wycheproof/ecdh_secp256k1_test.h b/src/wycheproof/ecdh_secp256k1_test.h new file mode 100644 index 00000000..02a087e5 --- /dev/null +++ b/src/wycheproof/ecdh_secp256k1_test.h @@ -0,0 +1,2008 @@ +/* Note: this file was autogenerated using tests_wycheproof_ecdh.py. Do not edit. */ +#define SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS (503) + +typedef struct { + size_t pk_offset; + size_t pk_len; + size_t sk_offset; + size_t sk_len; + size_t shared_offset; + size_t shared_len; + int expected_result; + int wycheproof_tcid; +} wycheproof_ecdh_testvector; + +static const unsigned char wycheproof_ecdh_private_keys[] = { 0xf4,0xb7,0xff,0x7c,0xcc,0xc9,0x88,0x13,0xa6,0x9f,0xae,0x3d,0xf2,0x22,0xbf,0xe3,0xf4,0xe2,0x8f,0x76,0x4b,0xf9,0x1b,0x4a,0x10,0xd8,0x09,0x6c,0xe4,0x46,0xb2,0x54, + 0xa2,0xb6,0x44,0x2a,0x37,0xf8,0xa3,0x76,0x4a,0xef,0xf4,0x01,0x1a,0x4c,0x42,0x2b,0x38,0x9a,0x1e,0x50,0x96,0x69,0xc4,0x3f,0x27,0x9c,0x8b,0x7e,0x32,0xd8,0x0c,0x3a, + 0x2b,0xc1,0x5c,0xf3,0x98,0x1e,0xab,0x61,0xe5,0x94,0xeb,0xf5,0x91,0x29,0x0a,0x04,0x5c,0xa9,0x32,0x6a,0x8d,0x3d,0xd4,0x9f,0x3d,0xe1,0x19,0x0d,0x39,0x27,0x0b,0xb8, + 0x93,0x8f,0x3d,0xbe,0x37,0x13,0x5c,0xd8,0xc8,0xc4,0x8a,0x67,0x6b,0x28,0xb2,0x33,0x4b,0x72,0xa3,0xf0,0x98,0x14,0xc8,0xef,0xb6,0xa4,0x51,0xbe,0x00,0xc9,0x3d,0x23, + 0xc1,0x78,0x1d,0x86,0xca,0xc2,0xc0,0x52,0xb8,0x65,0xf2,0x28,0xe6,0x4b,0xd1,0xce,0x43,0x3c,0x78,0xca,0x7d,0xfc,0xa9,0xe8,0xb8,0x10,0x47,0x3e,0x2c,0xe1,0x7d,0xa5, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3a,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x41, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xc2,0x5e,0x8c,0xd0,0x36,0x41,0x41, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xca,0x5e,0x8c,0xd0,0x36,0x41,0x41, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8b,0xd0,0x36,0x41,0x41, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x40,0xc3, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x03, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x23, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x33, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x3b, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x3e, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xba,0xae,0xdc,0xe6,0xaf,0x48,0xa0,0x3b,0xbf,0xd2,0x5e,0x8c,0xd0,0x36,0x41,0x3f, + 0xc6,0xca,0xfb,0x74,0xe2,0xa5,0x0c,0x83,0xb3,0xd2,0x32,0xc4,0x58,0x52,0x37,0xf4,0x4d,0x4c,0x54,0x33,0xc4,0xb3,0xf5,0x0c,0xe9,0x78,0xe6,0xae,0xda,0x3a,0x4f,0x5d, + 0xcf,0xe7,0x5e,0xe7,0x64,0x19,0x7a,0xa7,0x73,0x2a,0x54,0x78,0x55,0x6b,0x47,0x88,0x98,0x42,0x3d,0x2b,0xc0,0xe4,0x84,0xa6,0xeb,0xb3,0x67,0x4a,0x60,0x36,0xa6,0x5d, + 0xd0,0x91,0x82,0xa4,0xd0,0xc9,0x4b,0xa8,0x5f,0x82,0xef,0xf9,0xfc,0x1b,0xdd,0xb0,0xb0,0x7d,0x3f,0x2a,0xf8,0x63,0x2f,0xc1,0xc7,0x3a,0x36,0x04,0xe8,0xf0,0xb3,0x35}; + +static const unsigned char wycheproof_ecdh_public_keys[] = { 0x04,0xd8,0x09,0x6a,0xf8,0xa1,0x1e,0x0b,0x80,0x03,0x7e,0x1e,0xe6,0x82,0x46,0xb5,0xdc,0xbb,0x0a,0xeb,0x1c,0xf1,0x24,0x4f,0xd7,0x67,0xdb,0x80,0xf3,0xfa,0x27,0xda,0x2b,0x39,0x68,0x12,0xea,0x16,0x86,0xe7,0x47,0x2e,0x96,0x92,0xea,0xf3,0xe9,0x58,0xe5,0x0e,0x95,0x00,0xd3,0xb4,0xc7,0x72,0x43,0xdb,0x1f,0x2a,0xcd,0x67,0xba,0x9c,0xc4, + 0x02,0xd8,0x09,0x6a,0xf8,0xa1,0x1e,0x0b,0x80,0x03,0x7e,0x1e,0xe6,0x82,0x46,0xb5,0xdc,0xbb,0x0a,0xeb,0x1c,0xf1,0x24,0x4f,0xd7,0x67,0xdb,0x80,0xf3,0xfa,0x27,0xda,0x2b, + 0x04,0x96,0x5f,0xf4,0x2d,0x65,0x4e,0x05,0x8e,0xe7,0x31,0x7c,0xce,0xd7,0xca,0xf0,0x93,0xfb,0xb1,0x80,0xd8,0xd3,0xa7,0x4b,0x0d,0xcd,0x9d,0x8c,0xd4,0x7a,0x39,0xd5,0xcb,0x9c,0x2a,0xa4,0xda,0xac,0x01,0xa4,0xbe,0x37,0xc2,0x04,0x67,0xed,0xe9,0x64,0x66,0x2f,0x12,0x98,0x3e,0x0b,0x52,0x72,0xa4,0x7a,0x5f,0x27,0x85,0x68,0x5d,0x80,0x87, + 0x04,0x06,0xc4,0xb8,0x7b,0xa7,0x6c,0x6d,0xcb,0x10,0x1f,0x54,0xa0,0x50,0xa0,0x86,0xaa,0x2c,0xb0,0x72,0x2f,0x03,0x13,0x7d,0xf5,0xa9,0x22,0x47,0x2f,0x1b,0xdc,0x11,0xb9,0x82,0xe3,0xc7,0x35,0xc4,0xb6,0xc4,0x81,0xd0,0x92,0x69,0x55,0x9f,0x08,0x0a,0xd0,0x86,0x32,0xf3,0x70,0xa0,0x54,0xaf,0x12,0xc1,0xfd,0x1e,0xce,0xd2,0xea,0x92,0x11, + 0x04,0xbb,0xa3,0x0e,0xef,0x79,0x67,0xa2,0xf2,0xf0,0x8a,0x2f,0xfa,0xda,0xc0,0xe4,0x1f,0xd4,0xdb,0x12,0xa9,0x3c,0xef,0x0b,0x04,0x5b,0x57,0x06,0xf2,0x85,0x38,0x21,0xe6,0xd5,0x0b,0x2b,0xf8,0xcb,0xf5,0x30,0xe6,0x19,0x86,0x9e,0x07,0xc0,0x21,0xef,0x16,0xf6,0x93,0xcf,0xc0,0xa4,0xb0,0xd4,0xed,0x5a,0x8f,0x46,0x46,0x92,0xbf,0x3d,0x6e, + 0x04,0x6d,0xa9,0xeb,0x2c,0xda,0xc0,0x21,0x22,0xd5,0xf0,0x5c,0xf6,0xa8,0xcd,0x76,0x8e,0x37,0x8f,0x66,0x4e,0xa4,0xa7,0x87,0x1d,0x10,0xe2,0x5f,0x57,0xeb,0x1e,0xe1,0xcc,0x5b,0x2b,0x5a,0xbf,0x9c,0x6c,0x65,0x96,0xf8,0xf3,0x83,0xdd,0xbc,0xb3,0xbc,0xc2,0xd5,0xa7,0xcc,0x60,0x59,0x84,0x93,0x12,0x39,0xca,0x96,0x69,0x94,0x60,0x32,0xee, + 0x04,0xf2,0x97,0x61,0x54,0xc4,0xf5,0x3c,0xe3,0x92,0xd1,0xfe,0x39,0xa8,0x91,0xa4,0x61,0x1b,0xa8,0xcf,0x04,0x60,0x23,0xcd,0x8f,0x1b,0xcd,0x9f,0xdd,0x2e,0x92,0x11,0x91,0xb2,0x5c,0xf3,0x1c,0xae,0xdf,0xbb,0x41,0x53,0x81,0x63,0x7b,0xc3,0xf5,0x99,0xa3,0x4f,0xba,0x3e,0x14,0x13,0xf6,0x44,0xcb,0x16,0x68,0x46,0x9f,0x45,0x58,0xa7,0x72, + 0x04,0x5e,0x42,0x2f,0xea,0x67,0xcc,0xa5,0xeb,0xae,0xac,0x87,0x74,0x5c,0x81,0xb1,0x0e,0xf8,0x07,0x03,0x03,0x67,0xe6,0xfc,0xe0,0x12,0x25,0x41,0x76,0xec,0x8c,0xf1,0x99,0x88,0x15,0x92,0xf4,0x2c,0x26,0x43,0x71,0xe1,0x9e,0x30,0x37,0x38,0x8a,0xb6,0x4f,0x32,0xfa,0x88,0x70,0xe6,0x29,0x05,0xe7,0xaf,0x20,0x5e,0x43,0xb0,0x2a,0xad,0x12, + 0x04,0xbb,0x57,0xb9,0xa1,0x23,0x1b,0xe0,0x42,0xd1,0x85,0xc0,0x3e,0xda,0x69,0x26,0xa6,0xde,0xf1,0x77,0xfe,0x67,0x45,0xed,0xa0,0x00,0xc5,0x20,0xd6,0x65,0x81,0xf0,0xcd,0xf1,0xd7,0x3c,0x80,0x45,0x3f,0x2f,0xe3,0x07,0x25,0xad,0xf9,0x51,0x39,0x0c,0x73,0x9e,0x36,0xfc,0x86,0x77,0x69,0x1d,0xb1,0x07,0x88,0x13,0x42,0x61,0x3d,0x00,0xab, + 0x04,0x55,0x63,0xc7,0x6c,0x19,0x37,0x76,0x38,0xf7,0xd5,0x17,0xbd,0xbe,0x0a,0xce,0x46,0x7e,0xb5,0xd4,0xdd,0x9f,0xb4,0xbf,0x18,0x33,0x2b,0xab,0x8f,0x07,0xb1,0xd8,0x0c,0x26,0x13,0x32,0xd4,0x6e,0x31,0x67,0x11,0x27,0x8b,0xac,0xcc,0xd8,0x80,0x05,0xee,0x4c,0x11,0x5f,0xa8,0x40,0x89,0xfd,0x19,0x06,0x74,0x62,0x6e,0x5e,0xd1,0xeb,0xfe, + 0x04,0x89,0x83,0xaa,0xe8,0xc0,0x02,0xf2,0xb5,0x55,0xac,0xb2,0x37,0x0a,0xdb,0x9b,0x50,0xba,0x4c,0xac,0x1b,0xfc,0xc9,0x03,0x9a,0x12,0x5c,0x70,0xca,0x7c,0x5f,0xc0,0xd1,0xf6,0xef,0xeb,0x8a,0xe4,0xba,0x8c,0x69,0x42,0x9d,0x93,0x24,0x43,0x82,0x44,0x7a,0xc5,0x34,0x89,0x1c,0x66,0x09,0x00,0x25,0x28,0x26,0x55,0x71,0x9b,0xd7,0x25,0x12, + 0x04,0x23,0x55,0x65,0x64,0x85,0x0c,0x50,0xfb,0xa5,0x1f,0x1e,0x64,0xef,0x98,0x37,0x8e,0xf5,0xc2,0x2f,0xea,0xfa,0x29,0x49,0x9c,0xa2,0x76,0x00,0xc4,0x73,0xca,0xce,0x88,0x9d,0x56,0x79,0xe9,0x17,0xda,0xa7,0xf4,0xc7,0x89,0x95,0x17,0xd3,0x78,0x26,0x28,0x4f,0x03,0x1d,0xe0,0x1a,0x60,0xbc,0x81,0x36,0x96,0x41,0x4d,0x04,0x53,0x1a,0x21, + 0x04,0xdd,0xbf,0x80,0x7e,0x22,0xc5,0x6a,0x19,0xcf,0x6c,0x47,0x28,0x29,0x15,0x03,0x50,0x78,0x10,0x34,0xa5,0xed,0xde,0xc3,0x65,0x69,0x4d,0x4b,0xd5,0xc8,0x65,0xea,0xd1,0x4e,0x67,0x41,0x27,0x02,0x8c,0x91,0xd3,0x39,0x4c,0xac,0x37,0x29,0x3a,0x86,0x60,0x55,0xd1,0x0f,0x0f,0x40,0xa3,0x70,0x6a,0xd1,0x6b,0x64,0xfc,0x9d,0x59,0x98,0xbd, + 0x04,0x64,0x68,0x8e,0xae,0x7a,0xab,0xd2,0x48,0xf6,0xf4,0x4a,0x0d,0x6e,0x2c,0x43,0x8e,0x41,0x00,0x00,0x18,0x13,0xeb,0x71,0xf9,0xf0,0x82,0xfa,0xd3,0xdf,0xe4,0x3e,0x28,0x7d,0xab,0x3d,0xab,0xe7,0xd4,0x36,0x00,0x1a,0x0f,0xb7,0x63,0x01,0x5d,0xed,0xbb,0x90,0xf8,0x11,0x00,0x0e,0xc8,0xf5,0xf2,0x99,0x53,0xe3,0xaf,0x42,0xf9,0x20,0x65, + 0x04,0xc4,0x04,0xe1,0x71,0x41,0xd1,0x02,0xbb,0xa2,0xf1,0xcb,0x16,0xbb,0x95,0x4a,0x20,0x87,0x98,0xb0,0x4d,0xca,0x8d,0xd1,0x39,0xa8,0xab,0x7f,0x01,0xf0,0xdb,0xef,0x39,0xc7,0xb8,0xe5,0x5f,0x22,0x57,0xa4,0x80,0x07,0x7e,0x41,0x90,0x57,0x0a,0x00,0x4c,0xbe,0x66,0x82,0x00,0xc9,0xc7,0x8e,0xaa,0x53,0xb6,0x1b,0x20,0xfc,0xe4,0xc6,0x85, + 0x04,0xe1,0x60,0xe8,0x7c,0x0a,0x56,0x2a,0x1d,0xbb,0x59,0xb4,0xc2,0xf6,0x14,0x72,0x0e,0x77,0x53,0x60,0x86,0x72,0xeb,0x8d,0x88,0x3b,0x91,0xe2,0x5f,0x8c,0xfc,0x58,0x47,0x46,0x23,0xcb,0xa5,0x84,0xe1,0x32,0x4b,0xc4,0x9b,0xcd,0xf0,0x89,0x11,0x66,0xb5,0x45,0xb7,0x70,0x4e,0x2b,0xbd,0xa7,0x05,0xd0,0xd7,0x3b,0x75,0x30,0xe4,0x79,0x52, + 0x04,0x5d,0x4d,0x18,0x2b,0x18,0x78,0x2a,0x02,0x68,0x5d,0xcc,0x7b,0x67,0x1e,0xc7,0x42,0xce,0x30,0x8c,0x7a,0xcc,0x8e,0x62,0x60,0xf6,0x7e,0x81,0x51,0x6e,0xb5,0x46,0xe8,0xa3,0x8f,0x07,0x56,0x07,0x4e,0xea,0x48,0x57,0x95,0x33,0x98,0xb6,0xd0,0x55,0x97,0xc7,0xce,0xb5,0xe6,0x5e,0x4e,0x8c,0xee,0x31,0xe8,0x1c,0x56,0x58,0x82,0x4c,0xe4, + 0x04,0x8e,0xcd,0x6a,0x25,0x76,0xf4,0x26,0x26,0x79,0x20,0x76,0x93,0x5e,0x2f,0xe9,0x61,0x59,0x9e,0x48,0x4c,0xd2,0x12,0xbc,0xe2,0x62,0x3b,0x83,0xaa,0x22,0xf5,0x46,0xd2,0xa7,0xf8,0x55,0xb0,0x9b,0xef,0x28,0x6b,0xcb,0xe9,0xe8,0xba,0xb1,0x7f,0xd5,0x6d,0x70,0x55,0xdf,0x64,0xf3,0x44,0x31,0x0c,0x35,0x22,0xe8,0xf2,0x27,0xe4,0x72,0xc8, + 0x04,0x68,0x26,0xf7,0x9e,0xf8,0x4d,0xa8,0x03,0x46,0x0a,0xed,0x09,0x19,0x8d,0x2b,0xbb,0x42,0xd7,0x89,0x2e,0xd6,0x08,0xaa,0xcb,0xb2,0x81,0xa9,0x5a,0xca,0xe1,0x14,0x65,0xa2,0x58,0x09,0x19,0x1a,0xa5,0xbd,0xfa,0x61,0xb8,0x96,0x3b,0xea,0xcb,0x4e,0xb1,0x33,0x26,0x6a,0x90,0xf3,0x3d,0x1b,0x2c,0xa4,0xf6,0x15,0x2d,0x37,0xa9,0x4f,0xd8, + 0x04,0xa5,0x4b,0xb2,0xae,0x80,0x08,0x60,0x53,0xa5,0xfa,0x4f,0xdb,0x18,0x36,0xa8,0xc6,0xac,0x41,0x78,0x36,0x50,0xb0,0xf7,0x9a,0x54,0x28,0xc9,0x8f,0xf6,0x4d,0x07,0x8a,0x12,0xbb,0xb4,0xcb,0x8a,0xf2,0x0c,0xa7,0x5e,0xc1,0x5b,0x2e,0x0d,0x47,0xa8,0x3c,0xa9,0x3f,0xc7,0x8c,0xd9,0x26,0x40,0xa0,0x2e,0x80,0x02,0x96,0x6f,0x1f,0xe8,0x0b, + 0x04,0xba,0xce,0x46,0xee,0xd4,0x92,0x74,0x3c,0x69,0x3e,0x1a,0x33,0xad,0xb0,0x46,0xb7,0x72,0x2c,0x55,0xce,0x36,0x9d,0x14,0x38,0xe6,0x7f,0x9c,0x5b,0x34,0x12,0x78,0x31,0x45,0x26,0x2d,0xd4,0xa8,0x6c,0x8a,0x52,0x7b,0x23,0xf4,0x11,0x4b,0x8a,0x9b,0x9f,0x36,0xf9,0x70,0x18,0x35,0xf5,0x0b,0x67,0x8b,0x24,0xd2,0xa9,0x15,0x5e,0xbc,0x2c, + 0x04,0x01,0x05,0x51,0x47,0x86,0x3a,0xa0,0x60,0xc0,0xe1,0x04,0xe2,0x43,0xec,0x01,0xed,0xa2,0xb0,0xe0,0xc6,0x81,0x4e,0x23,0x2d,0x67,0x1a,0xbc,0xba,0x97,0x15,0xd5,0xce,0x0c,0x13,0x00,0x6a,0xa7,0x96,0x0c,0x54,0xfe,0x3f,0x20,0x22,0x0b,0xef,0x76,0x67,0x56,0xc9,0x10,0xfd,0x05,0x76,0x4a,0xfc,0x31,0x83,0x75,0x54,0x0c,0xef,0x2d,0x5c, + 0x04,0x59,0x5e,0x46,0xee,0x7c,0x2d,0x71,0x83,0xff,0x2e,0xa7,0x60,0xff,0xd8,0x47,0x2f,0xb8,0x34,0xec,0x89,0xc0,0x8b,0x6e,0xf4,0x8f,0xf9,0x2b,0x44,0xa1,0x3a,0x6e,0x1a,0xe5,0x63,0xe2,0x39,0x53,0xc9,0x7c,0x26,0x44,0x13,0x23,0xd2,0x50,0x0c,0x84,0xe8,0xce,0xe0,0x4c,0x15,0xd4,0xd5,0xd2,0xcc,0x45,0x87,0x03,0xd1,0xf2,0xd0,0x2d,0x31, + 0x04,0x6a,0x40,0xad,0xc8,0x11,0xb0,0x9e,0x83,0xba,0x0f,0xb8,0xa9,0x4f,0xea,0x50,0x59,0x1c,0xa9,0xe5,0x8b,0xb7,0xd4,0x73,0x04,0x95,0x0d,0xbf,0xf7,0x8d,0xad,0x77,0x7e,0xe3,0xbd,0x08,0xf7,0x42,0xd7,0xe8,0xe3,0x0c,0xff,0x31,0xbc,0x6a,0x6c,0xc0,0x2c,0x87,0x17,0xee,0x25,0x83,0x8a,0xab,0xff,0xa6,0xe4,0x8f,0x65,0xcc,0xe7,0x4d,0x81, + 0x04,0x5a,0x33,0xfe,0x91,0xd7,0xe3,0x5d,0xb7,0x87,0x52,0x08,0xbe,0xe7,0x7f,0x4c,0xc0,0x00,0x6f,0x14,0x39,0xcc,0x84,0x5f,0x69,0x5b,0x6a,0x12,0x67,0x3d,0xcd,0x03,0xd1,0x8f,0x86,0xee,0x12,0x1c,0x5e,0xa0,0xda,0x3e,0xb0,0x21,0x05,0x09,0xe1,0x2d,0xb8,0x45,0x29,0x62,0x25,0xca,0x97,0x3e,0x2e,0x19,0xce,0x3e,0x3d,0x01,0x48,0x60,0x90, + 0x04,0xf6,0xeb,0xaa,0xb6,0x2c,0x35,0xfd,0x4b,0x8b,0xec,0x9d,0x95,0xbc,0xfc,0x43,0x3e,0x6b,0xde,0x7c,0x0f,0x0d,0x5e,0xf7,0x5d,0x6f,0xd3,0x26,0xaa,0xf2,0x8f,0x23,0xb0,0xb2,0xf4,0xd1,0xc2,0xe8,0x91,0x70,0x6b,0x7b,0xad,0xa5,0x9f,0xb0,0xf6,0xa3,0x2b,0x54,0x63,0x98,0x2a,0x9c,0x8c,0x2d,0x8e,0xa3,0x89,0x54,0x41,0x81,0x83,0xb6,0x34, + 0x04,0x52,0x43,0x92,0x41,0x6f,0x8c,0xfc,0x5f,0x84,0xdc,0x9b,0x72,0xf2,0x88,0x7c,0x68,0x4e,0x4b,0xd2,0x47,0x96,0xf0,0x06,0x50,0x78,0xe1,0x8d,0x16,0xbc,0x43,0xb5,0x6e,0xa0,0x21,0x78,0x31,0x17,0x99,0xeb,0x61,0xad,0x3b,0x3e,0x7d,0xcd,0xa1,0x04,0x04,0xdc,0x45,0x41,0xc1,0x3e,0x3d,0xe0,0xce,0xb4,0x0c,0x9a,0xa7,0xaf,0xab,0xc5,0x3b, + 0x04,0x99,0x96,0x5c,0x47,0x7a,0x24,0x0a,0xeb,0xbd,0x19,0xcd,0x09,0x4c,0x8b,0x62,0x85,0x2d,0xe8,0x66,0x3d,0x0c,0xc9,0xf0,0x6e,0xeb,0x39,0x5f,0xfc,0x92,0xd1,0x21,0xf6,0x48,0x11,0x88,0x2f,0x40,0x60,0x80,0xd7,0xd0,0x4e,0xa4,0xf3,0x39,0xbd,0xdd,0x2e,0x5e,0xf0,0x34,0x5b,0x58,0x34,0x14,0x2f,0x75,0xb5,0x62,0x15,0x4d,0x5e,0xc7,0xae, + 0x04,0xad,0x3d,0x17,0x98,0x77,0xe7,0x4e,0xe2,0x58,0xba,0x6f,0x8e,0x12,0x8b,0xc2,0xa0,0x04,0x5c,0x06,0xa3,0xd3,0xc3,0x0f,0xcc,0xe0,0x1c,0xa8,0xd9,0xe1,0xaf,0xee,0x4e,0xa3,0xfe,0x47,0x15,0x6f,0xb7,0x27,0xfc,0x1c,0x55,0xef,0x9d,0xb5,0x16,0xdf,0x66,0x5c,0xbb,0x07,0x34,0x05,0xc2,0xc3,0x01,0xa8,0xfe,0x1d,0x10,0xf3,0xb9,0xb3,0x00, + 0x04,0x4b,0xb1,0x9d,0xea,0xe6,0x38,0xfc,0x5f,0xa7,0x07,0x0c,0xc9,0x0e,0x96,0x9b,0xac,0x3f,0x83,0x84,0xa5,0x9e,0xa1,0x1c,0xb0,0x1b,0xc0,0x91,0xed,0xf1,0xa4,0xcb,0xd6,0x77,0xed,0x6b,0xdf,0x89,0x71,0xd3,0xe6,0x3c,0x90,0x3d,0x9a,0xca,0xbc,0x28,0xb7,0x5a,0xf6,0x61,0xa0,0x34,0x57,0x26,0x1c,0x5a,0x8d,0x59,0x40,0xad,0x02,0xc5,0x09, + 0x04,0x24,0x17,0x5c,0x07,0x8e,0x30,0x5d,0x31,0x39,0xe5,0xda,0xb7,0x27,0xa6,0xab,0x85,0x87,0xb2,0x6d,0xaa,0x47,0x0a,0x52,0x9a,0x23,0xc1,0x05,0x85,0xcb,0x56,0xc0,0x38,0xbf,0x1f,0x2b,0x93,0x7a,0xe0,0x74,0xff,0x94,0xb1,0x5f,0x5c,0xb5,0xe6,0x0e,0xb5,0xd3,0x2a,0xfb,0xa2,0x07,0x75,0x39,0xdb,0x79,0x42,0x94,0xbc,0xaa,0xb7,0x1a,0x81, + 0x04,0xef,0x69,0x1a,0xfe,0x2e,0xe4,0xaa,0x18,0xa8,0x48,0x5a,0x71,0xc0,0xe2,0x0e,0xff,0x13,0x37,0xae,0x06,0x22,0xac,0xc0,0x9c,0xcd,0xa1,0x0f,0x49,0x57,0x4a,0xe8,0x40,0xb8,0x27,0x30,0xbb,0x2e,0xef,0x59,0xa1,0x7a,0xb0,0x95,0xac,0xd1,0x31,0xe5,0xfc,0xf8,0xba,0x11,0x15,0x0a,0x94,0x21,0xbb,0xab,0x6b,0x9f,0x14,0x6a,0xa7,0x8f,0xfb, + 0x04,0x06,0x7e,0x7d,0xf0,0x9f,0x5e,0x38,0xf2,0xb2,0x82,0x3f,0x65,0xa6,0xb1,0x13,0x5c,0x32,0x90,0x58,0x6f,0xef,0x6e,0xce,0xff,0xa6,0xd5,0x95,0x95,0x74,0x88,0x79,0xf6,0x69,0x32,0xb3,0xf7,0x0d,0x60,0x32,0x29,0xe1,0x0a,0x57,0x34,0x4e,0xcd,0xe5,0x03,0xa2,0xdf,0x93,0x06,0x51,0x04,0x6c,0x2f,0x1d,0x2b,0x71,0x9b,0xfc,0x93,0xe0,0xa1, + 0x04,0xb8,0x72,0x2e,0xcd,0xde,0x7c,0x85,0x31,0x7e,0x48,0x6b,0x03,0x65,0x6b,0x83,0x91,0x0a,0xc3,0xc8,0x86,0x87,0xa4,0x29,0x1e,0x8b,0xb9,0xa4,0xb6,0xa5,0x2c,0xc6,0xe0,0x2e,0x41,0x58,0xa5,0xa8,0x8d,0xe0,0x23,0xd6,0xa1,0x35,0xbd,0x04,0xc1,0x58,0x5e,0xf4,0x67,0x41,0x89,0x03,0x76,0x13,0x54,0x53,0xec,0x56,0x2d,0xa5,0xb3,0x76,0x0b, + 0x04,0x72,0x8e,0x15,0xd5,0x78,0x21,0x2b,0xc4,0x22,0x87,0xc0,0x11,0x8c,0x82,0xc8,0x4b,0x12,0x6f,0x97,0xd5,0x49,0x22,0x3c,0x10,0xad,0x07,0xf4,0xe9,0x8a,0xf9,0x12,0x38,0x5d,0x23,0xb1,0xa6,0xe7,0x16,0x92,0x58,0x55,0xa2,0x47,0xb1,0x6e,0xff,0xe9,0x27,0x73,0x31,0x52,0x41,0xac,0x95,0x1c,0xdf,0xef,0xdf,0xac,0x0e,0xd1,0x64,0x67,0xf6, + 0x04,0xc3,0xef,0x35,0xfd,0x4c,0xda,0x66,0xe8,0xe8,0x50,0x09,0x5e,0x1e,0x69,0x7a,0xee,0x56,0xde,0xcc,0x29,0x48,0x4a,0xa4,0x63,0xf8,0x79,0xc7,0xb6,0xdd,0x76,0x69,0xe6,0x25,0x94,0x53,0x51,0x27,0x67,0x19,0xc5,0xe3,0xbb,0x8e,0x51,0x4f,0x69,0x30,0x5b,0x60,0x85,0xb7,0xc7,0x82,0xa0,0x7b,0x26,0xa8,0x42,0x88,0x7c,0x33,0xa9,0x3d,0xc6, + 0x04,0x78,0x49,0x07,0xc6,0xbe,0x62,0x02,0x77,0x0b,0x98,0xd0,0x1f,0x1f,0xfe,0x11,0xb9,0xed,0x2c,0x97,0x51,0x58,0x43,0xf5,0x7c,0x2c,0x06,0x36,0x3a,0x9d,0xad,0xc7,0x01,0x1d,0xe5,0xfb,0xaa,0x73,0x56,0xcf,0x3b,0xa2,0x8c,0xb7,0xb9,0x32,0xa0,0x7c,0x83,0x21,0x00,0x7c,0x7c,0x45,0x39,0x67,0x51,0xfe,0x70,0x72,0x43,0x43,0xd2,0xb1,0x9f, + 0x04,0x7c,0x01,0x6d,0xee,0x8b,0x54,0x11,0xf8,0xe9,0x51,0x84,0xda,0xf8,0xe3,0x18,0x11,0x9e,0x84,0x4b,0x8b,0xdc,0x70,0xd7,0x5e,0xfb,0x99,0xb8,0xd0,0xff,0x10,0xab,0x74,0x5e,0x90,0x51,0x03,0xd5,0x7d,0x65,0x37,0x90,0x8e,0x6e,0x98,0x64,0xae,0xe4,0xf0,0x91,0x7f,0x5b,0x92,0x0d,0x06,0xf9,0x80,0xaa,0x82,0x3f,0x04,0x3e,0xf9,0x13,0x9e, + 0x04,0x36,0xe1,0xe7,0x6f,0xfd,0xbe,0x85,0x77,0x52,0x0b,0x07,0x16,0xeb,0x88,0xc1,0x8e,0xa7,0x2a,0x49,0xe5,0xa4,0xe5,0x68,0x0a,0x7d,0x29,0x00,0x93,0xf8,0x41,0xcb,0x6e,0x73,0x10,0x72,0x8b,0x59,0xc7,0x57,0x2c,0x4b,0x35,0xfb,0x6c,0x29,0xc3,0x6e,0xba,0xbf,0xc5,0x35,0x53,0xc0,0x6e,0xcf,0x74,0x7f,0xcf,0xbe,0xfc,0xf6,0x11,0x4e,0x1c, + 0x04,0x7a,0x19,0x50,0x1d,0x64,0x6f,0xc9,0x33,0x2a,0x85,0x25,0xaf,0x4c,0xc7,0x95,0x23,0xb5,0x7d,0x73,0x6b,0x69,0xbb,0x24,0xb0,0x62,0x70,0xc1,0xb1,0xda,0xdf,0x88,0xce,0x83,0x4e,0xfa,0x1b,0xce,0x85,0x4f,0xf5,0xbc,0xad,0xe4,0x0c,0xbc,0xee,0x9f,0x40,0x15,0x4b,0xc2,0x60,0x36,0xad,0xc5,0xcf,0x87,0xe5,0x0e,0xa3,0x88,0xaf,0x29,0x87, + 0x04,0xf4,0x3b,0x61,0x0a,0x2a,0x5c,0x5f,0x6e,0x2b,0x39,0x55,0x67,0x48,0x96,0x57,0x05,0x9e,0x33,0x51,0xc6,0xf9,0xa7,0xe2,0xeb,0xde,0x52,0x63,0x8a,0xbf,0xea,0x00,0x6a,0xb2,0xd6,0x90,0x51,0x3e,0x91,0x87,0xc0,0xcc,0x90,0x3c,0xee,0xe0,0x22,0xee,0x42,0x1c,0x59,0x4a,0x8b,0xd7,0x61,0x0c,0x68,0xcd,0x81,0x43,0xad,0xfc,0x74,0x1d,0xde, + 0x04,0xd9,0x3b,0xfd,0xaa,0x79,0x7c,0xd4,0xbd,0x81,0xde,0xa8,0x0d,0x7c,0x72,0xa2,0x49,0x23,0xce,0x50,0xe9,0x4b,0xfc,0x4e,0xe1,0xbd,0x5f,0x5f,0x10,0xee,0xa3,0xf8,0xec,0xc0,0xb5,0x94,0x18,0x90,0xa2,0x6e,0x88,0xe5,0x02,0x9c,0x28,0x3e,0x0f,0xad,0xec,0xcc,0x0b,0x98,0x0f,0x8a,0x50,0x98,0xaa,0x78,0x35,0xc5,0xc9,0x58,0xd4,0x71,0xe5, + 0x04,0x0a,0xc1,0xea,0x7a,0x29,0xf7,0xac,0xe8,0xa3,0x8b,0x2f,0xed,0xbf,0xe4,0xd0,0xd9,0xae,0x45,0x34,0x44,0x32,0xab,0x3e,0xb5,0xe0,0xa5,0xb6,0x67,0x16,0xf6,0x1c,0x6a,0xaa,0xa3,0x9a,0x5f,0x09,0x8f,0xd4,0x47,0x25,0x87,0xd1,0x4b,0xdf,0x72,0xb3,0xdd,0x3e,0x96,0x6b,0x5f,0x0b,0x6e,0x40,0x0f,0xff,0x6e,0x0e,0x9c,0x84,0x53,0xfc,0x79, + 0x04,0xbf,0x2e,0x8a,0x61,0xa2,0x1d,0x96,0xe7,0x4a,0x29,0x6b,0x39,0x7e,0x53,0x04,0x4f,0x37,0x3a,0xcb,0x73,0xa6,0xea,0x4a,0x39,0x8d,0x89,0xc5,0x65,0x49,0xe9,0x6b,0x7f,0xe8,0x46,0xfd,0x0d,0xf2,0x39,0x69,0x1d,0x06,0x82,0xb0,0x67,0xa5,0x0a,0x24,0x23,0xd8,0x8b,0x4d,0x97,0x0b,0x1d,0x3d,0x81,0x41,0xa0,0x66,0xd1,0x3c,0x18,0x6f,0x96, + 0x04,0x56,0xba,0xf1,0xd7,0x26,0x06,0xc7,0xaf,0x5a,0x5f,0xa1,0x08,0x62,0x0b,0x08,0x39,0xe2,0xc7,0xdd,0x40,0xb8,0x32,0xef,0x84,0x7e,0x5b,0x64,0xc8,0x6e,0xfe,0x1a,0xa5,0x63,0xe5,0x86,0xa6,0x67,0xa6,0x5b,0xbb,0x56,0x92,0x50,0x0d,0xf1,0xff,0x84,0x03,0x73,0x68,0x38,0xb3,0x0e,0xa9,0x79,0x1d,0x9d,0x39,0x0e,0x3d,0xc6,0x68,0x9e,0x2c, + 0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0xa2,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0xed,0x35,0x3c,0x9f,0x10,0x39,0xed,0xcc,0x9c,0xc5,0x33,0x6c,0x03,0x4d,0xc1,0x31,0xa4,0x08,0x76,0x92,0xc2,0xe5,0x6b,0xc1,0xdd,0x19,0x04,0xe3,0xff,0xff,0xff, + 0x04,0x5e,0x4c,0x2c,0xf1,0x32,0x0e,0xc8,0x4e,0xf8,0x92,0x08,0x67,0xb4,0x09,0xa9,0xa9,0x1d,0x2d,0xd0,0x08,0x21,0x6a,0x28,0x2e,0x36,0xbd,0x84,0xe8,0x84,0x72,0x6f,0xa0,0x5a,0x5e,0x4a,0xf1,0x1c,0xf6,0x3c,0xea,0xaa,0x42,0xa6,0xdc,0x9e,0x4c,0xcb,0x39,0x48,0x52,0xcf,0x84,0x28,0x4e,0x8d,0x26,0x27,0x57,0x2f,0xbf,0x22,0xc0,0xba,0x88, + 0x04,0x02,0xa3,0x0c,0x2f,0xab,0xc8,0x7e,0x67,0x30,0x62,0x5d,0xec,0x2f,0x0d,0x03,0x89,0x43,0x87,0xb7,0xf7,0x43,0xce,0x69,0xc4,0x73,0x51,0xeb,0xe5,0xee,0x98,0xa4,0x83,0x07,0xeb,0x78,0xd3,0x87,0x70,0xfe,0xa1,0xa4,0x4f,0x4d,0xa7,0x2c,0x26,0xf8,0x5b,0x17,0xf3,0x50,0x1a,0x4f,0x93,0x94,0xfe,0x29,0x85,0x6c,0xcb,0xf1,0x5f,0xd2,0x84, + 0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x03,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x03,0x1a,0x6b,0xf3,0x44,0xb8,0x67,0x30,0xac,0x5c,0x54,0xa7,0x75,0x1a,0xef,0xdb,0xa1,0x35,0x75,0x9b,0x9d,0x53,0x5c,0xa6,0x41,0x11,0xf2,0x98,0xa3,0x8d, + 0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24,0xdc,0xb0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x01,0x3b,0xc6,0xf0,0x84,0x31,0xe7,0x29,0xed,0x28,0x63,0xf2,0xf4,0xac,0x8a,0x30,0x27,0x96,0x95,0xc8,0x10,0x9c,0x34,0x0a,0x39,0xfa,0x86,0xf4,0x51,0xcd, + 0x04,0x5e,0x4c,0x2c,0xf1,0x32,0x0e,0xc8,0x4e,0xf8,0x92,0x08,0x67,0xb4,0x09,0xa9,0xa9,0x1d,0x2d,0xd0,0x08,0x21,0x6a,0x28,0x2e,0x36,0xbd,0x84,0xe8,0x84,0x72,0x6f,0xa0,0xa5,0xa1,0xb5,0x0e,0xe3,0x09,0xc3,0x15,0x55,0xbd,0x59,0x23,0x61,0xb3,0x34,0xc6,0xb7,0xad,0x30,0x7b,0xd7,0xb1,0x72,0xd9,0xd8,0xa8,0xd0,0x3f,0xdd,0x3f,0x41,0xa7, + 0x04,0x02,0xa3,0x0c,0x2f,0xab,0xc8,0x7e,0x67,0x30,0x62,0x5d,0xec,0x2f,0x0d,0x03,0x89,0x43,0x87,0xb7,0xf7,0x43,0xce,0x69,0xc4,0x73,0x51,0xeb,0xe5,0xee,0x98,0xa4,0x83,0xf8,0x14,0x87,0x2c,0x78,0x8f,0x01,0x5e,0x5b,0xb0,0xb2,0x58,0xd3,0xd9,0x07,0xa4,0xe8,0x0c,0xaf,0xe5,0xb0,0x6c,0x6b,0x01,0xd6,0x7a,0x93,0x33,0x0e,0xa0,0x29,0xab, + 0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x03,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xe5,0x94,0x0c,0xbb,0x47,0x98,0xcf,0x53,0xa3,0xab,0x58,0x8a,0xe5,0x10,0x24,0x5e,0xca,0x8a,0x64,0x62,0xac,0xa3,0x59,0xbe,0xed,0x0d,0x67,0x58,0xa2, + 0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24,0xdc,0xb0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xc4,0x39,0x0f,0x7b,0xce,0x18,0xd6,0x12,0xd7,0x9c,0x0d,0x0b,0x53,0x75,0xcf,0xd8,0x69,0x6a,0x37,0xef,0x63,0xcb,0xf5,0xc6,0x04,0x79,0x0b,0xaa,0x62, + 0x04,0x54,0x50,0xca,0xce,0x04,0x38,0x6a,0xdc,0x54,0xa1,0x43,0x50,0x79,0x3e,0x83,0xbd,0xc5,0xf2,0x65,0xd6,0xc2,0x92,0x87,0xec,0xd0,0x7f,0x79,0x1a,0xd2,0x78,0x4c,0x4c,0xeb,0xd3,0xc2,0x44,0x51,0x32,0x23,0x34,0xd8,0xd5,0x10,0x33,0xe9,0xd3,0x4b,0x6b,0xb5,0x92,0xb1,0x99,0x5d,0x07,0x86,0x78,0x63,0xd1,0x04,0x4b,0xd5,0x9d,0x75,0x01, + 0x04,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x12,0x6b,0x54,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x41,0x06,0xa3,0x69,0x06,0x8d,0x45,0x4e,0xa4,0xb9,0xc3,0xac,0x61,0x77,0xf8,0x7f,0xc8,0xfd,0x3a,0xa2,0x40,0xb2,0xcc,0xb4,0x88,0x2b,0xdc,0xcb,0xd4,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x42,0x18,0xf2,0x0a,0xe6,0xc6,0x46,0xb3,0x63,0xdb,0x68,0x60,0x58,0x22,0xfb,0x14,0x26,0x4c,0xa8,0xd2,0x58,0x7f,0xdd,0x6f,0xbc,0x75,0x0d,0x58,0x7e,0x76,0xa7,0xee, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x66,0xfb,0xe7,0x27,0xb2,0xba,0x09,0xe0,0x9f,0x5a,0x98,0xd7,0x0a,0x5e,0xfc,0xe8,0x42,0x4c,0x5f,0xa4,0x25,0xbb,0xda,0x1c,0x51,0x1f,0x86,0x06,0x57,0xb8,0x53,0x5e, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x2f,0x23,0x33,0x95,0xc8,0xb0,0x7a,0x38,0x34,0xa0,0xe5,0x9b,0xda,0x43,0x94,0x4b,0x5d,0xf3,0x78,0x85,0x2e,0x56,0x0e,0xbc,0x0f,0x22,0x87,0x7e,0x9f,0x49,0xbb,0x4b, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2c,0x0e,0x99,0x4b,0x14,0xea,0x72,0xf8,0xc3,0xeb,0x95,0xc7,0x1e,0xf6,0x92,0x57,0x5e,0x77,0x50,0x58,0x33,0x2d,0x7e,0x52,0xd0,0x99,0x5c,0xf8,0x03,0x88,0x71,0xb6,0x7d, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x3c,0x81,0xe8,0x72,0x41,0xd9,0x45,0x1d,0x28,0x6d,0xdb,0xe6,0x5b,0x14,0xd4,0x72,0x34,0x30,0x7b,0x80,0xce,0x74,0xb8,0x92,0x1a,0xf7,0xd4,0x93,0x57,0x07,0x54,0x9d, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07,0x15,0x09,0x85,0x98,0xdc,0x12,0xcf,0x29,0x4e,0xa5,0xac,0x1e,0xb5,0xee,0xae,0x91,0x39,0xf5,0xcf,0xd3,0xd0,0xff,0xdc,0xfa,0x72,0x97,0xa0,0x1d,0xce,0x1e,0xe9,0xdf, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x61,0xbd,0x3a,0x38,0xf7,0x07,0x71,0x3b,0x97,0xea,0xf8,0xd0,0x18,0x4e,0x00,0x79,0xe2,0xa6,0x2c,0xfb,0xa7,0x5d,0x42,0x8b,0x13,0x26,0xea,0x86,0x1a,0xad,0xe9,0x50, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x15,0x82,0x0e,0x7e,0x26,0x67,0x0c,0x6b,0x45,0xc1,0xe0,0xca,0xa9,0x51,0xea,0xb3,0x12,0x75,0x41,0x80,0xba,0xa9,0xfc,0xff,0x9f,0x7e,0x7b,0xf4,0x6d,0xee,0xa7,0xfc, + 0x04,0x0b,0x7b,0xeb,0xa3,0x4f,0xeb,0x64,0x7d,0xa2,0x00,0xbe,0xd0,0x5f,0xad,0x57,0xc0,0x34,0x8d,0x24,0x9e,0x2a,0x90,0xc8,0x8f,0x31,0xf9,0x94,0x8b,0xb6,0x5d,0x52,0x07,0x74,0x35,0xa6,0xbe,0xf9,0x1b,0x92,0xae,0x32,0xcf,0x51,0xd7,0x14,0x9c,0xad,0x03,0x53,0xa4,0x65,0x13,0x85,0x14,0x27,0xc3,0x44,0x36,0x53,0x6e,0xc7,0xea,0xe4,0x83, + 0x04,0x21,0x0c,0x79,0x05,0x73,0x63,0x23,0x59,0xb1,0xed,0xb4,0x30,0x2c,0x11,0x7d,0x8a,0x13,0x26,0x54,0x69,0x2c,0x3f,0xee,0xb7,0xde,0x3a,0x86,0xac,0x3f,0x3b,0x53,0xf7,0x5f,0x45,0x0d,0xbb,0xf7,0x18,0xa4,0xf6,0x58,0x2d,0x7a,0xf8,0x39,0x53,0x17,0x0b,0x30,0x37,0xfb,0x81,0xa4,0x50,0xa5,0xca,0x5a,0xcb,0xec,0x74,0xad,0x6c,0xac,0x89, + 0x04,0x42,0x18,0xf2,0x0a,0xe6,0xc6,0x46,0xb3,0x63,0xdb,0x68,0x60,0x58,0x22,0xfb,0x14,0x26,0x4c,0xa8,0xd2,0x58,0x7f,0xdd,0x6f,0xbc,0x75,0x0d,0x58,0x7e,0x76,0xa7,0xee,0x37,0x26,0x9a,0x64,0xbb,0xcf,0x3a,0x3f,0x22,0x76,0x31,0xc7,0xa8,0xce,0x53,0x2c,0x77,0x24,0x5a,0x1c,0x0d,0xb4,0x34,0x3f,0x16,0xaa,0x1d,0x33,0x9f,0xd2,0x59,0x1a, + 0x04,0x39,0xf8,0x83,0xf1,0x05,0xac,0x7f,0x09,0xf4,0xe7,0xe4,0xdc,0xc8,0x4b,0xc7,0xff,0x4b,0x3b,0x74,0xf3,0x01,0xef,0xaa,0xaf,0x8b,0x63,0x8f,0x47,0x72,0x0f,0xda,0xec,0x24,0xf5,0x0e,0xfd,0x39,0xb8,0xae,0x75,0x36,0xe8,0x80,0x69,0x27,0xea,0xc6,0xfd,0x52,0x21,0x0a,0x23,0x9f,0xb4,0x12,0x9e,0x0b,0xfe,0xd3,0x33,0x47,0x65,0x75,0xea, + 0x04,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x50,0x13,0x4a,0x74,0xfc,0x6e,0x7d,0x7a,0xce,0xf5,0xbb,0x20,0xe9,0x69,0xab,0xb6,0xf0,0x26,0xec,0x0c,0xb0,0x4d,0xff,0x34,0xf7,0x91,0x6c,0xa6,0x4b,0x07,0xff,0xf5,0x11, + 0x04,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x76,0x9a,0xfe,0x39,0x7a,0x57,0x09,0x20,0x1b,0xda,0x50,0xce,0x2d,0x31,0xa1,0x3f,0xde,0x40,0x76,0x72,0x2a,0x85,0x77,0x19,0x92,0x40,0x09,0xcc,0x28,0x15,0x98,0x69, + 0x04,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x04,0x34,0xe8,0x77,0xea,0xa7,0x13,0x40,0xaa,0x5e,0x57,0xe5,0x8a,0x01,0xf0,0xb0,0xae,0xc8,0xd2,0x4b,0x5c,0x64,0xaa,0x77,0xef,0x95,0xfa,0xe9,0xb4,0x95,0x8c,0x5d, + 0x04,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcb,0x2e,0x80,0x8a,0x8b,0x6c,0x6e,0x5b,0xc0,0x68,0xf9,0x63,0x48,0xd6,0x81,0x71,0xe6,0x61,0x59,0xa0,0xee,0x27,0x07,0x3c,0x82,0xfc,0x3f,0x95,0x81,0xa4,0xa1,0xfb,0x28, + 0x04,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0c,0x1d,0x85,0x42,0x10,0xf7,0x97,0xc5,0x47,0xbd,0x3b,0x3f,0xec,0xcd,0xe1,0xce,0x3e,0x67,0xc6,0x1c,0x34,0x00,0x14,0x1d,0xa2,0x06,0x85,0x20,0xe2,0xba,0xe9,0xbf,0x90, + 0x04,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x22,0xbc,0xbf,0x40,0xd6,0x58,0xbf,0x3f,0xf0,0x2d,0x98,0xae,0xa5,0xae,0x45,0xd4,0x3e,0xd8,0x5f,0x6d,0xe9,0x26,0x8f,0x0e,0xae,0x85,0x21,0x0f,0x2f,0xed,0x81,0xc6, + 0x04,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x21,0x0a,0x46,0x30,0x48,0x81,0x32,0x9c,0x98,0x07,0xb7,0x1b,0x63,0x93,0xba,0x10,0x4b,0x9f,0x27,0xd9,0x76,0x06,0x5e,0x85,0x24,0x29,0xfd,0x66,0x4d,0xe9,0x8e,0xee, + 0x04,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x70,0x11,0xd6,0xe8,0x51,0xe5,0xa5,0x3f,0xde,0x41,0xc1,0xf3,0x48,0x69,0x0c,0x01,0x88,0xf2,0x4c,0x10,0x5d,0x5c,0xfc,0xa5,0xb6,0xff,0x3c,0x93,0xdb,0xfd,0xef,0x99, + 0x04,0x7f,0xff,0x00,0x01,0xff,0xfc,0x00,0x07,0xff,0xf0,0x00,0x1f,0xff,0xc0,0x00,0x7f,0xff,0x00,0x01,0xff,0xfc,0x00,0x07,0xff,0xf0,0x00,0x1f,0xff,0xc0,0x00,0x7f,0xff,0x4b,0x66,0x00,0x3c,0x74,0x82,0xd0,0xf2,0xfd,0x7b,0x1c,0xb2,0xb0,0xb7,0x07,0x8c,0xd1,0x99,0xf2,0x20,0x8f,0xc3,0x7e,0xb2,0xef,0x28,0x6c,0xcb,0x2f,0x12,0x24,0xe7, + 0x04,0x80,0x00,0xff,0xfe,0x00,0x03,0xff,0xf8,0x00,0x0f,0xff,0xe0,0x00,0x3f,0xff,0x80,0x00,0xff,0xfe,0x00,0x03,0xff,0xf8,0x00,0x0f,0xff,0xe0,0x00,0x3f,0xff,0x7f,0xff,0x0a,0x23,0x31,0x88,0x0c,0xb3,0xf8,0xf9,0x00,0x4b,0xf6,0x8f,0xc3,0x79,0xbe,0xb6,0xe3,0xaf,0xfa,0xdc,0xbe,0x81,0xbd,0x4f,0x9b,0xf7,0x6e,0x4a,0xc5,0xab,0x2c,0x37, + 0x04,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xfd,0x3b,0x6a,0x26,0x29,0xd5,0x98,0xa0,0x45,0xbe,0x28,0xa1,0x68,0x72,0x88,0xcc,0x4d,0x0c,0x38,0x9c,0xc6,0xfe,0x62,0x7c,0x5c,0xc3,0xaa,0x2a,0xb9,0x63,0xdb,0x74,0x95, + 0x04,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xfe,0xff,0xfe,0x35,0xe3,0x9d,0x53,0xd1,0x01,0xa6,0xaa,0x4a,0xb4,0x34,0xc5,0x5a,0x70,0xb0,0x3d,0x24,0x4b,0x6a,0x20,0x25,0xa1,0x8d,0x4d,0x54,0x9d,0xea,0x45,0x1c,0x03,0x13,0x92, + 0x04,0x80,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x07,0xff,0xff,0xfe,0x00,0x00,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x1f,0xff,0xff,0xf8,0x00,0x00,0x03,0xff,0xff,0xfd,0x3a,0xa7,0x74,0xf4,0xd2,0x9f,0xef,0xdd,0xd9,0x54,0x6a,0xd1,0xf7,0xb2,0xb7,0x9c,0xf4,0x26,0x34,0x28,0x4f,0xbb,0x1d,0x7c,0x70,0x2e,0x9f,0xca,0x3f,0xe0,0x49,0xaf, + 0x04,0x7f,0xff,0xff,0xe0,0x00,0x00,0x0f,0xff,0xff,0xfc,0x00,0x00,0x01,0xff,0xff,0xff,0x80,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x07,0xff,0xff,0xfd,0xff,0xff,0xfe,0x23,0xe4,0xbc,0xa0,0x98,0x4d,0xa4,0x24,0xa6,0x12,0x0a,0x13,0xdc,0x67,0x6c,0x77,0x76,0x07,0x56,0x2d,0x16,0xed,0x9b,0x8f,0xa9,0x4c,0x21,0xff,0xf7,0x15,0x1d,0x4e, + 0x04,0x00,0x00,0x03,0xff,0xff,0xff,0x00,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x03,0xff,0xff,0xff,0x00,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x03,0xff,0xff,0xfc,0x2a,0x95,0xc8,0x12,0x53,0xac,0x55,0x48,0x46,0x81,0x2d,0x2a,0x44,0x15,0xf6,0xed,0xcf,0x95,0x42,0x09,0x00,0x8d,0x26,0x0a,0x80,0x6b,0x85,0xab,0xa7,0x59,0xff,0x72, + 0x04,0xff,0xff,0xfc,0x00,0x00,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x0f,0xff,0xff,0xfc,0x00,0x00,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x0f,0xff,0xff,0xfb,0xff,0xff,0xfe,0x03,0x15,0x37,0xfc,0xab,0xe5,0xd5,0xe2,0x51,0x65,0xa1,0x8b,0x1b,0xd4,0x08,0x21,0x2c,0xb5,0x23,0xef,0xea,0x0f,0xc0,0xfd,0x1e,0xac,0x46,0xe8,0x3b,0x0d,0x0b,0x52, + 0x04,0xff,0xff,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0x63,0xa8,0x8b,0x2e,0x0c,0x89,0x87,0xc6,0x31,0x0c,0xf8,0x1d,0x0c,0x93,0x5f,0x00,0x21,0x3f,0x98,0xa3,0xda,0xd2,0xf4,0x3c,0x81,0x28,0xfa,0x31,0x3a,0x90,0xd5,0x5b, + 0x04,0x00,0x00,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xbf,0xff,0xff,0xfd,0x24,0x07,0xbd,0xdc,0x5a,0x50,0xb2,0xa7,0xb9,0x6a,0x28,0x8e,0xfb,0x83,0x8b,0xf7,0x68,0xc6,0x06,0x6e,0x60,0xb7,0x2f,0x08,0xa9,0x78,0x2d,0xa2,0xe3,0x9b,0xd3,0x4f, + 0x04,0xff,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x7f,0xff,0xff,0xfd,0x4a,0xf9,0xcc,0x40,0x6a,0x46,0x94,0x3f,0xfe,0x0f,0xe6,0x30,0xbd,0x21,0xf2,0x05,0xee,0xfa,0x05,0x35,0x5f,0x3a,0x13,0xc9,0x94,0x3d,0x58,0xe1,0x6e,0x88,0x04,0x35, + 0x04,0x00,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x27,0x96,0xcf,0x7b,0xde,0x36,0xdc,0x6b,0x19,0x50,0x00,0x12,0x28,0xb7,0x24,0x9d,0x34,0x38,0xa3,0x5f,0xe5,0xbe,0x98,0x66,0x12,0x55,0xbf,0x63,0xa8,0x79,0xb3,0xa5, + 0x04,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x73,0xb0,0x88,0x64,0x96,0xae,0xd7,0x0d,0xb3,0x71,0xe2,0xe4,0x9d,0xb6,0x40,0xab,0xba,0x54,0x7e,0x5e,0x0c,0x27,0x63,0xb7,0x3a,0x0a,0x42,0xf8,0x43,0x48,0xa6,0xb1, + 0x04,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x00,0x13,0xa9,0xbe,0x0c,0xba,0xaa,0xcf,0x4e,0x0f,0x53,0xee,0x45,0xbc,0x57,0x3e,0xaa,0x44,0xdb,0xf4,0x8d,0x5f,0xaf,0xc2,0x68,0x56,0xb4,0x4d,0x6d,0x00,0xe2,0xbe, + 0x04,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x6e,0x56,0x3b,0xca,0x87,0x3b,0xd5,0x91,0xc9,0x66,0x33,0x91,0xc8,0x26,0x15,0x07,0x95,0xe3,0xc4,0x2c,0xed,0xd2,0x69,0xe6,0x8f,0xf0,0xe5,0x6d,0xc9,0x71,0xd5,0x54, + 0x04,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5b,0x5b,0x2e,0xc5,0x53,0xbe,0x67,0xfd,0x73,0xad,0xd4,0xcc,0x2b,0xce,0xd4,0xeb,0xe6,0xd0,0x4a,0x05,0xb0,0xe9,0x26,0xe3,0x12,0x03,0x7b,0x39,0x51,0x66,0x78,0x47, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x31,0xcf,0x13,0x67,0x1b,0x57,0x4e,0x31,0x3c,0x35,0x21,0x75,0x66,0xf1,0x8b,0xd2,0xc5,0xf7,0x58,0xc1,0x40,0xd2,0x4e,0x94,0xe6,0xa4,0xfd,0xa7,0xf4,0xc7,0xb1,0x2b, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0x3a,0x54,0x14,0x15,0x98,0x33,0x46,0x50,0xd1,0xf9,0x9a,0x12,0x85,0x07,0x69,0xf5,0x3d,0x34,0x52,0x9b,0x07,0xae,0x59,0x12,0x44,0xc6,0xed,0x70,0x2f,0x1a,0xa1,0x71, + 0x04,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xff,0xff,0xfe,0xbc,0x7c,0x97,0x6b,0xdd,0xab,0x1d,0x1a,0x30,0x2c,0xfa,0x17,0x6c,0x25,0x43,0x45,0x58,0xec,0x7c,0xac,0x23,0x8e,0x73,0x9c,0xa9,0x84,0x9a,0xa1,0x04,0x32,0x3b,0x10,0x6c, + 0x04,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x32,0xff,0xff,0xff,0x3c,0x7b,0x2b,0xf3,0x71,0x6a,0x9e,0x33,0x6e,0x16,0x29,0x66,0x59,0x7e,0x5c,0x42,0x3b,0xb9,0xd3,0xd0,0xd0,0xc3,0xc0,0x2b,0x9e,0x2d,0xc4,0xaa,0xba,0xd1,0x7b,0xfd,0xcb, + 0x04,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x6d,0xb6,0xda,0xe2,0x28,0x17,0x58,0x8a,0xa1,0x9f,0x91,0x0e,0x8b,0xed,0x1f,0x89,0xa6,0xb5,0xea,0x6c,0xde,0x48,0x00,0xdd,0x9b,0xeb,0x28,0xd1,0x33,0x6b,0xb4,0x60,0x75,0x11,0x81,0x44, + 0x04,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x55,0x55,0x54,0xe8,0x3c,0x4d,0x16,0xba,0x69,0x91,0x01,0x1c,0xf3,0xf9,0x4f,0xee,0xff,0x3f,0x48,0xad,0x29,0xed,0x9a,0x22,0xbc,0xef,0x8f,0xac,0x40,0xd9,0xb2,0xaf,0x25,0xe2,0xb9,0x09, + 0x04,0x59,0x29,0x4e,0x8b,0xc5,0x4e,0x76,0xd4,0x8b,0x55,0x94,0xf0,0x1f,0xe4,0x72,0x95,0x66,0xd9,0xb6,0xdf,0x63,0x85,0x98,0x2f,0xbb,0x53,0x31,0x83,0x92,0x1f,0x1a,0x12,0x45,0x43,0xe4,0x11,0x0b,0xf4,0xcd,0x22,0xe1,0xd4,0x44,0xd8,0x3e,0x24,0xc5,0xec,0xdb,0x32,0x8a,0x98,0xf2,0xf9,0x3e,0x8e,0xdc,0xb9,0x9b,0x07,0xd5,0xd9,0xfa,0xfc, + 0x04,0x29,0xb5,0x79,0x69,0x02,0x64,0x95,0x49,0x85,0x18,0x7a,0xaa,0x9e,0xa3,0x13,0xd3,0x9b,0x5c,0x82,0x8e,0x02,0x2a,0xfc,0xe8,0xfd,0x0c,0xb7,0x64,0xed,0x69,0x34,0x73,0xba,0x8c,0xde,0x1b,0x2b,0xe1,0x74,0x9c,0xf4,0xd5,0xbc,0x0d,0xf5,0x78,0x00,0x9c,0x96,0x50,0xe4,0x4b,0x6c,0x38,0x5c,0x5e,0xe2,0x62,0x1f,0xff,0xfc,0x20,0x5c,0xb7, + 0x04,0x41,0x50,0xa1,0x11,0xe0,0x48,0x9c,0xc8,0x2d,0x43,0xba,0x66,0xf4,0x04,0xba,0x0d,0xf2,0xb1,0xfa,0x13,0xff,0xea,0x36,0x14,0x42,0xf7,0x85,0x4f,0x9a,0xbb,0x38,0x14,0x65,0x62,0x7e,0x96,0xf3,0x72,0xfd,0x04,0x00,0xec,0xa4,0x21,0x13,0x89,0x0c,0xb1,0x10,0xc1,0x1e,0xda,0x22,0x40,0x5b,0xcd,0x29,0x5b,0x1c,0xaa,0xb9,0xd9,0x3a,0xf7, + 0x04,0xa7,0x46,0x46,0xc7,0x98,0xfd,0x5a,0x0a,0xf4,0x42,0xda,0x69,0xc8,0x22,0xcd,0xf1,0x13,0x4a,0xdb,0xa3,0x61,0xf9,0x06,0x63,0xd6,0x26,0x48,0x1a,0xa1,0x0e,0x00,0x04,0x56,0x71,0x60,0x69,0x68,0x18,0x28,0x6b,0x72,0xf0,0x1a,0x3e,0x5e,0x8c,0xac,0xa7,0x36,0x24,0x91,0x60,0xc7,0xde,0xd6,0x9d,0xd5,0x19,0x13,0xc3,0x03,0xa2,0xfa,0x97, + 0x04,0x61,0x1c,0x65,0xee,0xcd,0x9e,0x3d,0xe5,0x28,0xf6,0x39,0xe8,0xb6,0x69,0x86,0x88,0xdb,0x1f,0x4f,0xc8,0xc1,0x16,0x50,0xa6,0x01,0xfe,0x6d,0xae,0xca,0x5c,0x59,0x66,0x5f,0xa4,0x5a,0x23,0x40,0x06,0x33,0xba,0x36,0x30,0x24,0x4a,0xa6,0xb0,0x14,0x4d,0xe2,0xab,0x3b,0x62,0x95,0xe3,0xdf,0xa1,0x5f,0x58,0x6e,0x40,0xa8,0x40,0x53,0xaf, + 0x04,0xb4,0x9c,0x67,0x91,0x64,0x79,0x37,0x56,0x8c,0x75,0x70,0x06,0x48,0x56,0x42,0x08,0x35,0xd4,0x4a,0xf1,0xce,0xdd,0xd6,0x82,0x96,0x7f,0xbd,0x44,0xfc,0x97,0x29,0x4c,0xd1,0x35,0x65,0x1b,0xd7,0xee,0x3a,0xab,0x95,0x7e,0xba,0x10,0xed,0x4b,0x7a,0x5c,0x40,0xca,0x00,0xd9,0x59,0xca,0x66,0x30,0x80,0xc4,0xea,0xf0,0xe1,0x89,0xbc,0x21, + 0x04,0xc7,0x3c,0x71,0xd8,0x56,0xcb,0x94,0x9a,0x31,0xc2,0x49,0xc1,0xe9,0x9b,0x11,0xff,0xb6,0x98,0xcb,0xc1,0xdb,0xf4,0x00,0x2e,0x95,0x6c,0xde,0xb6,0x55,0xf8,0x40,0x45,0x71,0x6e,0x98,0xde,0xc1,0x0a,0x99,0x05,0xfa,0x1d,0x3a,0x85,0x1f,0x4f,0x1f,0xe6,0x17,0x35,0x6c,0xb5,0x6d,0x56,0x43,0xa1,0x48,0xee,0xc3,0x76,0x23,0x7a,0x27,0xf1, + 0x04,0xac,0xab,0xed,0xbe,0x76,0x0e,0x93,0x30,0xaf,0x35,0x08,0x20,0x9b,0xa0,0x08,0x1b,0x9c,0xe0,0x61,0x32,0x7d,0x1e,0xa0,0xb6,0xff,0xdc,0x57,0x7d,0xba,0xf2,0x8e,0x26,0x9c,0xd0,0x01,0x76,0x35,0x88,0x28,0x21,0x5d,0x30,0xad,0xe0,0xcf,0xf8,0xcd,0xc0,0x85,0x6c,0x84,0xfc,0xdb,0x42,0x4f,0xeb,0x93,0xce,0x58,0xa2,0x55,0x4a,0x9b,0xcd, + 0x04,0x4c,0xc9,0x19,0x7b,0xfd,0xef,0x17,0xd3,0x3a,0x9e,0xa7,0x43,0xbf,0x83,0x74,0x7b,0x56,0x4d,0x6a,0xd1,0x1e,0x60,0x80,0x95,0x7a,0x9d,0x3a,0xc4,0x41,0x65,0xfa,0x79,0x3c,0xe2,0x0d,0x13,0xd4,0x31,0x07,0x1b,0xe3,0x67,0xe5,0x92,0xf8,0xa2,0x2f,0x88,0xed,0xee,0x1c,0xd5,0x1c,0xad,0xb0,0x84,0x5e,0xbe,0xa6,0x4b,0x11,0xc4,0x57,0x08, + 0x04,0xfb,0xf4,0x11,0xaf,0xc8,0x83,0x58,0xdf,0xf2,0xba,0x15,0x6c,0xe2,0x73,0xd7,0xb1,0x5d,0x0b,0xa3,0x98,0x0a,0x60,0xa8,0x2e,0xb3,0x8b,0xfa,0x58,0x99,0x5e,0x16,0x3d,0x57,0xc6,0x2e,0x53,0x07,0x0e,0x8e,0x6c,0xb1,0xdf,0x4e,0xf5,0x09,0xeb,0x25,0x98,0xdb,0xdb,0x07,0xa5,0xff,0xd7,0x13,0x01,0xea,0xa2,0x89,0x2a,0xd1,0x23,0x8f,0x4a, + 0x04,0xcd,0x78,0x63,0xad,0xdd,0xaf,0x00,0x99,0x64,0x71,0x39,0xce,0x64,0xca,0x0b,0x39,0xdb,0xd3,0x12,0xcc,0xf9,0x6c,0x15,0xa6,0x2f,0x2c,0x49,0xe6,0x28,0x24,0x82,0x35,0x99,0x9f,0x82,0xaf,0xd0,0xf7,0x6e,0x74,0x4a,0xfd,0x0f,0xca,0x2a,0xab,0x36,0xf2,0x2f,0xf7,0xeb,0xef,0xd8,0xe5,0x41,0xfc,0xb6,0xe9,0x72,0x70,0x4b,0x8a,0xc5,0x21, + 0x04,0xbd,0x4f,0xd8,0x57,0x64,0x0a,0x6b,0xdf,0x5d,0xa4,0x2f,0xfc,0x5c,0x2c,0x17,0x55,0xc4,0xc1,0x25,0xa9,0x9d,0x38,0x0a,0x59,0x35,0xeb,0x1c,0x4c,0x3a,0x9c,0x2a,0x3a,0x47,0x60,0xdf,0x25,0xca,0x56,0x17,0x24,0xa8,0x2e,0x3f,0x9c,0x9d,0x78,0x25,0x36,0xdb,0x43,0x10,0xd6,0xc9,0xc7,0x69,0xf5,0x1b,0x73,0x3d,0xe4,0x4a,0x9c,0x02,0xf1, + 0x04,0x45,0x65,0x4b,0x3b,0x66,0x06,0x57,0x43,0xac,0x86,0x85,0x4d,0xaa,0x77,0xc9,0xe5,0xcf,0x71,0x3a,0x40,0x2f,0xbd,0x4a,0xda,0x36,0x5f,0x4f,0x96,0xbf,0x17,0x17,0xcd,0x63,0xcf,0x23,0xba,0x03,0x5d,0xe4,0x30,0xa2,0x12,0x8d,0xab,0x0d,0x2c,0x7b,0x93,0x9d,0x44,0xc6,0x66,0x24,0xf6,0x97,0x92,0x75,0xcd,0x37,0xcd,0x02,0x37,0x06,0x69, + 0x04,0xdd,0xa7,0x93,0xfe,0x7f,0xde,0xa5,0xc7,0x48,0x1c,0x75,0x6f,0x59,0xfb,0xff,0x48,0x48,0x17,0x77,0xa5,0x42,0x18,0xd9,0x5e,0xaa,0x24,0xe7,0xb8,0x6d,0x8a,0x58,0x58,0xfd,0xac,0x18,0x59,0x0c,0xd9,0x6e,0x19,0x3d,0xb5,0x1c,0x50,0x30,0x7d,0x26,0x06,0x67,0x4d,0x5b,0x8a,0xfc,0xc8,0x2d,0x1b,0x67,0x2d,0xd8,0xe0,0x97,0x19,0xa6,0xac, + 0x04,0x2e,0x04,0x3b,0x85,0x1f,0xc5,0xa5,0xf1,0x2d,0xeb,0x76,0xfe,0x94,0x18,0x2b,0x99,0xbb,0xce,0x72,0x7b,0x47,0x67,0x83,0xf9,0xd8,0x68,0xad,0x3a,0xb7,0xac,0x7a,0x25,0x14,0x62,0xb4,0x69,0xc2,0xe0,0x24,0x91,0xe0,0x5a,0x3a,0x45,0x23,0xe0,0x9a,0x6b,0xe8,0xe5,0xb2,0xd1,0x04,0x19,0xcb,0x77,0x60,0xa8,0x50,0x3a,0xe4,0xeb,0x7e,0x7b, + 0x04,0x3d,0x8f,0xdd,0xf4,0x1e,0x52,0x32,0x0c,0x80,0x81,0xe0,0xd6,0x0f,0x53,0x97,0x99,0x3a,0xbd,0xfa,0x97,0x9c,0x4b,0x5e,0x83,0x2a,0xc6,0x1b,0xf3,0xcc,0x2e,0x6f,0xd9,0x45,0x04,0xfe,0x32,0x07,0xdb,0xd1,0x8e,0xba,0xd2,0xb9,0x21,0xa5,0x2a,0x16,0xa3,0x36,0x59,0x93,0x9c,0x16,0xfb,0xb9,0x18,0x6c,0xaf,0x5e,0x2c,0xf3,0x17,0x03,0x46, + 0x04,0x65,0x10,0x6f,0xdc,0xa0,0xc4,0x08,0x73,0x8c,0x23,0x16,0xf3,0xec,0x22,0x38,0xd4,0x59,0x15,0x7b,0xab,0x2c,0x28,0x55,0x32,0x3b,0x95,0xbd,0x27,0x1c,0x91,0xde,0xdc,0xd9,0xfc,0x2d,0x68,0x54,0x46,0x78,0x98,0x29,0x25,0x1d,0x29,0x3a,0x50,0xd1,0x50,0xdf,0x5f,0x1f,0xc1,0xa0,0x60,0x4e,0x4d,0xef,0xaa,0x9a,0x8e,0x3f,0x8c,0x91,0x69, + 0x04,0x32,0x0c,0x81,0x35,0x48,0x18,0x3a,0xad,0xb0,0xe7,0xd2,0x1a,0x0f,0xfe,0x47,0x2b,0xfa,0x9b,0x4f,0xfe,0x81,0x5a,0xde,0xfd,0x09,0x18,0x0a,0x3a,0xe2,0xd1,0x5f,0xbc,0xd0,0xca,0x20,0x61,0x1d,0x22,0x32,0x84,0x7a,0xa8,0x0e,0x7f,0x76,0x91,0xc0,0x08,0xff,0x88,0x6d,0xfc,0xe5,0x50,0xf9,0x0c,0x4c,0x19,0x98,0x2e,0xd7,0x79,0xb4,0x66, + 0x04,0xa0,0xe2,0xb1,0xa9,0x2a,0x6a,0xfa,0x9f,0xe6,0x84,0x24,0xbc,0x63,0xdc,0xad,0x62,0x0b,0x7d,0xc8,0x44,0xe4,0x57,0x1f,0x54,0x04,0xab,0x9d,0x18,0xbf,0x08,0x54,0x5c,0xcb,0xa1,0xc1,0xff,0x49,0xbf,0x7b,0xaa,0x9b,0xe1,0xfc,0x0a,0xc4,0xbb,0xa6,0x3b,0x41,0xba,0x7a,0x37,0x4e,0x15,0xfc,0x39,0xb8,0x84,0xd8,0x0a,0x75,0xb0,0x70,0x92, + 0x04,0xdc,0x97,0x13,0x9a,0x3d,0xd1,0x41,0x1d,0x74,0x61,0x61,0x54,0xaa,0x0d,0x6b,0xce,0x78,0x7c,0xfa,0xfb,0xd8,0xfd,0x06,0x0b,0x68,0x0b,0x04,0xb4,0x22,0xb0,0xd2,0x2f,0x6a,0xb5,0x0e,0x5c,0x68,0xe0,0x27,0x80,0x59,0x53,0xbf,0x7c,0x3b,0xe4,0x0a,0x8f,0x7c,0x9b,0x56,0xc6,0xdb,0xbe,0x86,0x33,0x7e,0x61,0x63,0xad,0xa0,0x1d,0x9d,0x63, + 0x04,0x09,0x78,0xd4,0x2e,0x15,0x94,0x56,0x95,0x89,0xb5,0x78,0x26,0x6c,0xed,0xb6,0x08,0x8a,0x84,0xc9,0xcc,0x9b,0xaf,0xf0,0x07,0x0d,0xc1,0xd9,0x34,0x34,0x26,0x05,0xe6,0x2c,0xe8,0x0a,0x96,0x6b,0x5c,0xa0,0x34,0x49,0x81,0xf4,0x22,0x9c,0x7a,0xb6,0x22,0xa8,0x53,0xbd,0x9b,0xc5,0x9b,0x66,0x2e,0xcd,0x92,0xdf,0x23,0x8e,0x4e,0x46,0xed, + 0x04,0xa8,0x63,0x0a,0x7b,0xdb,0x78,0xa9,0x70,0xa0,0x1b,0x20,0xc3,0xe7,0xb9,0x5d,0x25,0xd3,0xee,0xbd,0xc8,0xe9,0x4e,0xcf,0xe0,0xf5,0x08,0xe4,0x13,0x6e,0xca,0x49,0xaf,0xa5,0xeb,0x12,0x11,0x4b,0x50,0xac,0x77,0xd6,0x8d,0x41,0x0c,0xd5,0xef,0x51,0x07,0xb2,0xe6,0x8f,0x08,0x60,0x0e,0x5e,0x69,0x38,0xc4,0x52,0xd5,0x1d,0x69,0x93,0xba, + 0x04,0xc4,0xea,0x8e,0xd3,0x1a,0xb4,0xa8,0xc9,0x94,0xa9,0x65,0xef,0xd4,0x77,0x0b,0xbb,0x5e,0x26,0xee,0x54,0xcb,0x72,0x17,0xff,0xd3,0x1f,0xa8,0x88,0xc1,0x08,0xfe,0xca,0x06,0x3c,0x41,0x52,0x01,0x32,0x9d,0xda,0x13,0x0f,0x43,0x97,0x3f,0x44,0x2a,0xd3,0x20,0xda,0x0c,0xcf,0x28,0x9c,0xd1,0xb7,0x14,0x89,0xca,0x0a,0x72,0x01,0xd5,0xa6, + 0x04,0x91,0x78,0x0d,0x19,0x05,0x31,0x61,0x05,0xd6,0xa6,0xac,0xa9,0x4a,0x0d,0x44,0x88,0xd1,0x34,0xf9,0x85,0xf7,0xe2,0x9a,0xde,0xcb,0x1b,0xc6,0xcd,0x0c,0x21,0x1a,0x78,0x80,0x35,0xb0,0x6e,0x49,0x5d,0x1e,0x58,0xb0,0x85,0xbf,0xb6,0x72,0x0b,0xca,0x84,0x55,0x7b,0x67,0x0d,0xe3,0x45,0x87,0xdf,0x0d,0x7e,0x3a,0xad,0x5b,0xbc,0x80,0x3a, + 0x04,0x19,0x61,0xa1,0xa4,0xb2,0x96,0x71,0xf1,0xd8,0x35,0xb3,0x13,0xff,0xeb,0xa4,0xd8,0x20,0x3d,0x84,0x14,0xcd,0xc0,0xea,0x11,0xe4,0x7d,0x61,0x9b,0x47,0x03,0x8b,0x1d,0xe5,0x0a,0x63,0xb8,0x9c,0xbc,0x89,0x56,0xa5,0x87,0x0c,0x6c,0x48,0x30,0xe2,0x10,0x2d,0x52,0x81,0xb9,0xb5,0xdc,0x12,0x7b,0x10,0x52,0xfe,0x7b,0x3e,0x11,0xc4,0x38, + 0x04,0x29,0xa9,0xe7,0xf2,0x51,0x09,0xa8,0xc4,0xbd,0x80,0xdb,0xea,0x05,0xfb,0xb4,0x6a,0xad,0xe5,0x87,0x97,0xc3,0xb2,0xfa,0x5f,0x00,0xf0,0xf0,0x81,0x66,0x9a,0xe3,0x9d,0x2c,0x78,0xfb,0x11,0x60,0xde,0x6e,0xda,0x50,0xf4,0x72,0xba,0x65,0x9d,0x4f,0x1d,0xb4,0xea,0x6e,0x29,0x72,0x44,0xb6,0xae,0x68,0xa0,0x51,0xd9,0x6e,0x62,0xe7,0x5e, + 0x04,0x16,0x17,0xdc,0x03,0xd3,0xee,0xa4,0x2e,0x8e,0xa2,0xc5,0xbd,0x03,0x4a,0x38,0xc5,0xa3,0xd7,0x41,0x65,0xa5,0x48,0x07,0x4b,0x7b,0x57,0x65,0xcc,0xd8,0x46,0x5b,0x7f,0x61,0x08,0x9d,0x6d,0xde,0x53,0x43,0x0f,0x34,0xcf,0x82,0x85,0xdd,0xbc,0x58,0x4d,0x15,0x43,0xfd,0xc7,0x0c,0x23,0x33,0xfc,0x31,0x5e,0xed,0x4e,0x93,0x0a,0xc3,0xa1, + 0x04,0x20,0xe7,0xa1,0x35,0x84,0x36,0xf6,0x75,0xf3,0x77,0x4d,0x60,0x95,0x4b,0x56,0x21,0x14,0x5b,0x8f,0x52,0x60,0xb5,0x50,0x36,0x36,0xf5,0x48,0x78,0xec,0xaa,0xff,0x8d,0xcc,0xaf,0x2f,0xff,0xcb,0x7c,0x70,0x84,0xe3,0x25,0xda,0xe5,0xe2,0x4b,0xff,0x5a,0x34,0xe3,0x79,0x80,0xd1,0x72,0x20,0x16,0xdd,0x66,0x67,0xda,0x71,0xf1,0x64,0xc4, + 0x04,0x27,0x59,0xbf,0x4c,0x33,0x65,0x01,0x34,0x0c,0xbc,0x67,0xaf,0xb4,0xa8,0xf5,0x74,0x4f,0x91,0x31,0xd9,0x73,0x96,0x6a,0x9d,0xe5,0x0d,0xed,0x60,0xfb,0xe0,0x45,0x12,0x1b,0x67,0xa9,0xe8,0x1e,0x53,0xb0,0x64,0xad,0xed,0xdd,0x16,0xa4,0xc0,0x30,0xdb,0xb1,0x89,0xcc,0xd7,0x01,0x9b,0x32,0x9d,0x67,0xa5,0x27,0xc3,0x11,0x72,0x34,0x69, + 0x04,0x19,0xb8,0xa1,0x0f,0x50,0x21,0xf1,0x1e,0x29,0xe1,0x86,0x11,0xfa,0x82,0x84,0xb7,0xe9,0xa3,0xf6,0x7c,0xf3,0x6e,0xec,0x8e,0xcc,0x4d,0x7a,0x5b,0x54,0x80,0x34,0x11,0x31,0x1a,0x8a,0x4e,0x19,0x9d,0x98,0xeb,0x35,0x8e,0x19,0xa2,0x7e,0x80,0xcd,0xa6,0xaf,0x14,0x2d,0x60,0x91,0xdd,0xaa,0x93,0x70,0xed,0x61,0x04,0x53,0xab,0xc6,0xc8, + 0x04,0x9b,0xa8,0x41,0xf4,0x12,0x45,0xac,0x08,0x95,0x59,0x66,0x47,0x04,0x25,0x59,0x32,0x90,0xb9,0xe1,0xd8,0x7b,0xda,0x8f,0x47,0xdf,0x19,0x04,0x8d,0xb8,0xe3,0xd8,0x30,0x97,0xf6,0x89,0x05,0xf3,0x60,0xce,0xd2,0x68,0x01,0x87,0x2a,0x7f,0xf1,0x24,0xc3,0x63,0x7b,0x02,0xc4,0xa5,0x96,0xb8,0x3a,0xba,0xfe,0x7b,0xce,0x56,0x7c,0xa1,0x77, + 0x04,0x68,0xaf,0x76,0x1d,0x05,0x3d,0xee,0x64,0xac,0xa5,0xe9,0x8f,0x54,0x7f,0xeb,0x2d,0xfb,0x6f,0x5e,0xdb,0x81,0x38,0x01,0x1c,0x7f,0x5c,0x33,0x80,0x9b,0x4b,0x9e,0x00,0x46,0x6d,0xd7,0x6c,0xb8,0xce,0xeb,0x51,0x32,0x86,0x20,0x52,0xad,0x3e,0x08,0xbf,0xea,0x24,0x5e,0xf1,0x6c,0xa0,0xd0,0x0e,0xd0,0xc4,0xb4,0x5f,0xb6,0xbd,0x30,0x28, + 0x04,0x05,0xdc,0x8b,0x18,0xbc,0x28,0x6f,0x20,0x32,0x13,0xb1,0x31,0x94,0x13,0xdf,0xa4,0x91,0x1d,0x6c,0x2e,0x30,0xf3,0xc7,0x78,0xc5,0x5e,0x4e,0x5f,0x5d,0x9b,0xfd,0xba,0xcd,0x0b,0x3b,0x20,0x9e,0x76,0x04,0x98,0x95,0xae,0x80,0xff,0x63,0xc0,0x22,0x5a,0x56,0x32,0x28,0xcd,0x99,0x24,0x3f,0x62,0x8a,0x9d,0xba,0xe7,0x0d,0x77,0x3c,0x66, + 0x04,0xba,0xcb,0x60,0x63,0x84,0xb1,0x93,0x0b,0xb4,0xb7,0x4d,0xed,0x23,0x6d,0x03,0xd3,0xbb,0x17,0x39,0xa5,0x1b,0x73,0xf2,0x0d,0xc3,0x34,0x9e,0xc3,0xb3,0x83,0x18,0x0a,0x68,0x96,0xed,0x59,0xfa,0x0b,0x65,0x4a,0x9c,0x40,0x4b,0x34,0xfe,0xe2,0xc7,0x67,0xbe,0x23,0x83,0xf4,0xb8,0xb1,0x71,0xd2,0x35,0x98,0x06,0xb0,0x4b,0x50,0x2d,0x16, + 0x04,0x48,0xab,0x89,0xb2,0xa3,0x12,0xde,0x51,0x0a,0x6d,0x3c,0x9a,0xc9,0xe4,0xc4,0xf5,0xb4,0x6e,0x04,0xd3,0xf8,0x58,0x43,0x3b,0x76,0x46,0xe4,0x62,0x73,0xd9,0x4d,0xce,0x4a,0x0c,0x7d,0xa6,0x16,0x38,0x8f,0x1e,0xb8,0xd5,0x5e,0xce,0x64,0xab,0x69,0x5e,0x54,0x05,0xd7,0x79,0xc9,0x2f,0x3b,0xc2,0x59,0x5c,0x27,0xd6,0x5d,0xef,0x8d,0xb9, + 0x04,0xfd,0x9d,0xe3,0x04,0xea,0x5f,0x18,0xdd,0x64,0x15,0x10,0xb9,0x80,0x94,0x73,0xd3,0x9a,0x23,0x73,0xed,0x5a,0x47,0x0f,0xfc,0x5e,0xa7,0xc8,0x30,0x93,0x91,0x1b,0x45,0x40,0xba,0xab,0xb9,0xd9,0x12,0x27,0x9a,0xee,0xa4,0x43,0x79,0x11,0x0a,0xbe,0xc7,0x5a,0xb7,0x99,0x4a,0x61,0x83,0xc6,0x29,0x4b,0xad,0x27,0xba,0xb5,0xbb,0xf8,0x21, + 0x04,0xbf,0x89,0x76,0xa2,0x82,0x21,0x00,0x0d,0x7f,0x52,0x19,0xfa,0x8d,0x06,0xf9,0xf8,0xae,0x47,0xbe,0x62,0x6f,0x89,0xc2,0xbb,0x6c,0x4d,0x03,0x23,0xbf,0x02,0xf8,0x49,0x0c,0x78,0xbc,0x94,0x8c,0x6b,0xf8,0x2a,0x19,0x1f,0x1d,0xe9,0x72,0xe5,0x7d,0xb3,0x5b,0x05,0x91,0x85,0x94,0xcc,0xfb,0xe8,0xda,0x19,0xbd,0x46,0xfa,0xcb,0xda,0x78, + 0x04,0xc3,0x22,0x9c,0x9b,0x4f,0x40,0x9a,0x65,0x39,0x48,0x41,0x52,0xb3,0x95,0x35,0xc5,0x12,0xa6,0x67,0x48,0x97,0x20,0x25,0x16,0x5f,0xd8,0x88,0xc3,0x88,0x36,0x9f,0xb3,0x29,0x8c,0xc4,0x1d,0xda,0x36,0xfc,0xb1,0x5a,0x0d,0x97,0xca,0xbf,0x75,0x7b,0xf0,0x73,0x7d,0xae,0x70,0x82,0x9f,0x4b,0x9a,0x1d,0x49,0x9d,0x9e,0x99,0x11,0x67,0x3a, + 0x04,0x6f,0x2c,0x3d,0xd8,0x4b,0x44,0xda,0xca,0x93,0x6a,0x2e,0xda,0xf4,0x3a,0xdc,0x8c,0x1b,0xd5,0xf4,0x28,0x01,0x23,0x17,0x18,0xfc,0xe6,0xf5,0xe9,0x4d,0x14,0x47,0x17,0xa2,0x47,0x59,0x8c,0x11,0xea,0xa2,0xc5,0x07,0xb0,0xe9,0x6d,0xfd,0xd0,0x32,0x94,0xcb,0xa4,0x47,0x2a,0xe8,0xa2,0x12,0x8e,0x36,0xf1,0xea,0xbd,0x31,0x5a,0xeb,0x25, + 0x04,0xa5,0x11,0xb0,0x93,0x34,0xf0,0x32,0xcc,0x33,0xee,0x4d,0xdb,0xb8,0x39,0x30,0x4f,0x6b,0xbf,0x1d,0xaa,0x4a,0x80,0xde,0x52,0x4c,0xa2,0x4e,0xbb,0x65,0xa0,0xa9,0x2e,0x4e,0xa4,0x82,0x43,0xcf,0x7e,0x26,0xde,0xaf,0x4d,0xe7,0x77,0x9c,0xa7,0x1f,0x76,0xd9,0xdc,0x6c,0x8c,0x1b,0x7f,0x44,0xcf,0x19,0x0f,0xdd,0xbe,0x82,0xc2,0xc9,0x40, + 0x04,0x7c,0xf4,0xa6,0xec,0x11,0x0d,0xb8,0x92,0xe4,0x5a,0x7b,0x2a,0xb3,0x8b,0x41,0x1a,0x6c,0x41,0xe8,0x6f,0xd2,0x1a,0x64,0x55,0xca,0x1a,0x4c,0x2e,0x22,0x20,0x68,0x13,0x09,0xb3,0xe3,0x99,0xae,0x30,0x09,0x8b,0xf8,0x72,0xc9,0xae,0xd5,0xdb,0x69,0xd1,0x4c,0xb7,0x11,0x49,0xab,0xb0,0x5c,0xf5,0x22,0x7a,0x62,0x0c,0x4b,0x16,0xb7,0x40, + 0x04,0x36,0xc7,0xdc,0xd1,0x52,0xfb,0x7e,0x53,0xfd,0x16,0x22,0x84,0x65,0xea,0x0c,0x41,0x9d,0xa2,0x9c,0xc6,0xc7,0x9f,0xd4,0x26,0x63,0x03,0xb3,0xbd,0x06,0xaa,0x0b,0x90,0x36,0x36,0x3a,0x95,0x9f,0x8c,0x0b,0x40,0x0d,0xa5,0x25,0xad,0x76,0x74,0x67,0x7f,0x82,0x90,0x92,0xae,0x7f,0x7e,0x8d,0xbf,0x88,0x39,0x7f,0xcd,0x19,0x04,0x7a,0xf5, + 0x04,0xb6,0x1d,0x3c,0xd2,0x7b,0xfa,0x12,0x69,0x23,0x4a,0x77,0x7e,0x11,0x8f,0x7d,0xb1,0x0a,0x38,0x44,0xe8,0xc7,0xd1,0x16,0x2c,0x09,0x9a,0x80,0x99,0xd8,0x87,0xdf,0xb8,0x49,0x52,0x0e,0x9a,0x03,0x8f,0x8b,0xa8,0x80,0x4d,0x44,0xf2,0x2b,0x37,0x45,0x25,0x14,0xf0,0xae,0xfe,0xa9,0x3b,0xab,0x7b,0xdf,0x18,0x0d,0xb5,0x44,0x85,0xaa,0xda, + 0x04,0xac,0x9c,0xbc,0x8b,0xd9,0x17,0x19,0x29,0x28,0xd9,0xa0,0x65,0xfb,0x1f,0x89,0xbe,0x4b,0xea,0x85,0x01,0x86,0xfd,0x46,0x6a,0x7a,0x90,0x14,0x06,0x6c,0xe0,0x02,0xc5,0x1a,0x90,0x6c,0x90,0xee,0xe5,0x5c,0xb5,0x69,0x2f,0x0a,0xc0,0x46,0x74,0x6e,0xe4,0xbd,0x22,0x05,0xfe,0x5f,0x43,0x5d,0x1e,0x71,0xf1,0x9a,0x8c,0xb8,0x55,0x0f,0x3e, + 0x04,0xc0,0x50,0xd0,0x58,0xaa,0xda,0x9e,0x43,0x76,0x7f,0x1f,0x76,0x0a,0xbd,0xbc,0x42,0x1a,0xe2,0x20,0xfd,0x01,0xe8,0x32,0xae,0x81,0xc6,0x28,0xbf,0xb1,0x27,0x7c,0x99,0xd3,0x54,0x83,0xfe,0x6a,0xea,0x51,0xde,0xa9,0xc0,0x17,0xc3,0x26,0xba,0x7b,0xbd,0x41,0x75,0x68,0x7a,0x72,0xdc,0x5c,0x4f,0x44,0x9e,0xed,0x0c,0x53,0xa0,0x80,0x52, + 0x04,0x39,0x95,0x42,0x88,0x2c,0xa4,0xd5,0xfa,0xe3,0x28,0x2c,0x4e,0xdf,0xfc,0x3c,0x7e,0xda,0x7c,0x45,0x1e,0x46,0xad,0xee,0x42,0x19,0x01,0x5e,0x91,0xc8,0xc6,0x9c,0xf8,0xb1,0x23,0xf8,0xed,0xe4,0x8a,0xb7,0x6f,0xe2,0xc9,0x21,0x83,0x26,0xcb,0x06,0x54,0x2a,0x83,0x2d,0x0a,0x32,0xb7,0xac,0x0d,0x48,0x5b,0x46,0x29,0xbf,0xaf,0x0d,0x76, + 0x04,0xbf,0xc3,0x04,0xfd,0x88,0xad,0x8f,0x11,0x80,0x1d,0x35,0x28,0x6a,0x49,0x50,0x5c,0xf3,0x49,0x40,0x3d,0x81,0x00,0xef,0xe9,0x03,0xd0,0x78,0xef,0xd5,0xd3,0xa6,0x6e,0xbf,0x05,0xd6,0xfe,0x2a,0x14,0xc0,0x69,0x90,0x2f,0x0d,0x8e,0xb6,0x80,0x04,0x60,0x73,0x1d,0x48,0x39,0x5e,0xfa,0xc4,0x42,0x8e,0xd8,0x7b,0x00,0xf3,0xfc,0x6f,0xb0, + 0x04,0x68,0x81,0x67,0x8d,0x6c,0x6d,0x8c,0xeb,0x01,0xde,0x5d,0x66,0x64,0xa0,0xb5,0x7b,0x47,0x0f,0x14,0x94,0x92,0xe8,0xe7,0x51,0x3e,0x12,0x1f,0xad,0x84,0x9a,0xba,0x1b,0x2a,0xd3,0x4d,0xb0,0x24,0xcc,0xd2,0x69,0x4e,0x49,0x7f,0x6a,0xdf,0x4d,0x3c,0xf5,0xad,0xbf,0x51,0x8c,0x76,0x8a,0x46,0x28,0xbc,0x2e,0x15,0x9d,0x09,0x49,0xf2,0xaa, + 0x04,0xe3,0x8d,0xac,0x9c,0xa4,0xef,0x5b,0x35,0xda,0x77,0xd8,0x46,0x09,0x3e,0x0d,0x29,0xc1,0xca,0x35,0x0e,0x72,0xb5,0xa6,0xce,0x90,0x1b,0xed,0x9f,0x47,0x2e,0xa1,0x99,0xf8,0x05,0xfc,0x32,0x02,0x92,0x07,0x82,0xf4,0x9f,0x4b,0x6e,0x72,0x57,0xa4,0x36,0x4d,0xd5,0x45,0x1d,0x98,0x2f,0x29,0xb6,0x2d,0x5d,0x4b,0x8e,0x07,0xa3,0x30,0x68, + 0x04,0x2d,0x8c,0x67,0x32,0xe3,0xd0,0xe1,0x82,0x21,0x93,0x24,0x3b,0xb9,0xec,0x3f,0xc2,0xc7,0xf2,0x64,0xe9,0x4e,0xe6,0x1b,0x29,0x5d,0xe5,0xb3,0xc1,0x0d,0xb9,0x37,0xf1,0x35,0x34,0x34,0x53,0x83,0x81,0x14,0xa4,0x75,0x2a,0x55,0x14,0xbc,0xfb,0x9d,0xce,0x10,0xf8,0x3e,0x01,0x90,0xc5,0x40,0xfe,0xf1,0x06,0x75,0xcb,0x42,0x58,0x4a,0x05, + 0x04,0x20,0xbe,0xc8,0xd2,0xb5,0xaa,0xe1,0xf9,0x55,0xb7,0x99,0x21,0x98,0xbc,0xfe,0x20,0x88,0x04,0x94,0x15,0x00,0x58,0xcf,0x61,0x51,0xfe,0x14,0xf6,0x07,0x1b,0xad,0x31,0x32,0xdc,0x1c,0xe5,0x03,0x96,0x9b,0x82,0x4c,0x5a,0x9e,0x23,0xae,0xb4,0x72,0x25,0x5d,0xd2,0x3f,0x97,0xd0,0x2f,0x68,0x28,0x1a,0xd0,0x26,0x98,0x18,0xb1,0x7e,0x49, + 0x04,0xf4,0x56,0x94,0x67,0x70,0xaf,0x5d,0x06,0x9d,0x60,0xb2,0x79,0xae,0x51,0x9e,0xa1,0x8e,0x71,0x9a,0xba,0xf5,0x78,0x74,0x76,0x87,0x3a,0x5e,0x61,0xf9,0x69,0x07,0x4d,0x47,0xeb,0x27,0x52,0x0d,0x72,0xfc,0xe1,0x06,0x50,0xd3,0x12,0xa5,0x43,0x1b,0xbd,0x6b,0x3f,0x37,0xcd,0x46,0x75,0x5b,0x7a,0x8e,0x1e,0xf1,0xa7,0x96,0xf9,0x09,0x08, + 0x04,0xd1,0x39,0x0a,0x94,0x4d,0x24,0xf3,0x00,0xfd,0xab,0x9b,0xd2,0x72,0xbb,0xac,0xa0,0x56,0xfe,0xb7,0x1c,0x0c,0x37,0x46,0x8e,0x03,0x27,0xb0,0x85,0x04,0xd5,0x5f,0x3a,0x80,0xa4,0xb2,0x40,0x56,0x5a,0xa4,0x3b,0xe8,0xf3,0xe2,0x08,0x9b,0x47,0x88,0x04,0x9c,0x5d,0x37,0x8b,0x66,0x7e,0x98,0x7e,0x01,0xaa,0x8a,0x08,0xa4,0xcd,0x2c,0x95, + 0x04,0x3e,0x61,0xff,0x24,0x43,0xd1,0x0b,0x1e,0x25,0xfb,0x0c,0xe1,0x9f,0x57,0xae,0x39,0x22,0x3d,0x33,0xfb,0xb0,0xe5,0xee,0x2b,0x47,0x40,0xfa,0x19,0x38,0x4b,0x7d,0x0e,0x14,0x08,0x11,0x9a,0x70,0xaa,0x9b,0x23,0x0d,0x9f,0x18,0x26,0x9c,0x06,0x5c,0x53,0xd4,0xc2,0x61,0x96,0x73,0xb4,0x93,0x77,0xaf,0x4c,0xdd,0x53,0x6c,0x93,0x1a,0xae, + 0x04,0xb0,0x60,0x28,0xd7,0x29,0x03,0x96,0x17,0xf9,0x12,0xe8,0x6d,0x1d,0x1f,0x44,0xe9,0x3e,0x63,0xaa,0x21,0x6a,0xb0,0x64,0x18,0x13,0xd0,0x6c,0x16,0xa3,0xed,0xae,0xe9,0x79,0xd2,0x15,0x72,0xf9,0x54,0x0d,0x7b,0x07,0xb0,0xa6,0x66,0x7f,0x7e,0x0a,0x94,0x52,0xf6,0xf9,0xf3,0x67,0x1e,0x52,0x2e,0x2b,0x49,0x7e,0xec,0x13,0x8a,0x46,0xea, + 0x04,0x0a,0x8f,0x74,0xce,0xe5,0x0d,0x1e,0x85,0x3a,0x38,0xc0,0x26,0xf6,0x27,0xfe,0x47,0xd8,0x1f,0xc1,0x1f,0x88,0x62,0x68,0xb3,0x53,0x79,0xa3,0x2a,0xda,0x24,0x9b,0xb9,0x1d,0x63,0xcf,0x01,0x98,0xe1,0xc9,0x26,0xbc,0xb6,0x5c,0xe2,0x18,0x13,0xe4,0xd7,0x21,0x18,0xb7,0x09,0x2a,0x5e,0x8b,0xc1,0x52,0x90,0x92,0x22,0xac,0x19,0x60,0x3a, + 0x04,0x0e,0xdb,0x70,0x20,0xcf,0x4d,0x6a,0xb1,0x4b,0x5a,0x3f,0x8f,0x69,0x8d,0x66,0xef,0xf9,0x83,0x58,0x88,0x46,0xd7,0x18,0xb4,0x84,0x5d,0x67,0x4e,0x7b,0xbf,0xc0,0xed,0xd9,0x2a,0x27,0xe4,0x0e,0x5a,0xb2,0xe0,0xcd,0x2d,0x0a,0xc1,0xab,0x67,0x94,0x02,0xce,0x36,0xf1,0x6d,0x3e,0xbf,0xc0,0xfd,0x9d,0xf8,0x17,0xda,0xb1,0x72,0x92,0xd9, + 0x04,0xf0,0x6c,0x77,0xca,0xc2,0x4a,0x6e,0xe5,0x14,0x21,0x86,0x3a,0x0d,0x14,0x69,0x41,0x8f,0x0a,0x64,0x30,0xe0,0x62,0xda,0x18,0xf2,0x7d,0xd5,0x74,0x01,0xc0,0xb6,0x12,0x03,0x2b,0x7e,0x05,0x91,0x45,0x5c,0xa3,0x3b,0x4e,0x49,0xe5,0x3f,0xac,0xf5,0x86,0x44,0x10,0xba,0x04,0x6b,0xa5,0xd4,0xfc,0x6b,0xac,0xfe,0xa9,0xa0,0x78,0x2f,0xf3, + 0x04,0xcb,0x2b,0x9d,0xf4,0xdd,0xc4,0x30,0xdf,0x7b,0x0b,0xef,0xcb,0x5a,0x82,0x6d,0xa1,0x58,0x9a,0x15,0xbe,0xf1,0xb6,0xb2,0x5f,0x12,0x01,0xda,0xab,0x5b,0x2f,0xa4,0xac,0x38,0x01,0xe2,0x7d,0x11,0x2f,0x0f,0x32,0x76,0x72,0x2d,0xcb,0x58,0xb8,0xb4,0xf4,0x84,0x4a,0x2e,0x61,0x4d,0xe4,0x9d,0xb4,0x40,0xb7,0xcc,0x76,0x20,0x81,0x27,0x34, + 0x04,0x45,0x20,0x6b,0x62,0xe4,0xa3,0xc4,0x40,0x4c,0x74,0xae,0x86,0x95,0xcd,0xb9,0x05,0xa8,0xe6,0xa9,0x45,0x6d,0xa0,0x9c,0x72,0xc7,0x2e,0xb7,0x71,0x2d,0x9d,0x52,0xe8,0x1d,0xdc,0x2d,0x56,0xb6,0x34,0xe4,0xab,0x66,0xb7,0x98,0xcd,0xb4,0xdb,0x86,0xcf,0x94,0xf0,0x22,0x08,0xf7,0x47,0x30,0x4a,0xb3,0xd5,0xaa,0x2b,0xb1,0x25,0xe1,0x37, + 0x04,0x58,0x4d,0x2d,0xc2,0x58,0xbd,0x46,0x50,0xe6,0xfa,0x04,0xfe,0x9d,0x3d,0x2a,0x5e,0x76,0x8d,0x79,0x59,0x45,0xed,0x23,0x23,0xf8,0x44,0xd0,0xa8,0xfa,0x0c,0x6f,0xbd,0x5f,0x96,0x25,0x6b,0x9e,0x1b,0x72,0x63,0xfa,0x00,0xfa,0x75,0x8c,0xd6,0xbe,0x15,0xd9,0xf6,0x15,0x7f,0xad,0x66,0xc7,0x29,0xab,0x0d,0xad,0x69,0x45,0x64,0xe8,0x34, + 0x04,0x6c,0x55,0x27,0x89,0x8a,0xe8,0x06,0x7d,0xa5,0x6a,0xc8,0x2c,0xaf,0x33,0x8c,0x9e,0x7f,0x40,0xee,0x44,0x89,0x11,0x5d,0xaf,0x0a,0xba,0x92,0x3a,0x8b,0x6e,0x50,0x1e,0x43,0x0f,0x59,0x70,0xce,0x9d,0x01,0xd0,0x3e,0xc0,0x76,0xf8,0xda,0xf6,0x85,0xcf,0x4d,0x5a,0x9c,0xcd,0x5e,0xb9,0xe8,0x49,0xd4,0x3a,0xe2,0xf3,0x6f,0x2e,0x80,0xe5, + 0x04,0x52,0xcd,0x99,0x24,0x79,0x5f,0xe2,0xa2,0x51,0xaf,0x7c,0xb5,0x69,0xf6,0x6d,0x91,0x41,0xdb,0x89,0x45,0x45,0xd7,0x98,0xa0,0xdb,0x3d,0x30,0xe5,0x0f,0x10,0x0f,0xe2,0x04,0xea,0x81,0xc8,0x08,0x58,0x7c,0x90,0xf3,0xf2,0xc9,0x4d,0x99,0x3c,0x2d,0x0c,0xc4,0xbe,0x64,0xdd,0x6a,0xeb,0x9d,0xc8,0x1c,0x70,0xd7,0x88,0x85,0xb2,0xf7,0x76, + 0x04,0xbb,0xad,0x8d,0xa4,0xc0,0x18,0xbd,0xc1,0x5a,0x5a,0xf8,0xf3,0xda,0x4b,0x38,0x4c,0x53,0x0e,0xa7,0x55,0x60,0xcd,0xfd,0x24,0x2b,0xfa,0x32,0x35,0xd8,0xd3,0x59,0x5f,0x73,0x4c,0xbd,0x86,0x64,0x87,0xb8,0x3f,0xcb,0x84,0xa4,0xac,0x74,0xac,0x54,0x8f,0x25,0x35,0xb7,0x9b,0x57,0xd0,0x2f,0x03,0xa1,0xa3,0x7e,0x27,0x91,0xa0,0x96,0xe4, + 0x04,0x38,0x9a,0xa5,0x22,0x35,0x04,0x3b,0xbd,0x75,0x98,0x68,0x89,0x8b,0xbe,0x27,0x7a,0xb9,0x96,0xea,0x93,0x87,0xbd,0x70,0x98,0xb0,0x07,0x24,0x42,0xbd,0x2b,0x42,0xf5,0xb8,0x23,0x36,0x4e,0x91,0x44,0xa1,0xee,0xf1,0xf1,0x00,0x93,0xfd,0xa0,0xc3,0x01,0x68,0xf3,0x00,0x4e,0x2c,0x2e,0xa7,0x4f,0xde,0x49,0x78,0xf3,0xaa,0x1a,0x31,0xc0, + 0x04,0xfd,0x1b,0xac,0x14,0x43,0x54,0xcf,0xe1,0xcd,0x4c,0x64,0xaa,0x3a,0x2f,0x77,0xf0,0xae,0xfa,0x26,0xcc,0x51,0x41,0x08,0x26,0x76,0x37,0x0a,0x0f,0x1e,0xc9,0x2c,0xd8,0xfe,0xe6,0x69,0x92,0xd2,0xd2,0xfc,0xb8,0x7f,0x90,0xda,0x0a,0x67,0x43,0x37,0x84,0x66,0x65,0x55,0x19,0xbc,0x78,0x2d,0xd7,0xb0,0xab,0x57,0x0f,0x6e,0xd4,0x51,0xd8, + 0x04,0x78,0xc9,0x26,0xb0,0xee,0x01,0xc0,0x00,0xc2,0x5a,0x83,0x63,0x12,0x19,0xf0,0x8d,0x8b,0x34,0x74,0x5d,0x2e,0xa2,0xfd,0xc9,0xeb,0xdc,0x5a,0x22,0x88,0xfa,0x9b,0x03,0x06,0xbc,0x00,0xab,0x37,0x90,0x50,0x8e,0x57,0x05,0xee,0xab,0xfb,0xaa,0x07,0x44,0x71,0x9c,0x9b,0xd7,0xb4,0x67,0xca,0x4a,0x37,0xa0,0x6f,0x6f,0xdb,0xe6,0xd8,0x6c, + 0x04,0x4c,0xae,0x56,0x06,0xba,0xd6,0x01,0x3f,0x7f,0x36,0x19,0x0d,0x72,0x54,0xcb,0xf0,0xd5,0xa9,0x2b,0x33,0x8e,0x4a,0x47,0x70,0x2a,0x3c,0x97,0xa3,0x37,0x1d,0x7e,0xc2,0x80,0xd2,0x73,0xdd,0x59,0x8c,0x20,0x39,0x2c,0x54,0x0e,0x58,0xbe,0xc9,0xb1,0x80,0x40,0x6f,0x3f,0xa6,0xe6,0xc5,0x29,0xa8,0x51,0xbc,0xf2,0xb9,0x6d,0x8f,0x38,0x09, + 0x04,0x08,0xcc,0xbd,0x74,0xf2,0x97,0xfe,0x71,0xca,0x31,0x15,0xc0,0xb1,0xef,0x4e,0x04,0x21,0xb9,0x9c,0xe9,0x1f,0xfc,0xd4,0xb7,0x2a,0x53,0x0b,0x22,0x99,0x3e,0x18,0xe9,0xba,0x0a,0xe1,0xbd,0xbe,0x1c,0x28,0x36,0xff,0xe9,0xa6,0x1a,0xe5,0xa8,0x99,0xf1,0x52,0xc9,0x0b,0x42,0x82,0x36,0x38,0xbe,0x4d,0x51,0xdc,0x3a,0xfa,0x99,0xe6,0xa0, + 0x04,0xaa,0xcc,0xef,0x83,0x4f,0x57,0xe6,0xc5,0x52,0x6f,0xe9,0x27,0x48,0xcd,0x8c,0xdc,0x13,0x75,0xc2,0xac,0x71,0x13,0x9f,0x5d,0x25,0x87,0x30,0x5b,0xd3,0xfd,0xd3,0xcd,0x96,0x5d,0xd5,0x37,0x4b,0x6a,0x31,0x98,0x50,0xc2,0x3e,0xbc,0x2e,0xc7,0xa2,0xde,0xb7,0xff,0x3e,0x42,0x86,0x79,0xd4,0xaf,0xc9,0xdf,0x7e,0x75,0xf2,0xe0,0x6e,0x4d, + 0x04,0xa5,0x85,0xe1,0xed,0x6e,0x47,0x22,0x4a,0x47,0x2c,0xf4,0xed,0x4f,0xf3,0x4e,0x62,0x51,0xc6,0x2a,0xc6,0x82,0xe4,0xb7,0x09,0x92,0xd5,0x00,0x2f,0x08,0xd9,0xe2,0x03,0xe9,0xb7,0xb2,0x88,0x95,0xb9,0xdb,0x40,0x16,0xe5,0xd9,0x4a,0x9f,0x59,0x38,0x5c,0x16,0xdb,0x73,0x8a,0x83,0xb8,0x4e,0x6d,0x43,0xec,0xef,0x82,0x0c,0x55,0xd4,0x62, + 0x04,0xb1,0x04,0xd0,0xcc,0x4a,0x98,0x77,0x71,0x65,0x51,0x05,0xcf,0xc8,0x40,0xf1,0x95,0x74,0x6e,0x11,0x23,0x34,0xc5,0x48,0x01,0xfd,0x93,0xf4,0xbe,0x8b,0x11,0x4a,0x1d,0x3c,0xd8,0xcb,0xcf,0x4b,0x27,0x41,0x66,0xf8,0x2c,0xfe,0x57,0x39,0x30,0x42,0xe3,0x53,0x4e,0x68,0xdf,0x2f,0x4c,0x3d,0xad,0x1b,0x7c,0xe7,0x2b,0x47,0xca,0xd2,0x56, + 0x04,0x82,0xbe,0xd3,0xd5,0x52,0x09,0x8d,0x2f,0xc9,0xe0,0x2f,0x1f,0x3c,0xc3,0x2f,0x5f,0x31,0xcf,0x6c,0xd1,0x01,0xbb,0xb8,0xb4,0x2b,0xc6,0xf7,0x32,0xba,0xdc,0x19,0x76,0x22,0x92,0x57,0xd9,0x2b,0x24,0x1f,0x20,0x31,0xec,0xae,0xba,0x10,0xf1,0xac,0x15,0x4d,0x8a,0x3b,0xea,0x30,0x93,0x28,0x23,0x12,0x72,0xeb,0x6a,0xa0,0x1a,0xa6,0x5f, + 0x04,0x5c,0x4f,0xb6,0x81,0x21,0x3b,0xf3,0x9b,0x68,0xe7,0xca,0x91,0x4d,0x28,0x30,0xb1,0x2a,0x7a,0x32,0xc9,0x6a,0x9c,0x78,0x8a,0xd2,0x98,0x7c,0x00,0x9e,0x08,0xd0,0xa3,0x76,0xa0,0x2c,0xcf,0x59,0x4c,0x28,0x99,0x5c,0xfc,0xb2,0x85,0xed,0x5d,0x91,0xdd,0xed,0x92,0x92,0x11,0x08,0xa0,0xb4,0x09,0x28,0x48,0x7c,0xd0,0x71,0x80,0xab,0x21, + 0x04,0x6b,0x29,0xf8,0xc0,0x06,0x86,0x9a,0xb6,0xbe,0x79,0x3e,0xa7,0x2b,0x97,0x0a,0xce,0xeb,0xb7,0xa4,0xc4,0xb6,0xfb,0xaf,0xec,0xd1,0xe3,0x57,0x13,0xa2,0x8b,0xf2,0x84,0xc7,0x6b,0x07,0xdc,0x14,0xf1,0xdc,0x53,0x3f,0x1c,0x4c,0xcb,0x09,0x73,0xeb,0x53,0xe5,0x30,0x23,0xf0,0xb0,0xf1,0xa8,0x91,0x4c,0x77,0x08,0xc2,0xd7,0x3d,0x48,0x17, + 0x04,0x6e,0x68,0x49,0xc2,0xb0,0x7a,0x37,0xc4,0xf3,0x6b,0xe9,0x11,0xb3,0x23,0xe4,0xce,0x70,0xc1,0x8b,0x15,0x90,0x26,0x12,0xc4,0xfc,0x0f,0xe6,0xd9,0x1e,0x7c,0x18,0x0d,0xe9,0x25,0x54,0x43,0x63,0xc6,0x80,0x35,0x49,0x8c,0xbb,0x22,0x36,0xf5,0xc1,0xec,0xd0,0xe4,0xb2,0xcb,0xb5,0x80,0x1a,0x8c,0xac,0x4d,0x08,0x83,0xf6,0x51,0xbb,0xd0, + 0x04,0x33,0x64,0x9a,0x1e,0x74,0xc7,0xff,0xb5,0xed,0xc3,0x94,0x9c,0x58,0xb7,0xa7,0xf4,0xb5,0x34,0x82,0x88,0xf6,0x21,0xc5,0x0f,0xbb,0xdb,0x71,0x4f,0xa4,0x2a,0xa7,0x93,0xcb,0xfd,0x96,0x9e,0x07,0x7b,0x00,0xea,0xd2,0x10,0x82,0xf0,0x98,0x00,0x09,0x86,0x8f,0x79,0xe4,0x30,0xef,0x1c,0x21,0x63,0x94,0xbb,0x0e,0x9e,0xda,0x13,0x5e,0x9c, + 0x04,0xbf,0x97,0x6e,0xf2,0x04,0x53,0x2b,0xf6,0x74,0x43,0xe8,0xb8,0xd9,0x98,0x7a,0x68,0x31,0x84,0xec,0x26,0x42,0x03,0x29,0xba,0x26,0x8e,0x54,0xe9,0x0b,0x48,0x0d,0xe0,0xbe,0xb1,0x08,0xdf,0x26,0xed,0xa9,0x1e,0xb4,0xfd,0x23,0xd2,0x6a,0xf6,0xf2,0xd7,0x8a,0x42,0x81,0xd5,0xed,0xe0,0x75,0xc2,0xc7,0x15,0xfb,0x1c,0x4f,0x87,0x67,0x84, + 0x04,0x2c,0x43,0x5d,0x9f,0xaa,0x59,0x80,0x70,0xb4,0x92,0x02,0x77,0x50,0x6c,0x10,0x0d,0xe6,0x2a,0x7d,0xf0,0x5c,0x34,0xa3,0x93,0x17,0x78,0x5d,0x62,0x8d,0x74,0xdd,0xe3,0xc7,0xf5,0xd0,0xbe,0xdf,0x54,0xaf,0x1c,0x7d,0x21,0xff,0x95,0x51,0x28,0x00,0x2f,0xd5,0x29,0x62,0x37,0x38,0x47,0x23,0xfe,0xf1,0xfb,0x80,0x6c,0x2a,0x6d,0x8e,0xa9, + 0x04,0x38,0x19,0xdf,0xaa,0xb5,0x53,0x78,0x63,0xc8,0xdb,0xf4,0x06,0xac,0x18,0xdd,0x67,0x56,0x19,0xc9,0xa7,0xa5,0x54,0x62,0x0a,0xd8,0xa1,0x44,0x92,0xbb,0xa4,0x25,0xa3,0xd6,0x8e,0x8c,0x68,0x18,0x15,0x55,0xe2,0x23,0x62,0x41,0x5c,0x95,0xa3,0x17,0x24,0xeb,0xfe,0x8b,0x2b,0xf1,0x76,0x4e,0x20,0x9e,0xae,0x9e,0x53,0xb3,0xf4,0x62,0xa0, + 0x04,0x70,0xad,0x3a,0x9c,0x9a,0x9d,0xb7,0x1d,0x42,0x0a,0xba,0xe8,0x4c,0xcd,0xb1,0x27,0x68,0x85,0x1b,0xac,0x6a,0x82,0xff,0xd0,0x3d,0x89,0x62,0x1a,0x50,0xa7,0xc3,0x11,0xbf,0xff,0x7c,0x66,0x4c,0x21,0x1f,0x93,0x76,0x8f,0x84,0xb5,0x25,0x5d,0x95,0xc7,0xf6,0x78,0x87,0xc3,0x30,0x5d,0x78,0x9d,0x7f,0xce,0xdc,0x2d,0x29,0x98,0x9f,0x9a, + 0x04,0x58,0x39,0x13,0x61,0xfb,0xc8,0x11,0x5c,0x97,0x8e,0x82,0x03,0x78,0x14,0xd3,0x1a,0xa3,0xa8,0x88,0x73,0xed,0x6c,0x74,0xc4,0xaa,0xea,0x97,0x27,0xe3,0x00,0xd9,0x45,0x42,0x92,0x4c,0x67,0xb5,0xcf,0x82,0x8b,0xe8,0x27,0xe5,0x81,0xda,0xfc,0xbd,0x16,0xe6,0x53,0xe7,0x2a,0x4f,0x2d,0x4d,0x05,0x50,0x80,0x53,0x87,0xb9,0x41,0x7e,0x77, + 0x04,0x23,0xa2,0xbe,0x68,0x4b,0x0b,0x5f,0x04,0xbe,0xf5,0xc6,0xca,0x8a,0x99,0x1b,0xf7,0x52,0xf5,0x96,0x4f,0x6f,0xdf,0x36,0xd7,0x12,0x91,0x00,0xda,0xf8,0x0f,0x14,0x34,0xb6,0xf3,0xca,0x2a,0x5e,0x85,0xce,0x00,0x5e,0x1c,0xb6,0xd2,0xb1,0x30,0x94,0xc4,0x34,0xfd,0xc1,0xc0,0x95,0xa3,0xae,0x5e,0x53,0xf6,0x49,0x49,0xca,0x56,0x69,0x1b, + 0x04,0x14,0x7b,0x8a,0x2f,0xb4,0xf6,0xe8,0x5e,0xea,0xd8,0x1c,0xa0,0xb3,0xf2,0x30,0xb8,0xd8,0xcc,0x23,0x0d,0xe7,0x31,0x07,0xd9,0xca,0xbc,0xbc,0x5b,0x39,0xe4,0xe7,0xea,0xda,0xa4,0x4e,0xc1,0xed,0x0b,0x95,0xf6,0x10,0x92,0x23,0xbc,0x48,0x0e,0x91,0x74,0x19,0xd8,0x60,0xf9,0xb9,0xa7,0x5f,0x81,0xd6,0xf8,0xca,0x3a,0xda,0x37,0x75,0x33, + 0x04,0x2b,0x3f,0xe6,0x4b,0xb1,0x42,0x78,0x9e,0x89,0xe1,0x09,0x2d,0xb4,0x6b,0x61,0x30,0x12,0xbc,0xfa,0xe5,0x77,0x59,0xea,0x90,0x81,0x65,0xc0,0x36,0x2f,0x80,0x4f,0x36,0xc0,0x05,0x3f,0xaf,0x32,0x66,0xad,0x7e,0xec,0xed,0xcb,0x24,0x63,0x6b,0x99,0xc9,0x35,0xf1,0xc8,0xe7,0x31,0x68,0xf0,0xee,0xb3,0xdd,0xfb,0x66,0x08,0x01,0xe5,0x5b, + 0x04,0xc4,0xed,0x72,0x44,0x54,0x65,0xcd,0xb4,0x4f,0x58,0xb0,0xe1,0xaf,0x08,0x23,0x22,0x6e,0xa7,0x9e,0xb2,0xe1,0xbc,0x3f,0x27,0xfb,0x8e,0x4c,0xe7,0xb8,0x5f,0x4a,0x30,0xc2,0x37,0xe5,0x74,0xc5,0x9a,0x99,0x24,0x06,0xfd,0x51,0x7f,0x4d,0x90,0x5e,0x03,0xd7,0xa2,0xb0,0xa4,0x0e,0xf8,0x5a,0xa3,0xc7,0x3b,0xd4,0x6a,0x1a,0x06,0xa9,0x18, + 0x04,0x18,0xef,0x4e,0x2f,0xad,0xaa,0xc1,0xb9,0x82,0xa7,0xd2,0xd1,0x2e,0x9d,0x51,0x48,0xec,0xf3,0x36,0xb1,0xd3,0x77,0x5d,0xa2,0xf7,0xdf,0x82,0x2a,0xd4,0x9a,0x13,0x24,0xbd,0x07,0x04,0x6a,0x3f,0x8e,0x94,0x9e,0x7a,0x0d,0x96,0x0f,0xe9,0xd9,0xa1,0xde,0x0f,0x61,0x49,0x7c,0xb4,0xe7,0xb2,0xf3,0x9a,0xee,0x68,0x44,0x39,0x6f,0x99,0x7f, + 0x04,0x39,0x8c,0xa1,0xa9,0x44,0x21,0x0a,0x10,0xb1,0xf5,0x73,0x20,0x71,0x25,0x95,0x28,0xdf,0x87,0xd4,0x2d,0x3d,0x7b,0x00,0x6b,0xc6,0xfd,0x9e,0x1e,0x09,0xf6,0xfa,0x30,0xfe,0xd3,0x79,0xdb,0x3f,0x1b,0xd9,0x15,0xdb,0x2b,0xa2,0x73,0x84,0xec,0x13,0x71,0x54,0x17,0x44,0x6e,0xe8,0x4f,0xb5,0xfd,0x0a,0x4b,0xf6,0x43,0x1c,0xfd,0x3f,0x15, + 0x04,0xd1,0xc1,0x82,0xad,0xb1,0x01,0xeb,0xe5,0xfe,0xc3,0x91,0x0f,0x80,0x05,0x8e,0x09,0x1d,0x13,0x25,0x43,0x3d,0x4f,0xd3,0xbb,0xb3,0x8e,0xb7,0x5b,0xca,0xf2,0x69,0x8a,0x21,0x21,0x8f,0x75,0x44,0xce,0x84,0xdc,0xfe,0x52,0xe8,0x17,0xec,0x0b,0xa6,0xbf,0x84,0x46,0x0f,0x49,0x93,0x2b,0x3e,0xc5,0xed,0x27,0x68,0x2d,0x33,0x7f,0x27,0x0d, + 0x04,0x3f,0x68,0xc4,0xe4,0x12,0xc5,0x7d,0xa0,0x15,0x56,0x8e,0x0a,0x9f,0xcc,0x3d,0xb4,0x99,0xb7,0x7e,0x6c,0x0f,0x55,0x05,0x08,0x28,0xc5,0x0c,0x35,0x49,0x3a,0xf5,0xe3,0xd0,0xb5,0x3f,0xe3,0x0b,0x0c,0x6c,0xf4,0x2c,0xdf,0x9f,0x4f,0x01,0xd5,0xc9,0x05,0x8f,0x81,0x69,0xb2,0x41,0xbd,0xea,0x22,0x59,0x32,0xf9,0x03,0x3f,0x8b,0xc5,0xeb, + 0x04,0x56,0xdd,0x4c,0x2b,0x1d,0x7a,0x1a,0x2d,0x65,0x59,0xb5,0x20,0x3f,0xcb,0x89,0x74,0xfa,0x81,0xbe,0x7d,0x64,0xcf,0x0a,0xe7,0xa1,0x4f,0xd9,0x65,0xdf,0xd6,0x9c,0xdd,0xeb,0xe1,0xca,0x78,0xd5,0x58,0x3f,0xda,0x34,0x87,0x04,0x0d,0xcd,0x94,0x76,0x4f,0x8d,0xc6,0x19,0xe8,0xd7,0x4a,0xae,0x8d,0x96,0x65,0xf3,0x40,0x69,0x3c,0x21,0xb3, + 0x04,0xe1,0xe5,0x05,0x3b,0x6f,0x43,0xb8,0x71,0x4a,0x02,0x5a,0xcf,0xb8,0x6a,0x8f,0x51,0x19,0x54,0x88,0x09,0x9b,0x1f,0x5d,0x63,0x31,0x0a,0x6b,0xec,0xd7,0xcc,0xb4,0x7e,0xf0,0xd1,0x6b,0xc0,0xc3,0x23,0x44,0x70,0xff,0xa8,0xd4,0x5f,0x58,0x2f,0xcb,0x65,0xff,0x9c,0xca,0xaa,0x6a,0xe0,0xcd,0x6b,0x57,0x2b,0xeb,0xaa,0x50,0xc1,0x77,0x41, + 0x04,0x1a,0x46,0x57,0x1a,0x14,0x38,0xca,0x23,0xdc,0x79,0x12,0xa8,0xa7,0xb2,0x24,0x5d,0x70,0xc8,0x52,0xa6,0xe9,0xf4,0xd3,0x85,0xdd,0x60,0x84,0x27,0xec,0x3c,0x41,0xe7,0xfe,0x06,0xe2,0xde,0xdf,0xba,0xa3,0x76,0xa6,0x14,0x65,0x7c,0xe6,0x17,0x01,0xa7,0xdb,0x18,0x1e,0x5b,0x1f,0x31,0x39,0x04,0x5b,0x84,0x24,0xee,0x54,0x96,0x4b,0x7a, + 0x04,0x8c,0xe5,0xa3,0xc8,0xbd,0x25,0x44,0x69,0x5a,0x00,0x58,0x41,0x61,0x2a,0x7c,0x5d,0x05,0xbe,0xb0,0x7c,0xf7,0xbc,0xa1,0x02,0x71,0x72,0xb0,0x30,0xac,0xf7,0xd2,0x75,0xfb,0xa0,0xc3,0x39,0xf7,0x4c,0xe3,0x6d,0x10,0x4f,0xff,0xbd,0x5a,0xe1,0xc9,0xc7,0x25,0x88,0x69,0x31,0x90,0xed,0x2b,0x36,0x87,0x43,0x30,0x87,0x21,0x3b,0x5b,0xdf, + 0x04,0xa0,0xab,0xcd,0xb1,0xef,0x03,0x5e,0x18,0x6e,0x72,0x06,0x06,0xb0,0x7f,0xd6,0x15,0x53,0x20,0x39,0x27,0x5a,0xc1,0xb6,0xf2,0x27,0x20,0xb7,0x56,0xc0,0xf8,0x57,0xcf,0x76,0xe4,0x65,0xcf,0xde,0xf3,0x06,0x02,0xb2,0xe0,0x55,0xa3,0x03,0xbc,0x6e,0x17,0x6d,0xfe,0x97,0x2d,0x06,0xcc,0x6f,0x38,0x21,0x78,0x03,0x87,0xbd,0x63,0x57,0xc1, + 0x04,0x85,0x9b,0x6b,0xeb,0x70,0x67,0x1b,0x3e,0x64,0x99,0x1b,0xb6,0x61,0x18,0x0d,0xbb,0xe8,0x35,0xf6,0x3c,0x0a,0x58,0x78,0xc3,0xf8,0x3f,0x09,0x22,0x66,0x0a,0x7c,0x09,0x33,0x89,0xbf,0x4c,0xe6,0xb5,0xc1,0xc2,0xf8,0x01,0xc8,0x4c,0x54,0x39,0x1d,0x53,0xaa,0x95,0x3e,0xad,0x5e,0x51,0xb7,0x75,0x7b,0x35,0x08,0x34,0x5b,0xb4,0xcd,0xeb, + 0x04,0x35,0x51,0x0d,0x43,0xf4,0xd1,0xa1,0x73,0xa0,0x46,0x7d,0x5c,0xb3,0x5a,0x41,0x70,0xc3,0xfc,0x40,0x7e,0x55,0xb4,0x16,0xb4,0xdf,0xce,0x28,0x65,0x0f,0x88,0x02,0xaf,0xe8,0xef,0x2a,0xdb,0xde,0x8b,0x40,0xa1,0x71,0x42,0x86,0x17,0x6d,0x67,0x44,0x89,0xbf,0x9a,0xcb,0x2e,0x4a,0x83,0x53,0xa7,0xda,0xe1,0xa9,0xe9,0x7c,0xbb,0x41,0x50, + 0x04,0xfa,0x4a,0xf0,0x89,0xc1,0x4d,0x6a,0x8b,0xe1,0x88,0x11,0x35,0x98,0x94,0x11,0x60,0x71,0x60,0xd1,0x41,0xa7,0xa8,0xcb,0x45,0x46,0xf3,0x58,0xa7,0x97,0xd2,0xaa,0xfd,0xbe,0x00,0x86,0x79,0x64,0x36,0x34,0x4d,0xae,0xec,0x06,0x3f,0x4f,0x4a,0x41,0x4a,0x87,0x79,0xe7,0x2a,0x96,0x08,0x92,0x33,0x5a,0xcd,0xfb,0xfd,0x45,0x2f,0x72,0x7a, + 0x04,0x3c,0xdc,0xaa,0x08,0x64,0x27,0x02,0x3b,0xbd,0x91,0xb5,0xb2,0xe2,0x12,0xbe,0x77,0xde,0x55,0x91,0xa1,0xa0,0xc2,0x10,0xd5,0x4f,0x04,0x82,0xf2,0x7c,0x42,0x65,0x58,0xf8,0xe1,0xf4,0xfe,0x6e,0x3b,0xf0,0x37,0xc0,0xe0,0x3d,0x40,0x43,0xc1,0xd9,0xb2,0x54,0x36,0xe0,0x80,0x3b,0x1a,0x42,0xb6,0xde,0x2e,0x40,0xd9,0x9e,0x83,0x9c,0x68, + 0x04,0xd7,0xad,0xbe,0x30,0xa5,0x68,0x2a,0xcf,0x9d,0x39,0x8f,0x58,0xda,0x8f,0xd3,0xb5,0x83,0x28,0x3d,0x9e,0xda,0x74,0xae,0x06,0x7b,0x9b,0x53,0x3c,0xd6,0xc0,0x82,0x4c,0xfe,0x50,0xd0,0x37,0x1c,0x0e,0x7b,0x59,0x04,0x3f,0xfa,0xd2,0x5e,0x17,0x44,0x5c,0xfb,0xdf,0xb3,0xfe,0xa4,0x0e,0x55,0xbc,0x7d,0xe1,0x9a,0xc5,0xf2,0x7c,0x64,0xa2, + 0x04,0x02,0x9e,0x1c,0x6e,0xb3,0x7c,0x38,0x3f,0xb4,0xe2,0x7e,0xbb,0x31,0x97,0x68,0x8f,0x8d,0x8a,0xf7,0x55,0xdb,0x83,0xb7,0x62,0x8e,0x17,0x57,0x9c,0xb3,0xf9,0x0f,0x05,0x8a,0x2b,0xf5,0x78,0x57,0xf5,0xff,0x63,0x31,0xcd,0xcf,0x87,0x44,0x0b,0x6e,0x69,0xcc,0x1b,0x6e,0x44,0x4c,0xe5,0x40,0xb8,0x22,0x2b,0x95,0x5c,0x98,0xa9,0x99,0x55, + 0x04,0x3a,0x35,0xde,0x21,0x3b,0x2d,0xc3,0x3e,0xb3,0x48,0x94,0x8a,0x22,0xed,0x5a,0x93,0x60,0x0f,0xad,0x07,0x1b,0xb0,0x17,0xa6,0xa2,0x50,0xe6,0x60,0x9b,0x13,0xf7,0xca,0xfb,0xec,0x06,0xb6,0x63,0xa5,0xf5,0x46,0x89,0xd0,0xee,0x67,0x09,0xfd,0x0d,0xa4,0x6a,0xcf,0xd2,0x60,0x38,0x93,0x59,0x35,0xf7,0x49,0xd6,0xd4,0xbc,0x21,0x06,0x0f, + 0x04,0x6b,0x91,0x0d,0x9e,0x99,0x43,0xcb,0xef,0xf7,0x17,0xca,0x95,0x46,0xaa,0x56,0x77,0xe0,0x61,0x18,0xf5,0xf0,0x4a,0x02,0x46,0xb5,0xba,0xb7,0x35,0x05,0x77,0x5d,0x65,0xc8,0x7a,0x4c,0x1f,0xd7,0xbc,0x58,0x4c,0x56,0x99,0x11,0x19,0x69,0x9b,0x90,0xb4,0xb3,0xa5,0x68,0xe5,0x08,0xea,0xa8,0x3f,0x11,0x83,0x32,0xda,0x91,0x52,0xb1,0x3a, + 0x04,0xf1,0x02,0xb9,0x0a,0xd3,0x78,0x72,0x5f,0xb7,0xff,0xe3,0xfc,0x3f,0xe6,0xef,0xb3,0x20,0xa7,0x28,0xa0,0x3c,0xe0,0x9a,0x88,0xee,0x25,0xba,0xb2,0xcf,0x13,0x3c,0x04,0xaf,0x2c,0xfe,0xe5,0x28,0xf3,0x91,0x3c,0x83,0x50,0x44,0x98,0xca,0x8b,0x3b,0x6d,0xeb,0x9e,0x28,0x42,0x41,0xb8,0xd0,0x1c,0x67,0x8a,0xb7,0x9a,0xd8,0x09,0x18,0x88, + 0x04,0x7f,0x42,0x0f,0xce,0xf9,0x3b,0x0b,0x9d,0x0a,0x9f,0x86,0xb2,0xc6,0x5e,0x18,0x93,0x8e,0x17,0xaa,0x84,0xea,0xde,0x2a,0x7a,0x64,0x40,0xad,0xec,0x91,0x4c,0xb2,0xf6,0xec,0x16,0x63,0xba,0xab,0x8a,0xf3,0x08,0x33,0x33,0x99,0xad,0xce,0xff,0x90,0x8e,0xe3,0x3c,0x8f,0x86,0xb3,0xdf,0x9e,0xf9,0x3a,0x51,0x52,0x09,0x31,0xf8,0x51,0xec, + 0x04,0x6b,0x83,0xad,0xf5,0x8b,0xbf,0x00,0xda,0x4b,0x77,0xb6,0xc4,0x61,0x59,0x25,0xcf,0x5a,0x8f,0x7b,0x72,0x99,0x7a,0xd9,0x69,0x04,0x85,0x54,0x90,0x83,0x4b,0xcf,0x82,0x22,0x4d,0xb9,0x40,0xbb,0xa0,0x28,0xdb,0xdd,0xaf,0x3c,0xba,0x94,0x9d,0xc4,0x1b,0x0d,0xb7,0x95,0x51,0x5e,0x34,0x54,0x9f,0xac,0x11,0xa1,0x83,0xb8,0x9d,0x5b,0xb7, + 0x04,0x04,0x10,0x23,0x67,0xdc,0x53,0x57,0x6a,0x83,0x85,0xfc,0x58,0xee,0x23,0x37,0xe2,0xb9,0xaf,0x54,0x7e,0x69,0x93,0x4f,0xe3,0xec,0x79,0x7a,0x84,0xc2,0x25,0xdf,0x0c,0x62,0x1c,0xec,0xc7,0x27,0x66,0x9f,0x2e,0x55,0x87,0x62,0xb6,0x5b,0x33,0xb3,0xcf,0x3f,0x22,0x8f,0xe9,0xa9,0xc2,0x22,0x23,0xab,0x71,0xe7,0x7f,0x90,0x4d,0x6a,0xa9, + 0x04,0x25,0x83,0x40,0x10,0x58,0x42,0xeb,0xe7,0x60,0xc4,0xfd,0xe1,0x3e,0x31,0xee,0xfd,0x52,0xe5,0x1a,0xae,0xf9,0x38,0xc4,0x47,0x7d,0x14,0x8b,0xba,0xc6,0xd3,0x74,0x12,0x30,0x1f,0x4b,0x4d,0x1b,0xfe,0x0e,0x70,0x46,0xcb,0x1f,0x99,0x3a,0x35,0x9f,0x91,0x91,0xfd,0x7b,0xca,0x7c,0x53,0xe0,0x39,0xfa,0x51,0xdb,0x8a,0x11,0x7e,0xfa,0xa3, + 0x04,0xd9,0xa5,0x21,0xd8,0x14,0x7c,0x1e,0x83,0xdf,0x82,0xb9,0xdb,0x62,0xb2,0x5e,0x6f,0xf1,0x41,0x7d,0xdd,0x41,0xae,0xf3,0xff,0xb1,0x82,0xad,0x23,0xf2,0x78,0x22,0xf7,0xb0,0xad,0x91,0x74,0x62,0xcd,0x2a,0x5a,0xbc,0xe2,0xec,0x2c,0x4a,0x4f,0x74,0x56,0xeb,0xdb,0x65,0xdb,0x10,0xd9,0x62,0x05,0x6e,0x75,0xf6,0xf8,0x85,0x3d,0x2a,0x4c, + 0x04,0x0b,0x58,0x00,0x6e,0x37,0x15,0x70,0x68,0x66,0x58,0xd4,0x58,0xf2,0x6f,0xaa,0x34,0xcc,0xf8,0xb4,0x9f,0xba,0x82,0x34,0xeb,0xd7,0x30,0x4c,0xbb,0xa3,0xab,0x1b,0x24,0x68,0x78,0x7e,0x9c,0x7e,0xa3,0x04,0x3e,0x0b,0xf2,0x7a,0xa9,0x73,0x0a,0x5a,0xbe,0x47,0x30,0x60,0xb7,0x7c,0x53,0xbd,0xdc,0x70,0xe2,0x01,0xd7,0xf5,0xb1,0xd8,0x9c, + 0x04,0x4a,0xb8,0xf5,0xac,0x88,0xee,0xcf,0xcb,0x03,0x94,0xf6,0xcf,0xe5,0x52,0x85,0x96,0xb6,0xb4,0xc4,0xfd,0xac,0x82,0x47,0xfd,0x62,0x95,0x72,0x89,0x13,0x3e,0x62,0x0e,0x1a,0xf5,0x18,0x52,0xe1,0x1b,0x19,0xd6,0x13,0x78,0x52,0xe2,0x18,0xfd,0x64,0xd2,0xeb,0xb5,0x67,0xf8,0xfa,0x92,0xa1,0xed,0x43,0xa5,0xe3,0x4f,0x56,0x94,0xa9,0x4b, + 0x04,0x90,0x32,0x01,0xba,0x08,0x35,0x3b,0xa6,0x15,0x8c,0x06,0xe6,0x6d,0xf0,0xb4,0x13,0xb7,0x71,0xd2,0x1a,0xcc,0x08,0x32,0x21,0x3b,0xd0,0x3d,0x58,0x95,0x75,0xe6,0x76,0x77,0xa9,0x0c,0xcf,0x2f,0x30,0x79,0xcd,0x2a,0xc6,0xc5,0x9c,0xc0,0x25,0x6a,0x61,0x2c,0x07,0x9b,0x8a,0x91,0xb5,0x9e,0xce,0x1e,0xfd,0x07,0x6f,0x53,0xbf,0x5b,0x04, + 0x04,0xc8,0x02,0x1b,0xe2,0x26,0x9a,0x2e,0xe8,0x38,0x53,0xe4,0xa1,0x2b,0xb0,0x68,0x08,0x25,0x08,0x8d,0x9a,0xc0,0xe5,0x6f,0xb5,0x05,0x10,0x9f,0x47,0x08,0xdd,0x9d,0x5d,0xd8,0x02,0xad,0x69,0x0d,0x8e,0x8b,0x81,0x7a,0x81,0x5d,0xe6,0x07,0x86,0x5a,0xfa,0xbf,0xbe,0xd7,0x65,0x09,0x88,0xf9,0x25,0xec,0xf2,0x3f,0xe5,0x65,0x4d,0x0c,0x9c, + 0x04,0xa5,0x3f,0x7c,0x41,0x2c,0x11,0xad,0x6a,0x36,0x2b,0xd2,0xbe,0x2e,0x7d,0x1f,0x20,0x44,0x02,0x97,0xbe,0x86,0x59,0x4a,0xbb,0xcb,0xea,0x25,0x94,0xdd,0xf9,0x37,0x23,0x79,0xdb,0x08,0xad,0x87,0xb5,0x36,0x93,0x9a,0x70,0x58,0x26,0x82,0xcb,0x75,0x70,0x26,0x36,0x55,0xcc,0x25,0xa2,0x97,0x9f,0x84,0x5f,0xd6,0x8b,0xe3,0xd8,0x29,0x53, + 0x04,0x46,0xfe,0xed,0x4e,0x52,0x29,0x63,0x19,0x2c,0xbd,0x6c,0x6e,0xda,0xbd,0x51,0x75,0xd1,0x0f,0x93,0x99,0x9a,0x58,0x5a,0x04,0x5a,0x30,0x26,0xb6,0x9b,0xb4,0xd5,0x28,0xed,0x7f,0x6a,0xbd,0x7b,0x39,0xe4,0x0e,0x08,0xe2,0x12,0x69,0x91,0xed,0x41,0x03,0x94,0xbf,0xda,0xbe,0xa9,0x90,0xab,0xb7,0xb2,0xca,0x5e,0xb9,0xf0,0x48,0xfa,0x4f, + 0x04,0x67,0xdb,0x11,0xee,0x0b,0x73,0x07,0x1b,0xf3,0xb8,0x15,0x86,0x4a,0x17,0x85,0x81,0xad,0xa3,0xd1,0x00,0x91,0x83,0x65,0xe7,0x12,0x0d,0x9b,0xde,0xc9,0xcd,0x9c,0x33,0x25,0xf5,0xeb,0x5a,0x1b,0x66,0xad,0x10,0x4a,0x5c,0x9e,0x43,0xb0,0x7a,0xfa,0x4b,0x15,0x2a,0x75,0xfa,0x22,0xa3,0xe4,0x29,0xaf,0x41,0xe4,0x59,0xe7,0x99,0x3e,0x45, + 0x04,0x14,0xcd,0xc4,0xf1,0x6c,0x07,0xd6,0xe6,0x07,0x4c,0xaa,0x8e,0xcc,0xa2,0x6a,0x01,0x86,0x34,0x7e,0x72,0x3d,0xce,0xdf,0x9a,0xff,0x9d,0xc6,0xfc,0x8c,0x38,0x15,0xbf,0x5d,0x64,0xfe,0x2d,0x7e,0x6a,0xbc,0x20,0x80,0x2a,0x1c,0x15,0x80,0x40,0xce,0xbd,0x61,0x4d,0xed,0xa0,0x34,0x79,0x87,0xe0,0xcd,0xcf,0xd4,0x1e,0x09,0x61,0x8c,0xf5, + 0x04,0x24,0x19,0x3c,0x35,0x01,0xff,0xa7,0x7e,0xbf,0x1e,0xe6,0x2f,0x7c,0x11,0x8b,0x28,0xc0,0x5a,0x1c,0x0a,0x94,0x6f,0x44,0x2b,0x20,0x8a,0x83,0x05,0xc6,0xa7,0x45,0xf8,0x86,0x36,0x03,0x29,0x9d,0xfd,0xf5,0xd2,0xbd,0xa1,0x92,0x30,0x00,0x7d,0x0e,0x03,0xae,0x61,0xfe,0x1c,0xae,0xaf,0xa5,0x84,0xdd,0xad,0x4c,0xea,0x6d,0xc7,0xd7,0x6a, + 0x04,0x08,0x1c,0xea,0xb1,0xd3,0xcd,0x53,0x17,0xfc,0x78,0x2c,0x9c,0x8d,0xc3,0x33,0x99,0x70,0x5a,0xba,0x68,0x99,0xc0,0xb8,0x04,0xef,0xa9,0x6e,0xd4,0xee,0x94,0x4d,0xa9,0x00,0xad,0xf5,0x1c,0xd3,0x1b,0x50,0x00,0xf2,0xd1,0x75,0x69,0x5d,0x48,0xa1,0x22,0x13,0xae,0x15,0x95,0xb9,0x83,0x72,0x64,0x3e,0xc0,0xeb,0x40,0x0e,0xf7,0x9d,0x41, + 0x04,0x13,0xe5,0x6b,0x20,0x78,0x55,0xea,0xbb,0x4b,0x8a,0x27,0xdf,0xe8,0xd1,0xec,0x89,0x64,0x4b,0xe7,0xc0,0x96,0xf6,0xc2,0xf3,0xa1,0x22,0xc9,0xcd,0x0b,0x8b,0x50,0x8b,0xb5,0xb7,0x97,0x0e,0x3a,0x14,0x11,0xf4,0xff,0xe3,0x71,0x14,0x05,0xec,0x65,0xef,0x98,0xdb,0x12,0xa2,0xb3,0x7d,0x8c,0x18,0xc8,0xd1,0x98,0x41,0x34,0xe8,0x54,0x92, + 0x04,0x5c,0xf9,0x5e,0x23,0xe6,0x81,0x05,0x9f,0x00,0x8b,0x32,0xdf,0x32,0x6f,0xfb,0x77,0x95,0xbd,0xf7,0x4b,0xb3,0x37,0xf7,0x7c,0xff,0x50,0x52,0xde,0x78,0x26,0x79,0x4b,0x5c,0xb0,0x38,0xec,0x1f,0xde,0xfd,0xe5,0x1f,0x6c,0x68,0xdc,0x5e,0x12,0xa1,0x98,0xa5,0x1c,0xe8,0x6b,0x92,0x16,0x78,0x83,0x68,0x7b,0x25,0x34,0x15,0xd6,0xd3,0x7a, + 0x04,0x9c,0x49,0x75,0x4a,0x4c,0x45,0xd9,0x7e,0x5b,0x70,0xd0,0x93,0x1b,0x98,0xf6,0x0b,0x3a,0x99,0xf5,0x1a,0x95,0x49,0x75,0x37,0xbd,0x85,0xed,0xe7,0xe9,0x87,0x94,0x29,0xdc,0xad,0xfe,0x27,0x3a,0x40,0x86,0xc3,0x0d,0xde,0x47,0x55,0x66,0x79,0x23,0xe5,0x8c,0x46,0x3e,0x8d,0x94,0xcb,0xb7,0xd5,0x6c,0x9e,0x0f,0x4d,0xe7,0x9e,0x6d,0x21, + 0x04,0xfc,0x7f,0xd9,0x84,0xdd,0x0d,0xc3,0xc9,0x38,0x46,0xf8,0xb4,0x1b,0x07,0x29,0x6e,0xa8,0x54,0x40,0x13,0x25,0xf1,0x55,0xf1,0x23,0x6f,0x2e,0x44,0x14,0xa9,0xb9,0xda,0x47,0x3f,0x38,0xa5,0xf8,0x4d,0x08,0xc0,0xac,0x7a,0x1d,0xab,0x8a,0x56,0x8e,0xac,0x21,0x06,0x60,0x74,0x94,0x74,0x49,0xa8,0xc3,0xd1,0x6f,0x05,0x5a,0x37,0x9b,0xff, + 0x04,0x33,0x7e,0x2e,0x26,0x0a,0x35,0x65,0xff,0x81,0xe0,0xbe,0x90,0x0c,0x8d,0xaf,0xb2,0xce,0x23,0x10,0x68,0x8c,0x3e,0xeb,0x6c,0x02,0x5c,0xac,0x20,0x8b,0x08,0xa1,0x8a,0x44,0x84,0xfc,0x5f,0xb0,0x1c,0x2d,0x40,0x4d,0xa9,0x9b,0x56,0xa4,0xdc,0x22,0x64,0x20,0xdc,0x3e,0x67,0x6f,0xd0,0x22,0x3b,0xa3,0xa4,0x5d,0x43,0xcd,0xcf,0x35,0x62, + 0x04,0xe2,0xb1,0x70,0xd1,0xdc,0x4d,0x9e,0x32,0x95,0x14,0xa5,0x4f,0x10,0xdc,0x81,0xd9,0x02,0xf3,0x75,0x2c,0x3a,0x6e,0x2f,0x8b,0xe5,0xd8,0x20,0xfa,0xfe,0xfa,0x9d,0x8b,0xe0,0x87,0xdb,0xd3,0x90,0x15,0x2e,0xbb,0x04,0xc7,0x3b,0x8c,0x50,0x4b,0x99,0x4a,0x76,0x83,0x72,0xd3,0xf9,0x20,0xa5,0xce,0xdc,0x42,0x42,0xbf,0x83,0x4c,0xcc,0x6f, + 0x04,0x67,0x02,0xab,0x6b,0x25,0x7c,0x24,0x44,0x0b,0xf7,0x19,0xc0,0x2d,0x21,0x61,0xe4,0xe3,0x1e,0x22,0xd5,0x5e,0xd8,0xad,0x0f,0x33,0xe5,0xaf,0x95,0x68,0xac,0x4a,0x9a,0xbf,0x87,0xac,0xcc,0x75,0x85,0x77,0x38,0x90,0x42,0xf5,0xb6,0x50,0xc3,0x7d,0xb6,0xb0,0xc7,0x68,0x22,0x03,0x15,0x6d,0xe7,0x37,0x28,0xa5,0x82,0xbe,0xd6,0xa6,0xd4, + 0x04,0x0c,0xec,0x0a,0xa4,0xde,0x0c,0x14,0x3f,0x5d,0x4c,0x3d,0x36,0xde,0x3d,0xb4,0xcd,0x72,0xe8,0xfe,0x0f,0xbd,0x33,0x6d,0xe8,0x79,0xa5,0x62,0xac,0x87,0xe6,0x28,0xd8,0xe7,0x5d,0x0d,0x0a,0xe3,0xd7,0xb4,0xd8,0x69,0xe7,0xf6,0xff,0x56,0x4e,0x21,0xef,0xc3,0x0a,0x15,0xff,0x2d,0x4c,0x87,0x61,0x81,0x04,0xfb,0xd4,0x2e,0xf5,0xe0,0x0b, + 0x04,0x92,0x76,0x15,0x1f,0xb9,0x99,0xff,0x3f,0x7f,0xcf,0x54,0x24,0x91,0xfb,0x62,0x47,0x9f,0xd1,0xea,0xe9,0x3f,0xc2,0xe7,0xd2,0x2c,0x38,0xd9,0x44,0x86,0x7c,0x44,0x7e,0xf0,0xe7,0x18,0x5e,0x4d,0x55,0xa1,0xc2,0xea,0xfa,0x2c,0xf8,0xd2,0x62,0x63,0x6d,0x6e,0x4b,0x35,0x3f,0xe7,0x1a,0xe3,0xd3,0xcc,0xe6,0xb1,0x58,0xd8,0x6c,0xf5,0xfe, + 0x04,0xe6,0x57,0xa9,0x1a,0xbd,0xcb,0x67,0xbf,0xfa,0x8f,0x78,0x56,0x5e,0xc7,0x96,0xb4,0x90,0x1f,0x29,0x91,0xc1,0x27,0x22,0xd2,0x7b,0xca,0x6a,0x02,0x17,0xf2,0xb0,0x0c,0x9b,0xb2,0xcf,0x5f,0x6c,0x57,0x80,0xc7,0x0f,0xa8,0xf0,0x31,0x59,0xbc,0xb0,0xd5,0x60,0x96,0xae,0xec,0xf5,0x3e,0xa5,0xe2,0x8d,0x10,0x58,0xc3,0xa5,0x0d,0x20,0x91, + 0x04,0x7c,0x05,0x1c,0x1e,0xeb,0xc7,0x67,0x46,0xeb,0x26,0x7e,0x8e,0x91,0xa4,0x7d,0x8a,0xb8,0x1b,0x89,0xbd,0x3b,0x3a,0x9d,0xe6,0xf1,0xc3,0xe6,0xb9,0x8d,0xb8,0x1c,0x7b,0x75,0xdf,0x08,0x88,0x82,0x15,0x0b,0x97,0xe2,0x01,0x46,0x54,0x7e,0xe0,0x7b,0x6b,0x56,0x20,0xbc,0xec,0xe4,0xd4,0x0a,0x53,0xee,0xed,0x84,0xe5,0xd4,0x77,0x9a,0x1f, + 0x04,0xd8,0x90,0x40,0x0f,0x12,0x30,0xfa,0x80,0xd8,0xd4,0xc9,0x51,0x73,0x92,0x4e,0x9e,0x7b,0x34,0x58,0xf7,0xe5,0x46,0x80,0xab,0x18,0x34,0xe5,0x05,0xa2,0xdc,0xcb,0x26,0xf7,0x14,0x37,0x4c,0x99,0x78,0x43,0x28,0x30,0xb8,0xe1,0xb8,0x27,0x42,0xca,0x86,0x77,0x7f,0x9b,0x8b,0x68,0x6b,0x19,0x24,0xee,0x55,0xe7,0xc5,0x72,0xc2,0xb1,0x19, + 0x04,0xf4,0x48,0x66,0xb8,0xee,0x1b,0x93,0x7d,0x18,0x2f,0xf7,0x9a,0xad,0xe4,0x1b,0x54,0x9b,0x71,0xff,0x1b,0xfa,0x88,0x2a,0x19,0x2e,0xc9,0x0d,0xc8,0x7a,0x51,0x77,0x4d,0x5e,0x33,0x5f,0x19,0x88,0x0e,0x84,0x38,0xb9,0xf2,0x05,0x93,0x26,0x64,0x51,0x2c,0xd6,0xdd,0x53,0xd5,0xa4,0x0a,0x70,0x08,0xfc,0x5c,0x98,0x12,0x4a,0x7d,0x95,0x54, + 0x04,0xfd,0x29,0x8a,0xb9,0x44,0xa0,0x87,0x02,0x81,0x6a,0x73,0x95,0xf8,0x4e,0x45,0xed,0x78,0x29,0x68,0xb7,0x01,0x83,0x8b,0x67,0xfa,0x25,0x28,0x11,0x1c,0xd4,0xf4,0x14,0x85,0x99,0x86,0x7c,0x89,0x17,0x4f,0x00,0xcc,0xf3,0x06,0x27,0x81,0x5e,0x66,0x18,0xbd,0x28,0x45,0xf3,0x58,0x19,0xdb,0x07,0x54,0x18,0x05,0x35,0xbb,0x4d,0x4b,0x2f, + 0x04,0x7b,0x78,0xd5,0x99,0x67,0xed,0x07,0xc8,0x3f,0x0e,0xd7,0xf8,0xf0,0xb2,0x63,0x88,0xdb,0x76,0xb0,0x86,0x3b,0x64,0xac,0x14,0xb7,0xec,0xbe,0xd8,0xe3,0xa1,0xbd,0xa2,0x4b,0x49,0xda,0xe1,0xad,0xf9,0x48,0x86,0x07,0x41,0x37,0x6c,0x91,0x9c,0xfd,0x50,0xff,0xcf,0x74,0x96,0x72,0xf1,0x9f,0x78,0xad,0x56,0x5e,0x88,0xf6,0x09,0x6d,0xf6, + 0x04,0x79,0x1c,0x90,0x17,0xb3,0xa9,0x3c,0xa2,0xf2,0xd0,0x3f,0xcf,0x18,0xb4,0x23,0x03,0x31,0xfd,0xc3,0xde,0x57,0x85,0xe8,0x47,0xc9,0xf5,0x1d,0x22,0xca,0xf5,0x0c,0xdb,0xed,0xc7,0x29,0xc9,0x2f,0x0a,0x88,0x23,0x3a,0x29,0xa2,0x25,0x9e,0x7e,0x62,0x65,0xb9,0x2a,0x14,0x38,0xc0,0xb5,0x95,0x91,0x67,0xfb,0xe2,0xaa,0x4a,0x65,0xa6,0xc0, + 0x04,0x47,0x57,0x86,0xce,0x21,0x5a,0x18,0x73,0xe0,0x4a,0x0c,0x67,0x64,0x2c,0x31,0x9a,0x6d,0x24,0xdf,0xfb,0x06,0xa4,0xcf,0xfb,0xb1,0x5a,0x82,0x56,0xd2,0xc8,0x11,0xec,0x5a,0x1b,0xba,0x7f,0x66,0x1e,0x38,0xd6,0x94,0xd9,0xa1,0x15,0x64,0xb5,0x11,0xaf,0x6c,0x66,0x32,0xa5,0xef,0xc9,0x33,0x73,0x26,0x42,0xdd,0x5c,0x49,0x28,0xa4,0x1b, + 0x04,0x75,0x9a,0xe7,0x72,0x33,0xb1,0x19,0xfb,0x37,0x89,0x05,0x97,0x60,0x11,0x2f,0x38,0xe8,0xd9,0xe6,0x9f,0x43,0x1c,0xf0,0xe8,0xf0,0xbb,0xe6,0xa0,0x6e,0x23,0xbc,0x5b,0x18,0xd6,0x9b,0x80,0x98,0x0f,0x53,0xb7,0xe8,0xc7,0x6c,0x9b,0x82,0xdc,0x61,0xf0,0x5c,0xdc,0x03,0x82,0x6c,0x2c,0x96,0x37,0xcc,0x02,0xaf,0x2a,0x6d,0xb0,0xe4,0xfa, + 0x04,0x3a,0xf2,0xb8,0x62,0x9a,0x34,0x75,0x29,0x4e,0xe0,0xd5,0x43,0x73,0x21,0xfc,0xd5,0xfa,0x45,0x54,0xc7,0x80,0xb6,0xb1,0x8b,0x86,0x24,0x2d,0x3e,0xdf,0x36,0xf5,0x51,0xed,0xe3,0x7c,0x4e,0xa3,0x19,0xd4,0x2f,0x8f,0xc3,0xcf,0x97,0xcf,0xe7,0xdd,0x17,0xe8,0x5b,0xa6,0xe1,0x1b,0xa2,0x60,0xed,0x99,0x1c,0x22,0xee,0x89,0x1a,0xbc,0x2b, + 0x04,0xca,0x2d,0xf3,0xb3,0xd7,0xd9,0x58,0xb0,0xd4,0x6e,0xd6,0xe0,0xff,0xe3,0xb7,0x48,0x8f,0x2e,0x13,0x66,0x09,0x51,0xeb,0x82,0x1c,0x24,0x24,0x6d,0x6c,0x7f,0x2e,0xc2,0x05,0x5e,0x78,0x0e,0x6a,0x53,0x4f,0x9f,0xf4,0x69,0xb0,0xba,0x3c,0x8d,0x38,0x96,0x2a,0xc0,0xac,0xdc,0x7b,0x4b,0x3d,0xc0,0x57,0xc0,0x7e,0xad,0x3f,0x4b,0x7a,0xa0, + 0x04,0xef,0x17,0xac,0x08,0x4a,0xba,0xd1,0x24,0x96,0xdf,0x80,0xd8,0x0d,0xbe,0x21,0xdf,0xad,0xe5,0x8e,0x30,0x2a,0xc0,0x39,0x80,0x02,0xc5,0x34,0x9d,0x85,0x25,0x28,0xcc,0xef,0x34,0x50,0x02,0x66,0xa5,0xdd,0x3f,0xb4,0x54,0x82,0x8e,0xd8,0x56,0x84,0xa6,0x2e,0x6e,0xb1,0x42,0xf6,0x5f,0x54,0x97,0xe6,0x4d,0x23,0x14,0x8f,0x75,0x79,0x76, + 0x04,0x62,0x4c,0xf7,0x45,0x9a,0x3e,0x09,0x7f,0x11,0x43,0x83,0xa1,0x25,0xc7,0xcd,0xec,0x33,0xb9,0x47,0xc5,0xbc,0x0a,0x26,0x79,0xd7,0xaa,0xe5,0x08,0xb5,0xd4,0x64,0x79,0x40,0x8c,0xac,0x79,0x1f,0x2e,0xd7,0x1d,0x9b,0xd5,0x94,0xbd,0x66,0xf6,0xce,0x70,0xd9,0x28,0xd3,0xb2,0x0f,0xe0,0x2b,0x5b,0x66,0xcf,0x74,0x3b,0x51,0x73,0x9a,0x74, + 0x04,0xe4,0x1e,0xc5,0x56,0xbb,0x3f,0x85,0xce,0xf6,0x65,0x1a,0x2d,0xb1,0x81,0x6d,0xab,0x3b,0xc8,0x28,0x98,0x87,0x14,0x82,0xdb,0xf1,0xcc,0x80,0x14,0x07,0xce,0x4d,0x1d,0xed,0xea,0xfe,0x8c,0x33,0x72,0x12,0x50,0xbf,0x75,0xcd,0xb9,0x18,0x1e,0x99,0x04,0x92,0xd3,0x70,0x80,0xe7,0xda,0xb4,0x1d,0xa1,0x67,0x3d,0x62,0xa8,0xb8,0x35,0xdf, + 0x04,0xb5,0xc3,0xcb,0x14,0x6d,0x30,0xfe,0xcf,0xd7,0xfe,0xd0,0x09,0x3d,0xcb,0xa0,0x18,0x46,0xa2,0x8a,0xa5,0x0c,0x7f,0xe3,0xc0,0xcf,0x4b,0x8c,0x5a,0xa8,0x37,0xd5,0xb0,0xb2,0x1b,0x76,0x05,0xca,0xdb,0xc7,0xb6,0x20,0x6e,0x5d,0xd4,0x28,0x9e,0x1d,0xe9,0xcc,0x36,0xbc,0x98,0x09,0x4f,0xb1,0x82,0x23,0xbe,0x63,0x6e,0x6d,0x36,0xe0,0xfa, + 0x04,0xb3,0xc6,0x28,0x48,0xbe,0xb0,0x63,0xfc,0x8f,0x28,0x5c,0x0d,0xa7,0x20,0x7e,0x70,0x7c,0x71,0x46,0x0b,0x8f,0x79,0x2a,0xe0,0x89,0x0f,0x23,0x62,0xfc,0x8f,0x02,0x10,0x9c,0xf8,0x0c,0x0e,0x0d,0x75,0xd2,0xf5,0x4a,0x6b,0xff,0xe3,0xfe,0xf3,0x94,0x41,0xed,0x0c,0xbf,0x29,0xc8,0x39,0x7b,0x76,0xa8,0x24,0xff,0x9e,0xcf,0x4c,0x77,0x2b, + 0x04,0x07,0xad,0x8c,0xd0,0x55,0x52,0x8f,0xeb,0x4b,0x3a,0x53,0xd3,0x54,0xc7,0xc7,0xcc,0x06,0x16,0xca,0x3f,0xf7,0x87,0xbb,0xb0,0xbf,0x79,0x90,0x96,0x06,0xd2,0x7e,0x8a,0x70,0xb4,0xd2,0x71,0xeb,0xd8,0x36,0x3d,0x9a,0xd9,0x10,0xcf,0x4d,0x84,0xe5,0x21,0x71,0xb5,0xb3,0x59,0x79,0x2f,0x7f,0xf8,0xa8,0x9c,0x44,0x27,0xfb,0x6a,0xfa,0x21, + 0x04,0x7c,0x66,0xfd,0x67,0xb7,0x9f,0x88,0x53,0x1a,0x07,0x47,0x28,0x87,0x26,0xdb,0xeb,0x29,0x9d,0xd8,0xe1,0x15,0x96,0x12,0xbf,0xf2,0xd9,0x79,0xfe,0x4b,0xd1,0x06,0x0c,0x15,0xc5,0x4c,0x5c,0xf4,0x0b,0x7a,0x6b,0x36,0xf4,0x40,0x0b,0xdb,0xaa,0x2b,0x6d,0xd0,0x66,0x9c,0x3b,0x45,0xa5,0x59,0x25,0x63,0x52,0x87,0x11,0x6a,0xaa,0xff,0x1c, + 0x04,0x94,0x06,0x46,0x98,0x28,0x0e,0x7e,0xb6,0xe1,0x4d,0xd8,0x1e,0xfa,0x9f,0x0a,0xb5,0x27,0xfe,0x6c,0xee,0xde,0xd6,0x0c,0xd4,0xd4,0x22,0x16,0x2c,0x39,0x7d,0x5b,0xad,0x16,0x3a,0x63,0x34,0x2b,0x44,0x62,0x9e,0x57,0xc0,0x9b,0xb4,0x90,0x11,0x8b,0x1d,0xaf,0x06,0xbc,0x0b,0xd1,0xde,0x48,0xa9,0x8e,0xa7,0xac,0x3e,0x89,0x3e,0x44,0x70, + 0x04,0xb4,0x54,0x03,0x93,0x84,0xab,0xb1,0x91,0xe5,0x93,0x46,0x39,0x76,0xde,0xa9,0x37,0x42,0x8b,0x76,0xa2,0xf2,0x1f,0x85,0x53,0xa9,0x94,0xe0,0xe2,0x3a,0x0d,0xe3,0x28,0x28,0x88,0xd4,0xe2,0x2e,0xaa,0x98,0x6d,0xfc,0xd2,0x0e,0x5a,0x4c,0x96,0x66,0xa2,0xa3,0x41,0xea,0xad,0xcd,0xf8,0x6b,0x6e,0x13,0x76,0x60,0xc9,0x55,0x61,0x56,0x6f, + 0x04,0xd4,0x3b,0x70,0x4b,0xcd,0xa6,0xed,0x2c,0xd8,0xca,0xcd,0x64,0xa6,0x71,0x91,0xda,0x2f,0x68,0xf2,0x5a,0x6a,0x98,0x3d,0xd7,0x90,0x10,0xb1,0x06,0x69,0x42,0x73,0x0f,0x2e,0xaa,0x0d,0x09,0x33,0xf7,0x10,0x91,0x7e,0x32,0x23,0xf2,0xfe,0xb2,0x33,0x88,0xad,0xd3,0xfe,0xd3,0xa2,0xa7,0xde,0x18,0xaf,0x50,0x80,0x3b,0x0b,0x20,0xd6,0xc9, + 0x04,0x9e,0xa3,0xdb,0x44,0xd3,0xc1,0xe0,0x97,0x15,0xec,0x33,0x0d,0x36,0x07,0xa0,0x6c,0xfd,0xc1,0xb0,0xba,0xf4,0xf5,0x70,0xfb,0xad,0x15,0xd6,0x3e,0x1a,0x8d,0x19,0x0b,0xda,0xe7,0x8a,0x1a,0x46,0xed,0x6f,0xda,0xa0,0x2e,0xa2,0x78,0x5c,0x2b,0xad,0x33,0xaa,0xce,0x95,0x39,0x7b,0x29,0x0e,0xb7,0xc2,0x64,0x28,0xef,0x68,0x49,0x4a,0xbf, + 0x04,0xe4,0xcb,0x3b,0x67,0xd6,0x21,0x08,0x68,0x7c,0x74,0xb3,0x6a,0x08,0x1c,0x3a,0xdb,0x9f,0xc4,0xe1,0x88,0xb5,0xe6,0x11,0x72,0x73,0x12,0xb7,0x08,0x86,0xe8,0x1a,0x79,0x5e,0xdb,0xa4,0xdf,0x71,0xb9,0xc4,0xb0,0x6f,0x7b,0x05,0x2b,0x5b,0x48,0xd9,0xe0,0xbe,0x85,0x5f,0xfc,0xc2,0xf2,0x79,0x26,0x52,0x4c,0xb2,0x2f,0xfb,0xb9,0xe8,0x65, + 0x04,0x6e,0x83,0x3d,0xc7,0x86,0x03,0x9c,0xb0,0x81,0xca,0x12,0x03,0x4a,0xdf,0xae,0x41,0xe3,0x45,0x4c,0xad,0x09,0x76,0xa0,0x96,0x12,0xf1,0xaf,0x4c,0x39,0x0d,0x58,0x9f,0x16,0xf4,0x99,0xbb,0x67,0x9c,0xe6,0x3d,0x15,0xbd,0x4b,0x82,0x13,0x92,0xe6,0xc3,0xde,0xb9,0xac,0x21,0x63,0xd0,0x21,0x1a,0x68,0xa6,0x16,0x7b,0xcb,0x5d,0xd0,0xe2, + 0x04,0x93,0xb0,0xcf,0x66,0xe6,0xc5,0x1e,0xc9,0xf5,0xb0,0x25,0x89,0x60,0x74,0x43,0xba,0xb7,0xb9,0x7b,0x18,0xf3,0xdd,0x2c,0x9c,0xc8,0x31,0xc0,0xa3,0x56,0xb6,0x0c,0x21,0xf9,0x60,0xbe,0xbf,0x79,0xb0,0xc2,0x95,0x79,0x42,0x37,0xc6,0x05,0x76,0xd6,0xa7,0x4e,0x5f,0x69,0x4d,0x9f,0xcc,0xdc,0x2c,0x4a,0x46,0x9e,0x00,0xb1,0x81,0x15,0xac, + 0x04,0x67,0xf4,0xd7,0xcf,0x5b,0x85,0x74,0xfa,0x36,0xec,0x8d,0x3d,0x4c,0xaa,0x36,0x9e,0xfe,0x05,0x21,0xff,0x9e,0x25,0x76,0x0c,0xf9,0x98,0x94,0xc6,0x4f,0x06,0x4c,0xa3,0x4d,0xb1,0x59,0x7f,0xbd,0x96,0xd7,0xb7,0xe3,0x19,0x23,0x6e,0x06,0x60,0xb0,0x58,0x00,0xed,0x99,0x09,0x9c,0x8c,0x10,0x22,0xd5,0x5b,0xe3,0xa8,0xfd,0x23,0x1e,0x96, + 0x04,0x43,0x96,0x38,0xad,0xcd,0xa8,0x70,0x13,0x74,0x36,0xee,0xb0,0x9e,0x27,0xc3,0x26,0x37,0x30,0x79,0x21,0x97,0x4b,0x64,0xb9,0xf7,0x3e,0x26,0x6d,0x8e,0x95,0x39,0x30,0x94,0xcf,0xcf,0x35,0x0b,0x98,0x28,0x24,0x37,0x97,0x4d,0xb3,0xe4,0x02,0xfd,0x86,0xe3,0xeb,0xdd,0xdc,0x5e,0x23,0xfc,0xd0,0x73,0x03,0xa0,0xa5,0xcf,0x28,0x2b,0xa4, + 0x04,0xbf,0x32,0x69,0x3d,0xd7,0x7e,0x18,0x2d,0x8b,0x26,0x50,0x38,0x28,0x32,0xf3,0x7f,0x67,0x70,0x09,0x01,0x32,0xaa,0x77,0xa7,0xeb,0xc1,0x82,0x15,0xe0,0x0c,0x44,0xc0,0x46,0x42,0xea,0x34,0x61,0xff,0x10,0xe2,0xe1,0x80,0x0d,0xc3,0x92,0x73,0x8d,0x7d,0x01,0x17,0x46,0x79,0xc9,0xd2,0xe3,0x82,0xa8,0x0e,0xd4,0x96,0x1f,0xe4,0x8b,0x6b, + 0x04,0xd2,0x0a,0x02,0xa6,0xd0,0x42,0x48,0x20,0xf7,0xc2,0xed,0x6a,0xfd,0x1b,0x7c,0x14,0x9f,0x67,0x62,0xbf,0x8c,0xe4,0xdb,0xa5,0x0d,0xed,0x97,0x92,0x36,0x8d,0xce,0xac,0xc5,0x74,0xcc,0x62,0x98,0xfa,0x1d,0x96,0xed,0xd1,0x78,0x30,0x9f,0x75,0x08,0xce,0x8a,0xab,0xf6,0x9f,0xc0,0xc4,0x9b,0x85,0x29,0x9b,0xaf,0x91,0x23,0x9e,0x66,0x65, + 0x04,0xaf,0xd3,0x21,0xe9,0xff,0x7b,0x24,0xd8,0x56,0xbf,0x14,0xbb,0xc5,0xaf,0xef,0x19,0x52,0x74,0x48,0x67,0xca,0xe4,0xa9,0xf3,0xe3,0x8f,0x66,0x73,0xda,0x90,0x8a,0xed,0x71,0x49,0x66,0xdf,0xee,0x5a,0xf5,0xb7,0xdd,0xfc,0x17,0x79,0xdb,0x74,0x98,0x7e,0x9e,0x87,0xf5,0x32,0xbe,0xa7,0x6a,0x2c,0xbe,0xd7,0x17,0xa3,0x6c,0x91,0x00,0xe7, + 0x04,0xcf,0xd6,0xd8,0x41,0x13,0xfc,0x92,0x0b,0x44,0xbf,0x6d,0x67,0xcb,0x84,0x16,0x91,0xdb,0xae,0x07,0xbd,0x67,0x32,0xe5,0xde,0xc0,0x45,0xe6,0x0d,0x90,0xb9,0x8f,0x71,0x10,0xcb,0xf8,0xc9,0xff,0xae,0xf3,0x6f,0x3d,0x53,0x13,0x2b,0x1c,0x10,0xdb,0x56,0x72,0xac,0xd5,0xdf,0x5b,0x87,0xcb,0x98,0xd1,0x9d,0xaf,0x87,0xb0,0xde,0x35,0x73, + 0x04,0xf0,0x96,0x16,0x82,0x7b,0x93,0xb6,0x01,0x7d,0x77,0x0c,0x75,0xe3,0x5b,0x01,0x62,0xc5,0x45,0x5c,0xe2,0x38,0x0e,0xf2,0xfe,0xc5,0x4e,0x33,0x6d,0xfe,0x94,0xcb,0xbc,0xf3,0xd0,0x1b,0x7b,0x10,0x2b,0xec,0x4f,0xf0,0x24,0x5d,0xb8,0xc9,0x43,0xc6,0x8c,0x23,0xcf,0x11,0x72,0xc6,0x55,0x44,0xaa,0x11,0x74,0xe4,0x4c,0xd5,0x24,0xf0,0x49, + 0x04,0xbf,0xeb,0x62,0xd5,0xcd,0xb7,0x33,0x3e,0x09,0x76,0xfa,0xd3,0xa2,0x59,0xdd,0xb9,0xcb,0x52,0x5a,0xee,0xe6,0x83,0x27,0x65,0x7a,0xed,0x59,0x28,0x53,0x52,0xf3,0x47,0x6e,0x88,0xbc,0x97,0x99,0xdf,0x4d,0x0c,0x14,0x2b,0xc6,0x32,0xc8,0x1d,0x40,0x48,0x6f,0xe2,0x37,0x63,0x92,0xe0,0x18,0x0a,0xf9,0x3d,0xeb,0xcb,0x82,0xc6,0x39,0xcd, + 0x04,0x6d,0x86,0x4a,0x7c,0xb7,0xf8,0xe3,0xa1,0xfe,0x1c,0x80,0x94,0xe3,0x85,0x2f,0x8f,0x43,0xcc,0x4c,0xa6,0xa9,0x03,0x95,0x12,0xb2,0xad,0xe5,0xf0,0x40,0xe3,0xb4,0x23,0x7c,0x90,0x8e,0xc1,0xcb,0x9f,0xbc,0x1f,0x6d,0x49,0x46,0x0a,0xc1,0x9f,0x2d,0x45,0x26,0xf6,0x6e,0x00,0xdb,0x60,0xd2,0x07,0x40,0x8b,0xd4,0x6c,0x95,0xbf,0xff,0xf0, + 0x04,0xfe,0xb6,0x8f,0x41,0xe8,0x06,0xa2,0x39,0xf6,0x24,0x45,0xd2,0x3d,0x1b,0x92,0x59,0x78,0xa9,0xb6,0x96,0xd6,0xf0,0xca,0xa9,0xdc,0x29,0xf4,0x05,0x39,0xb0,0x73,0xcc,0x2c,0x90,0x2a,0xff,0xb2,0x00,0x66,0xd2,0xc2,0xc9,0x20,0xce,0xb8,0xa4,0x53,0xe4,0x2c,0xd2,0x45,0x49,0x88,0xc3,0x32,0xcf,0x0d,0xb9,0x07,0xbb,0x4f,0xe9,0x59,0x43, + 0x04,0x57,0xd0,0x4c,0x65,0x33,0x25,0xa6,0xcb,0x99,0x8f,0x61,0xce,0x34,0x71,0x09,0xec,0xa0,0xef,0xff,0x9a,0x16,0xa7,0x34,0x13,0x4a,0x69,0xcd,0x1e,0x0b,0x08,0x1a,0xce,0xb4,0x3a,0xea,0x4f,0x71,0xb1,0xf2,0x80,0x2f,0xbe,0x41,0x07,0xd0,0xbf,0xb9,0xf6,0xfb,0xbd,0xa4,0x64,0x50,0x1b,0x87,0xff,0x73,0xc4,0x71,0x03,0xe3,0x72,0xf6,0x35, + 0x04,0x60,0x5f,0xd3,0x3a,0x42,0xd9,0x21,0xe0,0x1e,0xe7,0xf7,0x58,0x06,0x10,0x6d,0xe7,0x2c,0xb5,0x03,0x9f,0x65,0xff,0x31,0xd6,0xca,0x2e,0x1e,0xfd,0x6a,0xa8,0x1a,0x1c,0x95,0x78,0x9f,0x09,0x23,0xd7,0x05,0xfd,0x19,0xd5,0xa8,0xae,0x18,0xb6,0x66,0x87,0xcb,0x29,0x09,0x1e,0x17,0x94,0x4b,0x37,0xd2,0x7f,0x39,0x8b,0xd5,0x54,0x6b,0xdb, + 0x04,0x30,0x3c,0xe8,0x96,0xaa,0x57,0x0c,0xf8,0xf9,0x79,0x54,0xba,0x48,0xfc,0xc2,0x5f,0x5f,0x25,0x28,0x67,0xf0,0x1a,0x9b,0x9e,0xde,0xce,0xaa,0x6b,0xfc,0xce,0xdf,0x56,0x11,0x34,0xd6,0x29,0x0e,0x16,0x49,0xbb,0x02,0x8a,0x16,0xc6,0xf5,0x4e,0xb0,0x6c,0x7e,0x72,0x4a,0x94,0x7a,0x62,0x48,0x27,0x4a,0x4b,0xf6,0xa6,0xaa,0x13,0x90,0x96, + 0x04,0x1c,0x2c,0xa6,0x73,0x11,0xdc,0x5c,0x45,0x4d,0xc8,0x30,0x38,0x6b,0x79,0x97,0xe5,0x0b,0xc6,0x7e,0x3d,0x5f,0xf5,0x22,0xd3,0xe8,0xa3,0x9f,0x14,0x49,0x98,0xf8,0x84,0x86,0x2c,0x97,0x5f,0x54,0x8a,0x5f,0x55,0xdd,0x85,0x04,0xda,0xb5,0xc9,0xe8,0x8f,0x0e,0xd3,0x12,0x36,0x88,0xd4,0x75,0xb2,0x11,0xda,0x5a,0x4d,0x69,0x20,0xdd,0x63, + 0x04,0x56,0x33,0xcb,0xcf,0xdf,0x74,0x32,0x7d,0xe0,0x88,0x3f,0x59,0xe1,0x78,0x8e,0xed,0x76,0xbb,0x0b,0x9e,0x0f,0x9e,0x55,0xe2,0x76,0x9e,0xc9,0xaa,0x36,0x5a,0x30,0xe1,0xd9,0x13,0xbd,0x53,0x1f,0x4a,0x61,0xc2,0xd0,0x7b,0x84,0x7d,0x31,0x8e,0xe9,0x64,0x82,0xd2,0xf8,0xfa,0x7a,0x12,0xaa,0xb3,0xb3,0x03,0xc1,0x08,0x51,0xce,0x7f,0xcd, + 0x04,0x19,0xd5,0x3e,0x44,0xb0,0x58,0xc3,0x17,0xfb,0xed,0xbf,0x10,0x6c,0x98,0xf3,0x18,0x32,0xcd,0xfb,0x84,0xf2,0x1a,0xdd,0x75,0x3c,0xf2,0x13,0xba,0x5d,0xe9,0x02,0x6a,0x61,0x4c,0xf7,0xb7,0xb6,0x0e,0x75,0x9a,0x15,0xa6,0xc7,0xd8,0x64,0xed,0xde,0xc6,0xdc,0x25,0x35,0x19,0x97,0x5d,0xf7,0xf3,0xe9,0xbc,0x0c,0x77,0xfd,0x80,0xe5,0x10, + 0x04,0x1c,0x96,0xcc,0x2b,0x22,0xe5,0xbd,0xb1,0x95,0xb2,0xa4,0x71,0x87,0xfa,0xd5,0xee,0x67,0x36,0xbd,0x96,0xdc,0xef,0xef,0x20,0x25,0x9a,0x55,0x1e,0x98,0x47,0xb5,0xe0,0xc5,0xab,0x05,0x2c,0x88,0x36,0xe4,0xf7,0xcc,0x7b,0x65,0x54,0x57,0x75,0xd5,0x5b,0x0c,0x7b,0x0c,0x7f,0x83,0x0c,0x65,0x39,0x91,0x5c,0xb6,0x24,0xa5,0x07,0xdb,0xfe, + 0x04,0x73,0x32,0x42,0xcc,0x4a,0xfb,0x82,0x27,0x10,0x34,0x11,0x1b,0x81,0x30,0x9e,0x15,0x6a,0xe4,0x46,0x6e,0x7f,0x2f,0xc5,0xfc,0x10,0x42,0xf4,0xf6,0xe3,0xc4,0x4f,0x43,0x5c,0x6f,0x61,0x4d,0x4b,0xe1,0x8a,0x73,0x17,0x0c,0x85,0xa6,0xb6,0x8a,0x96,0x14,0x05,0x29,0x34,0xe1,0xd6,0x12,0x46,0x6d,0xd4,0x92,0x19,0x89,0x47,0x4f,0xf5,0x13, + 0x04,0x1a,0x24,0xb6,0x52,0x0a,0xf4,0xf0,0x28,0x82,0x4b,0xee,0xce,0x59,0xb6,0x03,0xd1,0x5d,0x6d,0x15,0xcd,0xe0,0x71,0x9a,0xd2,0xf7,0xb8,0xe3,0xfc,0xb6,0xc1,0x34,0x2c,0x7e,0xd7,0x02,0xa3,0x0e,0x87,0x5b,0x24,0x36,0xdb,0x2f,0x2d,0x36,0x87,0xd9,0x58,0x0d,0x3b,0xd7,0xb3,0xf8,0xd1,0x28,0x0a,0x81,0x07,0x1f,0x3c,0xcd,0x6b,0x40,0x7d, + 0x04,0x4a,0xde,0x6f,0xa1,0x3e,0x59,0x11,0x7e,0x05,0x4a,0xc1,0xbc,0xa3,0xca,0x52,0xf4,0x14,0x03,0x54,0x93,0xac,0x2e,0xe7,0xb1,0xa8,0x11,0xf1,0xfb,0x52,0x52,0x1e,0x81,0x16,0xad,0x61,0x2c,0xd7,0xab,0x0c,0x21,0xef,0x78,0x93,0x89,0x45,0xd8,0x70,0xda,0xc8,0x27,0xbe,0xcb,0x5b,0x87,0x3c,0x84,0x22,0x5c,0x4a,0xef,0x15,0x9e,0xe4,0xbb, + 0x04,0x34,0xb2,0xac,0x5a,0x3e,0x49,0x16,0xd0,0x81,0xd1,0xed,0x40,0x4b,0x5b,0xcc,0xfe,0x07,0x6a,0xa7,0xf4,0x1e,0x29,0xd0,0x36,0x23,0x90,0xf7,0xf0,0x84,0x58,0xb4,0x4c,0x25,0x98,0x7b,0x7f,0x7a,0x21,0x43,0x23,0x76,0x3e,0x1a,0xa1,0x04,0x4a,0x87,0x79,0xbb,0xff,0xc5,0xe2,0x2b,0xe6,0x28,0x13,0x8a,0x1d,0x80,0x26,0x83,0x64,0x69,0x8e, + 0x04,0x58,0xc2,0x5f,0x40,0x47,0x78,0x2b,0x81,0x5b,0x41,0x00,0x1d,0xea,0x63,0x6c,0x86,0xef,0x19,0xd6,0x7e,0xc0,0x56,0x32,0x41,0x27,0x22,0x5a,0xaf,0x6f,0xf1,0x08,0x32,0x76,0x13,0x25,0xc4,0xa7,0x03,0x07,0xdc,0xeb,0x9b,0xf4,0x51,0xc7,0x40,0x5e,0x42,0x58,0x08,0x68,0xe6,0x65,0xf3,0xf2,0x59,0x99,0x5f,0x8c,0x35,0x8e,0xb0,0x79,0x9d, + 0x04,0xe3,0xd0,0x5f,0x1a,0xff,0x72,0xac,0xff,0x70,0xe4,0xd5,0x1b,0x42,0x07,0x88,0x0e,0xc0,0x6b,0x4c,0x26,0x9d,0xb0,0x27,0x53,0xd6,0xd8,0x58,0xaa,0x5e,0x6d,0x56,0x1e,0x7c,0x75,0x6f,0x6b,0x0c,0xd1,0x06,0xbb,0x73,0x2e,0x5f,0x20,0xc9,0x1d,0xdd,0xe4,0xf2,0x4a,0x36,0x99,0xdf,0x11,0x25,0x20,0x6f,0xcc,0x47,0x44,0x9a,0xbb,0x7d,0x1e, + 0x04,0x75,0x63,0x8c,0xa9,0xef,0x9f,0xa2,0x52,0x42,0x9d,0x21,0x24,0x3c,0x77,0x8b,0xe3,0x55,0xbd,0x13,0x0c,0x1e,0xf6,0x26,0x59,0x3c,0xa0,0xc2,0x44,0xcf,0x2b,0x6e,0xf2,0x53,0xb8,0x87,0x66,0x23,0x0c,0xe8,0xde,0xd7,0x90,0x09,0x56,0xa5,0x29,0x1a,0x69,0x67,0xc2,0xa5,0x42,0x79,0x84,0x4c,0xb0,0x7d,0x7c,0x58,0x5d,0x87,0xd4,0x06,0x61, + 0x04,0x44,0x68,0x2e,0x43,0x74,0x48,0x73,0x0f,0x59,0x4a,0x82,0x0e,0xad,0x23,0x2c,0x44,0x43,0xf7,0xe7,0x84,0x37,0x0b,0xfb,0x03,0x13,0x04,0xb8,0x51,0x99,0xc4,0x15,0x9f,0x71,0x51,0xec,0xea,0xa0,0xa6,0x98,0xd1,0x57,0x85,0xcc,0x7a,0x2e,0x81,0x2a,0xed,0xa1,0x2f,0x9b,0xa4,0x23,0x8a,0x7f,0x5e,0x76,0xe9,0x30,0xf3,0x90,0x50,0x15,0xaa, + 0x04,0xc9,0x8b,0x01,0xfe,0x92,0xfe,0xae,0x44,0x1d,0x9f,0x4d,0xe5,0x0d,0x4d,0xfb,0xe9,0x78,0x97,0x11,0xd9,0x11,0xbe,0x6e,0xf7,0xcd,0x9c,0x55,0xf4,0xb3,0xe8,0xca,0xbd,0xd9,0xe3,0xaa,0xf1,0x66,0x05,0xb0,0xab,0x50,0x63,0x2d,0xf6,0xc0,0x0e,0xc8,0x55,0x4f,0x36,0xec,0xf4,0x27,0xd3,0x1d,0xf9,0x30,0xd4,0x45,0x8f,0xe1,0xcb,0xaf,0x11, + 0x04,0x91,0x73,0xae,0x01,0x4b,0x64,0x57,0x24,0x58,0x7e,0xe2,0x6e,0x17,0xbf,0xeb,0x61,0xf9,0x12,0x53,0xfe,0x86,0x53,0xda,0xfb,0xda,0x43,0x81,0xda,0x9f,0xa5,0x7e,0x98,0x15,0xa9,0x16,0x6e,0x1d,0xfc,0x2a,0x81,0xcb,0xe1,0x26,0xa2,0x59,0x4e,0x51,0xfb,0x98,0xfb,0xee,0x7b,0x3d,0x65,0x88,0xad,0x86,0xa8,0x64,0x31,0x14,0x14,0x44,0xf4, + 0x04,0xe4,0x10,0x2f,0x16,0xfa,0x7f,0x38,0x6e,0x91,0x2d,0x3a,0x7f,0x77,0xdc,0xc7,0xdc,0x9f,0x8a,0xf5,0x4c,0xae,0x11,0x7d,0xdb,0xa1,0x0a,0x3d,0x09,0x62,0x0e,0xff,0x8c,0x68,0x9c,0x20,0xe1,0x2c,0xe8,0xf7,0x84,0x12,0x94,0x5e,0x1d,0x3a,0xcb,0xf9,0x93,0x5e,0x46,0x53,0xfb,0x0d,0xce,0x02,0xb1,0x4a,0x7d,0x52,0x6a,0x11,0x4f,0x13,0x87, + 0x04,0x7a,0xa6,0x7d,0x00,0x33,0x22,0x6f,0xb2,0xb1,0xbf,0x97,0x5d,0x45,0x68,0xe1,0xf2,0x29,0x9e,0x82,0xf2,0xe4,0x59,0xff,0x0b,0x6e,0xe3,0xc0,0xc5,0x7d,0xbd,0x40,0x41,0x7c,0x20,0x63,0x46,0x44,0x99,0x3b,0xd8,0x4a,0xa3,0x61,0x03,0x7c,0xe8,0xbf,0x3f,0xb7,0x22,0x86,0xdf,0xdf,0x44,0x82,0x45,0x8b,0x07,0x6a,0x7a,0x5f,0x46,0xd1,0xdd, + 0x04,0x80,0x69,0x4b,0xa7,0xd6,0xad,0x6e,0xfa,0x8a,0xd5,0xce,0x04,0x35,0xa1,0xbd,0x22,0x5e,0x02,0x88,0xb6,0xfc,0x22,0xa1,0x1e,0x70,0x13,0xaa,0x0d,0x4e,0x9a,0x49,0x6b,0x31,0x6d,0x67,0xd1,0xc7,0x0e,0x6c,0x13,0x04,0x20,0xf5,0x7c,0xb6,0xe0,0xd6,0x0c,0xda,0x15,0x4c,0x73,0x7f,0x01,0x18,0x00,0x7c,0xfe,0xa5,0xc2,0xd5,0xb4,0xe3,0x97, + 0x04,0x06,0xc6,0x69,0x70,0xe5,0x39,0xd9,0xae,0x0f,0x8f,0x67,0xa7,0x2f,0x42,0x6c,0x10,0x0b,0x3b,0x2c,0xf2,0xe2,0x76,0xe9,0xb0,0xae,0xa7,0x5b,0x4e,0xfc,0x98,0x83,0x25,0x24,0xee,0xab,0x2b,0x41,0x3b,0xa1,0x7d,0xb8,0x11,0xf7,0x40,0xf9,0xfb,0x9f,0xc3,0xc7,0x3b,0x5c,0xe5,0x1f,0x1e,0x74,0xe7,0xe0,0x8b,0xcd,0x8a,0xb4,0x8d,0xae,0x83, + 0x04,0x41,0x27,0x7a,0x6f,0x20,0xd8,0x55,0xaf,0x6a,0xce,0xc5,0x3e,0x99,0x23,0x21,0x6d,0x74,0xee,0x2a,0xed,0x18,0xa4,0x14,0x05,0x91,0xeb,0xbb,0x0b,0x34,0x55,0x07,0x26,0x69,0xbc,0x7f,0x19,0xd6,0x46,0x47,0xe7,0x4f,0xf0,0x0d,0x0c,0x89,0xbb,0xfe,0x50,0x8e,0x32,0x2b,0x43,0x97,0xdd,0xb8,0x56,0x4e,0xd2,0x83,0x2e,0xaa,0x5b,0x2d,0x92, + 0x04,0x14,0x6d,0xee,0x2b,0xca,0xa5,0xcc,0x08,0x17,0xfe,0x19,0x1b,0x6d,0x10,0xde,0xf6,0x25,0x9d,0xf7,0x44,0xaf,0xdc,0x9e,0x5b,0x0d,0xde,0x52,0x3b,0x34,0x8a,0xaa,0xb4,0x45,0xb1,0x54,0x6f,0x79,0xb7,0xa6,0xaa,0xdf,0xa5,0x47,0xbf,0xa4,0x16,0xf6,0x2b,0x54,0xf7,0xa4,0x76,0xd6,0xd8,0x88,0x05,0x6b,0x9c,0x05,0xc7,0x2e,0x01,0x39,0xf1, + 0x04,0xc4,0x8e,0xe9,0x0f,0x8f,0xe8,0x00,0x66,0x40,0x86,0xed,0x5b,0xa1,0x29,0x30,0xca,0xcd,0xfa,0x17,0x5a,0x67,0xa2,0xc4,0x39,0x81,0x68,0xf6,0x26,0x69,0x9d,0xeb,0x8d,0xd7,0x8c,0x35,0xa4,0x80,0x42,0xaa,0xfb,0xc6,0xc7,0xca,0xf3,0xa6,0x83,0x85,0xdd,0xb5,0xd4,0x06,0xac,0xee,0x86,0xd9,0x64,0x03,0xe7,0x5b,0xaf,0xfe,0xce,0x00,0xe3, + 0x04,0x73,0x7d,0x92,0xf5,0xda,0xd5,0x1d,0x58,0x26,0x1a,0x77,0xe7,0x55,0x67,0x8a,0xb0,0x2b,0x10,0x79,0x12,0x04,0x1c,0x5d,0x29,0x5f,0x58,0x29,0xcb,0xd1,0x0c,0xd8,0xc5,0x9b,0x55,0xdd,0x08,0x4f,0x84,0x93,0x7c,0x27,0x56,0x5a,0x90,0x75,0xfe,0x10,0x87,0x45,0xe1,0x70,0x01,0x66,0x67,0x43,0xdb,0x55,0x14,0x36,0xe6,0x91,0xea,0x81,0x8d, + 0x04,0x59,0xef,0xed,0x74,0x73,0x03,0x89,0x1b,0xaa,0xb0,0xe1,0xdf,0xdc,0x32,0xd6,0x99,0x06,0xe0,0xfc,0x68,0x15,0xb0,0x56,0xda,0xe0,0xed,0xa2,0x08,0x09,0x57,0xa3,0xeb,0xf2,0x05,0xfd,0x29,0x9c,0x63,0xe5,0x49,0xd2,0x4c,0x15,0x39,0x35,0xd9,0x50,0x14,0x1c,0x3d,0xc2,0x69,0x9a,0xfe,0x87,0x31,0xa4,0x63,0x04,0xe2,0x03,0xca,0xc1,0x5d, + 0x04,0x8e,0xf9,0xa7,0x99,0x7b,0x71,0x7f,0xdb,0xc5,0xd2,0xa7,0xf9,0xa6,0x7f,0x70,0x5e,0x5d,0xee,0x4c,0x82,0xca,0x38,0x3b,0x7e,0xe2,0xd0,0x7c,0x24,0x85,0x03,0x96,0xd0,0x72,0xc9,0x8f,0x7d,0xc1,0x65,0x8f,0x9d,0xc3,0xc4,0x34,0xa9,0xfd,0xdc,0x2f,0x98,0x6c,0xc0,0xe3,0xe3,0xef,0x40,0x98,0x27,0x53,0x76,0x17,0xee,0x67,0x10,0x5f,0x2b, + 0x04,0x04,0x56,0x9e,0xc9,0xfb,0x3d,0x6b,0xce,0xdc,0x05,0x9e,0x7f,0xd0,0x4a,0xb7,0xd3,0xf6,0xba,0xc7,0x30,0xb1,0xb7,0x5a,0x11,0x74,0x9e,0x43,0x46,0x45,0x8f,0x92,0x96,0xa0,0x51,0xc8,0x4d,0x55,0x8d,0xbd,0x29,0x57,0xc1,0x59,0x07,0x47,0x77,0x76,0xaf,0x66,0x0a,0xc0,0x15,0x82,0xc0,0x01,0xdc,0x1f,0x86,0x8e,0xbf,0xc6,0xb3,0xb2,0x64, + 0x04,0x4b,0x29,0x8a,0x3e,0xba,0x6a,0x09,0xfc,0xd8,0x41,0x59,0x76,0xe0,0xfa,0xea,0x99,0x7f,0xd5,0x19,0xff,0xd3,0x36,0x3b,0xd2,0x01,0x07,0x75,0x21,0x23,0xe1,0x01,0x46,0x6a,0xbb,0x70,0xc0,0x13,0xba,0x23,0x89,0xc3,0x71,0xbe,0x19,0xdd,0x32,0x96,0xf0,0x60,0x0e,0x64,0xf0,0x57,0x55,0xe1,0x5c,0xf8,0x93,0x20,0xac,0x7f,0xfb,0x25,0xd6, + 0x04,0x18,0xbd,0xe0,0x79,0x52,0xd7,0xbe,0x89,0x14,0xd2,0xb2,0x54,0x4c,0x65,0xa3,0xde,0xbd,0xdd,0xd9,0xe7,0xce,0x8a,0x9c,0x46,0xa0,0x3d,0x12,0x4a,0xcf,0xb8,0x54,0x8b,0x01,0xa4,0xa1,0x75,0xa2,0xa8,0x1a,0xf9,0x8e,0x60,0x28,0x77,0x0d,0x05,0x5e,0x22,0xf1,0x01,0x6d,0xf1,0x54,0x62,0xb6,0x5f,0x55,0xa2,0xd4,0x85,0x0c,0xc4,0x15,0xe5, + 0x04,0x00,0x2b,0xeb,0x75,0x5f,0x69,0x4a,0x09,0xf6,0x0b,0xce,0x5b,0x34,0xdc,0x34,0x7c,0x5c,0x3a,0xa2,0x36,0xde,0x90,0x07,0xbc,0xdd,0x07,0x07,0xe9,0xbc,0x80,0x71,0x69,0x4f,0x44,0x3b,0x00,0x45,0x99,0x9f,0x2f,0x58,0x99,0xca,0x79,0x34,0x24,0xa9,0xb4,0x23,0xb0,0xec,0x0a,0x3e,0xdc,0xbb,0xf4,0xaf,0xb9,0xe6,0x65,0x26,0xcf,0x89,0xb2, + 0x04,0x95,0x7e,0x5b,0xcd,0x11,0xfc,0x45,0x0b,0xff,0xce,0xfe,0x63,0x6c,0x0b,0x73,0xf1,0x0f,0xe8,0x58,0x5e,0x04,0xc6,0xc7,0xaa,0x7f,0xa0,0xb6,0x03,0xd2,0x41,0x62,0xd9,0x9e,0x55,0x3e,0x94,0x09,0x56,0xaa,0x04,0xa2,0x37,0xa0,0xc2,0x57,0x0a,0x0c,0x7b,0xc3,0x71,0x21,0x72,0xb8,0xf7,0x8c,0x7b,0x47,0x0a,0x04,0x2a,0xe3,0x1f,0x32,0x23, + 0x04,0xc4,0x3b,0x1b,0x40,0x99,0xda,0x70,0xf8,0xd3,0x3f,0xbb,0x61,0xb6,0x8d,0x9b,0x0e,0x9c,0x7a,0xed,0xd4,0xf4,0x76,0x1c,0x67,0x22,0x99,0x66,0x66,0x97,0x4e,0x29,0x8e,0x97,0x8c,0x02,0xea,0x78,0x99,0xcd,0xd4,0x6a,0x47,0x40,0x5a,0xc0,0xd8,0x9f,0xd6,0xa4,0xd6,0x67,0x18,0xa4,0x50,0x24,0x38,0xad,0x45,0x46,0x32,0x60,0x97,0x68,0x41, + 0x04,0xde,0xb8,0x5f,0x60,0x4b,0xe1,0x93,0x0d,0xba,0xc6,0x62,0x9c,0xb9,0x62,0x10,0xf6,0xfb,0xc8,0x7c,0xe2,0xb2,0x60,0xb6,0x6c,0xc7,0xd6,0x61,0x86,0x18,0x06,0xaf,0xe1,0x12,0x0b,0xbc,0xf8,0x35,0x6d,0xcf,0xbf,0x1d,0xe4,0xbb,0xb7,0xd2,0x06,0x6c,0x3d,0xdd,0xfb,0xaf,0x33,0x0a,0xf7,0x54,0xc5,0x78,0x59,0x13,0x7a,0x9c,0xc4,0xa6,0x8e, + 0x04,0x27,0x89,0x9f,0xe2,0x48,0x11,0xad,0xc8,0x69,0xd4,0x9a,0xc4,0x51,0xcb,0x21,0x06,0x31,0xd1,0x9a,0xff,0x89,0x71,0xac,0x7c,0x3d,0xd2,0xfe,0x82,0x62,0x62,0x50,0x7f,0xd9,0xdd,0xff,0xef,0x4c,0xc9,0xcd,0x81,0xbd,0xd3,0xea,0xb8,0xac,0xdd,0x5c,0x28,0x7a,0x89,0x34,0xf8,0x2d,0xfc,0x25,0x5d,0xde,0xd1,0xac,0x1f,0x11,0x00,0xaa,0x17, + 0x04,0x43,0x01,0xf5,0x4b,0x35,0x92,0xd1,0xea,0x2a,0x40,0x98,0x9c,0x94,0x26,0x1d,0x2b,0x1d,0x1f,0xe2,0x97,0xed,0x6e,0xd6,0x41,0x25,0xee,0x24,0x1d,0xe0,0x5d,0x00,0x4b,0xc7,0x90,0x14,0xf1,0x56,0xe9,0xb7,0xbf,0xb3,0x6b,0x8a,0xd2,0xd6,0x6d,0x55,0xf3,0xa7,0x53,0x82,0x9a,0x9d,0xdb,0x86,0x05,0x5b,0xb9,0x16,0x6d,0xd3,0xaf,0xf4,0x57, + 0x04,0x36,0xb0,0xf6,0x6b,0xf5,0xf9,0xfd,0x4b,0x2d,0xf9,0xcd,0xae,0x2a,0xf8,0x73,0xa0,0x75,0xc5,0x54,0x97,0xd7,0xfe,0xc4,0x73,0x7a,0x7c,0x96,0x43,0xc2,0xc7,0x6f,0xe5,0xda,0x9f,0x72,0x87,0xb3,0xcd,0x4e,0x5f,0x05,0xb9,0xa1,0xa4,0xf6,0x4e,0x8a,0x8d,0x96,0xc3,0x16,0xe4,0x52,0x59,0x4d,0x02,0xa4,0x59,0x2a,0x21,0x07,0xec,0xe9,0x0b, + 0x04,0x82,0xab,0xb5,0x8a,0xfb,0x62,0xd2,0x61,0x87,0x8b,0xde,0xe1,0x26,0x64,0xdf,0x14,0x99,0xb8,0x24,0xf1,0xd6,0x0f,0xb0,0x28,0x11,0x64,0x2c,0xb0,0x2f,0x4a,0xff,0x5d,0x30,0x71,0x98,0x35,0xd9,0x6f,0x32,0xdc,0x03,0xc4,0x9d,0x81,0x5f,0xfa,0x21,0x28,0x57,0x33,0x13,0x7f,0x50,0x7c,0xe3,0x16,0xce,0xc6,0x5c,0xa5,0x62,0xce,0x2a,0xd0, + 0x04,0x7d,0xe7,0xb7,0xcf,0x5c,0x5f,0xf4,0x24,0x0d,0xaf,0x31,0xa5,0x0a,0xc6,0xcf,0x6b,0x16,0x9a,0xad,0x07,0xd2,0xc5,0x93,0x6c,0x73,0xb8,0x3e,0xe3,0x98,0x7e,0x22,0xa1,0x94,0x0c,0x1b,0xd7,0x8e,0x4b,0xe6,0x69,0x25,0x85,0xc9,0x9d,0xc9,0x2b,0x47,0x67,0x1e,0x2c,0xcb,0xcf,0x12,0xa9,0xa9,0x85,0x4c,0x66,0x07,0xf9,0x82,0x13,0xc1,0x08, + 0x04,0x06,0xfa,0x93,0x52,0x72,0x94,0xc8,0x53,0x3a,0xa4,0x01,0xce,0x4e,0x6c,0x8a,0xeb,0x05,0xa6,0x92,0x1b,0xc4,0x87,0x98,0xa8,0xe2,0x0a,0x0f,0x84,0xa5,0x08,0x5a,0xf4,0xec,0x48,0x28,0xf8,0x39,0x4d,0x22,0xde,0x43,0x04,0x31,0x17,0xb8,0x59,0x5f,0xb1,0x13,0x24,0x5f,0x72,0x85,0xcb,0x35,0x43,0x93,0x89,0xe8,0x54,0x7a,0x10,0x50,0x39, + 0x04,0x8a,0x4f,0x62,0x52,0x10,0xb4,0x48,0xdc,0x84,0x6a,0xd2,0x39,0x9b,0x31,0xcd,0x1b,0xc3,0xf1,0x78,0x8c,0x7b,0xed,0x69,0xcc,0x1c,0xb7,0xaa,0xc8,0xab,0x28,0xd5,0x39,0x30,0x07,0xc6,0xf1,0x1f,0x3e,0x24,0x8d,0xe6,0x51,0xc6,0x62,0x2d,0xe3,0x08,0xee,0x55,0x76,0xbe,0x84,0xef,0x1e,0xd8,0xed,0x91,0xfd,0x24,0x4f,0x14,0xfc,0x20,0x53, + 0x04,0x88,0x5e,0x45,0x2c,0xbb,0x0e,0x4b,0x2a,0x97,0x68,0xb7,0x59,0x6c,0x15,0x31,0x98,0xa9,0x22,0xda,0xbb,0xb8,0xd0,0xca,0x1d,0xc3,0xfa,0xf4,0xf0,0x97,0xf0,0x91,0x13,0xbe,0x9a,0xaa,0x63,0x09,0x18,0xd5,0x05,0x60,0x53,0xec,0xf7,0x38,0x8f,0x44,0x8b,0x91,0x2d,0x9c,0xcf,0xbe,0xd8,0x0d,0x7c,0xa2,0x3c,0x0e,0x79,0x91,0xa3,0x49,0x01, + 0x04,0xe2,0x26,0xdf,0x1f,0xcf,0x7c,0x13,0x7a,0x41,0xc9,0x20,0xff,0x74,0xd6,0x20,0x4f,0xaa,0x20,0x93,0xee,0xff,0xc4,0xa9,0xee,0x0a,0x23,0xfb,0x2e,0x99,0x40,0x41,0xc3,0x45,0x71,0x07,0x44,0x2c,0xc4,0xb3,0xaf,0x63,0x1c,0x4d,0xfb,0x5f,0x53,0xe2,0xc5,0x60,0x8b,0xed,0x04,0xff,0x66,0x53,0xb7,0x71,0xf7,0xcd,0x46,0x70,0xf8,0x10,0x34, + 0x04,0xf5,0x3e,0xad,0x95,0x75,0xee,0xbb,0xa3,0xb0,0xeb,0x0d,0x03,0x3a,0xcb,0x7e,0x99,0x38,0x8e,0x85,0x90,0xb4,0xad,0x2d,0xb5,0xea,0x4f,0x6b,0xd9,0xbd,0xe1,0x69,0x95,0xb5,0xf3,0xab,0x15,0xf9,0x73,0xca,0x9e,0x3a,0xa9,0xdf,0xe2,0x91,0x4e,0xeb,0xbd,0x2e,0x11,0x01,0x0b,0x45,0x55,0x13,0x90,0x79,0x08,0x80,0x03,0x96,0xfb,0x9d,0x1a, + 0x04,0x88,0x27,0x73,0xec,0x7e,0x10,0x60,0x5c,0x8f,0x9e,0x2e,0x3b,0x87,0x00,0x94,0x3b,0xe2,0x6b,0xcc,0x4c,0x9d,0x1f,0xed,0xf2,0xbd,0xcf,0xb3,0x69,0x94,0xf2,0x3c,0x7f,0x8e,0x5d,0x05,0xb2,0xfd,0xd2,0x95,0x4b,0x61,0x88,0x73,0x6e,0xbe,0x3f,0x56,0x46,0x60,0x2a,0x58,0xd9,0x78,0xb7,0x16,0xb5,0x30,0x4e,0xa5,0x67,0x77,0x69,0x1d,0xb3, + 0x04,0xa6,0x0b,0x64,0x58,0x25,0x6b,0x38,0xd4,0x64,0x44,0x51,0xb4,0x90,0xbd,0x35,0x7f,0xea,0xde,0x7b,0xb6,0xb8,0x45,0x3c,0x1f,0xc8,0x97,0x94,0xd5,0xa4,0x5f,0x76,0x8d,0x81,0xee,0xe9,0x05,0x48,0xa5,0x9e,0x5d,0x2c,0xec,0xd7,0x2d,0x4b,0x0b,0x5e,0x65,0x74,0xd6,0x5a,0x9d,0x83,0x7c,0x7c,0x59,0x0d,0x1d,0x12,0x5e,0xe3,0x7c,0x4d,0x51, + 0x04,0x52,0xd9,0xa4,0x4b,0xf0,0xbc,0x72,0x9e,0x5f,0x3f,0xfc,0x8a,0x73,0xa4,0xda,0x33,0x2e,0x29,0x62,0xb2,0x20,0x13,0x39,0x1b,0x60,0xeb,0x66,0xde,0x6e,0x1b,0x83,0x43,0x1e,0xb0,0xd9,0xc6,0xe9,0x2a,0x42,0x4b,0xc2,0x4a,0xb2,0x3c,0xaf,0x99,0xe3,0xcd,0xa8,0x30,0x26,0x36,0x89,0x65,0x36,0x26,0xf8,0xbe,0x91,0x59,0x0f,0xb7,0x5c,0xbd, + 0x04,0x78,0xa9,0x9d,0xfc,0xb7,0xdf,0x4d,0x92,0x77,0xf9,0x7b,0x5e,0x24,0xe9,0x79,0xf4,0x8a,0x8a,0xa8,0x98,0x3e,0xf9,0xdd,0x86,0x76,0x5d,0xcc,0xc3,0x3d,0x8a,0xde,0x9f,0x98,0x57,0xdc,0xcc,0xe2,0xa7,0xff,0x0a,0xc4,0x1b,0x25,0x5e,0xb8,0xdf,0x45,0xdf,0x61,0xb4,0xdb,0x58,0xfb,0x5e,0x99,0x76,0x14,0xbf,0x0d,0x5a,0xb2,0x17,0xdd,0x90, + 0x04,0x11,0x62,0x42,0x4a,0xa9,0xfa,0x0d,0x42,0xbf,0x60,0xe0,0x6a,0x16,0xb7,0xe7,0xea,0x45,0xac,0x0e,0x2f,0x07,0xf1,0xe3,0x67,0x35,0xbd,0x0d,0x98,0xc7,0x0b,0x88,0x50,0x69,0x3f,0x2a,0xc1,0x28,0xf4,0x7f,0x21,0x33,0x22,0xc5,0xf8,0x87,0x2d,0xde,0x92,0x61,0xaf,0xfe,0x61,0x4e,0x3f,0x36,0x4a,0x79,0x2d,0x17,0xb0,0xe8,0x42,0x18,0x40, + 0x04,0x30,0xd2,0xd4,0x2a,0x85,0x38,0x5b,0x64,0x81,0x7d,0x09,0x00,0xbc,0x8c,0x98,0x47,0x16,0x93,0x45,0x29,0x05,0x6d,0xa0,0x32,0xd5,0xfd,0xe8,0x44,0x91,0x5d,0x66,0x9b,0x0e,0x5e,0xf4,0x0d,0x56,0x6f,0x5b,0x23,0x99,0x21,0x32,0xc4,0xae,0x58,0x80,0x17,0xeb,0xd1,0x60,0xe5,0xdb,0xf4,0x80,0x4f,0x93,0x6c,0xb0,0xf2,0x57,0xa9,0x34,0x46, + 0x04,0xa7,0x7a,0x25,0x9a,0x55,0xed,0x98,0xd6,0x43,0xe1,0xa3,0xe1,0x38,0x04,0xc9,0x5e,0x54,0x3c,0x15,0x57,0xe6,0x14,0x1e,0x4e,0xd4,0x7d,0xcf,0x13,0xb9,0x41,0xa6,0xfa,0x8b,0xfa,0x5f,0x87,0x9a,0xb1,0x4a,0xeb,0xa7,0xb2,0xac,0x06,0xe5,0xa7,0x19,0xc8,0x6f,0x4a,0x2e,0xd3,0x91,0x16,0x03,0x80,0xaa,0x3b,0x6f,0x74,0x14,0x1c,0xd3,0x54, + 0x04,0xf8,0x94,0x54,0x59,0x3d,0xba,0x57,0x20,0x16,0x4d,0x17,0xbc,0x1c,0xa3,0x2f,0x10,0xdd,0xd1,0xa7,0xd3,0x7b,0x7b,0xf0,0x2e,0x5e,0xc0,0xd5,0x97,0x94,0xf4,0xd6,0x3d,0x34,0x26,0x8d,0xe3,0xf6,0xa2,0xc1,0x08,0x51,0x4a,0x52,0x70,0x2f,0x7e,0x67,0xd2,0x78,0x29,0xfa,0x03,0x40,0xb3,0xc4,0x71,0x06,0x51,0x29,0x14,0x83,0xc8,0xb2,0x13, + 0x04,0xb0,0x0b,0xef,0xcb,0x86,0x8e,0xeb,0x5d,0x55,0x8e,0xf2,0xec,0x2e,0xc6,0x79,0xdc,0x08,0x2e,0xc1,0x5a,0x57,0xc5,0x89,0x93,0x11,0x17,0x84,0x24,0x67,0x4b,0x8f,0x50,0x58,0x87,0x42,0x72,0x8a,0x63,0x84,0xa1,0x80,0x50,0x6b,0x87,0x39,0xa7,0x9c,0x4c,0xe9,0x5e,0x10,0x55,0xc0,0xd0,0xea,0xb2,0x25,0x4c,0xa5,0x5b,0x18,0xa3,0xe7,0xb2, + 0x04,0xb3,0xe2,0xf9,0xc7,0xf9,0xf0,0x68,0xc5,0xda,0x88,0x82,0xfd,0x58,0x1e,0x71,0x12,0xe5,0x38,0xaa,0x01,0xfe,0xb5,0xf0,0x17,0x43,0x3c,0x00,0xfc,0x8a,0x82,0x8f,0xcc,0xc5,0x6a,0x3f,0x69,0x2e,0x3b,0x23,0x7b,0x7c,0xaf,0x49,0x86,0x90,0x09,0xe6,0x74,0x3e,0x35,0xec,0x5a,0xed,0x19,0xd8,0x14,0xcf,0xc1,0x38,0x69,0xf7,0x8e,0xb8,0x95, + 0x04,0xe5,0xda,0xe9,0x77,0x9e,0x0c,0x16,0x8e,0x60,0xb8,0x42,0x50,0x8e,0x25,0x3d,0x2a,0xc8,0x0e,0x7e,0x50,0x4d,0xae,0xd9,0xfa,0xc0,0x77,0xb9,0xb4,0x49,0xc3,0x68,0xb5,0x7b,0xd8,0x66,0x1b,0xbb,0xcc,0xef,0x47,0x8f,0x05,0x0f,0x4f,0xfe,0xc8,0xaa,0x47,0xed,0x7f,0x98,0xe8,0x95,0x14,0xd9,0x08,0x3f,0xac,0xf0,0xa7,0xf2,0xf7,0xb7,0x0f, + 0x04,0x42,0x0e,0x10,0xbb,0x81,0xb3,0x79,0xd7,0x28,0x87,0x9f,0xe6,0x00,0xe6,0xf1,0xbf,0x2b,0x85,0xd8,0x02,0x38,0x48,0xa0,0x40,0xc7,0x65,0x4a,0x97,0x34,0xda,0x1a,0xc4,0xcb,0xee,0x56,0x15,0x71,0xa6,0x16,0xb0,0x94,0xa3,0x84,0x36,0xe0,0x2c,0x6d,0x7b,0x54,0xb4,0x27,0x9a,0x23,0x41,0x93,0xa8,0x28,0xe8,0x6e,0x21,0xe6,0xb7,0x1d,0x16, + 0x04,0x8d,0xbf,0x1b,0xa8,0x75,0x97,0x00,0x4a,0xf5,0x52,0x31,0x72,0x25,0x91,0x6a,0xbf,0x3d,0x71,0xdf,0xf9,0x0f,0xe9,0xe6,0x1f,0x9d,0x28,0x63,0xa6,0xde,0x21,0x8d,0x4a,0x08,0x97,0xe3,0x34,0x00,0x01,0x39,0xb0,0x84,0x9d,0x77,0x27,0x57,0xb1,0x50,0xe5,0xd8,0x6b,0x55,0xd7,0xa0,0x0a,0x74,0x4b,0xcc,0xbb,0x7c,0xb8,0xd1,0xa6,0xb0,0x7b, + 0x04,0x1a,0xcc,0xb8,0x5b,0x61,0x2d,0x32,0xd5,0x84,0x59,0xca,0xec,0x0b,0xb6,0x76,0x8f,0x05,0xce,0x80,0x94,0xe3,0x86,0x24,0x22,0xa7,0xc1,0x23,0x40,0xdd,0x31,0xbd,0x73,0x97,0xe0,0x37,0x7d,0x33,0xcc,0xdc,0xe8,0xbd,0x87,0x2f,0x89,0x8b,0xe6,0xcb,0xcf,0x72,0x74,0xb3,0xbe,0xef,0xb5,0xdd,0x7c,0xad,0xdd,0xf0,0x27,0xd0,0xc0,0x2c,0x2e, + 0x04,0x14,0xee,0xf4,0x1b,0x67,0xc1,0x7b,0x1d,0x4a,0x04,0x05,0x54,0x28,0x7c,0xd6,0xa9,0xe6,0xb3,0x08,0x03,0x35,0xea,0x4e,0x16,0x82,0x1d,0xbd,0x64,0x3e,0xc6,0x7d,0xba,0x6d,0x67,0xca,0xdc,0xbd,0x1a,0x3f,0x02,0x27,0xb7,0xca,0xf2,0xc0,0x60,0x4d,0x2b,0x35,0x07,0xae,0xb9,0x6e,0xd9,0x8c,0x32,0xe2,0x35,0x0f,0xe2,0x95,0xed,0x89,0x98, + 0x04,0xa9,0x9a,0xf5,0xde,0xc3,0xc9,0x95,0x08,0x0d,0xdc,0xc1,0x5d,0x79,0x94,0xda,0xff,0x26,0x6a,0xa5,0x3f,0x18,0x1f,0xba,0x4b,0xcd,0xd5,0x04,0xd2,0x06,0xbf,0xca,0x2f,0x37,0x39,0x58,0x8f,0x07,0x1e,0x41,0x92,0xb6,0x15,0x36,0x1e,0xc8,0x17,0x35,0xfe,0x2e,0xf2,0x92,0x3c,0x40,0x56,0xc4,0x32,0xf4,0xc2,0x78,0x2e,0x5d,0x72,0x22,0x15, + 0x04,0xa3,0x55,0xd8,0xd1,0x7d,0x50,0xf6,0x42,0x8e,0x0a,0xf3,0x45,0x92,0x16,0x62,0x58,0x7e,0x2b,0x62,0x49,0xee,0xd1,0xe3,0x26,0xab,0xb7,0xc8,0x60,0x50,0x36,0xb1,0xdb,0x1f,0xd7,0x2e,0xfa,0xca,0x90,0x82,0xbb,0x6f,0xab,0x44,0x35,0x9f,0xa7,0xf6,0xef,0x8a,0x45,0xd0,0x36,0x85,0x28,0x32,0xe2,0xad,0xe9,0xd4,0x1f,0x28,0x21,0x91,0x44, + 0x04,0xfa,0x53,0xe5,0xb5,0x8d,0x55,0xeb,0xf5,0x17,0xd8,0xdb,0x07,0xb0,0x21,0xd8,0x09,0x18,0xd1,0xf2,0x60,0xf9,0xe0,0xb3,0xd0,0x0b,0xd4,0x7b,0x24,0xa9,0x1a,0xe6,0xab,0x85,0xab,0x2a,0xdc,0xc3,0x1b,0x98,0xca,0xae,0xc2,0x68,0x1a,0x84,0x1d,0x50,0xbc,0x0e,0xda,0x87,0x55,0x61,0xfa,0xb7,0x0c,0x97,0x94,0x63,0xff,0xb6,0xa1,0xd7,0x4c, + 0x04,0x33,0xfe,0x37,0x94,0x93,0x75,0xde,0xbd,0x97,0x34,0xf5,0x4b,0x70,0x36,0xb7,0xa9,0x78,0xbc,0x8f,0xc4,0xae,0x3f,0xe9,0x27,0xa5,0x21,0xf9,0x40,0xd9,0xe3,0x5d,0xd3,0x8f,0x81,0xa9,0x16,0x0c,0x05,0xdf,0x04,0xe3,0x42,0x90,0xdb,0x40,0xc3,0xe0,0x45,0xb8,0x32,0x37,0x39,0x41,0xca,0x85,0xb4,0x33,0x85,0x4e,0x43,0xca,0xed,0x32,0x3d, + 0x04,0xb9,0xba,0x84,0x45,0x06,0x7d,0x0e,0x81,0xbd,0x32,0xdd,0x99,0xe6,0xb4,0xea,0x3d,0x44,0x2d,0x06,0x3a,0x8e,0xb9,0x87,0x35,0x18,0xee,0x3b,0xb1,0x8c,0x05,0x37,0x06,0x09,0x99,0x64,0xb6,0x88,0x91,0x05,0x78,0x4d,0x9d,0x6d,0x9d,0x9a,0xa7,0x9c,0x76,0xb6,0xa3,0xd3,0x37,0x63,0x15,0x95,0x3a,0xfd,0xcb,0x5a,0x74,0x39,0xe7,0xc7,0x06, + 0x04,0x78,0xb2,0x48,0x63,0x42,0x70,0xa7,0xa6,0x64,0x0b,0xd0,0xc6,0x45,0x95,0xdc,0x4e,0x98,0xad,0xfe,0x6b,0xdb,0x81,0x12,0x59,0x3a,0x41,0x73,0xe3,0x6d,0x4a,0x9b,0x49,0x69,0xa1,0xf3,0xd1,0x9b,0x32,0x58,0x98,0xe3,0x64,0x59,0xc4,0x1e,0xba,0x1d,0xe9,0x92,0x29,0xb0,0xba,0x2c,0xf1,0x33,0x74,0x61,0xc8,0x43,0x91,0xd9,0xae,0xa1,0xfc, + 0x04,0xc7,0x88,0x88,0x4a,0xc8,0x68,0x59,0x3d,0xb2,0x41,0xf5,0xb3,0xea,0x70,0x13,0x81,0x0d,0x3c,0xe2,0x8a,0x02,0x68,0x0a,0x96,0xff,0x35,0x7b,0x26,0x1f,0xad,0x61,0x1b,0xef,0x35,0x3b,0x0e,0x82,0xc1,0xc6,0x8c,0x47,0x1f,0xf1,0xed,0x5c,0x47,0x49,0xe1,0x68,0xe7,0xaf,0x85,0x91,0xa5,0xe6,0xda,0xb5,0x99,0xb9,0x66,0x20,0xde,0x0e,0xde, + 0x04,0x18,0x64,0xe3,0x73,0xac,0x60,0xc2,0x35,0x43,0xfe,0xa9,0xe1,0xf2,0x37,0x95,0x0a,0x81,0x69,0xe0,0x7c,0x81,0x7d,0xb6,0x9d,0x50,0x0e,0x55,0x92,0xd1,0xdf,0x9d,0x5a,0x10,0xda,0x46,0x51,0xef,0xcc,0xc4,0x6d,0x37,0xe7,0xea,0xe1,0x6c,0x36,0xac,0x86,0xa9,0xa8,0x6b,0x88,0xad,0x08,0x75,0x1a,0x8d,0xcd,0x15,0x06,0x00,0x19,0x70,0x4b, + 0x04,0xdd,0x73,0x08,0xd2,0xa6,0x75,0x7f,0x92,0x4d,0xc9,0x79,0x06,0x6e,0x75,0xee,0x6f,0xa5,0x2b,0x03,0x39,0x3d,0x28,0x92,0xf5,0x97,0x88,0xef,0xfa,0x55,0x3b,0x69,0x0d,0x1f,0xef,0x00,0xc1,0xc2,0x2b,0xa8,0x0b,0x95,0xd5,0x29,0x78,0x2d,0xbe,0xf5,0x5a,0x63,0x04,0x61,0x79,0xfb,0x4e,0xf0,0x0f,0xdc,0xcf,0x5b,0x62,0xce,0x55,0xc1,0x36, + 0x04,0x57,0x5d,0x51,0xbe,0x2b,0xdd,0xf5,0xbf,0x1a,0xb4,0x24,0x31,0xba,0x7e,0x3b,0x5f,0x29,0x47,0xbc,0x57,0x4d,0xf9,0xf6,0x0a,0x44,0x8b,0x8d,0xb5,0xca,0x28,0xc9,0x2c,0xd8,0x36,0xf5,0x5c,0x55,0x64,0x40,0xa7,0xdf,0x12,0x5d,0xe6,0x59,0x9b,0x21,0xae,0x68,0xf1,0x5d,0x5b,0x9f,0x42,0x2d,0x6e,0xec,0x88,0xab,0x2f,0x65,0x40,0x6b,0xf9, + 0x04,0xc7,0x42,0x2a,0x80,0xae,0xbd,0xb5,0x18,0xbd,0x2d,0xab,0xa6,0x91,0xd3,0x9a,0x25,0xea,0x2f,0xe4,0x9a,0x35,0xcd,0xfb,0x2a,0x0f,0x94,0xbd,0xfb,0xad,0xc6,0x62,0x9a,0xe5,0x5a,0xc7,0xc4,0x00,0xaf,0xd2,0x97,0x6b,0x7c,0x3b,0x24,0xf7,0x12,0x68,0x07,0xa5,0xa0,0xaf,0xb9,0x31,0xcf,0xa5,0xc6,0xad,0xa1,0xf4,0xff,0x98,0x4e,0xa5,0xa7, + 0x04,0xad,0x40,0x62,0x21,0x6f,0x84,0xff,0xd6,0x6e,0x32,0x64,0x97,0xbc,0xbc,0xab,0x98,0x22,0x83,0x49,0x33,0x92,0xec,0x0f,0x73,0x9c,0xef,0x8c,0xd7,0xea,0xf3,0x45,0x34,0x14,0xc5,0xa2,0x89,0xa8,0x46,0xe2,0x8b,0xf2,0x04,0x2e,0xa5,0xdc,0x7b,0x15,0xe2,0x52,0xf4,0x8d,0x3c,0xf9,0x80,0xe7,0xc4,0x75,0x1c,0xc3,0x54,0x93,0xa1,0xc3,0x28, + 0x04,0xcc,0xac,0xd1,0xbf,0x7c,0x7f,0x4e,0xa9,0xc7,0xe5,0x9b,0xd8,0x02,0x80,0x4a,0x9d,0x33,0x52,0x62,0x71,0x6a,0xc2,0x88,0xc6,0xee,0xfd,0x7a,0x71,0x35,0x34,0x9a,0x4f,0x7b,0x86,0x12,0xe2,0xbd,0xbd,0x43,0xb3,0xfc,0x4f,0xa6,0x94,0x1a,0xc1,0x5a,0x8f,0x37,0xe3,0x4f,0xe7,0x81,0x0a,0x0c,0x0d,0x43,0xc0,0x5a,0xfa,0xfb,0x64,0x80,0xef, + 0x04,0x9a,0xa7,0xf1,0xf9,0x34,0x74,0xfa,0x37,0x0c,0x4d,0xf3,0x80,0x5b,0xd2,0x83,0x93,0x28,0x89,0x58,0x80,0xdc,0xe1,0x97,0xa0,0x6c,0xf9,0x05,0x2e,0x6a,0xb7,0xa6,0x93,0x8c,0x9a,0x20,0x8b,0x33,0x5b,0xfd,0xa6,0xb0,0x13,0x21,0xf0,0x29,0xa0,0xd8,0x3c,0x8b,0xb9,0x65,0x61,0x20,0x84,0x81,0xf7,0xaf,0x6c,0x6c,0xf1,0xd2,0x65,0x78,0x43, + 0x04,0x83,0xb7,0xaf,0xfc,0xec,0x11,0x68,0x5d,0x15,0x61,0x4e,0x2d,0x53,0xc1,0xe7,0x35,0x04,0xe3,0xd9,0x83,0x44,0xbb,0xd5,0xfc,0x0a,0xd8,0x6d,0xc4,0xc3,0x67,0x04,0x32,0x3a,0x7f,0x73,0xa0,0x95,0x33,0xd1,0xa1,0x07,0x6a,0xa9,0xc4,0xaf,0x22,0xa6,0xba,0xb9,0x2f,0x3f,0x0d,0x76,0x67,0x98,0xdb,0x7a,0xa4,0x18,0x3c,0x03,0x7f,0x86,0xe6, + 0x04,0xae,0xeb,0xdd,0x97,0x1c,0xf4,0xe9,0x88,0xfa,0xbd,0x80,0x70,0xc7,0x5c,0x64,0xaa,0xb9,0x0a,0x83,0xa3,0x67,0x35,0xfe,0xcf,0xb3,0x85,0x60,0x59,0x79,0xc0,0x08,0xae,0x8c,0x39,0x88,0x8f,0x0d,0xaf,0x74,0xf9,0x8c,0xeb,0xbb,0x08,0xf6,0xb9,0x1a,0x51,0x93,0xf6,0x84,0xa5,0x67,0x61,0xb9,0xf2,0xb6,0x3d,0x87,0xd3,0xf6,0x04,0x91,0xed, + 0x04,0xe3,0x8e,0xec,0x4c,0x1a,0x4d,0x81,0xa5,0xd9,0x94,0xb0,0xd7,0x78,0x03,0x05,0xaf,0x65,0x18,0x92,0xcb,0xf0,0x7f,0x3a,0x07,0x62,0x8f,0x4e,0x24,0x73,0xa8,0xab,0x75,0x4b,0xda,0x96,0x62,0x24,0x62,0x88,0x0d,0x35,0x36,0xd3,0x90,0x13,0x2a,0x85,0xdb,0x61,0x47,0xf8,0x14,0xc6,0x2e,0xfb,0x58,0x0a,0x6f,0x52,0x95,0x98,0xb0,0xdd,0x1e, + 0x04,0x10,0xf0,0x2d,0x49,0x6e,0x9a,0x87,0x58,0xc8,0x31,0x38,0x98,0x92,0xa4,0x5e,0xd0,0x09,0x28,0x2e,0xa1,0xeb,0x20,0x1a,0xb8,0xca,0xf0,0x9e,0x6f,0x2d,0xe9,0xfa,0x4a,0xcc,0x12,0x6b,0xec,0xc2,0x04,0xc4,0x1a,0x94,0xaf,0xf4,0xf2,0xea,0xd7,0x55,0x2e,0xc2,0x3f,0xc6,0x8f,0x00,0x05,0x14,0x76,0x25,0xa9,0x56,0x22,0xb5,0x21,0x09,0x0d, + 0x04,0x4c,0x85,0x9a,0xff,0x34,0x2c,0x56,0xa9,0x50,0x8b,0x85,0x9a,0xb1,0x50,0x9e,0xdc,0xab,0xf6,0x6e,0x04,0x4e,0x20,0x26,0xcc,0x29,0x34,0x74,0x38,0x9b,0x3d,0x58,0xc1,0x6b,0xc0,0x6c,0xf9,0x9d,0xd6,0xd8,0x24,0x9c,0x5d,0x24,0x38,0x6a,0x55,0xa9,0x72,0x14,0xea,0x0c,0xda,0x27,0x0a,0xd9,0x47,0x09,0x86,0xc3,0xa3,0xd0,0x23,0xcb,0x07, + 0x04,0xd1,0xeb,0x4f,0x7c,0x68,0x0a,0x24,0x7a,0x14,0xf3,0xd6,0x7f,0x85,0xcd,0xb1,0xc4,0xc6,0xf1,0x3d,0x44,0x82,0x1f,0xc4,0x56,0xc9,0x24,0x7a,0x60,0x66,0x22,0xaf,0xec,0x49,0x52,0xcf,0x05,0xff,0x06,0xf0,0x6d,0x70,0x30,0xe8,0x89,0x04,0x73,0x70,0x96,0xcb,0xf8,0xdd,0x90,0xe4,0x78,0xa3,0xb5,0xdf,0xed,0x2e,0xe4,0x87,0xa0,0x83,0x5c, + 0x04,0x3b,0xf7,0x9d,0x6c,0x1a,0x20,0xd8,0x51,0x15,0xe9,0x73,0x07,0x97,0x07,0xf5,0x13,0x1e,0xed,0x2f,0x83,0xbe,0x56,0x83,0xc3,0x4d,0x0f,0xb3,0xee,0xe1,0xae,0x40,0xdf,0xd2,0xea,0x4f,0x1b,0x73,0x5c,0xf6,0x23,0x41,0x83,0x5a,0x57,0x21,0xc2,0x5d,0xaa,0x0d,0xc1,0xa3,0x88,0x6a,0xb7,0x5e,0xf6,0x53,0xf4,0x72,0xd8,0xf3,0xaa,0x1e,0x97, + 0x04,0xb1,0xf8,0x08,0x28,0x6a,0x42,0xee,0xee,0x85,0xd5,0x85,0xe5,0x4d,0xc2,0x8a,0xba,0x2a,0xeb,0xfb,0x95,0x68,0x05,0xf5,0xc0,0x11,0x27,0xbc,0xdf,0x43,0x51,0x54,0xcb,0x5b,0x17,0x8f,0xda,0x58,0x96,0xd9,0xe7,0x50,0x86,0x61,0xfe,0xe7,0xee,0x55,0xfa,0x96,0x23,0x61,0x0b,0x3d,0x9f,0x4a,0x59,0x15,0x6b,0x76,0xd8,0x87,0x7b,0x4e,0xf1, + 0x04,0xa2,0x1e,0x80,0xd0,0x9e,0x11,0xac,0xbc,0xcb,0xc9,0x09,0xde,0x6c,0x9f,0x11,0x59,0xad,0xdb,0xb5,0xdd,0x47,0x72,0x11,0xb9,0x0a,0x37,0x0f,0x8c,0x75,0x48,0xe6,0x0d,0x1d,0x7a,0xac,0xb6,0xe4,0x55,0xbc,0xdc,0x23,0x03,0x31,0xd7,0x9a,0xd9,0x46,0x4a,0x77,0xb7,0x02,0xc8,0x58,0x40,0x09,0x00,0xcb,0x44,0x88,0xcb,0x6c,0x28,0xbd,0x61, + 0x04,0x50,0x55,0xa8,0xc4,0x5e,0x81,0x38,0x5f,0x41,0x44,0xc7,0xb6,0xfb,0x32,0x11,0x93,0x95,0xa9,0x4d,0xbd,0x07,0x66,0x5e,0xd7,0xbc,0x1c,0xce,0x1e,0x62,0xdc,0x47,0xc8,0xb6,0xd5,0x0a,0x39,0xa5,0x5d,0x3b,0x8e,0x99,0x66,0x24,0xfb,0x6e,0xc2,0xf2,0x96,0x0c,0x7c,0x2b,0xc0,0xbc,0x94,0xb2,0xa6,0x3d,0x65,0x09,0x6f,0xd9,0x9c,0xa4,0x1a, + 0x04,0xaf,0x52,0x2f,0xc0,0xa6,0x14,0x40,0x17,0x39,0x45,0xb9,0x14,0xd6,0x40,0x4b,0x19,0x40,0xb5,0x47,0xa6,0xf7,0x68,0x55,0x02,0x80,0xfe,0x28,0xbd,0x33,0x1c,0x9c,0x66,0x1d,0x28,0x24,0x29,0xf2,0x91,0x12,0x98,0xf9,0xc5,0xb8,0x2f,0x87,0xc7,0xf5,0x04,0x47,0x06,0x74,0x8c,0x19,0x03,0x56,0x89,0xb2,0x16,0xd6,0x44,0x74,0xbf,0x5a,0xd0, + 0x04,0xec,0x1a,0x88,0x65,0x2d,0xe7,0x14,0xd2,0x1f,0xdd,0xb5,0x4d,0xb4,0xa3,0x42,0x35,0x21,0xae,0xad,0x58,0x28,0xb8,0x43,0xbd,0xde,0x9a,0x42,0xcf,0x4a,0x8b,0xf1,0x24,0xa6,0x95,0x68,0xc6,0x64,0xe2,0xd9,0x31,0x7a,0xc7,0x32,0xc9,0x8c,0x43,0x55,0x48,0xdc,0xec,0x0e,0xeb,0x8a,0xb3,0x10,0x27,0xee,0x5f,0x16,0x93,0xcc,0xd9,0x7c,0x68, + 0x04,0x48,0xe4,0xc9,0xcc,0x88,0xa6,0x01,0xeb,0x63,0x9f,0x81,0xff,0xa6,0x79,0x54,0x0b,0xf1,0xd7,0xbc,0xbe,0x87,0x6a,0x95,0x5e,0x73,0xbf,0xad,0xe0,0x55,0x38,0x41,0x60,0xba,0xe1,0x30,0x24,0x3e,0xf5,0xfd,0x32,0x8f,0x65,0x27,0x8e,0x00,0xca,0xd6,0x00,0x13,0x27,0xab,0x42,0xfd,0xf3,0xb9,0x65,0x4a,0xad,0x6f,0x26,0x05,0x42,0xb0,0x2b, + 0x04,0xe8,0x61,0x37,0x9f,0x1c,0x1b,0x07,0x54,0x01,0x55,0xbb,0xfe,0xf4,0xa6,0x9a,0x84,0xbe,0x81,0xb1,0x44,0x1d,0x43,0xe7,0x85,0x0c,0x7a,0xc1,0x00,0x5a,0x80,0x42,0x38,0xbb,0x33,0xc7,0x98,0x1d,0x38,0x3a,0x06,0xd1,0xb7,0x95,0x55,0x2a,0x7b,0x31,0xf4,0x91,0x45,0xfb,0xa9,0x37,0x87,0x6f,0xdc,0x9f,0x0d,0x13,0x8a,0xa5,0xb3,0xf3,0x22, + 0x04,0xb4,0x48,0x9c,0xd4,0x99,0x16,0x8b,0xd4,0x8c,0xd2,0xc3,0x11,0x67,0xed,0xad,0x24,0x6c,0x63,0x85,0x9b,0xf8,0xb4,0x83,0x98,0x61,0x7a,0x7a,0x05,0x56,0x34,0x1e,0x3c,0x0b,0x0f,0x66,0xf6,0x65,0x03,0x8b,0xaa,0x29,0xdb,0x8c,0x29,0x6d,0x4f,0x2a,0xe0,0x7b,0x9a,0xb9,0x19,0x3b,0xfc,0x00,0x98,0x1d,0x7d,0xf0,0x59,0x9c,0xe0,0x64,0x8d, + 0x04,0x88,0x4e,0x74,0x88,0x5e,0xa4,0x50,0xf5,0xaa,0xb0,0xcc,0x8f,0x06,0xc0,0x06,0x63,0x0e,0x8b,0x18,0x3a,0x06,0xbd,0xa5,0x09,0x32,0x2f,0xcd,0x97,0xba,0x5d,0x2d,0x2b,0x00,0xe1,0x37,0x3d,0x53,0x3b,0xd5,0x92,0x04,0x27,0xd1,0x06,0xb7,0xf3,0x3e,0xeb,0x53,0xd2,0x1b,0x5c,0xf4,0x6c,0xa0,0x15,0x1e,0x91,0x85,0x9e,0x81,0x1a,0x39,0xcb, + 0x04,0xc5,0x02,0x24,0xa8,0xcf,0x3a,0x19,0xda,0x61,0x33,0xe7,0x46,0xd0,0x02,0x17,0x28,0x5d,0xf8,0x55,0x89,0xed,0x33,0x4b,0x54,0xd9,0x5b,0x00,0x5b,0x8f,0x03,0x3f,0x7d,0xf7,0xbc,0x6a,0x5d,0xdc,0x59,0xd0,0x33,0xf0,0xc6,0x6b,0xed,0x57,0x14,0x9a,0x16,0x0f,0x25,0x72,0x31,0x17,0xa2,0xfc,0xd4,0x13,0xaf,0xf8,0xc9,0xad,0xa4,0x3b,0xf9, + 0x04,0xc6,0x6a,0x91,0x7f,0xc4,0x35,0xc9,0xf4,0x1c,0x47,0x42,0x8e,0x71,0x8a,0x30,0x17,0xb3,0xc5,0xc9,0x92,0xb4,0xd9,0x4a,0x66,0x36,0x02,0xf7,0x3f,0xd8,0x25,0xd0,0x43,0xa0,0x3c,0xb9,0xf5,0x81,0x74,0xcf,0xfb,0x35,0x9e,0x2f,0x54,0x1c,0xfb,0x5e,0x55,0x1c,0x50,0xfd,0x81,0x1b,0x82,0x36,0x2e,0xad,0xb2,0x16,0xa4,0xcf,0xd0,0xf8,0xc3, + 0x04,0xf5,0x5a,0x45,0x1e,0x6e,0x0d,0x8f,0x76,0x00,0xc7,0xbf,0x7c,0x05,0x74,0x1c,0x5e,0x59,0x85,0xb8,0xff,0xe4,0xea,0xb6,0x2d,0x4f,0xfc,0x04,0xae,0xdb,0x72,0x5a,0x66,0xe9,0x42,0xcf,0x48,0x6e,0xfc,0xf3,0xb8,0x54,0x88,0xcf,0x3c,0xd4,0xfb,0x02,0x48,0xb8,0x20,0x70,0x3b,0x93,0x8c,0xe7,0x7a,0x07,0x4a,0x2f,0x92,0x86,0xaf,0x03,0xbf, + 0x04,0xa9,0x6a,0xa2,0x5b,0xee,0x8c,0x8c,0xb6,0xf6,0xaa,0xf4,0x0b,0xe9,0x8c,0xa0,0x47,0xda,0x24,0x5e,0x8d,0x4c,0xae,0x28,0xfc,0x89,0x2a,0x03,0x69,0xb2,0x99,0xcb,0xa3,0xef,0x5f,0x54,0xbb,0x59,0xf4,0xad,0x58,0xa8,0x43,0x32,0xa0,0x0d,0x89,0xa1,0xcf,0x3d,0x56,0xc4,0xe6,0xec,0x9c,0x3a,0x46,0x7a,0x4a,0x2a,0x04,0xad,0x3b,0xce,0x97, + 0x04,0x49,0xf5,0x72,0xfa,0x8c,0xdf,0x67,0x50,0xad,0xab,0xc3,0xab,0x0e,0x46,0xbf,0x23,0xdd,0x7a,0xd7,0x11,0x4b,0xf3,0x19,0xf3,0x5a,0xfa,0x6a,0x2c,0xcb,0xe2,0xe7,0xd3,0x43,0xc4,0x4f,0x01,0x8f,0x8e,0xfc,0x9f,0x52,0x69,0x1b,0x27,0x4a,0x8c,0x89,0x28,0x3d,0x13,0xce,0x93,0xd1,0xb5,0x8a,0xea,0x11,0xd6,0x2c,0x88,0x59,0x9c,0x30,0x9c, + 0x04,0xb3,0x6f,0x6b,0x02,0xbf,0x1d,0x21,0x3d,0x9a,0xbc,0xfc,0x98,0xc2,0x5f,0xc8,0x1a,0xb3,0xb9,0x8c,0xb1,0x3d,0x67,0x8d,0xa8,0x71,0x31,0x0a,0xa0,0x93,0xab,0x7b,0x58,0xa5,0x0b,0x13,0x48,0x18,0x32,0x1a,0x48,0xff,0xc1,0xef,0x9f,0x86,0x24,0xe3,0x71,0xdd,0xf0,0x78,0xd8,0x98,0x3f,0xda,0x6c,0x4e,0xb2,0x7d,0xfb,0x25,0x51,0x74,0xe9, + 0x04,0x74,0xf5,0x7f,0xf3,0xda,0x8d,0x60,0xec,0x0b,0x38,0x2e,0x68,0x66,0xbe,0x45,0x02,0xf6,0x95,0x68,0x83,0x84,0xb4,0x05,0xe2,0x17,0x9a,0xab,0x61,0x06,0x61,0x96,0xd7,0xd2,0x40,0x64,0x18,0x5d,0x68,0xde,0x95,0xbd,0x72,0xb2,0x19,0xc0,0xc0,0xa9,0x38,0x79,0x32,0x4f,0x29,0x9f,0xb1,0x92,0x14,0xb3,0x3a,0x3e,0xd2,0xf1,0xbf,0x48,0x23, + 0x04,0x92,0x4f,0xe3,0x43,0x9d,0x35,0x42,0x7e,0x2a,0xd9,0xb1,0xf6,0xe6,0x78,0x77,0xed,0x34,0x41,0xd7,0x4b,0xdd,0x0e,0xb9,0xf8,0x2a,0xe3,0x60,0x43,0x4b,0xc2,0x06,0x24,0x53,0x7e,0x34,0x00,0x00,0x7c,0xd2,0xd1,0x40,0xf2,0xca,0xa0,0xf7,0xb6,0x1c,0x71,0x18,0xab,0xb9,0xac,0x5c,0x76,0x6e,0xca,0xb3,0xf8,0xf7,0x2e,0xa5,0xd9,0x6c,0xdf, + 0x04,0xfb,0x0e,0x48,0xa3,0x81,0x5a,0x2b,0x80,0xe9,0xe7,0x25,0x03,0x6a,0x23,0x97,0x57,0xe9,0xc5,0x98,0x78,0x50,0xa9,0x41,0xc5,0xf5,0xd2,0xb8,0x9b,0x77,0x6a,0xac,0x68,0x3a,0xdb,0x54,0x81,0xfc,0xd8,0x5f,0x00,0x13,0xfe,0xb2,0x05,0x05,0xeb,0xba,0xff,0x27,0xed,0xf8,0x47,0x4a,0x7c,0xf4,0xd9,0x85,0xec,0x56,0x73,0x65,0xec,0xbc,0x1d, + 0x04,0xe6,0x69,0x91,0x5e,0xe1,0x60,0x69,0x4e,0x85,0x59,0xd7,0x96,0x5f,0x7c,0xff,0x94,0x5c,0x1c,0xb0,0x76,0xf1,0x94,0xec,0x98,0x94,0xb1,0xa3,0x8b,0x10,0x72,0x6f,0xb0,0x38,0x96,0x75,0xe3,0x15,0x5b,0x06,0x9b,0x38,0x62,0xda,0x3d,0x11,0x12,0x17,0x9a,0x04,0xac,0xcb,0xe7,0xdb,0xb7,0x0b,0x3c,0xc4,0x8b,0xed,0xb7,0x59,0x1d,0x2e,0xac, + 0x04,0xb7,0x60,0xdf,0xff,0x4c,0x5c,0x20,0x0a,0xec,0x18,0xb9,0x30,0xb1,0x8d,0xf3,0x42,0x97,0xbb,0x42,0x1b,0x96,0x01,0x7e,0xf9,0x02,0x13,0x9f,0xe6,0xb1,0x23,0x49,0xf6,0xcc,0xb8,0xcf,0x83,0xd2,0x83,0x7c,0x75,0x20,0x30,0x0f,0x19,0x7b,0x49,0x1c,0x03,0x68,0x47,0x0e,0xe8,0x6f,0x74,0xca,0x03,0x81,0x68,0x2b,0xb6,0xad,0x80,0x34,0x4f, + 0x04,0xb0,0xe4,0xde,0x91,0x4f,0xe7,0x1b,0x61,0x63,0x6e,0x61,0x39,0x15,0x28,0xef,0xac,0x8b,0x6c,0x11,0xed,0xcd,0x41,0xc9,0x76,0x6a,0xf8,0x69,0x3d,0xbb,0x6e,0x41,0xf2,0x51,0x72,0x93,0x72,0x55,0x52,0xf2,0x2d,0xd6,0xe1,0xdb,0x7c,0x2c,0x24,0x3f,0x80,0xc1,0x07,0x13,0xf6,0xaa,0x48,0xfc,0x5e,0x39,0x5b,0xd9,0xec,0x51,0xf1,0xe9,0xc5, + 0x04,0x8e,0xb6,0xee,0x2e,0xe9,0xe0,0x61,0xac,0xb9,0x31,0x2a,0xd0,0x15,0xb1,0x95,0x4e,0xa4,0x7c,0xa3,0x04,0xa2,0xce,0xbb,0x77,0xf3,0xbf,0x6c,0x78,0x67,0x8c,0x11,0x49,0xd9,0x3f,0xc6,0xe8,0x05,0x61,0xf3,0x11,0x0f,0xd0,0xe9,0x5f,0xdc,0x0c,0xe8,0xda,0x2c,0x3f,0x32,0xf7,0xf5,0x81,0xf9,0xb6,0x66,0xd7,0x49,0x00,0xb3,0x76,0x0b,0x9f, + 0x04,0x90,0x12,0x10,0x21,0x54,0x6a,0x96,0xe7,0x87,0x9d,0x53,0xe7,0xb8,0x5c,0x21,0xf4,0x04,0x7d,0xf4,0x9b,0x9a,0xd8,0x50,0x20,0x10,0x4f,0x21,0x6d,0x01,0x0f,0x52,0x0d,0x1b,0xba,0x6e,0x76,0x57,0x42,0x39,0x5b,0x4c,0x89,0x4f,0xd0,0xea,0xaf,0x87,0x27,0x5d,0x1c,0x77,0x49,0x4c,0x01,0xcc,0xe8,0x82,0xde,0x28,0x05,0xd1,0x92,0x2c,0x0b, + 0x04,0x64,0xc1,0x71,0x2e,0x3e,0x9e,0xf4,0x40,0xc7,0xea,0x8f,0xaf,0x05,0x40,0xd2,0xe6,0xa0,0x5a,0xdc,0xcb,0xd5,0x3a,0x7f,0xb2,0x4f,0xf1,0x6a,0x95,0x02,0xa8,0x18,0xf7,0x47,0xcf,0xaf,0xd2,0x20,0x94,0x30,0xeb,0x77,0x94,0xf5,0xda,0x91,0xd6,0xc5,0xe2,0xdb,0x50,0x5b,0xa2,0x87,0xbc,0x6e,0xf3,0x97,0xbf,0x7f,0x30,0xc7,0x47,0x53,0x6a, + 0x04,0xcb,0xb0,0xde,0xab,0x12,0x57,0x54,0xf1,0xfd,0xb2,0x03,0x8b,0x04,0x34,0xed,0x9c,0xb3,0xfb,0x53,0xab,0x73,0x53,0x91,0x12,0x99,0x94,0xa5,0x35,0xd9,0x25,0xf6,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0x24,0x80,0x0d,0xea,0xc3,0xfe,0x4c,0x76,0x5b,0x6d,0xec,0x80,0xea,0x29,0x9d,0x77,0x1a,0xda,0x4f,0x30,0xe4,0xe1,0x56,0xb3,0xac,0xb7,0x20,0xdb,0xa3,0x73,0x94,0x71,0x5f,0xe4,0xc6,0x4b,0xb0,0x64,0x8e,0x26,0xd0,0x5c,0xb9,0xcc,0x98,0xac,0x86,0xd4,0xe9,0x7b,0x8b,0xf1,0x2f,0x92,0xb9,0xb2,0xfd,0xc3,0xae,0xcd,0x8e,0xa6,0x64,0x8b, + 0x04,0x8f,0x33,0x65,0x2f,0x5b,0xda,0x2c,0x32,0x95,0x3e,0xbf,0x2d,0x2e,0xca,0x95,0xe0,0x5b,0x17,0xc8,0xab,0x7d,0x99,0x60,0x1b,0xee,0x44,0x5d,0xf8,0x44,0xd4,0x6a,0x36,0x9c,0xf5,0xac,0x00,0x77,0x11,0xbd,0xbe,0x5c,0x03,0x33,0xdc,0x0c,0x06,0x36,0xa6,0x48,0x23,0xee,0x48,0x01,0x94,0x64,0x94,0x0d,0x1f,0x27,0xe0,0x5c,0x42,0x08,0xde, + 0x04,0x14,0x6d,0x3b,0x65,0xad,0xd9,0xf5,0x4c,0xcc,0xa2,0x85,0x33,0xc8,0x8e,0x2c,0xbc,0x63,0xf7,0x44,0x3e,0x16,0x58,0x78,0x3a,0xb4,0x1f,0x8e,0xf9,0x7c,0x2a,0x10,0xb5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0xb0,0x34,0x44,0x18,0xa4,0x50,0x4c,0x07,0xe7,0x92,0x1e,0xd9,0xf0,0x07,0x14,0xb5,0xd3,0x90,0xe5,0xcb,0x5e,0x79,0x3b,0xb1,0x46,0x5f,0x73,0x17,0x4f,0x6c,0x26,0xfe,0x5f,0xe4,0xc6,0x4b,0xb0,0x64,0x8e,0x26,0xd0,0x5c,0xb9,0xcc,0x98,0xac,0x86,0xd4,0xe9,0x7b,0x8b,0xf1,0x2f,0x92,0xb9,0xb2,0xfd,0xc3,0xae,0xcd,0x8e,0xa6,0x64,0x8b, + 0x04,0x8a,0x98,0xc1,0xbc,0x6b,0xe7,0x5c,0x57,0x96,0xbe,0x4b,0x29,0xdd,0x88,0x5c,0x34,0x85,0xe7,0x5e,0x37,0xb4,0xcc,0xac,0x9b,0x37,0x25,0x1e,0x67,0x17,0x5f,0xf0,0xd6,0x9c,0xf5,0xac,0x00,0x77,0x11,0xbd,0xbe,0x5c,0x03,0x33,0xdc,0x0c,0x06,0x36,0xa6,0x48,0x23,0xee,0x48,0x01,0x94,0x64,0x94,0x0d,0x1f,0x27,0xe0,0x5c,0x42,0x08,0xde, + 0x04,0x1f,0xe1,0xe5,0xef,0x3f,0xce,0xb5,0xc1,0x35,0xab,0x77,0x41,0x33,0x3c,0xe5,0xa6,0xe8,0x0d,0x68,0x16,0x76,0x53,0xf6,0xb2,0xb2,0x4b,0xcb,0xcf,0xaa,0xaf,0xf5,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0x2b,0x4b,0xad,0xfc,0x97,0xb1,0x67,0x81,0xbc,0xff,0xf4,0xa5,0x25,0xcf,0x4d,0xd3,0x11,0x94,0xcb,0x03,0xbc,0xa5,0x6d,0x9b,0x0c,0xe9,0x6c,0x0c,0x0d,0x20,0x40,0xc0,0x5f,0xe4,0xc6,0x4b,0xb0,0x64,0x8e,0x26,0xd0,0x5c,0xb9,0xcc,0x98,0xac,0x86,0xd4,0xe9,0x7b,0x8b,0xf1,0x2f,0x92,0xb9,0xb2,0xfd,0xc3,0xae,0xcd,0x8e,0xa6,0x64,0x8b, + 0x04,0xe6,0x33,0xd9,0x14,0x38,0x3e,0x77,0x75,0xd4,0x02,0xf5,0xa8,0xf3,0xad,0x0d,0xeb,0x1f,0x00,0xd9,0x1c,0xcd,0x99,0xf3,0x48,0xda,0x96,0x83,0x9e,0xa3,0xcb,0x9d,0x52,0x9c,0xf5,0xac,0x00,0x77,0x11,0xbd,0xbe,0x5c,0x03,0x33,0xdc,0x0c,0x06,0x36,0xa6,0x48,0x23,0xee,0x48,0x01,0x94,0x64,0x94,0x0d,0x1f,0x27,0xe0,0x5c,0x42,0x08,0xde, + 0x04,0xd1,0xc1,0xb5,0x09,0xc9,0xdd,0xb7,0x62,0x21,0xa0,0x66,0xa2,0x2a,0x3c,0x33,0x3f,0xee,0x5e,0x1d,0x2d,0x1a,0x4b,0xab,0xde,0x4a,0x1d,0x33,0xec,0x24,0x7a,0x7e,0xa3,0x01,0x62,0xf9,0x54,0x53,0x4e,0xad,0xb1,0xb4,0xea,0x95,0xc5,0x7d,0x40,0xa1,0x02,0x14,0xe5,0xb7,0x46,0xee,0x6a,0xa4,0x19,0x4e,0xd2,0xb2,0x01,0x2b,0x72,0xf9,0x7d, + 0x04,0x75,0x5d,0x88,0x45,0xe7,0xb4,0xfd,0x27,0x03,0x53,0xf6,0x99,0x9e,0x97,0x24,0x22,0x24,0x01,0x55,0x27,0xbf,0x3f,0x94,0xcc,0x2c,0x69,0x3d,0x1b,0x6b,0xa1,0x22,0x98,0x60,0x4f,0x81,0x74,0xe3,0x60,0x5b,0x8f,0x18,0xbe,0xd3,0x74,0x2b,0x68,0x71,0xa8,0xcf,0xfc,0xe0,0x06,0xdb,0x31,0xb8,0xd7,0xd8,0x36,0xf5,0x0c,0xfc,0xda,0x7d,0x16, + 0x04,0xc6,0xf9,0xfc,0x86,0x44,0xba,0x5c,0x9e,0xa9,0xbe,0xb1,0x2c,0xe2,0xcb,0x91,0x1c,0x54,0x87,0xe8,0xb1,0xbe,0x91,0xd5,0xa1,0x68,0x31,0x8f,0x4a,0xe4,0x4d,0x66,0x80,0x7b,0xc3,0x37,0xa1,0xc8,0x2e,0x3c,0x5f,0x7a,0x29,0x27,0x98,0x7b,0x8f,0xae,0x13,0x62,0x72,0x37,0xd2,0x20,0xfa,0xfb,0x40,0x13,0x12,0x3b,0xfb,0xd9,0x5f,0x0b,0xa5, + 0x04,0xd3,0x17,0x9f,0xce,0x57,0x81,0xd0,0xc4,0x9c,0xe8,0x48,0x0a,0x81,0x1f,0x6f,0x08,0xe3,0xf1,0x23,0xd9,0xf6,0x01,0x0f,0xbf,0x61,0x9b,0x5d,0x86,0x8a,0x8e,0xa8,0x33,0xdd,0xf9,0xa6,0x66,0xbf,0x00,0x15,0xb2,0x0e,0x49,0x12,0xf7,0x0f,0x65,0x5e,0xf2,0x1b,0x82,0x08,0x75,0x96,0xaa,0x1e,0x2f,0x1e,0x28,0x65,0x35,0x0d,0x15,0x91,0x85, + 0x04,0x9e,0x09,0x80,0x95,0x46,0x3c,0x91,0xac,0x71,0x07,0xa9,0x20,0xcc,0xb2,0x76,0xd4,0x5e,0x1f,0x72,0x40,0xef,0x2b,0x93,0xb9,0x57,0xee,0x09,0x39,0x3d,0x32,0xe0,0x01,0x50,0x3a,0xf4,0xa2,0xe3,0xb2,0x62,0x79,0x56,0x4f,0xed,0x8e,0x77,0x2a,0x04,0x3e,0x75,0x63,0x0e,0x4e,0x38,0x59,0x97,0x6e,0xde,0x88,0xff,0xcf,0x16,0xf5,0xca,0x71, + 0x04,0xbf,0x30,0x34,0xa9,0x93,0x51,0x82,0xda,0x36,0x25,0x70,0x31,0x50,0x11,0x54,0x4a,0xc2,0xce,0x8a,0x9c,0x22,0x77,0x7c,0x2f,0xc7,0x67,0xac,0x9c,0x5c,0x0d,0xae,0xeb,0xcf,0x33,0x35,0x62,0xf3,0xe0,0x18,0x89,0x23,0x74,0x35,0x36,0x74,0xde,0x84,0x90,0xfc,0x9d,0x30,0x42,0x65,0x98,0xeb,0x60,0x07,0x79,0x15,0x4b,0xaf,0x2a,0xec,0x17, + 0x04,0x70,0x9c,0x71,0x79,0xc2,0xbb,0x27,0xce,0x39,0x85,0xba,0x42,0xfe,0xb8,0x70,0xf0,0x69,0xda,0xce,0xad,0x92,0x94,0xc8,0x05,0x57,0xbe,0x88,0x2f,0xb5,0x77,0x90,0x48,0x1e,0x6f,0xe2,0xc1,0xa7,0x15,0x16,0x3e,0xfa,0xf8,0x6e,0xa8,0xb1,0xe5,0x5e,0xa5,0x74,0x2d,0x6b,0x04,0x2e,0x6c,0xbf,0x8a,0xcc,0x69,0xc9,0x9f,0x82,0x71,0xa9,0x02, + 0x04,0x26,0x4c,0x00,0xa2,0xd9,0x25,0x14,0xa6,0xdb,0xe6,0x55,0xde,0x3c,0x71,0xa5,0x74,0x0c,0xec,0x4f,0xcb,0x25,0x1a,0xa4,0x8c,0xa6,0x74,0x5d,0xbe,0xa6,0xf5,0xf7,0xcf,0xc1,0xd5,0xee,0x9f,0xc3,0xce,0x49,0xfd,0x45,0x09,0xd3,0x3c,0x4d,0xcf,0xcc,0x1a,0x20,0xa6,0x60,0x52,0x9f,0xa9,0xeb,0xd6,0xe6,0xaf,0xc3,0xd5,0xc8,0x4c,0x72,0xbb, + 0x04,0xa1,0x21,0x24,0x60,0x6b,0xcb,0xbb,0x33,0xce,0xce,0xc7,0xfc,0x8d,0x78,0xb3,0x89,0x71,0x92,0xca,0x85,0x15,0x60,0xc5,0x39,0xe4,0x7d,0xd2,0x76,0xc6,0x3b,0xd3,0xc2,0xf2,0x0a,0x0c,0xa6,0x18,0xba,0x01,0x31,0xa2,0xe3,0x73,0xf3,0x1f,0x73,0xb3,0xf5,0x5e,0x91,0x88,0xd4,0x6f,0xdd,0xbc,0x63,0x87,0xe3,0x2a,0xef,0xb9,0xf3,0xba,0x12, + 0x04,0x24,0x4b,0x7a,0xfe,0x7f,0x31,0x28,0x9f,0x9d,0x6a,0xae,0xb7,0xf7,0x0d,0x29,0xa7,0xb4,0x9a,0x22,0x8c,0x7b,0xb2,0x02,0x76,0x4a,0xba,0x94,0xda,0xaa,0xa3,0x33,0x22,0x70,0xc6,0x09,0x75,0x74,0x8f,0x0c,0x74,0x9a,0x8b,0x0f,0x8f,0xc1,0xe2,0x22,0xdd,0xcb,0xd3,0x38,0x4f,0x6d,0x68,0xf0,0xb6,0xb6,0xff,0x67,0x9b,0x43,0x5c,0xdc,0xb1, + 0x04,0x2a,0xc2,0x9d,0xb2,0xeb,0xc4,0xfa,0x94,0x73,0xb4,0x2b,0xd3,0x35,0xa6,0x02,0x26,0x57,0x9c,0xc1,0x86,0xb2,0xc6,0x76,0xa3,0xb0,0x1b,0xc6,0x0e,0x58,0x96,0x16,0x16,0x5a,0xa9,0xc0,0xd1,0xb2,0x40,0xe6,0xdd,0x42,0x11,0xe3,0x23,0x54,0x25,0x63,0x4b,0x27,0x8a,0xd8,0x8f,0xed,0xe0,0x33,0x7d,0x5a,0xcf,0x31,0x36,0x58,0x7d,0x84,0x13, + 0x04,0xe6,0x2a,0xee,0x52,0x05,0xa8,0x06,0x3e,0x3a,0xe4,0x01,0xd5,0x3e,0x93,0x43,0x00,0x1e,0x55,0xeb,0x5f,0x4e,0x4d,0x6b,0x70,0xe2,0xb8,0x41,0x59,0xcf,0x31,0x57,0xe6,0x4b,0xa2,0xe4,0x20,0xca,0xbc,0x43,0xb6,0xe8,0xe8,0x65,0x90,0xfc,0x23,0x83,0xd1,0x78,0x27,0xdd,0x99,0xa6,0x0c,0x21,0x1f,0x19,0x0a,0x74,0x26,0x91,0x00,0xc1,0x41, + 0x04,0x31,0xdc,0xe6,0xde,0x74,0x1f,0x10,0x26,0x7f,0x2e,0x8f,0x3d,0x57,0x2a,0x4f,0x49,0xbe,0x5f,0xe5,0x2f,0xf7,0xbf,0xf3,0xc3,0xb4,0x64,0x6f,0x38,0x07,0x6c,0x06,0x75,0x27,0x02,0xa5,0x15,0xa9,0xa5,0x0d,0xb1,0xd8,0x6f,0xd4,0x2a,0xea,0x08,0x34,0xda,0xeb,0x62,0xbe,0x03,0xd0,0xcd,0x90,0x33,0xf8,0x4b,0x9c,0x4b,0x56,0xa1,0x9f,0x12, + 0x04,0x65,0x18,0xcd,0x66,0xb1,0xd8,0x41,0xe6,0x89,0xd5,0xdc,0x66,0x74,0xc7,0xcc,0x7d,0x96,0x45,0x74,0xd1,0x49,0x0f,0xff,0x79,0x06,0xbd,0x37,0x34,0x94,0x79,0x15,0x99,0x10,0x42,0x77,0x17,0x06,0x92,0xfa,0x6b,0xf2,0x27,0x05,0x80,0xd5,0x6d,0x1b,0xc8,0x1b,0x54,0xf4,0x77,0xd8,0xab,0x6c,0x3f,0x58,0x42,0x65,0x0a,0xc7,0x17,0x6d,0x71, + 0x04,0x95,0x2a,0x88,0xce,0x31,0xad,0x4c,0xb0,0x86,0x97,0x8e,0x6c,0x56,0x21,0xc3,0xd8,0x02,0x3b,0x2c,0x11,0x41,0x8d,0x6f,0xd0,0xdc,0xef,0x8d,0xe7,0x21,0x23,0xef,0xc1,0x5d,0x36,0x76,0x88,0xfd,0xe5,0xe0,0x82,0xf0,0x97,0x85,0x5a,0x0c,0x0a,0xdc,0x30,0x5d,0xd6,0xcf,0x46,0xf5,0x0c,0xa7,0x58,0x59,0xbb,0x24,0x3b,0x70,0x24,0x96,0x05, + 0x04,0x2a,0x43,0xf3,0x35,0x73,0xb6,0x19,0x71,0x90,0x99,0xcf,0x54,0xf6,0xcc,0xcb,0x28,0xd1,0x6d,0xf3,0x99,0x22,0x39,0xfa,0xdf,0x79,0xc7,0xac,0xb9,0xc6,0x4f,0x7a,0xf0,0xf4,0xd1,0xd2,0x2a,0xf7,0x18,0x7c,0x8d,0xe1,0xb9,0x92,0xa4,0x04,0x6c,0x41,0x9b,0x80,0x1c,0xde,0x57,0xd6,0x38,0xd3,0x0f,0x2e,0x1a,0xc4,0x93,0x53,0x11,0x7a,0x20, + 0x04,0x1b,0x1b,0x0c,0x75,0x40,0x87,0x85,0xe8,0x47,0x27,0xb0,0xe5,0x5e,0x4b,0xa2,0x0d,0x0f,0x25,0x99,0xc4,0xed,0x08,0x48,0x2d,0xc1,0xf3,0xb5,0xdf,0x54,0x56,0x91,0x38,0x01,0x62,0xf9,0x54,0x53,0x4e,0xad,0xb1,0xb4,0xea,0x95,0xc5,0x7d,0x40,0xa1,0x02,0x14,0xe5,0xb7,0x46,0xee,0x6a,0xa4,0x19,0x4e,0xd2,0xb2,0x01,0x2b,0x72,0xf9,0x7d, + 0x04,0x4d,0xd1,0x28,0x3b,0xcc,0xd3,0x6c,0xc3,0x40,0x2f,0x3a,0x81,0xe2,0xe9,0xb0,0xd6,0xa2,0xb2,0xb1,0xde,0xbb,0xbd,0x44,0xff,0xc1,0xf1,0x79,0xbd,0x49,0xcf,0x0a,0x7e,0x60,0x4f,0x81,0x74,0xe3,0x60,0x5b,0x8f,0x18,0xbe,0xd3,0x74,0x2b,0x68,0x71,0xa8,0xcf,0xfc,0xe0,0x06,0xdb,0x31,0xb8,0xd7,0xd8,0x36,0xf5,0x0c,0xfc,0xda,0x7d,0x16, + 0x04,0xa4,0x99,0xdb,0xf7,0x32,0xe4,0x38,0xbe,0x0e,0xb0,0x84,0xb9,0xe6,0xad,0x87,0x9d,0xd7,0xa2,0x90,0x4b,0xbb,0x00,0x4b,0x40,0x02,0x79,0x69,0xa1,0x71,0xf2,0xd4,0x26,0x7b,0xc3,0x37,0xa1,0xc8,0x2e,0x3c,0x5f,0x7a,0x29,0x27,0x98,0x7b,0x8f,0xae,0x13,0x62,0x72,0x37,0xd2,0x20,0xfa,0xfb,0x40,0x13,0x12,0x3b,0xfb,0xd9,0x5f,0x0b,0xa5, + 0x04,0xad,0xcf,0x0f,0xfb,0xa9,0xcb,0x6e,0xf0,0xc8,0x03,0x1c,0x42,0x91,0xa4,0x34,0xb1,0x8d,0x78,0xf4,0x2e,0x45,0xe6,0x2b,0xa0,0x1f,0xbe,0x91,0xf9,0x27,0x3f,0x0a,0xd1,0xdd,0xf9,0xa6,0x66,0xbf,0x00,0x15,0xb2,0x0e,0x49,0x12,0xf7,0x0f,0x65,0x5e,0xf2,0x1b,0x82,0x08,0x75,0x96,0xaa,0x1e,0x2f,0x1e,0x28,0x65,0x35,0x0d,0x15,0x91,0x85, + 0x04,0x21,0x71,0x27,0x25,0xd9,0x80,0x6a,0xcf,0x54,0xd3,0xa6,0xc8,0x2b,0xf9,0x3c,0x0f,0xe2,0x49,0x26,0x8c,0xa9,0xf4,0x2e,0xce,0xac,0x19,0xe9,0x3a,0x5e,0xab,0x80,0x56,0x50,0x3a,0xf4,0xa2,0xe3,0xb2,0x62,0x79,0x56,0x4f,0xed,0x8e,0x77,0x2a,0x04,0x3e,0x75,0x63,0x0e,0x4e,0x38,0x59,0x97,0x6e,0xde,0x88,0xff,0xcf,0x16,0xf5,0xca,0x71, + 0x04,0x1e,0x02,0x17,0x68,0x24,0xbd,0x31,0xea,0xbd,0xce,0x03,0xa9,0x40,0x3c,0x7d,0x3c,0x2a,0xc6,0x31,0xf9,0xb0,0xe8,0x8d,0x9a,0x92,0x47,0x01,0xc1,0xb2,0xf2,0x9b,0x85,0xcf,0x33,0x35,0x62,0xf3,0xe0,0x18,0x89,0x23,0x74,0x35,0x36,0x74,0xde,0x84,0x90,0xfc,0x9d,0x30,0x42,0x65,0x98,0xeb,0x60,0x07,0x79,0x15,0x4b,0xaf,0x2a,0xec,0x17, + 0x04,0x63,0xe7,0xa1,0xaf,0x36,0xd6,0xb5,0x40,0xa4,0x92,0x76,0xaa,0xc3,0xfe,0xc9,0xcb,0x45,0xed,0x6b,0xab,0x16,0x7c,0x06,0xb0,0x41,0x9a,0x77,0xb9,0x13,0x99,0xf6,0x18,0x1e,0x6f,0xe2,0xc1,0xa7,0x15,0x16,0x3e,0xfa,0xf8,0x6e,0xa8,0xb1,0xe5,0x5e,0xa5,0x74,0x2d,0x6b,0x04,0x2e,0x6c,0xbf,0x8a,0xcc,0x69,0xc9,0x9f,0x82,0x71,0xa9,0x02, + 0x04,0x1e,0x26,0x5a,0xb5,0xb7,0xf7,0x19,0x94,0x70,0xe5,0x32,0x65,0x3d,0x2a,0x7b,0x9a,0x8b,0x72,0x89,0x70,0xb8,0x38,0x13,0x7c,0x96,0x92,0xed,0x06,0x92,0x89,0x7b,0x2a,0xc1,0xd5,0xee,0x9f,0xc3,0xce,0x49,0xfd,0x45,0x09,0xd3,0x3c,0x4d,0xcf,0xcc,0x1a,0x20,0xa6,0x60,0x52,0x9f,0xa9,0xeb,0xd6,0xe6,0xaf,0xc3,0xd5,0xc8,0x4c,0x72,0xbb, + 0x04,0x54,0xd2,0xa4,0x39,0x4c,0x10,0x9f,0xcb,0xd3,0xcb,0x98,0x86,0xfe,0xc3,0xad,0xd5,0x1b,0xa4,0xd2,0xe4,0x4e,0x1d,0x56,0x76,0xe4,0xb9,0x8f,0x0c,0x13,0x65,0x5f,0xc5,0xf2,0x0a,0x0c,0xa6,0x18,0xba,0x01,0x31,0xa2,0xe3,0x73,0xf3,0x1f,0x73,0xb3,0xf5,0x5e,0x91,0x88,0xd4,0x6f,0xdd,0xbc,0x63,0x87,0xe3,0x2a,0xef,0xb9,0xf3,0xba,0x12, + 0x04,0x93,0xf1,0x45,0x92,0x07,0xfb,0x09,0xc6,0xf0,0xa8,0x8c,0x39,0x8a,0xc8,0x0d,0x10,0x52,0xa4,0xcd,0x33,0xe7,0xee,0xf5,0x68,0x7d,0xa9,0x9a,0xb9,0x7c,0x60,0x24,0xb7,0x70,0xc6,0x09,0x75,0x74,0x8f,0x0c,0x74,0x9a,0x8b,0x0f,0x8f,0xc1,0xe2,0x22,0xdd,0xcb,0xd3,0x38,0x4f,0x6d,0x68,0xf0,0xb6,0xb6,0xff,0x67,0x9b,0x43,0x5c,0xdc,0xb1, + 0x04,0x1f,0xa0,0x49,0xa1,0x89,0x2b,0x67,0x98,0x57,0xc6,0xdf,0xf0,0x8a,0xf1,0x9d,0xb7,0x0c,0xbc,0x99,0xb6,0xf2,0xd7,0xbc,0x51,0xa3,0x41,0xfe,0x79,0xd1,0x64,0x7f,0x4a,0x5a,0xa9,0xc0,0xd1,0xb2,0x40,0xe6,0xdd,0x42,0x11,0xe3,0x23,0x54,0x25,0x63,0x4b,0x27,0x8a,0xd8,0x8f,0xed,0xe0,0x33,0x7d,0x5a,0xcf,0x31,0x36,0x58,0x7d,0x84,0x13, + 0x04,0x84,0xe0,0xb1,0x92,0xd6,0x0a,0xbf,0x53,0x1e,0x82,0x8e,0x88,0x7d,0x36,0x6d,0x86,0x9e,0x10,0x33,0xa1,0x6e,0x9c,0x7f,0x11,0x67,0x45,0x8c,0x81,0x34,0xc1,0x0f,0xba,0x4b,0xa2,0xe4,0x20,0xca,0xbc,0x43,0xb6,0xe8,0xe8,0x65,0x90,0xfc,0x23,0x83,0xd1,0x78,0x27,0xdd,0x99,0xa6,0x0c,0x21,0x1f,0x19,0x0a,0x74,0x26,0x91,0x00,0xc1,0x41, + 0x04,0x2f,0x97,0x07,0xc6,0x71,0x18,0x72,0x41,0x11,0xef,0xbb,0xbb,0xf0,0x6b,0x62,0x3a,0xb2,0xff,0xd9,0x25,0x9d,0xdc,0x35,0x4f,0xca,0xaf,0x81,0xba,0x01,0xf6,0xfa,0x7b,0x27,0x02,0xa5,0x15,0xa9,0xa5,0x0d,0xb1,0xd8,0x6f,0xd4,0x2a,0xea,0x08,0x34,0xda,0xeb,0x62,0xbe,0x03,0xd0,0xcd,0x90,0x33,0xf8,0x4b,0x9c,0x4b,0x56,0xa1,0x9f,0x12, + 0x04,0xac,0x1f,0xbb,0xe4,0x22,0x93,0xa9,0xf9,0xae,0x10,0x4e,0xe2,0xda,0x0b,0x0a,0x9b,0x34,0x64,0xd5,0xd8,0xb1,0xe8,0x54,0xdf,0x19,0xd3,0xc4,0x45,0x6a,0xf8,0xf9,0xa6,0x10,0x42,0x77,0x17,0x06,0x92,0xfa,0x6b,0xf2,0x27,0x05,0x80,0xd5,0x6d,0x1b,0xc8,0x1b,0x54,0xf4,0x77,0xd8,0xab,0x6c,0x3f,0x58,0x42,0x65,0x0a,0xc7,0x17,0x6d,0x71, + 0x04,0xba,0xe1,0x0c,0xf9,0x3f,0xf7,0xb7,0x2d,0x6e,0xd9,0x85,0x19,0x60,0x2e,0x9f,0x03,0xaa,0x40,0x30,0x3f,0xa0,0x67,0x4f,0xb3,0xdd,0xee,0x7d,0x2d,0xb1,0xc9,0x2b,0xb2,0x5d,0x36,0x76,0x88,0xfd,0xe5,0xe0,0x82,0xf0,0x97,0x85,0x5a,0x0c,0x0a,0xdc,0x30,0x5d,0xd6,0xcf,0x46,0xf5,0x0c,0xa7,0x58,0x59,0xbb,0x24,0x3b,0x70,0x24,0x96,0x05, + 0x04,0xed,0xb4,0x28,0x8c,0xf5,0x56,0x76,0x73,0xd5,0x0a,0x1c,0xd9,0xe6,0xbe,0xa4,0x53,0x17,0x82,0x3f,0x30,0x38,0x3f,0x60,0xd9,0xbc,0x3b,0x9e,0xe4,0x2a,0xc2,0x98,0x71,0xf4,0xd1,0xd2,0x2a,0xf7,0x18,0x7c,0x8d,0xe1,0xb9,0x92,0xa4,0x04,0x6c,0x41,0x9b,0x80,0x1c,0xde,0x57,0xd6,0x38,0xd3,0x0f,0x2e,0x1a,0xc4,0x93,0x53,0x11,0x7a,0x20, + 0x04,0x13,0x23,0x3e,0x80,0xf5,0x9a,0xc2,0xb5,0x97,0x37,0xe8,0x78,0x77,0x78,0x2a,0xb3,0x02,0x7c,0x49,0x0d,0xf8,0xac,0x0b,0xf3,0xf3,0xef,0x16,0x33,0x87,0x2e,0xec,0x54,0x01,0x62,0xf9,0x54,0x53,0x4e,0xad,0xb1,0xb4,0xea,0x95,0xc5,0x7d,0x40,0xa1,0x02,0x14,0xe5,0xb7,0x46,0xee,0x6a,0xa4,0x19,0x4e,0xd2,0xb2,0x01,0x2b,0x72,0xf9,0x7d, + 0x04,0x3c,0xd1,0x4f,0x7e,0x4b,0x77,0x96,0x15,0xbc,0x7c,0xce,0xe4,0x7e,0x7f,0x2b,0x07,0x39,0x4b,0xf8,0xf9,0x85,0x03,0x26,0x34,0x11,0xa5,0x49,0x26,0x4a,0x8f,0xcf,0x19,0x60,0x4f,0x81,0x74,0xe3,0x60,0x5b,0x8f,0x18,0xbe,0xd3,0x74,0x2b,0x68,0x71,0xa8,0xcf,0xfc,0xe0,0x06,0xdb,0x31,0xb8,0xd7,0xd8,0x36,0xf5,0x0c,0xfc,0xda,0x7d,0x16, + 0x04,0x94,0x6c,0x27,0x82,0x88,0x61,0x6a,0xa3,0x47,0x90,0xca,0x19,0x36,0x86,0xe7,0x45,0xd3,0xd5,0x87,0x02,0x86,0x6d,0xdf,0x1e,0x95,0x55,0x07,0x11,0xa9,0xbf,0xbd,0xb8,0x7b,0xc3,0x37,0xa1,0xc8,0x2e,0x3c,0x5f,0x7a,0x29,0x27,0x98,0x7b,0x8f,0xae,0x13,0x62,0x72,0x37,0xd2,0x20,0xfa,0xfb,0x40,0x13,0x12,0x3b,0xfb,0xd9,0x5f,0x0b,0xa5, + 0x04,0x7f,0x19,0x50,0x35,0xfe,0xb2,0xc0,0x4a,0x9b,0x14,0x9b,0xb2,0xed,0x3c,0x5c,0x45,0x8e,0x95,0xe7,0xf7,0xc4,0x18,0xc4,0xa0,0x7e,0xa6,0x10,0x7e,0x4e,0x32,0x45,0x5a,0xdd,0xf9,0xa6,0x66,0xbf,0x00,0x15,0xb2,0x0e,0x49,0x12,0xf7,0x0f,0x65,0x5e,0xf2,0x1b,0x82,0x08,0x75,0x96,0xaa,0x1e,0x2f,0x1e,0x28,0x65,0x35,0x0d,0x15,0x91,0x85, + 0x04,0x40,0x85,0x58,0x44,0xe0,0x43,0x03,0x84,0x3a,0x24,0xb0,0x17,0x07,0x54,0x4d,0x1b,0xbf,0x97,0x67,0x32,0x66,0xe0,0x3d,0x77,0xfb,0xf8,0x0d,0x8b,0x64,0x21,0x9b,0xd8,0x50,0x3a,0xf4,0xa2,0xe3,0xb2,0x62,0x79,0x56,0x4f,0xed,0x8e,0x77,0x2a,0x04,0x3e,0x75,0x63,0x0e,0x4e,0x38,0x59,0x97,0x6e,0xde,0x88,0xff,0xcf,0x16,0xf5,0xca,0x71, + 0x04,0x22,0xcd,0xb3,0xee,0x47,0xf1,0x4b,0x3b,0x0c,0x0c,0x8c,0x25,0x6f,0xb2,0x2e,0x79,0x12,0x6b,0x43,0x6a,0x2c,0x9f,0xf6,0x35,0xa6,0x51,0x51,0xa0,0xf0,0xff,0xb1,0xbf,0xcf,0x33,0x35,0x62,0xf3,0xe0,0x18,0x89,0x23,0x74,0x35,0x36,0x74,0xde,0x84,0x90,0xfc,0x9d,0x30,0x42,0x65,0x98,0xeb,0x60,0x07,0x79,0x15,0x4b,0xaf,0x2a,0xec,0x17, + 0x04,0x2b,0x7b,0xec,0xd7,0x06,0x6e,0x22,0xf1,0x21,0xe7,0xcf,0x12,0x3d,0x48,0xc5,0x44,0x50,0x37,0xc5,0xa7,0x56,0xef,0x31,0x4a,0x66,0xa7,0x00,0x16,0x36,0xee,0x75,0xcf,0x1e,0x6f,0xe2,0xc1,0xa7,0x15,0x16,0x3e,0xfa,0xf8,0x6e,0xa8,0xb1,0xe5,0x5e,0xa5,0x74,0x2d,0x6b,0x04,0x2e,0x6c,0xbf,0x8a,0xcc,0x69,0xc9,0x9f,0x82,0x71,0xa9,0x02, + 0x04,0xbb,0x8d,0xa4,0xa7,0x6e,0xe3,0xd1,0xc4,0xb3,0x34,0x77,0xbc,0x86,0x63,0xde,0xf1,0x67,0xa1,0x26,0xc4,0x22,0xad,0x47,0xf6,0xc2,0xf8,0xb5,0x39,0xc6,0x80,0x89,0x36,0xc1,0xd5,0xee,0x9f,0xc3,0xce,0x49,0xfd,0x45,0x09,0xd3,0x3c,0x4d,0xcf,0xcc,0x1a,0x20,0xa6,0x60,0x52,0x9f,0xa9,0xeb,0xd6,0xe6,0xaf,0xc3,0xd5,0xc8,0x4c,0x72,0xbb, + 0x04,0x0a,0x0c,0x37,0x66,0x48,0x23,0xa5,0x00,0x5d,0x65,0x9f,0x7c,0x73,0xc3,0x9e,0xa1,0x72,0xc8,0x62,0x96,0x9c,0x81,0xe4,0x4f,0x36,0xc8,0x9e,0x7c,0x26,0x5e,0xc8,0xa8,0xf2,0x0a,0x0c,0xa6,0x18,0xba,0x01,0x31,0xa2,0xe3,0x73,0xf3,0x1f,0x73,0xb3,0xf5,0x5e,0x91,0x88,0xd4,0x6f,0xdd,0xbc,0x63,0x87,0xe3,0x2a,0xef,0xb9,0xf3,0xba,0x12, + 0x04,0x47,0xc3,0x3f,0x6f,0x78,0xd3,0xcd,0x99,0x71,0xec,0xc5,0x0e,0x7e,0x2a,0xc9,0x47,0xf8,0xc1,0x10,0x3f,0x9c,0x5f,0x08,0x21,0x37,0x9b,0xd0,0x6a,0xd8,0xfc,0xa4,0x56,0x70,0xc6,0x09,0x75,0x74,0x8f,0x0c,0x74,0x9a,0x8b,0x0f,0x8f,0xc1,0xe2,0x22,0xdd,0xcb,0xd3,0x38,0x4f,0x6d,0x68,0xf0,0xb6,0xb6,0xff,0x67,0x9b,0x43,0x5c,0xdc,0xb1, + 0x04,0xb5,0x9d,0x18,0xab,0x8b,0x0f,0x9d,0xd3,0x34,0x84,0xf4,0x3c,0x3f,0x68,0x60,0x22,0x9b,0xa6,0xa4,0xc2,0x5a,0x61,0xcd,0x0a,0xac,0xa2,0x3b,0x76,0xd6,0x05,0x66,0xcf,0x5a,0xa9,0xc0,0xd1,0xb2,0x40,0xe6,0xdd,0x42,0x11,0xe3,0x23,0x54,0x25,0x63,0x4b,0x27,0x8a,0xd8,0x8f,0xed,0xe0,0x33,0x7d,0x5a,0xcf,0x31,0x36,0x58,0x7d,0x84,0x13, + 0x04,0x94,0xf4,0x60,0x1b,0x24,0x4d,0x3a,0x6e,0xa6,0x99,0x6f,0xa2,0x44,0x36,0x4f,0x79,0x43,0x99,0xe0,0xff,0x43,0x16,0x15,0x7d,0xb6,0x02,0x32,0x22,0xfc,0x0d,0x90,0xbe,0x4b,0xa2,0xe4,0x20,0xca,0xbc,0x43,0xb6,0xe8,0xe8,0x65,0x90,0xfc,0x23,0x83,0xd1,0x78,0x27,0xdd,0x99,0xa6,0x0c,0x21,0x1f,0x19,0x0a,0x74,0x26,0x91,0x00,0xc1,0x41, + 0x04,0x9e,0x8c,0x11,0x5b,0x1a,0xc8,0x7d,0x98,0x6e,0xe1,0xb5,0x06,0xb8,0x6a,0x4e,0x7b,0x8e,0xa0,0x41,0xaa,0x6a,0x63,0xd6,0xec,0x80,0xec,0x0f,0x0c,0xf6,0x9c,0xfb,0x3f,0x27,0x02,0xa5,0x15,0xa9,0xa5,0x0d,0xb1,0xd8,0x6f,0xd4,0x2a,0xea,0x08,0x34,0xda,0xeb,0x62,0xbe,0x03,0xd0,0xcd,0x90,0x33,0xf8,0x4b,0x9c,0x4b,0x56,0xa1,0x9f,0x12, + 0x04,0xee,0xc7,0x76,0xb5,0x2b,0x94,0x14,0x1f,0xc8,0x19,0xd4,0xb6,0xb1,0x2d,0x28,0xe7,0x35,0x55,0xb5,0x56,0x05,0x07,0xab,0xa7,0xdf,0x6f,0x04,0x84,0x00,0x8d,0xe9,0x1f,0x10,0x42,0x77,0x17,0x06,0x92,0xfa,0x6b,0xf2,0x27,0x05,0x80,0xd5,0x6d,0x1b,0xc8,0x1b,0x54,0xf4,0x77,0xd8,0xab,0x6c,0x3f,0x58,0x42,0x65,0x0a,0xc7,0x17,0x6d,0x71, + 0x04,0xaf,0xf4,0x6a,0x38,0x8e,0x5a,0xfc,0x22,0x0a,0x8e,0xec,0x7a,0x49,0xaf,0x9d,0x24,0x53,0x84,0xa3,0xaf,0x1e,0x0b,0x40,0x7b,0x45,0x21,0xf4,0xe9,0x2d,0x12,0xdc,0xeb,0x5d,0x36,0x76,0x88,0xfd,0xe5,0xe0,0x82,0xf0,0x97,0x85,0x5a,0x0c,0x0a,0xdc,0x30,0x5d,0xd6,0xcf,0x46,0xf5,0x0c,0xa7,0x58,0x59,0xbb,0x24,0x3b,0x70,0x24,0x96,0x05, + 0x04,0xe8,0x07,0xe4,0x3d,0x96,0xf3,0x70,0x1a,0x9a,0x5c,0x13,0xd1,0x22,0x74,0x90,0x84,0x17,0x0f,0xcd,0x36,0xa5,0x86,0xa4,0x46,0xc9,0xfc,0xb4,0x60,0x0e,0xed,0xe4,0xfd,0xf4,0xd1,0xd2,0x2a,0xf7,0x18,0x7c,0x8d,0xe1,0xb9,0x92,0xa4,0x04,0x6c,0x41,0x9b,0x80,0x1c,0xde,0x57,0xd6,0x38,0xd3,0x0f,0x2e,0x1a,0xc4,0x93,0x53,0x11,0x7a,0x20, + 0x04,0x79,0x88,0x68,0xa5,0x69,0x16,0xd3,0x41,0xe7,0xd6,0xf9,0x63,0x59,0xae,0x36,0x58,0x83,0x6e,0x22,0x14,0x59,0xf4,0xf7,0xb7,0xb6,0x36,0x94,0xde,0x18,0xa5,0xe9,0x24,0x77,0x13,0xfd,0xb0,0x3a,0x8d,0xe8,0xc6,0xd2,0x9c,0xa3,0x8a,0x9f,0xba,0xa8,0x2e,0x5e,0x02,0xbe,0xad,0x2f,0x9e,0xec,0x69,0xb6,0x44,0x4b,0x7a,0xdb,0x05,0x33,0x3b, + 0x04,0xff,0x41,0x99,0x09,0xd8,0xa8,0xce,0x0a,0x94,0x16,0x05,0x1f,0x4e,0x25,0x62,0x08,0xc1,0xdc,0x03,0x55,0x81,0xa5,0x33,0x12,0xd5,0x66,0x13,0x7e,0x22,0x10,0x4e,0x98,0x77,0x42,0x1a,0xb0,0x1e,0x00,0xe8,0x38,0x41,0xb9,0x46,0xda,0xe5,0xbb,0x5a,0x23,0x97,0x3d,0xaa,0x98,0xfe,0x1a,0x81,0x72,0x88,0x3a,0xbc,0xbe,0xdc,0xed,0x70,0x21, + 0x04,0x8b,0x48,0x11,0x9d,0x70,0x89,0xd3,0xb9,0x5c,0xd2,0xea,0xf8,0xc8,0x55,0x84,0xfa,0x8f,0x5e,0x56,0xc4,0xc4,0xcc,0xee,0x70,0x37,0xd7,0x4c,0xdb,0xf8,0x8e,0x57,0x17,0x14,0xc1,0xaa,0xc5,0xf0,0xbf,0x1b,0x48,0xa4,0xab,0xcf,0x1d,0x92,0x91,0xb9,0xa8,0x77,0x6a,0x00,0x43,0x80,0x54,0x6a,0x5a,0x1c,0x1f,0x29,0x46,0x90,0xf6,0x19,0x69, + 0x04,0xe2,0x88,0x81,0x19,0x37,0x9b,0x5b,0x21,0x51,0xbd,0x78,0x85,0x05,0xde,0xf1,0xd6,0xbd,0x78,0x63,0x29,0x43,0x1c,0xaf,0x39,0x70,0x5d,0x9c,0xbf,0x96,0xa4,0x2e,0xa4,0x3b,0xb7,0x32,0x88,0x39,0xd2,0xae,0xca,0xc6,0x4b,0x1c,0xdb,0x18,0x2f,0x08,0xad,0xcc,0xaa,0xc3,0x27,0xed,0x00,0x89,0x87,0xa1,0x0e,0xdc,0x97,0x32,0x41,0x3c,0xed, + 0x04,0x6d,0xcc,0x39,0x71,0xbd,0x20,0x91,0x3d,0x59,0xa9,0x1f,0x20,0xd9,0x12,0xf5,0x6d,0x07,0xe7,0xf0,0x14,0x20,0x6b,0xef,0x4a,0x65,0x3d,0xdf,0xe5,0xd1,0x28,0x42,0xc3,0x9b,0x51,0xb1,0x7b,0x76,0xea,0x6c,0xc1,0x37,0xee,0xbd,0x93,0xc8,0x11,0xe6,0x36,0xd8,0xae,0x26,0xc7,0x0d,0x06,0x46,0x50,0xf7,0x20,0x5a,0x86,0x5d,0x01,0xa6,0xee, + 0x04,0x7e,0xbe,0xa4,0x58,0x54,0x56,0x9a,0x1f,0x7e,0xa6,0xb9,0x5b,0x82,0xd6,0xbe,0xfe,0xfb,0xf6,0x29,0x6e,0xbc,0x87,0xc8,0x10,0xb6,0xcb,0xa9,0x3c,0x0c,0x12,0x20,0xb2,0x3f,0x18,0x74,0xfa,0x08,0xa6,0x93,0xb0,0x86,0x64,0x3e,0xf2,0x1e,0xb5,0x9d,0x75,0x56,0x2d,0xa9,0x42,0x2d,0x13,0xd9,0xa3,0x9b,0x0b,0x17,0xe2,0x41,0xb0,0x4d,0x32, + 0x04,0xce,0xab,0x59,0x37,0x90,0x0d,0x34,0xfa,0x88,0x37,0x8d,0x37,0x1f,0x4a,0xca,0xa7,0xc6,0xa2,0x02,0x8b,0x61,0x43,0x21,0x34,0x13,0xf1,0x6b,0xa2,0xdc,0x71,0x47,0x87,0x77,0x13,0xfd,0xb0,0x3a,0x8d,0xe8,0xc6,0xd2,0x9c,0xa3,0x8a,0x9f,0xba,0xa8,0x2e,0x5e,0x02,0xbe,0xad,0x2f,0x9e,0xec,0x69,0xb6,0x44,0x4b,0x7a,0xdb,0x05,0x33,0x3b, + 0x04,0xa4,0xff,0xea,0x5e,0x25,0xf7,0x5e,0x4f,0x68,0x9c,0x81,0x08,0x4a,0x35,0xc1,0x22,0x0e,0x8e,0x6b,0x91,0x4c,0x48,0x2f,0x4a,0x2e,0x8f,0x93,0xcf,0xfc,0xa6,0x96,0x47,0x77,0x42,0x1a,0xb0,0x1e,0x00,0xe8,0x38,0x41,0xb9,0x46,0xda,0xe5,0xbb,0x5a,0x23,0x97,0x3d,0xaa,0x98,0xfe,0x1a,0x81,0x72,0x88,0x3a,0xbc,0xbe,0xdc,0xed,0x70,0x21, + 0x04,0xde,0x88,0x09,0xea,0x0e,0xcc,0xe1,0xd2,0x4a,0x04,0x31,0x42,0x95,0x10,0x38,0x3a,0x6f,0x6e,0x5a,0x1c,0x51,0xce,0xa3,0x2d,0x83,0x0c,0x6c,0x35,0x30,0x42,0x60,0x3e,0x14,0xc1,0xaa,0xc5,0xf0,0xbf,0x1b,0x48,0xa4,0xab,0xcf,0x1d,0x92,0x91,0xb9,0xa8,0x77,0x6a,0x00,0x43,0x80,0x54,0x6a,0x5a,0x1c,0x1f,0x29,0x46,0x90,0xf6,0x19,0x69, + 0x04,0x56,0x62,0x09,0xf1,0x74,0xd6,0xbf,0x79,0x72,0x0b,0x70,0xed,0xb2,0x7e,0x51,0x35,0x0b,0xee,0xb2,0xb0,0xbc,0xd0,0x83,0xbb,0xae,0x72,0x14,0xf7,0x1c,0xf8,0x24,0xd4,0x3b,0xb7,0x32,0x88,0x39,0xd2,0xae,0xca,0xc6,0x4b,0x1c,0xdb,0x18,0x2f,0x08,0xad,0xcc,0xaa,0xc3,0x27,0xed,0x00,0x89,0x87,0xa1,0x0e,0xdc,0x97,0x32,0x41,0x3c,0xed, + 0x04,0xcc,0x31,0x81,0xc0,0x12,0x71,0x37,0x53,0x6c,0xee,0xc9,0x4f,0xd4,0x59,0x96,0x65,0x7d,0xf7,0x2e,0x0f,0x97,0xc4,0x4b,0x9d,0xad,0x14,0x76,0x3c,0xe5,0x06,0xe9,0xdc,0x9b,0x51,0xb1,0x7b,0x76,0xea,0x6c,0xc1,0x37,0xee,0xbd,0x93,0xc8,0x11,0xe6,0x36,0xd8,0xae,0x26,0xc7,0x0d,0x06,0x46,0x50,0xf7,0x20,0x5a,0x86,0x5d,0x01,0xa6,0xee, + 0x04,0xd7,0x05,0x2a,0x1e,0xea,0xfc,0x0e,0x78,0xd7,0x9e,0x7f,0x26,0x00,0x3a,0xa0,0xa4,0x09,0x28,0x7c,0xf4,0x76,0x00,0x7d,0xf2,0x8d,0x28,0x1b,0x14,0x2b,0xe1,0xa0,0xe2,0x3f,0x18,0x74,0xfa,0x08,0xa6,0x93,0xb0,0x86,0x64,0x3e,0xf2,0x1e,0xb5,0x9d,0x75,0x56,0x2d,0xa9,0x42,0x2d,0x13,0xd9,0xa3,0x9b,0x0b,0x17,0xe2,0x41,0xb0,0x4d,0x32, + 0x04,0xb7,0xcc,0x3e,0x23,0x06,0xdb,0xf7,0xc3,0x8f,0xf1,0x79,0x65,0x87,0x06,0xfe,0xff,0xb5,0xef,0xdb,0x60,0x44,0xc7,0xe7,0x14,0x35,0xd7,0xff,0x7d,0x0a,0xe8,0xc7,0xb3,0x77,0x13,0xfd,0xb0,0x3a,0x8d,0xe8,0xc6,0xd2,0x9c,0xa3,0x8a,0x9f,0xba,0xa8,0x2e,0x5e,0x02,0xbe,0xad,0x2f,0x9e,0xec,0x69,0xb6,0x44,0x4b,0x7a,0xdb,0x05,0x33,0x3b, + 0x04,0x5b,0xbe,0x7c,0x98,0x01,0x5f,0xd3,0xa6,0x03,0x4d,0x79,0xd8,0x67,0xa4,0xdc,0xd5,0x2f,0x95,0x91,0x19,0x32,0x12,0x9d,0xa2,0xfc,0x0a,0x58,0xaf,0xe1,0x49,0x13,0x7f,0x77,0x42,0x1a,0xb0,0x1e,0x00,0xe8,0x38,0x41,0xb9,0x46,0xda,0xe5,0xbb,0x5a,0x23,0x97,0x3d,0xaa,0x98,0xfe,0x1a,0x81,0x72,0x88,0x3a,0xbc,0xbe,0xdc,0xed,0x70,0x21, + 0x04,0x96,0x2f,0xe4,0x78,0x80,0xa9,0x4a,0x74,0x59,0x28,0xe3,0xc4,0xa2,0x9a,0x42,0xcb,0x01,0x33,0x4f,0x1e,0xe9,0x64,0x6e,0x62,0x45,0x1c,0x46,0xec,0xd7,0x2f,0x41,0x09,0x14,0xc1,0xaa,0xc5,0xf0,0xbf,0x1b,0x48,0xa4,0xab,0xcf,0x1d,0x92,0x91,0xb9,0xa8,0x77,0x6a,0x00,0x43,0x80,0x54,0x6a,0x5a,0x1c,0x1f,0x29,0x46,0x90,0xf6,0x19,0x69, + 0x04,0xc7,0x15,0x74,0xf5,0x53,0x8d,0xe5,0x65,0x3c,0x37,0x16,0x8d,0x47,0xa2,0xbc,0xf4,0x36,0x98,0xea,0x26,0x00,0x12,0xcd,0x0a,0xe1,0x30,0x4e,0x47,0x4c,0x63,0xa4,0xe6,0x3b,0xb7,0x32,0x88,0x39,0xd2,0xae,0xca,0xc6,0x4b,0x1c,0xdb,0x18,0x2f,0x08,0xad,0xcc,0xaa,0xc3,0x27,0xed,0x00,0x89,0x87,0xa1,0x0e,0xdc,0x97,0x32,0x41,0x3c,0xed, + 0x04,0xc6,0x02,0x44,0xce,0x30,0x6e,0x37,0x6f,0x39,0x68,0x17,0x8f,0x52,0x93,0x74,0x2d,0x7a,0x20,0xe1,0xdc,0x47,0xcf,0xc5,0x17,0xed,0xad,0xa9,0xdb,0x49,0xd0,0xcb,0xbf,0x9b,0x51,0xb1,0x7b,0x76,0xea,0x6c,0xc1,0x37,0xee,0xbd,0x93,0xc8,0x11,0xe6,0x36,0xd8,0xae,0x26,0xc7,0x0d,0x06,0x46,0x50,0xf7,0x20,0x5a,0x86,0x5d,0x01,0xa6,0xee, + 0x04,0xaa,0x3c,0x31,0x88,0xc0,0xad,0x57,0x67,0xa9,0xba,0xc7,0x7e,0x7c,0xee,0xa0,0x5c,0xfa,0xe1,0x59,0x9c,0xcd,0x77,0xb9,0xfc,0xbc,0x0c,0x3b,0xad,0xc8,0x0c,0x36,0xca,0x3f,0x18,0x74,0xfa,0x08,0xa6,0x93,0xb0,0x86,0x64,0x3e,0xf2,0x1e,0xb5,0x9d,0x75,0x56,0x2d,0xa9,0x42,0x2d,0x13,0xd9,0xa3,0x9b,0x0b,0x17,0xe2,0x41,0xb0,0x4d,0x32, + 0x04,0x2c,0xce,0x8d,0xdf,0xe4,0x82,0x7d,0xc0,0x30,0xdd,0xf3,0x8f,0x99,0x8b,0x3f,0x2e,0xd5,0xe0,0x62,0x1d,0x0b,0x38,0x05,0x66,0x6d,0xaf,0x48,0xc8,0xc3,0x1e,0x75,0xe5,0x19,0x8d,0x9e,0xf4,0xe9,0x73,0xb6,0xbd,0xeb,0xe1,0x19,0xa3,0x5f,0xaa,0xe8,0x61,0x91,0xac,0xd7,0x58,0xc1,0xed,0x8a,0xcc,0xaf,0x1e,0x70,0x6a,0xd5,0x5d,0x83,0xd7, + 0x04,0x14,0xbf,0xc3,0xe5,0xa4,0x6b,0x69,0x88,0x1a,0x9a,0x34,0x6d,0x95,0x89,0x44,0x18,0x61,0x4e,0xd9,0x14,0x76,0xa1,0xdd,0xce,0x48,0x67,0x6b,0x7c,0xba,0xb9,0xba,0x02,0xf3,0x34,0xd6,0x4f,0x2c,0xaf,0x56,0x1b,0x06,0x3b,0xc1,0xf7,0x88,0x9e,0x93,0x73,0x02,0xa4,0x55,0xff,0x68,0x5d,0x8a,0xe5,0x7c,0xb2,0x44,0x4a,0x17,0xda,0xd0,0x68, + 0x04,0xbd,0x44,0x2f,0xa5,0xa2,0xa8,0xd7,0x2e,0x13,0xe4,0x4f,0xd2,0x22,0x2c,0x85,0xa0,0x06,0xf0,0x33,0x75,0xe0,0x21,0x1b,0x27,0x2f,0x55,0x50,0x52,0xb0,0x3d,0xb7,0x50,0xbe,0x34,0x57,0x37,0xf7,0xc6,0xb5,0xe7,0x0e,0x97,0xd9,0xfe,0x9d,0xc4,0xca,0x94,0xfb,0x18,0x5f,0x4b,0x9d,0x2a,0x00,0xe0,0x86,0xc1,0xd4,0x72,0x73,0xb3,0x36,0x02, + 0x04,0x0d,0x7a,0x3f,0xf4,0x9b,0xda,0x6a,0x58,0x7e,0xd0,0x76,0x91,0x45,0x04,0x25,0xaa,0x02,0xd2,0x53,0xba,0x57,0x3a,0x16,0xad,0x86,0xc6,0x1a,0xf4,0x12,0xdd,0x3c,0x77,0x0b,0x6d,0x3b,0x9e,0x57,0x0b,0xa0,0x04,0x87,0x7c,0x9a,0x69,0xe4,0x81,0xfe,0x21,0x5d,0xe0,0x3a,0x70,0x12,0x63,0x05,0xa4,0x52,0x82,0x6e,0x66,0xd9,0xb5,0x58,0x3e, + 0x04,0xbd,0xea,0x5d,0x2a,0x3a,0xdd,0xe7,0xdf,0x2e,0x83,0x9f,0xf6,0x3f,0x62,0x53,0x4b,0x3f,0x27,0xcb,0x19,0x1b,0xb5,0x4d,0xfa,0x1d,0x39,0xcb,0xff,0x71,0x3b,0xa9,0xed,0x30,0x7d,0x8f,0x1d,0x02,0xc6,0xf0,0x71,0x46,0x65,0x5e,0x63,0x83,0xb0,0xef,0x30,0x35,0xbe,0xe7,0x06,0x7c,0x33,0x6f,0xdb,0x91,0x36,0x5e,0x19,0x7a,0x97,0xb6,0x16, + 0x04,0xd4,0xc0,0x63,0xe3,0xc0,0x36,0xf4,0x7c,0x92,0xf6,0xf5,0x47,0x0a,0x26,0xa8,0x35,0xe1,0xa2,0x45,0x05,0xb1,0x4d,0x1b,0x29,0x27,0x90,0x62,0xa1,0x6c,0xf6,0xf4,0x89,0x19,0x8d,0x9e,0xf4,0xe9,0x73,0xb6,0xbd,0xeb,0xe1,0x19,0xa3,0x5f,0xaa,0xe8,0x61,0x91,0xac,0xd7,0x58,0xc1,0xed,0x8a,0xcc,0xaf,0x1e,0x70,0x6a,0xd5,0x5d,0x83,0xd7, + 0x04,0x3c,0xb9,0xf0,0x79,0x97,0x75,0x68,0x59,0xe9,0xb9,0xa8,0x5b,0x68,0x1f,0xa5,0x0e,0xe2,0x03,0x57,0xf5,0x35,0xc1,0xb3,0x11,0xc4,0x63,0x7d,0x16,0xb7,0x6b,0x9e,0xbf,0xf3,0x34,0xd6,0x4f,0x2c,0xaf,0x56,0x1b,0x06,0x3b,0xc1,0xf7,0x88,0x9e,0x93,0x73,0x02,0xa4,0x55,0xff,0x68,0x5d,0x8a,0xe5,0x7c,0xb2,0x44,0x4a,0x17,0xda,0xd0,0x68, + 0x04,0x79,0x34,0x12,0xff,0x63,0x6c,0x08,0xa2,0xd0,0xf6,0xd6,0x0c,0xc6,0x08,0xe9,0xa9,0x09,0x83,0x49,0xa2,0x50,0x1f,0x91,0xc9,0x5f,0x69,0x20,0x10,0xbc,0x12,0x38,0xb2,0xbe,0x34,0x57,0x37,0xf7,0xc6,0xb5,0xe7,0x0e,0x97,0xd9,0xfe,0x9d,0xc4,0xca,0x94,0xfb,0x18,0x5f,0x4b,0x9d,0x2a,0x00,0xe0,0x86,0xc1,0xd4,0x72,0x73,0xb3,0x36,0x02, + 0x04,0xbd,0x1e,0xb0,0x84,0x9e,0x2e,0x6a,0x13,0xd5,0x4b,0x76,0x51,0x8f,0x11,0xba,0x87,0x75,0xc2,0xd7,0x63,0x4d,0x85,0x15,0x25,0x34,0xbc,0x7c,0x3a,0xf4,0x16,0x1e,0xfa,0x0b,0x6d,0x3b,0x9e,0x57,0x0b,0xa0,0x04,0x87,0x7c,0x9a,0x69,0xe4,0x81,0xfe,0x21,0x5d,0xe0,0x3a,0x70,0x12,0x63,0x05,0xa4,0x52,0x82,0x6e,0x66,0xd9,0xb5,0x58,0x3e, + 0x04,0x62,0x4b,0x3b,0x4b,0xa9,0x93,0xa8,0xb9,0x38,0x12,0x56,0x89,0xf6,0xcf,0x75,0x73,0x92,0xee,0x39,0x0d,0x14,0xa9,0x0f,0xea,0x6d,0xb9,0x44,0xb5,0xa8,0xde,0xb8,0xd0,0x30,0x7d,0x8f,0x1d,0x02,0xc6,0xf0,0x71,0x46,0x65,0x5e,0x63,0x83,0xb0,0xef,0x30,0x35,0xbe,0xe7,0x06,0x7c,0x33,0x6f,0xdb,0x91,0x36,0x5e,0x19,0x7a,0x97,0xb6,0x16, + 0x04,0xfe,0x71,0x0e,0x3c,0x5b,0x46,0x8d,0xc3,0x3c,0x2b,0x17,0x29,0x5c,0x4e,0x18,0x9b,0x48,0x7d,0x58,0xdd,0x43,0x7a,0xdf,0x70,0x6a,0xc0,0x54,0x93,0xcf,0xea,0x8d,0xf0,0x19,0x8d,0x9e,0xf4,0xe9,0x73,0xb6,0xbd,0xeb,0xe1,0x19,0xa3,0x5f,0xaa,0xe8,0x61,0x91,0xac,0xd7,0x58,0xc1,0xed,0x8a,0xcc,0xaf,0x1e,0x70,0x6a,0xd5,0x5d,0x83,0xd7, + 0x04,0xae,0x86,0x4b,0xa0,0xc4,0x1f,0x2e,0x1d,0xfb,0xac,0x23,0x37,0x02,0x57,0x16,0xd8,0xbc,0xad,0xce,0xf6,0x53,0x9c,0x6f,0x1f,0xf3,0x35,0x17,0x6b,0x8d,0xda,0xa3,0x6e,0xf3,0x34,0xd6,0x4f,0x2c,0xaf,0x56,0x1b,0x06,0x3b,0xc1,0xf7,0x88,0x9e,0x93,0x73,0x02,0xa4,0x55,0xff,0x68,0x5d,0x8a,0xe5,0x7c,0xb2,0x44,0x4a,0x17,0xda,0xd0,0x68, + 0x04,0xc9,0x87,0xbd,0x5a,0xf9,0xeb,0x20,0x2f,0x1b,0x24,0xda,0x21,0x17,0xca,0x90,0xb6,0xef,0x8c,0x82,0xe7,0xcf,0xbf,0x53,0x0f,0x71,0x41,0x8f,0x9a,0x93,0xb0,0x08,0x5c,0xbe,0x34,0x57,0x37,0xf7,0xc6,0xb5,0xe7,0x0e,0x97,0xd9,0xfe,0x9d,0xc4,0xca,0x94,0xfb,0x18,0x5f,0x4b,0x9d,0x2a,0x00,0xe0,0x86,0xc1,0xd4,0x72,0x73,0xb3,0x36,0x02, + 0x04,0x35,0x67,0x0f,0x86,0xc5,0xf7,0x2b,0x93,0xab,0xe4,0x13,0x1d,0x2b,0xea,0x1f,0xce,0x87,0x6a,0xd4,0xe2,0x5b,0x40,0xd4,0x2d,0x44,0x7d,0x68,0xcf,0xf9,0x0c,0xa0,0xbe,0x0b,0x6d,0x3b,0x9e,0x57,0x0b,0xa0,0x04,0x87,0x7c,0x9a,0x69,0xe4,0x81,0xfe,0x21,0x5d,0xe0,0x3a,0x70,0x12,0x63,0x05,0xa4,0x52,0x82,0x6e,0x66,0xd9,0xb5,0x58,0x3e, + 0x04,0xdf,0xca,0x67,0x8a,0x1b,0x8e,0x6f,0x67,0x99,0x6a,0x09,0x7f,0xc9,0xce,0x37,0x41,0x2d,0xe9,0xfb,0xd9,0xcf,0xa1,0xa2,0x1b,0x75,0x0c,0xef,0x48,0xe5,0xe5,0x95,0xa1,0x30,0x7d,0x8f,0x1d,0x02,0xc6,0xf0,0x71,0x46,0x65,0x5e,0x63,0x83,0xb0,0xef,0x30,0x35,0xbe,0xe7,0x06,0x7c,0x33,0x6f,0xdb,0x91,0x36,0x5e,0x19,0x7a,0x97,0xb6,0x16, + 0x04,0x32,0xbd,0xd9,0x78,0xeb,0x62,0xb1,0xf3,0x69,0xa5,0x6d,0x09,0x49,0xab,0x85,0x51,0xa7,0xad,0x52,0x7d,0x96,0x02,0xe8,0x91,0xce,0x45,0x75,0x86,0xc2,0xa8,0x56,0x9e,0x98,0x1e,0x67,0xfa,0xe0,0x53,0xb0,0x3f,0xc3,0x3e,0x1a,0x29,0x1f,0x0a,0x3b,0xeb,0x58,0xfc,0xeb,0x2e,0x85,0xbb,0x12,0x05,0xda,0xce,0xe1,0x23,0x2d,0xfd,0x31,0x6b, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e, + 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2e, + 0x04,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2f, + 0x04,0x49,0xc2,0x48,0xed,0xc6,0x59,0xe1,0x84,0x82,0xb7,0x10,0x57,0x48,0xa4,0xb9,0x5d,0x3a,0x46,0x95,0x2a,0x5b,0xa7,0x2d,0xa0,0xd7,0x02,0xdc,0x97,0xa6,0x4e,0x99,0x79,0x9d,0x8c,0xff,0x7a,0x5c,0x4b,0x92,0x5e,0x43,0x60,0xec,0xe2,0x5c,0xcf,0x30,0x7d,0x7a,0x9a,0x70,0x63,0x28,0x6b,0xbd,0x16,0xef,0x64,0xc6,0x5f,0x54,0x67,0x57,0xe4, + 0x04,0x49,0xc2,0x48,0xed,0xc6,0x59,0xe1,0x84,0x82,0xb7,0x10,0x57,0x48,0xa4,0xb9,0x5d,0x3a,0x46,0x95,0x2a,0x5b,0xa7,0x2d,0xa0,0xd7,0x02,0xdc,0x97,0xa6,0x4e,0x99,0x79,0x9d,0x8c,0xff,0x7a,0x5c,0x4b,0x92,0x5e,0x43,0x60,0xec,0xe2,0x5c,0xcf,0x30,0x7d,0x7a,0x9a,0x70,0x63,0x28,0x6b,0xbd,0x16,0xef,0x64,0xc6,0x5f,0x54,0x67,0x57,0xe2, + 0x04,0x07,0x4f,0x56,0xdc,0x2e,0xa6,0x48,0xef,0x89,0xc3,0xb7,0x2e,0x23,0xbb,0xd2,0xda,0x36,0xf6,0x02,0x43,0xe4,0xd2,0x06,0x7b,0x70,0x60,0x4a,0xf1,0xc2,0x16,0x5c,0xec,0x2f,0x86,0x60,0x3d,0x60,0xc8,0xa6,0x11,0xd5,0xb8,0x4b,0xa3,0xd9,0x1d,0xfe,0x1a,0x48,0x08,0x25,0xbc,0xc4,0xaf,0x3b,0xcf, + 0x04,0xcb,0xf6,0x60,0x65,0x95,0xa3,0xee,0x50,0xf9,0xfc,0xea,0xa2,0x79,0x8c,0x27,0x40,0xc8,0x25,0x40,0x51,0x6b,0x4e,0x5a,0x7d,0x36,0x1f,0xf2,0x4e,0x9d,0xd1,0x53,0x64,0xe5,0x40,0x8b,0x2e,0x67,0x9f,0x9d,0x53,0x10,0xd1,0xf6,0x89,0x3b,0x36,0xce,0x16,0xb4,0xa5,0x07,0x50,0x91,0x75,0xfc,0xb5,0x2a,0xea,0x53,0xb7,0x81,0x55,0x6b,0x39, + 0x04,0xfb,0x60,0x75,0xd2,0x6c,0x35,0x01,0xc0,0x14,0xe4,0x8c,0x79,0xb3,0x46,0x3c,0xd7,0x68,0x37,0x8c,0x39,0x0d,0x7e,0x6e,0xeb,0x37,0x97,0x17,0xd4,0x90,0xc4,0xe6,0x34,0x78,0x04,0x35,0x77,0x19,0x79,0x87,0x88,0x16,0x70,0xbc,0x13,0xfd,0x0b,0x5f,0x0b,0xa1,0x0f,0x06,0xbc,0xef,0x27,0x11,0xc2,0x8f,0x5e,0xfd,0x7e,0x31,0xd5,0x15,0x7c, + 0x02,0x97,0x7c,0xb7,0xfb,0x9a,0x0e,0xc5,0xb2,0x08,0xe8,0x11,0xd6,0xa0,0x79,0x5e,0xb7,0x8d,0x76,0x42,0xe3,0xca,0xc4,0x2a,0x80,0x1b,0xcc,0x8f,0xc0,0xf0,0x64,0x72,0xd4}; + +static const unsigned char wycheproof_ecdh_shared_secrets[] = { 0x54,0x4d,0xfa,0xe2,0x2a,0xf6,0xaf,0x93,0x90,0x42,0xb1,0xd8,0x5b,0x71,0xa1,0xe4,0x9e,0x9a,0x56,0x14,0x12,0x3c,0x4d,0x6a,0xd0,0xc8,0xaf,0x65,0xba,0xf8,0x7d,0x65, + 0x54,0x4d,0xfa,0xe2,0x2a,0xf6,0xaf,0x93,0x90,0x42,0xb1,0xd8,0x5b,0x71,0xa1,0xe4,0x9e,0x9a,0x56,0x14,0x12,0x3c,0x4d,0x6a,0xd0,0xc8,0xaf,0x65,0xba,0xf8,0x7d,0x65, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xfc,0x2c, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x0b,0x7b,0xeb,0xa3,0x4f,0xeb,0x64,0x7d,0xa2,0x00,0xbe,0xd0,0x5f,0xad,0x57,0xc0,0x34,0x8d,0x24,0x9e,0x2a,0x90,0xc8,0x8f,0x31,0xf9,0x94,0x8b,0xb6,0x5d,0x52,0x07, + 0x21,0x0c,0x79,0x05,0x73,0x63,0x23,0x59,0xb1,0xed,0xb4,0x30,0x2c,0x11,0x7d,0x8a,0x13,0x26,0x54,0x69,0x2c,0x3f,0xee,0xb7,0xde,0x3a,0x86,0xac,0x3f,0x3b,0x53,0xf7, + 0x42,0x18,0xf2,0x0a,0xe6,0xc6,0x46,0xb3,0x63,0xdb,0x68,0x60,0x58,0x22,0xfb,0x14,0x26,0x4c,0xa8,0xd2,0x58,0x7f,0xdd,0x6f,0xbc,0x75,0x0d,0x58,0x7e,0x76,0xa7,0xee, + 0x39,0xf8,0x83,0xf1,0x05,0xac,0x7f,0x09,0xf4,0xe7,0xe4,0xdc,0xc8,0x4b,0xc7,0xff,0x4b,0x3b,0x74,0xf3,0x01,0xef,0xaa,0xaf,0x8b,0x63,0x8f,0x47,0x72,0x0f,0xda,0xec, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x50, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33, + 0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcb, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0c, + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, + 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff, + 0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00, + 0x7f,0xff,0x00,0x01,0xff,0xfc,0x00,0x07,0xff,0xf0,0x00,0x1f,0xff,0xc0,0x00,0x7f,0xff,0x00,0x01,0xff,0xfc,0x00,0x07,0xff,0xf0,0x00,0x1f,0xff,0xc0,0x00,0x7f,0xff, + 0x80,0x00,0xff,0xfe,0x00,0x03,0xff,0xf8,0x00,0x0f,0xff,0xe0,0x00,0x3f,0xff,0x80,0x00,0xff,0xfe,0x00,0x03,0xff,0xf8,0x00,0x0f,0xff,0xe0,0x00,0x3f,0xff,0x7f,0xff, + 0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xfd, + 0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xfe,0xff,0xfe, + 0x80,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x07,0xff,0xff,0xfe,0x00,0x00,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x1f,0xff,0xff,0xf8,0x00,0x00,0x03,0xff,0xff,0xfd, + 0x7f,0xff,0xff,0xe0,0x00,0x00,0x0f,0xff,0xff,0xfc,0x00,0x00,0x01,0xff,0xff,0xff,0x80,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x07,0xff,0xff,0xfd,0xff,0xff,0xfe, + 0x00,0x00,0x03,0xff,0xff,0xff,0x00,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x03,0xff,0xff,0xff,0x00,0x00,0x00,0x3f,0xff,0xff,0xf0,0x00,0x00,0x03,0xff,0xff,0xfc, + 0xff,0xff,0xfc,0x00,0x00,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x0f,0xff,0xff,0xfc,0x00,0x00,0x00,0xff,0xff,0xff,0xc0,0x00,0x00,0x0f,0xff,0xff,0xfb,0xff,0xff,0xfe, + 0xff,0xff,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff, + 0x00,0x00,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xbf,0xff,0xff,0xfd, + 0xff,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x7f,0xff,0xff,0xfd, + 0x00,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0x80,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5, + 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x54,0xff,0xff,0xfe,0xbc, + 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x32,0xff,0xff,0xff,0x3c, + 0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x92,0x49,0x24,0x6d,0xb6,0xda,0xe2, + 0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x71,0xc7,0x1c,0x55,0x55,0x54,0xe8, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0xa2,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x7c,0x07,0xb1,0x99,0xb6,0xa6,0x2e,0x7a,0xc6,0x46,0xc7,0xe1,0xde,0xe9,0x4a,0xca,0x55,0xde,0x1a,0x97,0x25,0x1d,0xdf,0x92,0xfc,0xd4,0xfe,0x01,0x45,0xb4,0x0f,0x12, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x03,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24,0xdc,0xb0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x52,0x06,0xc3,0xde,0x46,0x94,0x9b,0x9d,0xa1,0x60,0x29,0x5e,0xe0,0xaa,0x14,0x2f,0xe3,0xe6,0x62,0x9c,0xc2,0x5e,0x2d,0x67,0x1e,0x58,0x2e,0x30,0xff,0x87,0x50,0x82, + 0x8a,0x8c,0x18,0xb7,0x8e,0x1b,0x1f,0xcf,0xd2,0x2e,0xe1,0x8b,0x4a,0x3a,0x9f,0x39,0x1a,0x3f,0xdf,0x15,0x40,0x8f,0xb7,0xf8,0xc1,0xdb,0xa3,0x3c,0x27,0x1d,0xbd,0x2f, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0x03,0x7e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x24,0xdc,0xb0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x52,0x06,0xc3,0xde,0x46,0x94,0x9b,0x9d,0xa1,0x60,0x29,0x5e,0xe0,0xaa,0x14,0x2f,0xe3,0xe6,0x62,0x9c,0xc2,0x5e,0x2d,0x67,0x1e,0x58,0x2e,0x30,0xff,0x87,0x50,0x82, + 0x8a,0x8c,0x18,0xb7,0x8e,0x1b,0x1f,0xcf,0xd2,0x2e,0xe1,0x8b,0x4a,0x3a,0x9f,0x39,0x1a,0x3f,0xdf,0x15,0x40,0x8f,0xb7,0xf8,0xc1,0xdb,0xa3,0x3c,0x27,0x1d,0xbd,0x2f, + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x12,0x6b,0x54,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xe5,0x9d,0xdc,0x76,0x46,0xe4,0xae,0xf0,0x62,0x3c,0x71,0xc4,0x86,0xf2,0x4d,0x5d,0x32,0xf7,0x25,0x7e,0xf3,0xda,0xb8,0xfa,0x52,0x4b,0x39,0x4e,0xae,0x19,0xeb,0xe1, + 0x12,0xc2,0xad,0x36,0xa5,0x9f,0xda,0x5a,0xc4,0xf7,0xe9,0x7f,0xf6,0x11,0x72,0x8d,0x07,0x48,0xac,0x35,0x9f,0xca,0x9b,0x12,0xf6,0xd4,0xf4,0x35,0x19,0x51,0x64,0x87, + 0x45,0xaa,0x96,0x66,0x75,0x78,0x15,0xe9,0x97,0x41,0x40,0xd1,0xb5,0x71,0x91,0xc9,0x2c,0x58,0x8f,0x6e,0x56,0x81,0x13,0x1e,0x0d,0xf9,0xb3,0xd2,0x41,0x83,0x1a,0xd4, + 0xb9,0x09,0x64,0xc0,0x5e,0x46,0x4c,0x23,0xac,0xb7,0x47,0xa4,0xc8,0x35,0x11,0xe9,0x30,0x07,0xf7,0x49,0x9b,0x06,0x5c,0x8e,0x8e,0xcc,0xec,0x95,0x5d,0x87,0x31,0xf4, + 0xe9,0x7f,0xb4,0xc4,0xfb,0x33,0xd6,0xa1,0x14,0xda,0x6e,0x0d,0x18,0x0e,0x54,0xf9,0x9e,0xc1,0xec,0xe9,0xff,0x55,0x88,0x71,0x05,0x4e,0x99,0xd2,0x21,0x93,0x0d,0x16, + 0x1e,0xea,0x9c,0x27,0x56,0xa3,0x30,0x5b,0xb5,0x17,0x8f,0x2c,0x37,0x43,0x6e,0x7b,0x41,0xcf,0x38,0x05,0xcd,0x0a,0x10,0x87,0xd2,0xd0,0x24,0x07,0xfc,0x55,0x3c,0x09, + 0x2f,0x1c,0x5c,0x59,0x0f,0x97,0xf7,0x93,0x51,0xfb,0x9d,0x36,0xc5,0x97,0xd1,0xc6,0x1f,0x1c,0x40,0x9f,0xcd,0xed,0xae,0xae,0x79,0x51,0x12,0xfa,0x1a,0x2c,0x74,0x53, + 0x82,0xb8,0xe9,0x0e,0x6b,0x64,0x41,0xb7,0x16,0x4c,0x97,0x25,0xac,0x1a,0x35,0xf0,0x98,0x78,0x80,0x96,0xaf,0x95,0xc2,0x76,0xfa,0xc3,0xc5,0xa3,0x83,0xd6,0xb5,0x6c, + 0x8a,0x95,0x5b,0x6c,0xf4,0xd5,0x18,0x55,0x8e,0x59,0x37,0x24,0x44,0xd3,0xfd,0x9b,0x78,0x93,0x3e,0x2d,0x32,0x29,0xdf,0xdf,0xa6,0xf5,0xf6,0x64,0x03,0x29,0x0e,0x19, + 0x56,0x26,0xbb,0xf7,0x9f,0x10,0x82,0x7e,0x23,0xfa,0x5a,0xef,0x9a,0x26,0x53,0x3f,0x5f,0x4e,0x74,0x72,0x93,0x4e,0xd9,0x75,0x9b,0x7b,0x3a,0x77,0xcd,0xa0,0x4b,0x82, + 0x19,0x08,0xae,0x93,0x6f,0x53,0xb9,0xa8,0xa2,0xd0,0x97,0x07,0xae,0x41,0x40,0x84,0x09,0x0b,0x17,0x53,0x65,0x40,0x14,0x25,0x47,0x9b,0x10,0xb8,0xc3,0xe8,0xd1,0xba, + 0x5e,0x13,0xb3,0xdc,0x04,0xe3,0x3f,0x18,0xd1,0x28,0x6c,0x60,0x6c,0xb0,0x19,0x17,0x85,0xf6,0x94,0xe8,0x2e,0x17,0x79,0x61,0x45,0xc9,0xe7,0xb4,0x9b,0xc2,0xaf,0x58, + 0xa9,0x95,0x57,0x2a,0xd1,0x74,0x89,0x7f,0xf1,0x97,0x1e,0x6d,0x1e,0x39,0xf9,0x08,0x44,0x8a,0x58,0x78,0xda,0x1e,0x60,0xf3,0x90,0x1f,0x57,0xca,0xcd,0x49,0xe5,0xf6, + 0xcd,0x84,0x27,0xea,0x93,0xf9,0xfe,0xde,0x38,0xa7,0x0d,0x0c,0x39,0xdb,0xd9,0x67,0x59,0x61,0x3b,0xa0,0x0f,0x27,0xb9,0xdb,0x39,0x71,0xc8,0x0a,0xec,0x07,0xe2,0xd6, + 0x76,0x6b,0x07,0x52,0xcd,0x89,0x5b,0x4b,0x85,0x43,0xd4,0x4c,0x9a,0x34,0x88,0x68,0xff,0xff,0x12,0xae,0xd6,0x32,0xf8,0x07,0x0e,0x73,0x1d,0x45,0x0d,0x8a,0x8c,0x94, + 0x09,0xb0,0xaa,0x83,0x98,0x93,0xb7,0xad,0x37,0xcc,0x83,0x16,0x0e,0x6f,0x3c,0x55,0x06,0xbb,0xe3,0x23,0x49,0x7c,0x21,0x50,0x5a,0xe9,0x93,0x7c,0x75,0xd9,0x43,0xc8, + 0x3c,0x2a,0x61,0x12,0x1f,0x09,0x4d,0x5e,0xec,0xdd,0xf7,0xd3,0xb0,0x01,0x6c,0x17,0x0b,0x90,0xfd,0x3f,0x2f,0xea,0x0b,0x12,0xe3,0x1d,0xb0,0x4a,0xe7,0xc2,0x79,0xa2, + 0x9a,0x64,0x1d,0x5e,0xfa,0x8b,0xe7,0xdc,0x72,0x3a,0xa5,0x8e,0x2e,0x52,0xa1,0x50,0xc8,0xef,0xce,0xd2,0xfa,0x10,0x84,0x04,0x12,0x49,0x77,0x3c,0x75,0x62,0xc6,0x6d, + 0xd3,0x29,0x77,0xec,0xa6,0x4d,0x22,0x3e,0xa9,0x0f,0x10,0xf7,0x2f,0x81,0x0e,0xc6,0x4d,0x66,0x18,0x33,0xac,0xc4,0xc8,0x39,0x59,0x1d,0xa8,0x13,0xef,0x86,0xf7,0x36, + 0x55,0x13,0x7f,0xec,0xb2,0x1e,0xb3,0xeb,0xed,0x1b,0x41,0xfb,0x2f,0x7e,0x1c,0xa3,0x37,0x00,0x94,0x65,0xf8,0x55,0xf3,0xf9,0x20,0xbc,0x7d,0x0b,0x73,0xc2,0xda,0x32, + 0x0b,0xde,0x65,0x9e,0xd8,0x92,0x81,0xe6,0xc8,0xa5,0xfb,0xda,0xb7,0x64,0xd0,0x49,0x9b,0x86,0xd1,0x9d,0x33,0xf4,0xc9,0x78,0xe2,0x60,0xbb,0xae,0x58,0x7d,0x40,0x57, + 0x31,0x35,0xa6,0x28,0x3b,0x97,0xe7,0x53,0x7a,0x8b,0xc2,0x08,0xa3,0x55,0xc2,0xa8,0x54,0xb8,0xee,0x6e,0x42,0x27,0x20,0x67,0x30,0xe6,0xd7,0x25,0xda,0x04,0x4d,0xee, + 0x2a,0x3d,0x29,0xce,0x04,0x9f,0xc5,0x0b,0x00,0xfa,0xb5,0x0e,0x75,0x81,0xb8,0x4d,0x44,0x1d,0x29,0x7b,0xe6,0x51,0x5f,0xbe,0x83,0xdc,0x48,0x5b,0xdf,0x32,0xb6,0xdc, + 0x03,0xc2,0x02,0xa6,0x4e,0x60,0xff,0x59,0x48,0xd2,0x98,0x16,0xd6,0x84,0x20,0xc6,0x4c,0x05,0x18,0xa7,0x52,0x2a,0x92,0x93,0x81,0x36,0x5b,0x12,0x45,0x77,0x0a,0x02, + 0xd0,0x7f,0xcf,0x7b,0x89,0xbd,0x1b,0xa2,0x41,0x94,0xca,0xf9,0x77,0xdb,0x68,0xa5,0x50,0x3a,0x47,0x1a,0x37,0xd3,0x74,0xe0,0x91,0x7a,0x5f,0xe3,0x1d,0x48,0xc9,0x9e, + 0xea,0x9f,0x3a,0x53,0xab,0x40,0x53,0xdf,0x0b,0xae,0x01,0x56,0x76,0x7a,0x62,0xec,0x5b,0xa0,0xde,0x43,0x73,0xef,0x12,0xcb,0xfb,0x19,0xaa,0x80,0xc6,0xbc,0xd9,0x04, + 0xf0,0x55,0x7b,0xe2,0xb2,0x6d,0xdb,0x56,0xd4,0x4d,0x2c,0xb8,0x52,0x22,0x4a,0x29,0x1d,0xe7,0x71,0x41,0x8f,0xe1,0x48,0xa7,0x30,0xa7,0x6d,0xad,0xf5,0x88,0x2f,0x18, + 0xc6,0x8f,0x07,0x23,0x3e,0xfd,0x07,0x45,0xd8,0xbc,0xd5,0x1a,0x89,0x15,0x87,0x17,0xc2,0xdc,0x53,0x2f,0x75,0xa9,0xe4,0xde,0x20,0x76,0xe1,0xb8,0x30,0x65,0x4e,0xc8, + 0x6e,0xec,0x8a,0x68,0xeb,0x5f,0x9c,0xaf,0x2a,0xb3,0x05,0x3a,0x30,0x47,0xbb,0xc0,0x84,0x12,0xa1,0xd4,0x33,0xd7,0x9e,0xea,0x65,0xef,0xfc,0x5e,0x0c,0xd5,0x83,0xbf, + 0xbb,0xd9,0xd3,0x05,0xb9,0x9f,0xf3,0xdb,0x56,0xf7,0x7f,0xea,0x9e,0x89,0xf3,0x22,0x60,0xee,0x73,0x26,0x04,0x00,0x67,0xce,0x05,0xdd,0x15,0xe0,0xdc,0xc1,0x3e,0xd8, + 0x1f,0x81,0xaa,0x3d,0x70,0xf8,0x75,0x6b,0x94,0x95,0xfb,0xa8,0x29,0x21,0x71,0x7d,0x40,0x06,0x20,0x6a,0x44,0x51,0xd8,0xd5,0x9f,0x3c,0x9b,0x8d,0x95,0xb5,0x48,0xe8, + 0x66,0xe7,0x07,0xfa,0xf9,0x54,0xd1,0xec,0x84,0xfe,0x0f,0x68,0xf8,0x29,0xbe,0xb2,0xfe,0x95,0x05,0x82,0x71,0xb6,0x36,0x36,0x2e,0x3e,0xb5,0xc5,0xd4,0x92,0xcb,0xf8, + 0x42,0xdd,0x6d,0x83,0xbb,0xce,0x6a,0xfa,0xb5,0x04,0x5e,0x13,0x93,0x83,0x8a,0x97,0xa4,0x61,0x61,0xc2,0x5a,0xe9,0x1d,0xb0,0x14,0x3e,0x98,0x5d,0x29,0x16,0x2f,0xaa, + 0xab,0x43,0x91,0x7a,0x64,0xc1,0xb0,0x10,0x15,0x96,0x43,0xc1,0x8e,0x2e,0xb0,0x6d,0x25,0xee,0xda,0xe5,0xb7,0x8d,0x02,0xfa,0x9b,0x3d,0xeb,0xac,0xbf,0x31,0xb7,0x77, + 0xf3,0x9b,0xf4,0x90,0x11,0xcb,0x32,0x3e,0xe0,0x0f,0x77,0xe0,0x34,0x4a,0x9b,0x9d,0xa1,0x25,0x6d,0xb9,0x26,0x46,0xdd,0xa0,0xe3,0x42,0xf8,0xc1,0xad,0x37,0x41,0xc5, + 0x27,0x86,0x0f,0xa0,0x67,0x9e,0xdd,0x45,0x56,0xf0,0x42,0x3a,0x21,0xcc,0x21,0xe1,0xe3,0xf1,0x70,0x1d,0xa3,0xe6,0x2a,0x54,0x49,0x74,0xae,0x94,0xf1,0x5f,0x91,0xa0, + 0x2b,0xcf,0xc9,0x5b,0xba,0x84,0x52,0x4d,0x80,0x93,0xdc,0xe1,0x09,0x2b,0xc1,0x57,0xca,0x1f,0xa4,0x2a,0x37,0xaa,0xca,0x9b,0x07,0x59,0x43,0x7f,0x94,0x0c,0x3e,0x7d, + 0x1a,0x32,0x74,0x9d,0xcf,0x04,0x7a,0x7e,0x06,0x19,0x4c,0xcb,0x34,0xd7,0xc9,0x53,0x8a,0x16,0xdd,0xab,0xee,0xed,0xe7,0x4b,0xea,0x5f,0x7e,0xf0,0x49,0x79,0xf7,0xf7, + 0x11,0x9a,0xa4,0x77,0xaf,0xad,0x55,0x0e,0x98,0xdb,0x77,0xbf,0xb4,0xe7,0x1a,0x4b,0x6e,0xc7,0x9e,0xc4,0xfe,0x17,0xb7,0x28,0x3f,0x9b,0x8b,0xb7,0xb9,0xfd,0xb5,0xec, + 0x21,0xed,0xb7,0x00,0xcf,0x62,0xc1,0xbb,0x81,0x6a,0x87,0x79,0x88,0xee,0x8c,0x5b,0xc1,0x6a,0x84,0x64,0xbc,0xb6,0x45,0x4a,0xdb,0x8a,0xbf,0x8b,0x5c,0xef,0x7c,0xeb, + 0x1b,0xa5,0x45,0x71,0xd1,0xd2,0x80,0xf5,0xfa,0x2d,0x0c,0x58,0x46,0xec,0x39,0x2c,0x72,0x1a,0xcd,0x4b,0xa7,0xe4,0xaa,0xdc,0x3d,0xc2,0x35,0x39,0x57,0xab,0xd8,0x0b, + 0x9d,0x42,0x2c,0xe4,0x2f,0x74,0xaa,0x02,0x72,0xe5,0x53,0x0b,0x5d,0xd0,0x94,0x22,0x5f,0x11,0xd1,0x10,0x0f,0xed,0x95,0x4f,0xf7,0x14,0xa2,0xd4,0x71,0x55,0x9c,0xef, + 0xa5,0xab,0x2c,0xc5,0xbb,0x68,0x81,0xf7,0xe7,0x34,0xd7,0xcc,0xc9,0xd4,0x48,0x12,0x7d,0x94,0x65,0xfd,0x34,0x2d,0x81,0xc8,0x38,0x15,0x72,0x05,0x9b,0x3a,0xa2,0xb7, + 0xe9,0x76,0x05,0x7e,0x8a,0x32,0x2d,0xfd,0xb2,0xde,0xbd,0x55,0xd8,0xe5,0x88,0x02,0xfb,0x54,0x42,0x59,0x50,0xb2,0xdb,0xfd,0x00,0xf0,0x81,0x3d,0xe2,0x71,0x05,0xe4, + 0x09,0xfa,0x5a,0x51,0x05,0x58,0xa1,0x21,0x10,0xda,0xf7,0x51,0x17,0xaf,0x1e,0x17,0x5f,0x93,0xd7,0xc4,0xd8,0xba,0x41,0xc5,0xbf,0x3e,0xfe,0x95,0xd8,0x29,0xff,0x50, + 0x98,0xbc,0x61,0x8f,0xae,0xf7,0xc4,0x31,0x1c,0x3d,0x8f,0xd3,0x7b,0x39,0xe9,0xba,0xad,0x78,0x0e,0x14,0xf0,0x52,0x7f,0xa6,0x9a,0x3f,0x4c,0x2b,0x66,0xac,0x63,0x94, + 0x8a,0x0b,0x2d,0xde,0xf3,0xa1,0x10,0x8f,0x6e,0xa3,0x67,0xed,0x08,0x07,0x9a,0x0e,0xc9,0x84,0x94,0xfe,0x46,0xcf,0xad,0x58,0x4b,0xdc,0x98,0xe9,0x9e,0x6d,0x7f,0x99, + 0x89,0xb8,0x63,0x29,0xf0,0xf1,0x3a,0xab,0x07,0xa4,0x8d,0x0d,0x3b,0x7a,0xfe,0x53,0x0a,0xd2,0x60,0xa9,0x0d,0xe6,0xc2,0x5e,0xc3,0xda,0x8b,0x69,0x05,0x50,0x25,0x51, + 0x75,0x1b,0x52,0x1d,0xe6,0x38,0x4a,0x01,0x7c,0xaa,0xfa,0x10,0x41,0x9f,0xc3,0x5d,0x58,0xf6,0xdb,0xac,0xe8,0x6f,0x6b,0x53,0x3c,0x11,0x7e,0x38,0xda,0xb1,0xd6,0x89, + 0xf2,0x82,0xa7,0x89,0x42,0x21,0x8f,0xac,0x63,0x8e,0xeb,0x0e,0xb1,0x50,0x98,0xf5,0xaa,0xba,0xe1,0x5b,0x3d,0xdb,0x7a,0xbd,0xd4,0x0a,0x8a,0xd3,0xb5,0x54,0x0c,0x8e, + 0x6a,0xeb,0x70,0x04,0xf6,0xcf,0x6b,0x05,0xf3,0x0b,0xf4,0x81,0xe8,0xb3,0x2a,0x1e,0x25,0xfc,0x66,0xd9,0x6a,0x4a,0x53,0x16,0x57,0x27,0xbb,0x30,0x4c,0xc2,0x7b,0xaa, + 0x67,0xb5,0xa9,0x92,0x6b,0xc5,0x80,0x25,0xc8,0xbc,0x2b,0x95,0x04,0xb7,0x2c,0x3a,0x84,0x65,0x17,0x3d,0x70,0xf5,0xd5,0xec,0x15,0x80,0xfe,0x88,0xc5,0xa4,0x88,0x7b, + 0x12,0x18,0x2c,0x05,0x56,0x8a,0x6b,0x18,0xa9,0x8e,0xa1,0x91,0x10,0x33,0x01,0x46,0xe7,0xdb,0xc4,0x92,0x74,0xf3,0x24,0xb5,0xed,0xef,0x4e,0xb8,0x61,0xf7,0x2b,0xec, + 0xf7,0x59,0x20,0xe6,0x1e,0x7d,0x05,0xc3,0xcf,0x41,0x07,0xe5,0xe8,0x1f,0x3c,0x1b,0xe7,0xff,0xb0,0x63,0x7f,0x0a,0xc8,0xb8,0x95,0xd8,0x73,0x61,0x34,0x5d,0x9a,0x87, + 0x37,0x3a,0xca,0x70,0xb0,0x36,0xb7,0x0c,0xf8,0xe4,0x6f,0xc9,0x45,0x7a,0x8e,0x19,0xc6,0x82,0x1b,0xe2,0xf2,0xd6,0xc1,0x6e,0xda,0xdd,0x20,0xd7,0xb3,0x0e,0xb3,0xba, + 0xca,0xec,0x9d,0xe4,0xa7,0x4d,0x76,0x60,0x3c,0x5d,0x5d,0x07,0xde,0x2d,0xf0,0xd4,0x35,0xbe,0xf2,0xb9,0x06,0x3b,0x51,0x23,0x30,0x5d,0x2f,0xcb,0xd5,0xdb,0xb3,0x18, + 0x27,0x98,0x05,0x11,0xf4,0x33,0xfe,0xea,0x84,0x47,0x5b,0x82,0x28,0x1b,0x1f,0xa6,0xb9,0x46,0xc9,0x7c,0x64,0x67,0x38,0xd5,0xac,0x33,0x45,0x25,0x0f,0x86,0x03,0x7d, + 0x20,0xb2,0x7f,0x84,0xae,0x12,0x8f,0x67,0x4e,0x14,0x4d,0x82,0xbc,0xd1,0x54,0x41,0x46,0xbf,0xd0,0x15,0x0b,0x08,0x43,0xea,0x58,0x53,0x14,0xf5,0x9c,0xc5,0x4a,0xae, + 0x92,0x59,0x27,0x91,0xff,0x90,0xb5,0x95,0xdd,0x2a,0xe7,0xec,0x03,0x9b,0xf6,0xb7,0xbf,0xea,0xe7,0xf0,0x44,0x76,0x1f,0x5e,0x7f,0xa8,0x65,0x64,0xeb,0xc4,0x6b,0x2b, + 0x8e,0x61,0xb2,0xe0,0x72,0xbd,0x14,0x01,0xda,0x12,0xa3,0xf3,0xd8,0x16,0x4d,0xae,0xda,0xb0,0xbf,0x0c,0xa7,0x95,0xbc,0xf5,0x6a,0xff,0x81,0xd0,0x7c,0xaf,0x72,0x81, + 0xa4,0x11,0x70,0xf6,0x16,0xc5,0x49,0x9e,0x28,0x9b,0x48,0x93,0xb3,0x97,0x3e,0x11,0x55,0xf6,0x6f,0xf3,0x54,0xae,0x6a,0x81,0x2b,0xcd,0x0e,0x33,0xbd,0x7d,0xd5,0xcc, + 0xb8,0xcb,0xc2,0x7d,0x4e,0xa1,0xb2,0x5f,0x22,0x92,0x29,0x2a,0xe5,0x3a,0x3b,0xb9,0x54,0xb7,0xca,0x77,0xcc,0xca,0x5b,0x4d,0xcc,0xf1,0xb9,0x58,0xb0,0xaa,0xd1,0x63, + 0x4b,0xaa,0xee,0x93,0xa7,0x52,0x39,0x7b,0xf2,0xad,0x0b,0xe7,0x2a,0xc8,0x2b,0x0a,0xd2,0x41,0x7e,0x16,0x7b,0xfd,0xfc,0xe4,0x90,0x4f,0x01,0x2d,0x4c,0x33,0xfe,0xa6, + 0x3b,0x3d,0x86,0x18,0x7d,0x05,0xa0,0x01,0x2d,0x83,0xbe,0x28,0x09,0x87,0xdc,0x95,0xb1,0xc0,0xc9,0xb5,0x7f,0x25,0x3b,0x64,0x53,0x0d,0x1d,0x42,0x20,0xaa,0x4a,0xbf, + 0x47,0x2d,0x4b,0x34,0xf5,0xbe,0x6b,0x49,0x9f,0x76,0xb0,0xd9,0xe4,0x39,0xe1,0x15,0xf6,0xa8,0x9b,0x72,0x5d,0x9e,0x9e,0x81,0x11,0x85,0xa6,0x15,0xf1,0x40,0x07,0xd0, + 0xfa,0x67,0xf4,0xa9,0xea,0x34,0xfd,0xe1,0x96,0xa7,0xdf,0xf6,0xbc,0x1a,0x29,0x17,0xb1,0x52,0x6d,0x54,0x95,0x03,0x35,0xbe,0xa2,0xab,0xe2,0x2e,0x1e,0xda,0xb4,0x10, + 0x95,0xc1,0x31,0xde,0x0c,0x89,0xe5,0xb1,0x7f,0x91,0xe5,0x67,0x79,0xc1,0x57,0x1d,0xe2,0xc8,0xa2,0x07,0x94,0x08,0x4f,0xa2,0x74,0xec,0xcc,0x8e,0xed,0x1d,0x3d,0x65, + 0x5b,0xae,0x6d,0x6d,0x23,0xa6,0x8f,0x28,0x3f,0xe0,0xde,0x46,0xf1,0xd7,0x4c,0x0f,0x52,0xe2,0x78,0xcb,0x18,0x1f,0x55,0xc4,0x35,0x3f,0x76,0x8b,0xa1,0x62,0xaa,0xc7, + 0xb4,0xfe,0x12,0x01,0xa8,0x64,0x7b,0xe6,0xd6,0xd5,0x9f,0x40,0x6f,0xa9,0x70,0xcc,0x85,0x8f,0x5a,0x46,0xa5,0x0a,0x6a,0xe9,0xd9,0x92,0xc0,0xe2,0x3f,0x5e,0x2a,0xd3, + 0xb7,0x21,0xeb,0xc7,0xeb,0x1b,0x09,0x43,0x8d,0x75,0x4a,0xe8,0x03,0x02,0xb2,0xa2,0xbf,0x40,0xf8,0x66,0xec,0x50,0x75,0x40,0xab,0x51,0x20,0xb2,0x2f,0x86,0x88,0x86, + 0xb8,0xda,0x5d,0x1b,0xf9,0x41,0x9e,0x2b,0x87,0x6e,0x70,0x88,0x71,0xa9,0xa2,0x95,0x74,0x68,0x66,0x89,0xba,0xe8,0xd8,0x79,0x85,0xd7,0x2a,0x4e,0x57,0x3d,0xde,0xd4, + 0x39,0xaa,0x2b,0xbc,0x4b,0x6f,0x30,0xc2,0x68,0xb1,0x99,0x09,0xd5,0x07,0x01,0x55,0xc3,0x9c,0x60,0x64,0x9b,0x7a,0x2e,0xbe,0xc2,0x66,0xbd,0xd1,0x8f,0xff,0x8c,0xbf, + 0xe4,0x03,0x96,0xa9,0x08,0xc2,0xcc,0xa4,0x50,0x4f,0x4f,0x40,0xbe,0x39,0x4a,0x12,0x24,0x4a,0xe1,0x84,0xf6,0x90,0x9e,0xc7,0x25,0xce,0x72,0x34,0x85,0xbb,0xbb,0x97, + 0x13,0xa2,0x1d,0xc5,0x0c,0xdf,0xae,0xab,0xd5,0x72,0xf2,0xd9,0x4d,0xc0,0xf3,0xf7,0x68,0xf1,0x7f,0x99,0x0e,0xe5,0x9d,0x7f,0x16,0xac,0xe9,0xbf,0xad,0x8a,0x70,0x5c, + 0xa8,0x2f,0xb3,0xbb,0xdf,0x6d,0x69,0xc7,0x39,0x8e,0xe9,0x02,0x0f,0xe0,0x06,0xd5,0xb2,0x8c,0x63,0x2f,0x2d,0xa3,0x57,0x39,0x3f,0xe5,0x8d,0xeb,0x8d,0x27,0xfd,0x08, + 0x8f,0xa4,0x4f,0x09,0xcf,0xdd,0xef,0x86,0xaa,0x90,0x07,0xcd,0x4b,0xea,0x6f,0x0b,0xc9,0xb5,0xb2,0x11,0x52,0x56,0x30,0x3d,0xf0,0x9f,0x8a,0x20,0x90,0x9c,0x52,0x71, + 0xef,0x76,0x29,0x92,0xd2,0x2b,0xac,0xaf,0x06,0xaa,0x1e,0x48,0x2c,0x07,0x11,0x04,0x6b,0x52,0xe0,0xe4,0x0d,0xe2,0xa2,0x1d,0x4e,0x38,0xdf,0x01,0x09,0xad,0x67,0xc0, + 0x3b,0x09,0x36,0xf2,0x23,0x37,0xec,0xe9,0x71,0xee,0x10,0x21,0x78,0xf3,0x7b,0xca,0x3c,0xb6,0x9b,0x50,0xb8,0xec,0x9c,0x9b,0x47,0x33,0x4c,0x68,0xb5,0xd4,0x32,0x0b, + 0xec,0x57,0x18,0x78,0xfb,0x1e,0x3b,0x1f,0x5d,0x4f,0x66,0xb8,0xb0,0x80,0xbd,0x4e,0x50,0x41,0x0b,0x6e,0xee,0xa4,0xdc,0xd3,0xce,0xdd,0x46,0x22,0xbf,0x87,0x61,0x60, + 0x9f,0x3d,0x9d,0xe8,0x7d,0x9c,0xc5,0x09,0x9f,0xf4,0xf5,0x6d,0x91,0x3b,0x98,0xb5,0xeb,0x12,0x60,0xe2,0xb3,0xa2,0xd7,0xa3,0xc5,0xe0,0x1a,0x7e,0x68,0x21,0x9d,0x10, + 0x23,0xad,0xda,0x65,0x71,0xd4,0xad,0x7e,0x94,0x0c,0x21,0x02,0x3a,0xf3,0xff,0xed,0xef,0x9d,0x8f,0x64,0xe8,0x3c,0xc1,0xcf,0x6e,0x99,0x2d,0x1d,0xa1,0x45,0x1d,0x91, + 0x91,0xe7,0x0b,0xd8,0xbf,0x85,0xbc,0x63,0x11,0xb2,0xcd,0x77,0x91,0xb7,0xed,0xf0,0x0e,0x22,0xf9,0xcb,0x8b,0xfd,0x72,0x57,0x1e,0xc9,0xa0,0x3b,0xbf,0x71,0x6f,0x37, + 0xa7,0xd2,0xf3,0xe3,0xfa,0xa7,0x72,0xd7,0xa8,0x60,0x26,0xe2,0xf1,0x83,0xdb,0xe7,0xa2,0x98,0xae,0x3d,0x1b,0xc3,0xab,0xce,0xa0,0xdf,0x3c,0x11,0xca,0xe4,0xca,0x60, + 0xc6,0x11,0xd2,0x7e,0x7c,0xb5,0x2e,0x7c,0x56,0xcf,0xa9,0x06,0x2e,0x59,0xf3,0xde,0xfe,0x7c,0x1e,0x22,0x57,0x27,0xb9,0x04,0x93,0x84,0xa1,0x80,0xbd,0x16,0x88,0xa8, + 0x66,0x1f,0x5d,0x36,0xb5,0x7a,0xf4,0x89,0x82,0xe4,0x4f,0xf8,0x9a,0xe7,0x5f,0x84,0x9a,0x08,0xb1,0xda,0xed,0x64,0x17,0xa2,0x02,0x12,0xbe,0xa8,0x8c,0x7f,0x2f,0x8a, + 0x54,0x0e,0x25,0x5f,0x6c,0xb5,0x8d,0x23,0x79,0x90,0xa7,0x43,0x7c,0xc7,0xaa,0xe7,0x70,0x42,0x87,0x96,0xde,0xb6,0x07,0xbc,0x29,0xfb,0xf0,0xa4,0xd1,0x18,0x73,0xc8, + 0xac,0x67,0x05,0xaf,0x9d,0x05,0x9c,0xac,0x99,0x77,0x96,0x7c,0x0c,0xe5,0x14,0xd7,0x0d,0xc5,0x1d,0x88,0xfd,0xe6,0x84,0x12,0x3a,0x92,0x12,0x44,0x93,0x3b,0xa8,0xec, + 0xf7,0xa5,0xb6,0x9b,0xc3,0x9a,0x97,0x6b,0xfa,0x66,0x44,0xa1,0x52,0x78,0x9c,0x31,0x49,0x35,0x20,0x93,0xb1,0xdc,0xc4,0xb6,0xb0,0x6f,0x6c,0x4c,0x7c,0x90,0xfd,0xf3, + 0xf0,0x58,0x7f,0xbd,0x10,0xe3,0x32,0xad,0x29,0x7b,0x5e,0x46,0x3d,0x4f,0x09,0xd2,0x16,0x7c,0x85,0x89,0xc4,0x6d,0xc6,0x68,0x0c,0x13,0xb0,0x44,0xa3,0x44,0x85,0xea, + 0x2f,0xb4,0x99,0x13,0x32,0xa5,0xd6,0x48,0xdf,0x5c,0xa6,0xbb,0xd0,0x85,0x75,0xc7,0x55,0x37,0x73,0xa9,0x73,0x12,0x30,0x34,0x40,0xcf,0xe7,0xe4,0x3d,0x3a,0x26,0x8c, + 0xcb,0x65,0x08,0x2d,0xf5,0xf5,0x4c,0xdc,0x66,0x86,0x25,0x01,0x7c,0xdf,0x45,0xf2,0x2f,0x30,0x5a,0x8f,0x34,0xad,0x91,0xfa,0xbf,0x36,0xc0,0x71,0x49,0x6c,0x84,0xcc, + 0x64,0x41,0xac,0x7b,0xe8,0x1c,0x2f,0xb6,0x47,0x26,0x55,0x52,0x8f,0x21,0x45,0x4d,0x40,0x23,0x6a,0x87,0x8f,0xba,0xc2,0xce,0x31,0xe4,0x35,0x8a,0xb4,0xed,0x02,0xcc, + 0x0b,0x58,0x6c,0x44,0x2e,0xaf,0x01,0x6f,0x38,0x21,0x99,0x72,0x9f,0x60,0x24,0x0c,0xe5,0x0c,0x0f,0x71,0x07,0xc4,0x88,0xa4,0x23,0xd4,0x27,0x94,0xdb,0x5f,0x66,0x63, + 0xb3,0x76,0xd9,0xbc,0x19,0x09,0xee,0xf9,0x29,0x53,0xce,0xbc,0x3b,0xd6,0xf2,0xbc,0x0c,0xd6,0xcc,0xa6,0x20,0xc1,0x90,0x14,0x17,0x40,0xf6,0x22,0x39,0x57,0x93,0x34, + 0xae,0x73,0x9f,0x62,0x4c,0xcb,0x1f,0x0e,0xc9,0x64,0xb2,0xd1,0x89,0x6d,0x2d,0xf8,0x3c,0xa1,0x96,0x9a,0xd6,0xca,0x26,0xb3,0x34,0x34,0x20,0x13,0xd8,0x32,0x82,0xaa, + 0x3c,0x25,0x12,0x6e,0xce,0x58,0xad,0x8e,0x93,0xeb,0xfe,0x6e,0x75,0x47,0xb0,0x5b,0x39,0xc6,0xd9,0x85,0x8e,0x55,0x9f,0xc0,0x1f,0xf6,0xb6,0xe5,0x0b,0x0a,0x22,0xac, + 0xe4,0x7d,0x65,0x8d,0xf5,0xc1,0xf9,0x59,0x9d,0x4e,0x56,0x09,0x54,0xab,0x86,0x0e,0x9a,0x63,0x77,0xde,0xcb,0x0b,0x56,0xef,0x3c,0x13,0xde,0xe3,0x61,0x85,0xb2,0xf3, + 0xd8,0x27,0x9c,0x1e,0xc9,0x51,0x89,0xfe,0x63,0xd7,0x5d,0x1c,0x6d,0x7f,0xc3,0x12,0xe4,0x11,0xa3,0xd1,0x1e,0x4d,0x67,0x1a,0x49,0xfa,0x17,0xfa,0x36,0xc3,0xce,0xe1, + 0x07,0x7c,0x7a,0x4e,0x60,0x60,0x99,0xd7,0x81,0xcb,0xe5,0xa8,0x9c,0xaf,0x7b,0xdf,0x4f,0x44,0x8b,0x1c,0x0d,0x7d,0x30,0x97,0x26,0x3a,0x04,0x51,0x70,0x27,0x5a,0x3a, + 0x20,0x25,0x80,0x8c,0x60,0x9a,0xb0,0xb0,0x79,0x24,0x44,0x4e,0xa4,0xaa,0x0f,0xa5,0x25,0x63,0x85,0x8a,0x53,0x22,0x1f,0x71,0x9c,0x91,0xb1,0x55,0x76,0xf4,0x9e,0xa2, + 0x98,0x32,0x40,0x5d,0x56,0x5c,0x97,0xba,0x1d,0x6f,0xf4,0x6e,0x1d,0x8f,0xe3,0x38,0x86,0x22,0x2c,0xba,0xa6,0x99,0x63,0x86,0x8d,0x12,0xa8,0xbe,0x07,0xab,0xac,0x6d, + 0xc4,0xbb,0xf4,0x45,0x47,0xe8,0x12,0x8b,0x9a,0x46,0xed,0x92,0xce,0xb0,0x7d,0xf6,0x91,0xe2,0xe9,0x1d,0x0b,0x47,0xda,0xc0,0xdc,0x2a,0xfd,0x14,0x12,0x1e,0x7a,0x80, + 0x17,0x0a,0x91,0xaa,0x81,0x96,0xdf,0x6f,0x0d,0x09,0xec,0x19,0x7f,0xc5,0x26,0x99,0x6f,0xfc,0xb6,0x79,0x28,0x80,0xf0,0x10,0x18,0xb3,0x32,0x7a,0x09,0x6f,0xe6,0x38, + 0xed,0x52,0x7e,0x31,0x22,0x3f,0x17,0x5a,0xa7,0x86,0xf1,0x46,0xb3,0xfe,0x05,0x61,0xa4,0x1b,0x10,0x51,0xd5,0xeb,0x32,0x24,0x97,0x90,0x48,0x1e,0xab,0x1e,0xf3,0x81, + 0x5a,0x74,0x55,0x57,0x32,0xd8,0x54,0x1d,0x2f,0x73,0xe3,0xa5,0x9e,0xb3,0x1a,0x13,0x1c,0x8d,0x41,0x46,0x4a,0x1f,0x2c,0x37,0x53,0x1a,0x25,0xf4,0xa6,0xd3,0xbf,0xe4, + 0xf2,0x75,0x0c,0x99,0x6f,0x22,0x76,0x26,0x29,0xa3,0xf8,0x08,0xda,0x6e,0xed,0xd7,0xcc,0x72,0xaf,0x4f,0xb0,0xbd,0x81,0x6c,0x86,0xe6,0x36,0x26,0x4b,0xf5,0x76,0x64, + 0x5d,0x21,0x63,0xca,0x85,0x07,0x49,0x99,0x1c,0xf7,0x82,0xc3,0x85,0x2e,0x86,0xb0,0x5e,0x6b,0x05,0xec,0x86,0x62,0x90,0x5b,0x60,0xcc,0x7b,0x7e,0x37,0x43,0x4f,0xbd, + 0xf8,0xcf,0x2c,0xcc,0xdc,0xb5,0x3b,0x3d,0x3c,0x6d,0x19,0x90,0xae,0x16,0xc7,0x1a,0xd9,0xd1,0x41,0xca,0x49,0xf8,0x57,0x4a,0x72,0x04,0x7c,0xe6,0xc2,0xda,0x95,0x0b, + 0xcc,0xf6,0xe1,0x4d,0x1a,0xdd,0x6e,0x4b,0x5a,0x42,0x28,0xe5,0xaa,0xd0,0xb3,0x1f,0xac,0x4b,0x45,0xe2,0x11,0x2c,0x1c,0x76,0x7e,0x93,0x3c,0x6a,0x0c,0x3f,0x2e,0xdb, + 0x57,0x55,0x64,0x59,0xe9,0xd3,0x2b,0x75,0xa1,0x37,0x76,0xbd,0xdc,0x8f,0x54,0x7c,0xb6,0x47,0x08,0x13,0x3e,0x79,0x17,0xb6,0x1e,0x36,0x97,0xc3,0x92,0x00,0x3d,0xe7, + 0xe5,0x49,0x0c,0xb4,0x94,0xbc,0x6a,0xb2,0x10,0x8d,0xa2,0xcb,0x0b,0x92,0x6c,0xd8,0x78,0x71,0x2f,0x54,0xbf,0xa7,0x2b,0x59,0xf7,0x02,0xc1,0x80,0xc6,0x2b,0x0c,0x91, + 0xb3,0xca,0x75,0x3c,0x1e,0x10,0x67,0xb5,0x50,0x73,0x6a,0x66,0xc0,0xd6,0xb6,0xf4,0x7e,0x93,0x94,0xc5,0x6b,0xb8,0x0b,0x5d,0x42,0x04,0xfb,0xec,0x9e,0x59,0xb4,0x90, + 0xb0,0xcf,0x8c,0x17,0x8a,0xd9,0x59,0x52,0x52,0x02,0x64,0xd0,0xf4,0xa2,0x43,0x89,0xbf,0x1b,0x23,0xdc,0x7a,0xc1,0xb6,0x5d,0x4e,0x8f,0xe8,0x22,0xdc,0xf2,0x0d,0x67, + 0x15,0xe4,0x0d,0xc4,0x9e,0xd6,0x2d,0x35,0xe8,0xc9,0x19,0x99,0xb0,0x50,0x68,0xf4,0x19,0x23,0x8a,0x22,0x2d,0xeb,0xa2,0x06,0xdf,0x47,0xd9,0x09,0xd3,0xa1,0xf4,0x0f, + 0xe9,0x45,0x80,0x64,0xd3,0xbf,0xc4,0x44,0x41,0x74,0x86,0xac,0x13,0x34,0xa9,0x3c,0x9a,0xa4,0x46,0x80,0x31,0x13,0x4e,0xe0,0x19,0x6c,0xa6,0xe3,0x17,0x13,0x95,0x6c, + 0xf4,0x44,0x6e,0x98,0xa6,0x3b,0x05,0x98,0x01,0x1b,0xaa,0xa4,0xf9,0x30,0x51,0x32,0x18,0xe8,0x37,0x0a,0xbf,0xbd,0x46,0xf7,0x21,0xc8,0xdb,0xf3,0x7e,0x17,0x0d,0x85, + 0xdc,0xa8,0x27,0x68,0x7a,0xa2,0x4f,0x2f,0xcb,0xca,0xb5,0xc3,0x80,0x69,0xf4,0x86,0x0d,0xee,0x66,0x98,0xfc,0x23,0x90,0x8b,0x06,0xc7,0xda,0xe7,0x13,0xa1,0x41,0xf9, + 0x19,0x71,0x4f,0x1d,0x4a,0xaf,0x8b,0xd6,0x15,0x20,0xb6,0x47,0x63,0x3a,0x8e,0x53,0x09,0x94,0x99,0xac,0x36,0x8c,0x3d,0xd6,0xf1,0xb0,0x84,0x89,0x16,0x19,0xb0,0xc0, + 0xd7,0xa2,0xda,0x8d,0xe2,0x43,0x4e,0x2a,0xd2,0x64,0xf9,0x70,0x6b,0x30,0xd0,0x65,0x7c,0x72,0x76,0x06,0xd8,0x28,0x5d,0x21,0x79,0x80,0x0a,0x97,0x0b,0x4f,0xae,0xe3, + 0x85,0x3d,0x4e,0x01,0xd4,0xdd,0x4c,0x9d,0x6e,0x78,0x20,0xad,0xc1,0x6f,0x32,0xce,0x7b,0xfe,0xec,0x0d,0x57,0x8d,0xea,0xf2,0x8a,0xf9,0xcb,0xb3,0x31,0x5e,0x8f,0x1b, + 0x35,0x71,0x5b,0xef,0xcf,0xde,0xd1,0x6e,0x67,0xfc,0x0d,0xce,0xbe,0x94,0x5c,0x62,0x64,0xca,0x0d,0x91,0xb3,0x66,0x3b,0xd3,0xec,0x07,0x22,0xb5,0x85,0xe5,0xd6,0x52, + 0x2b,0xaf,0x10,0x86,0x68,0xe8,0x2b,0x7f,0xca,0xf3,0xf5,0xe3,0x27,0x26,0x37,0xb4,0x26,0xc5,0x51,0xd8,0xaf,0x0e,0x55,0xf5,0xd7,0x4b,0xc3,0x17,0xa4,0x47,0x47,0x67, + 0xbb,0xa4,0x43,0xb1,0x60,0x99,0x7a,0xa8,0xb7,0xfb,0x27,0x48,0x91,0x1d,0xc2,0x15,0x4c,0x0f,0x6b,0x98,0x6f,0xbe,0x9a,0x49,0xe0,0xa2,0x93,0x4f,0xa5,0xf3,0x29,0x54, + 0xb4,0x83,0x17,0x36,0x60,0x1e,0x73,0x87,0x05,0x0b,0xa3,0xd4,0x01,0xae,0xa2,0x41,0xc3,0x50,0x6b,0x56,0xa0,0x47,0x38,0x86,0xc4,0x08,0xb3,0x66,0xc8,0x69,0x64,0x29, + 0xec,0xd0,0xc9,0xe1,0xac,0xb9,0x0f,0xf8,0xbd,0xe8,0x8f,0x77,0x57,0xa0,0x89,0xcc,0x86,0xcb,0xa2,0x7f,0x0d,0x15,0xfd,0xf7,0x37,0xab,0x3b,0x8e,0xcf,0x9f,0xd9,0xc8, + 0x6b,0x9e,0xe6,0x18,0x59,0x8f,0x33,0xc1,0x84,0xcd,0x63,0xcf,0x89,0x30,0xa4,0xdb,0x3a,0x2d,0x4e,0xa0,0x22,0xd5,0x0e,0x63,0xcd,0xff,0xf8,0x57,0x34,0xa7,0x7a,0xb4, + 0xd8,0x01,0xdc,0x93,0x54,0xcb,0x75,0x6e,0x6c,0x27,0xde,0x5a,0x7c,0xc8,0x8e,0xd5,0xcb,0x21,0x4a,0xc5,0x09,0x1b,0x40,0x90,0x62,0x4e,0xe8,0xaf,0xbc,0xba,0x35,0xf9, + 0x03,0x30,0x7e,0xa5,0x57,0x02,0x46,0x86,0x91,0x0d,0x2d,0x1d,0x2d,0x27,0x60,0xd8,0x26,0x64,0x41,0x3b,0x8f,0xee,0xc6,0x6a,0xe8,0xd2,0xdb,0xf1,0x02,0x5f,0x0c,0x45, + 0xdc,0x2c,0xd9,0x43,0x21,0x64,0x3e,0x89,0xdc,0xc9,0x2a,0xcb,0x01,0x28,0xd8,0x86,0xb2,0x8c,0xb7,0xd6,0x6a,0x0e,0xaa,0x5b,0x96,0x19,0x44,0x65,0x70,0x87,0x80,0xd6, + 0xb8,0x31,0xf4,0xa0,0xfb,0x75,0x92,0x7b,0xdd,0x29,0x45,0xc0,0x08,0x1f,0x11,0xcc,0xe8,0x71,0xc9,0xd6,0xdb,0xf8,0x3b,0x78,0x95,0x74,0x8c,0x3f,0x46,0x37,0x5a,0xc7, + 0xed,0x60,0x7a,0x9e,0x6d,0x41,0xa4,0xbc,0x05,0x35,0xc5,0x16,0x1c,0x98,0x61,0x3e,0xda,0xc6,0xb5,0x19,0x59,0x0b,0x48,0x14,0x20,0xfb,0x2b,0xa1,0xed,0x2c,0x35,0xe6, + 0x64,0xa6,0x8f,0xad,0x23,0x78,0x59,0x1a,0x18,0xf8,0xf2,0xa4,0xe3,0x46,0xfa,0xf5,0x9d,0xa2,0x94,0x46,0xec,0x16,0xb3,0xfb,0x8c,0x37,0xae,0xf2,0xd7,0x9f,0xae,0xa5, + 0x0f,0xdd,0xd5,0x0b,0xb2,0x76,0x66,0xd4,0xd3,0x8e,0x6e,0xc1,0x8c,0x8a,0xe1,0xbe,0x3d,0x76,0x3b,0xe7,0xdd,0x11,0x06,0x72,0x13,0xe9,0x97,0xfa,0x40,0x59,0xc6,0x7a, + 0x9c,0x41,0x20,0x23,0xb7,0xa6,0x6e,0xbc,0x95,0x79,0xa8,0xd1,0x6b,0xfd,0x31,0x09,0xba,0x08,0x5c,0x42,0xf3,0xfd,0x39,0x5e,0x07,0x53,0x45,0x29,0xad,0x23,0x40,0xa4, + 0x28,0x71,0x77,0x26,0xdc,0x36,0x74,0xab,0xb4,0xf8,0x2b,0x66,0x83,0x7e,0x86,0x85,0xed,0xe1,0x6c,0xb0,0xcd,0x96,0x58,0x24,0x35,0x2a,0xc0,0xa2,0xf9,0xd8,0x93,0xa7, + 0x2e,0x74,0x66,0x11,0x09,0xf0,0xcb,0xc6,0xd5,0x87,0x79,0x03,0x30,0xd6,0x79,0x88,0x65,0x8b,0xcf,0xab,0xf1,0xf7,0x49,0x8a,0x2b,0x32,0x79,0x21,0x28,0x28,0xe2,0x07, + 0xd2,0x02,0xdf,0x66,0x62,0xba,0x06,0xd3,0x08,0x83,0x63,0xc6,0x0e,0x34,0x12,0x83,0xf7,0xb6,0x30,0x01,0x04,0xd5,0x8c,0xf6,0xd7,0x07,0x26,0x2b,0xe6,0x97,0x2b,0x59, + 0xa5,0x4a,0x81,0xc1,0x8f,0x4b,0x7a,0xb0,0xf3,0x70,0x20,0x13,0x67,0x85,0x66,0xce,0x29,0xe9,0x1c,0x41,0x42,0x11,0x4d,0x62,0xf8,0x67,0xa5,0x27,0x8f,0x89,0xcf,0xff, + 0x9a,0x95,0x41,0x12,0xf5,0x2d,0x76,0x70,0x9d,0x64,0x73,0x9d,0xc7,0x5e,0x9c,0xe7,0xa7,0x6a,0xa1,0x92,0x42,0xb3,0x06,0x39,0x1f,0xcf,0x25,0xff,0x92,0xb7,0x69,0x01, + 0x87,0x63,0xcb,0x23,0x5f,0x27,0x80,0xc1,0xbb,0xd3,0x5f,0xe6,0xc3,0x87,0xd5,0x50,0x5f,0x72,0xeb,0x0a,0x77,0xb1,0x04,0xc7,0x75,0xc2,0xb3,0xb4,0x27,0x86,0xd7,0xc9, + 0xb9,0x30,0x9d,0xdc,0x5e,0xb6,0x4a,0x4d,0x81,0x9a,0x8a,0x33,0x2b,0x06,0x1a,0x59,0xf1,0x63,0xa5,0xf5,0x0d,0x48,0x65,0x69,0x7e,0x4d,0x12,0x3e,0xfc,0x9b,0x2b,0x29, + 0x87,0xe9,0xf5,0xec,0x4a,0x90,0x91,0xd9,0x4a,0xc2,0x2a,0x6a,0x71,0x40,0x82,0x13,0xf4,0x44,0xbe,0x09,0x4c,0x61,0x8d,0x45,0x96,0x82,0xe1,0x73,0x57,0x63,0x19,0x39, + 0xc6,0x9a,0x00,0x01,0x71,0x84,0xa1,0x3c,0x71,0x3c,0xc0,0xa7,0x0e,0x89,0xc6,0x01,0x74,0x36,0x1d,0x07,0xde,0xa5,0x08,0x5f,0xd7,0x07,0xf4,0xb5,0xed,0x3f,0xae,0xad, + 0xc1,0x39,0xb7,0x56,0x15,0xe1,0x01,0x0c,0x92,0x0b,0x07,0xd1,0x4f,0x6a,0x19,0x80,0xff,0x4c,0x97,0xa0,0xa9,0xbb,0x8a,0x09,0x7a,0xec,0x2a,0x45,0x6b,0x6b,0xc4,0xed, + 0x70,0xaa,0xb5,0xe9,0x6e,0x49,0x91,0x32,0x1f,0xaf,0x44,0x0c,0xa2,0xde,0xa8,0x61,0xba,0x00,0x7d,0xf0,0x8e,0xe4,0x6c,0x6f,0x57,0x97,0x31,0xea,0xd5,0x16,0x36,0xda, + 0xe2,0xae,0x03,0xb8,0x44,0xb3,0xf2,0x79,0xd5,0xcd,0x16,0xbf,0xf2,0x0a,0xb5,0xca,0xd0,0x7e,0x4c,0x98,0x4f,0x21,0xcb,0xe7,0x3e,0x19,0x97,0xa0,0x2b,0xd2,0xc2,0x91, + 0x0a,0xab,0x6b,0x19,0xe4,0x20,0x55,0x48,0xf9,0x29,0x36,0x2e,0x72,0xb0,0x77,0xf2,0x36,0x56,0x67,0xbd,0xd8,0x1d,0x93,0xa4,0x04,0x34,0x3e,0x7a,0x5f,0x84,0xc6,0xba, + 0xd9,0x6c,0xdd,0x08,0xe6,0xee,0xec,0xa6,0x90,0x98,0x9b,0x65,0x90,0x24,0xf3,0x24,0xe1,0x8c,0x2f,0xaf,0x5c,0x50,0x95,0x8d,0xa6,0x98,0x5f,0x70,0x82,0x60,0x95,0xc5, + 0x43,0x4b,0xd6,0x8e,0x45,0x63,0x0c,0xa1,0xb3,0x48,0x45,0x17,0xda,0x08,0x0e,0x3c,0x31,0x98,0xdd,0xec,0x5e,0xf1,0xf7,0xe9,0xd2,0xe3,0x42,0x5d,0xf2,0x14,0xb9,0x0d, + 0xae,0xa4,0x74,0x44,0xc8,0x97,0xf7,0x15,0x7f,0x33,0x6c,0x77,0xb7,0x40,0x19,0x79,0x06,0x6d,0x66,0x17,0xb5,0x9a,0x01,0x98,0x8f,0x78,0xf6,0xc9,0xa9,0x8f,0xee,0xdf, + 0x48,0x6c,0xf8,0x95,0x9f,0x7d,0x93,0x9c,0x4c,0x79,0xa0,0x71,0x5b,0xa7,0xbb,0xf0,0xcc,0x3f,0xa7,0xb2,0xa1,0xd6,0x0e,0x86,0xad,0x09,0x7c,0x91,0xe5,0x61,0x2e,0x24, + 0x5a,0x1f,0x06,0x74,0xb1,0x39,0x7b,0x6e,0x65,0x3f,0xf6,0xe4,0x73,0xd6,0x41,0xda,0x4f,0xb9,0xe7,0xbc,0x90,0xa7,0x38,0x02,0x73,0x9a,0x03,0x49,0x14,0x85,0x00,0xfa, + 0x9a,0x90,0x75,0x14,0xa9,0xec,0xc8,0x5f,0x96,0x59,0xb9,0xe9,0x79,0x09,0xa3,0x8f,0x97,0x2b,0x0c,0x9a,0x7c,0x00,0x97,0x78,0xb8,0x19,0x04,0x38,0xa8,0xeb,0xc0,0x0a, + 0x94,0x16,0x85,0xfe,0x4d,0xe8,0x16,0x26,0x11,0x57,0xb2,0xfe,0x3d,0x3a,0xc2,0x81,0x95,0xd8,0x1f,0xac,0x62,0x25,0xfd,0x31,0x03,0xee,0x60,0xa0,0xc2,0x4d,0xf4,0x72, + 0xb2,0x03,0xeb,0x03,0x65,0xa4,0x06,0x24,0xa4,0x42,0x57,0x2e,0x0b,0xad,0x80,0xe1,0xf0,0xc9,0x95,0x8e,0x57,0x09,0x51,0x2e,0x76,0xb2,0x8f,0x4e,0x0b,0xfb,0x22,0x91, + 0xe0,0x9d,0x25,0xf8,0x22,0x47,0x1e,0x64,0x70,0x64,0xb5,0xb6,0x8c,0xd2,0xae,0x42,0xd6,0xbe,0x7b,0x87,0x65,0xcd,0xc0,0x26,0xbb,0x76,0x96,0xa5,0x24,0xc8,0x3f,0x49, + 0x97,0xe3,0xc2,0x9f,0x69,0xd9,0x03,0x2e,0x67,0x69,0x33,0xed,0xb1,0x52,0xf2,0x43,0x8e,0xc7,0xdf,0xfb,0x17,0x64,0x14,0x42,0xce,0x93,0x42,0xe1,0x38,0xf8,0x16,0x67, + 0xcd,0x78,0x74,0x61,0x2d,0x68,0xc9,0x07,0xb4,0x34,0xbd,0x81,0xbf,0x1b,0x1a,0x83,0xcf,0x94,0x29,0xb2,0x4c,0xee,0x75,0x3c,0xc2,0x28,0xec,0xbd,0xd6,0x65,0x73,0x88, + 0x62,0x1d,0xdb,0x18,0x93,0x13,0x7c,0x12,0x14,0x7e,0x90,0x9d,0xff,0x83,0x08,0x59,0xdc,0xd7,0x3d,0xdb,0x00,0xac,0xdb,0x40,0x97,0xf1,0xd6,0x6e,0x14,0xfe,0x36,0x6e, + 0x19,0xad,0x36,0x2e,0xf4,0x4a,0x36,0x34,0x2c,0xf9,0x14,0x3b,0x88,0x47,0x0d,0x56,0x59,0xfc,0xa6,0xa3,0xa3,0x0c,0x90,0x42,0x71,0xf6,0xd6,0xbd,0xc0,0x5e,0x94,0x07, + 0x43,0xbd,0x8c,0xf3,0x70,0x25,0x7b,0xc8,0x8f,0x38,0xb0,0xde,0xd6,0x8a,0xf2,0xf9,0xd9,0x39,0x77,0x23,0x4a,0x19,0xfb,0xf6,0x7a,0xbf,0x2e,0x0a,0x4c,0x09,0xc1,0x20, + 0x9d,0x92,0x0e,0x7a,0x6f,0x61,0xfe,0x41,0x40,0xbb,0xe5,0x6f,0x43,0x17,0xe3,0x89,0x2d,0x21,0xa8,0x0f,0xb4,0x80,0xa0,0x91,0xa3,0xc1,0x6a,0x0a,0x67,0xa7,0xa9,0x7d, + 0x07,0x96,0x22,0x17,0x92,0x86,0x02,0x98,0xf1,0xb4,0xc5,0xaa,0x15,0x61,0xec,0x5d,0xb0,0x1a,0xd8,0x76,0xc3,0x55,0x2b,0xd9,0x6b,0x00,0xaa,0x23,0xef,0x47,0xb7,0x1d, + 0x8c,0xec,0x89,0x08,0x42,0x61,0x7d,0xe7,0x78,0x9c,0x3c,0x29,0x09,0xe2,0xd3,0x80,0x31,0xd5,0xaa,0xd9,0x57,0xd9,0x95,0xbd,0xec,0x62,0x2b,0x01,0x0c,0xe9,0xe0,0xb7, + 0x1d,0x4c,0x7c,0x7a,0xa3,0x59,0x14,0x0e,0xdf,0x90,0x7c,0x82,0x34,0xef,0x16,0xb9,0x2f,0x20,0x1f,0x56,0x2c,0x22,0x37,0xaa,0x32,0xad,0xbc,0xbd,0xc0,0xca,0xbd,0x0c, + 0xb1,0x51,0x34,0xb9,0xe9,0x19,0x96,0xe2,0x28,0xea,0x7b,0xa6,0xcb,0x45,0x00,0xa1,0x17,0x98,0x3c,0x8e,0xeb,0x68,0x71,0x74,0x65,0x73,0x54,0xe5,0x99,0x61,0xe5,0x21, + 0x90,0x6a,0xcb,0x96,0x12,0x0e,0xc7,0x68,0x4e,0x39,0x11,0x00,0xcf,0x0b,0xb7,0x47,0x69,0x16,0x78,0xeb,0x3e,0x14,0x7f,0x53,0xdb,0x88,0x6b,0xa0,0xfc,0x5a,0xa7,0x0d, + 0x73,0xdd,0x08,0x7b,0x1c,0xb3,0xc5,0xa0,0x7a,0xcd,0xb9,0xb0,0xa4,0xa0,0x2c,0x64,0xb7,0x08,0x7a,0xe9,0x78,0x36,0xe9,0x43,0x43,0x9d,0xbf,0xdf,0x41,0xea,0xc8,0x33, + 0xf7,0x3c,0x49,0xf6,0xda,0x53,0x7b,0x2f,0xf3,0x0e,0xad,0x75,0x38,0xc0,0x47,0x26,0xbc,0x74,0x15,0x25,0x35,0xd2,0x2b,0x6b,0xaf,0x92,0xd0,0x6a,0xdb,0x45,0xe6,0x76, + 0xf4,0xa7,0x57,0xce,0xb0,0xba,0x6c,0xb9,0x61,0x8a,0xcd,0x8f,0xef,0x68,0xd2,0xc8,0xfe,0x99,0x01,0xff,0xf1,0x41,0x77,0xf2,0x7b,0x6e,0x6b,0x8c,0x6b,0xd3,0x4c,0xb7, + 0x3e,0xb4,0xa6,0x34,0xd0,0x09,0x01,0x75,0x34,0x76,0x13,0xb7,0xee,0xd6,0xd4,0x9b,0x9b,0x59,0x44,0xe7,0x0a,0xcc,0x3e,0xd9,0x84,0x74,0x98,0x9d,0x30,0xa4,0xc2,0x99, + 0x52,0x0d,0xff,0x4d,0x04,0x08,0x58,0x71,0xcf,0xf6,0x9b,0x3a,0x20,0xa7,0x5b,0x8f,0x3b,0x10,0x3d,0xa0,0xe4,0x68,0x36,0x5e,0x8c,0x92,0x87,0xc0,0xa7,0xad,0x7d,0x9e, + 0xc8,0x0a,0xc1,0x3c,0x5d,0x2e,0x67,0x23,0xe8,0x48,0xed,0xb0,0x23,0xfc,0x17,0xec,0xae,0x55,0x37,0x81,0xa4,0xaa,0xc9,0x0f,0x25,0x77,0xfa,0xe7,0x51,0x17,0x11,0xcf, + 0xb0,0xc2,0x8a,0x99,0x38,0xcf,0x09,0x5a,0x4b,0x0e,0xbf,0x3d,0xaa,0x6a,0x16,0xe1,0x9e,0x3f,0x41,0x99,0xe3,0x47,0x5c,0xa3,0xaa,0x58,0x74,0x6f,0x65,0x1b,0x92,0x1e, + 0x78,0xdb,0xfe,0xc6,0xb4,0xaa,0xd2,0xd0,0xa9,0x9b,0xdd,0xe7,0xb9,0x09,0x96,0x32,0x4c,0x0f,0x7b,0x9d,0x13,0x6a,0x6e,0xde,0x5c,0x29,0x95,0x19,0x7d,0x0d,0x41,0x2a, + 0x36,0xa2,0xe7,0x7f,0x56,0xc3,0xe5,0xb1,0x1e,0x35,0xbf,0x4b,0xa5,0xde,0x18,0x85,0xcf,0x02,0x64,0x64,0x3c,0xac,0x5d,0x6f,0x7b,0xfb,0x1a,0xe0,0x1e,0x39,0xa6,0xc0, + 0x9f,0x4e,0x92,0xd9,0xa9,0x59,0xc0,0x9e,0xed,0xdd,0x15,0x2f,0x6d,0x95,0xff,0x2c,0x31,0x57,0x44,0x6f,0x47,0x7f,0xbe,0xd2,0x14,0xa0,0x06,0x21,0xd0,0x14,0xf9,0x36, + 0xd0,0xb1,0x65,0x61,0x34,0x9f,0x18,0x2e,0xf2,0x79,0x2d,0x0c,0x2d,0xd5,0x85,0x60,0x1c,0xe4,0xe0,0x32,0x75,0x4b,0x76,0x28,0xb3,0xd8,0x01,0xf1,0x87,0xc1,0x4f,0xd4, + 0x5f,0xd6,0xd7,0xf0,0xba,0x31,0x7a,0x36,0x43,0x4e,0x1a,0x99,0x5b,0xed,0x54,0xa4,0x28,0x98,0xd9,0x40,0xee,0x5f,0xa4,0x57,0x83,0x73,0xe8,0xd4,0xc2,0x3f,0x55,0x67, + 0xbb,0xe5,0x59,0xb7,0x7e,0x83,0x90,0x5b,0x08,0x95,0x4d,0xc3,0x73,0x6a,0x27,0x52,0xd5,0x6a,0x5b,0xc3,0x66,0xa5,0xfc,0xd8,0x4e,0x04,0x2a,0x78,0xc8,0xaf,0x68,0xd3, + 0xe6,0x24,0x29,0xb8,0xeb,0x32,0x2d,0x24,0xe4,0xbd,0xb9,0xa7,0x2b,0xf6,0xe9,0xc9,0x4d,0x82,0x96,0x2b,0x26,0xd9,0x9f,0x63,0x3e,0x1f,0x21,0x70,0x9b,0x7e,0xdd,0xbe, + 0x58,0x22,0xc1,0x68,0xaa,0xb9,0xbb,0x6f,0xfe,0x00,0xb7,0xc4,0xc7,0xbe,0x55,0x51,0xda,0xa8,0x30,0x4b,0x8d,0x2c,0x06,0x96,0xe2,0xd7,0x7f,0xe5,0x0b,0x9d,0x8d,0x8d, + 0xba,0xe2,0x6f,0xa6,0x9d,0xa0,0x0a,0xa0,0x3f,0xd9,0x02,0x8f,0xa8,0x4d,0x46,0xb9,0x2c,0x13,0xd5,0xe5,0x55,0xb2,0xe7,0xb3,0xdb,0x0d,0x09,0xbb,0x95,0xd4,0x14,0x86, + 0x97,0xce,0x8c,0x4b,0x6e,0x03,0x17,0x76,0xb1,0x9f,0xc7,0xc9,0x57,0x7c,0xb2,0x6f,0x08,0x52,0x74,0xa5,0x84,0x07,0x26,0x7b,0xca,0x35,0xa9,0x76,0x92,0xa2,0xe8,0xe6, + 0x5e,0xb5,0x72,0x2f,0x98,0xaa,0xd0,0x62,0x20,0x97,0xd9,0x44,0xbb,0x12,0x0e,0x09,0xe7,0xa1,0x22,0x49,0x8b,0x20,0xae,0x2b,0xff,0xf9,0x1c,0x8b,0x36,0x2d,0xaa,0xd2, + 0xf5,0xc9,0xb8,0x8d,0x48,0x11,0x20,0x41,0x33,0x4c,0x57,0x4f,0x93,0x31,0x36,0x70,0xcd,0xec,0xbe,0x0c,0x0b,0x6c,0x26,0x55,0x77,0x8d,0xf8,0xff,0x62,0x02,0x5d,0x3f, + 0xef,0xfa,0x36,0x2f,0xce,0x62,0xe2,0x71,0x01,0x6d,0x50,0xa0,0xe3,0x5c,0x03,0x14,0x55,0xfc,0xa2,0x80,0xb8,0x0e,0xd2,0xcc,0xe8,0x7c,0x83,0xe5,0x7e,0x3c,0xfd,0x36, + 0x59,0xb8,0xdc,0xdc,0x66,0x76,0x02,0x91,0x09,0x87,0x1f,0xc6,0x7b,0x46,0x6a,0x7f,0xb6,0x22,0x22,0x5c,0xd6,0xc7,0x7b,0xbc,0x21,0xb1,0xb6,0x28,0x46,0x47,0x98,0xa2, + 0x42,0xdd,0x3a,0x8e,0x14,0xdf,0xe9,0xfe,0x2e,0xbf,0x80,0x74,0x69,0x89,0xba,0x66,0xf2,0x8e,0x54,0x60,0x11,0x6a,0x02,0xbc,0xe2,0x4c,0x54,0x9d,0x11,0x7d,0x6b,0x0f, + 0xb0,0xe1,0x02,0x5b,0x39,0xc5,0x48,0x1a,0x74,0x8a,0x04,0x61,0xaa,0x77,0x73,0xa6,0xb3,0x42,0xad,0xea,0xd4,0xb4,0x58,0x75,0x21,0xa1,0x95,0x3d,0x4f,0xf0,0x29,0x6b, + 0x9d,0xd7,0x11,0x80,0x06,0xee,0x56,0xfc,0xcf,0x30,0x7a,0x31,0xa6,0x33,0x4b,0xe7,0xe1,0x9d,0xb2,0xde,0xca,0x68,0xfd,0x45,0xb3,0xf4,0xf9,0x4f,0x10,0x0d,0xe6,0xa4, + 0x1f,0xb1,0x63,0x36,0x39,0x3b,0xa6,0x03,0xfb,0x2e,0xb7,0x01,0xfe,0xd0,0xe9,0x82,0xad,0x32,0x96,0x4a,0xfa,0xe7,0xdb,0xbf,0xbc,0x5a,0x81,0x12,0x38,0x2e,0x51,0xe3, + 0x9a,0x6d,0x03,0xa1,0x7e,0x68,0x56,0x1a,0x10,0x5d,0xa6,0x6d,0x2f,0xb1,0xd9,0xec,0x9e,0x3c,0xa6,0xc6,0x86,0xf6,0x5d,0x9d,0xa9,0x26,0x84,0x9d,0x7a,0xf4,0xfc,0xb7, + 0x3c,0x03,0x07,0x7e,0x00,0x98,0xa8,0x45,0xf7,0xc9,0xb2,0x2b,0x73,0xee,0xcd,0x49,0x5a,0x2d,0x6a,0x0b,0x34,0xd2,0x11,0x15,0x4e,0xe3,0x89,0x86,0x34,0xf8,0x23,0xb4, + 0xb8,0x45,0x4b,0xcf,0x84,0x63,0xc2,0xbd,0x59,0xf7,0x53,0x8b,0x65,0xf1,0x1b,0x9c,0x98,0xc1,0x8c,0x13,0x43,0x84,0x17,0xcc,0x08,0xa3,0x9c,0x88,0x42,0xa0,0xb7,0xed, + 0xb4,0xdf,0x5f,0x33,0x5a,0x04,0x61,0xa3,0x88,0x52,0x20,0x5a,0xc7,0x3b,0xc5,0x15,0x12,0xb5,0xc7,0xf6,0xa8,0x30,0x5f,0x1a,0x8d,0x4f,0x19,0x1c,0xb6,0xfd,0x3b,0x2a, + 0xa9,0xde,0x6e,0x92,0xaf,0x14,0xbf,0x4e,0xb1,0x1d,0x75,0x33,0xbb,0xcb,0x28,0xcf,0x62,0x2e,0xc5,0xe5,0x2e,0x4a,0x2f,0x4c,0xde,0x4d,0xdc,0x3d,0x21,0xba,0xbc,0xee, + 0xed,0xcd,0x8e,0x48,0xdf,0x11,0xaa,0x67,0xa9,0x0c,0x75,0x61,0x49,0x83,0x46,0x6d,0x24,0x4e,0x4b,0x54,0x73,0xf8,0xac,0x01,0xa4,0x1c,0x14,0x6d,0xb1,0x3c,0x48,0x27, + 0x2c,0x8d,0xd7,0x47,0x92,0xce,0xd2,0x81,0xf9,0xcb,0x16,0x1d,0x2f,0x64,0xd2,0x38,0xcb,0xac,0x2d,0x18,0xf8,0x66,0x1b,0x0f,0x56,0x74,0xd7,0x9c,0xd5,0xc6,0xed,0xb8, + 0x50,0x3f,0xb9,0xbf,0x4b,0x57,0xb0,0x0e,0x0c,0x23,0x9b,0x3e,0x83,0x71,0xf2,0x46,0x60,0xaa,0x01,0xcb,0xf7,0x9f,0x4c,0x49,0x9e,0x4f,0xe1,0xa1,0x55,0x52,0x8f,0xf9, + 0xe6,0x1a,0xd5,0xf8,0x06,0x32,0x38,0x2b,0x62,0x6f,0x9a,0x77,0xfb,0x7f,0x5d,0xb0,0x20,0xdb,0xc0,0x84,0xc8,0x88,0xc6,0xb0,0x99,0x93,0xe1,0x2f,0xe4,0xd3,0x16,0x04, + 0x51,0xc1,0x0b,0x83,0x32,0xb3,0x3f,0xaf,0x52,0x9c,0x58,0xcc,0x2d,0xa4,0x5a,0x23,0xbb,0xfe,0xcc,0x1d,0x4e,0x0a,0xa4,0xea,0x54,0xfd,0x81,0x9b,0x7e,0x31,0xe5,0x55, + 0x98,0xd6,0x78,0x22,0xc3,0x18,0xdb,0x06,0x53,0xa4,0x70,0xa6,0xed,0x96,0xe7,0xc2,0x2a,0x04,0x6a,0x2a,0x25,0x66,0x4c,0x19,0x53,0x9a,0xf6,0x2a,0xe1,0xd3,0xa9,0x6b, + 0x7c,0x46,0x48,0xcd,0x80,0x8d,0xf9,0xa5,0x4f,0x99,0x2b,0x29,0x4a,0x3e,0xce,0x56,0x2b,0xa5,0xef,0xbe,0xba,0x7e,0x17,0x60,0xf1,0xf1,0x07,0xed,0x1a,0xf8,0xc1,0x87, + 0x41,0xb8,0x9b,0x46,0xf0,0x18,0xa3,0xac,0x88,0x4a,0xd9,0x21,0xe4,0x9f,0xcf,0x5d,0x96,0x77,0xae,0x84,0xe3,0x9e,0x6e,0xa8,0xde,0x84,0x4a,0xcc,0x33,0x7d,0x84,0x81, + 0xd1,0x55,0xb0,0xe0,0xe3,0x7d,0xa1,0xa1,0x9a,0xf0,0xe8,0x5e,0x68,0xe7,0xbb,0x41,0x80,0xaa,0xb5,0x5b,0x1e,0x95,0x50,0x1a,0x1a,0x3a,0xe0,0xcd,0x95,0x40,0x4a,0xee, + 0x12,0xbd,0x72,0xe9,0x52,0xe6,0xb8,0x12,0x55,0xad,0x79,0xaf,0x19,0x31,0x0d,0xa2,0xe0,0xef,0x97,0x72,0x00,0x33,0x84,0xa1,0xf3,0x57,0x53,0xe6,0xbe,0xab,0x71,0xd6, + 0x35,0x14,0xb8,0x36,0x2e,0xe1,0xe7,0x0e,0x84,0x6e,0xde,0x7e,0xd5,0x72,0x83,0xf5,0xd5,0x89,0x1f,0xdb,0x9b,0x0c,0x56,0x05,0xda,0x45,0xdb,0xc5,0xc6,0xf4,0x4e,0x53, + 0xf6,0xc8,0x29,0xed,0x9c,0xa3,0xdf,0xdd,0x1f,0x16,0x5a,0x20,0x44,0x61,0xe1,0xc1,0x66,0x20,0xe7,0x52,0x21,0x6e,0x2b,0x6e,0x3a,0xab,0x61,0x97,0xf3,0xdd,0x2b,0x3b, + 0x37,0x19,0xf7,0xaf,0xe8,0x2c,0x3f,0xa5,0x4c,0x0c,0x12,0x60,0x47,0x62,0x46,0x44,0x1d,0x38,0x79,0x70,0x93,0x5e,0x4c,0x76,0x96,0x5c,0xed,0x96,0xda,0x3a,0x07,0xde, + 0x0a,0x36,0x8c,0x74,0xc5,0x6c,0x61,0xaa,0xb0,0x24,0x40,0xe6,0x4b,0x26,0x99,0xc2,0x4c,0xda,0xcb,0x4d,0xfb,0xcd,0xeb,0xe0,0xb3,0xcf,0x80,0x1e,0x86,0xf1,0xf7,0x4f, + 0xde,0x5b,0x6c,0x29,0xf2,0xf4,0xf1,0x7f,0x8e,0xd9,0x25,0xf1,0x29,0x15,0x94,0x10,0xe4,0x55,0x7d,0xff,0xc5,0x47,0x29,0x44,0xb8,0x86,0x2c,0x42,0xbd,0x2b,0x18,0x0a, + 0x8f,0xca,0x30,0xfc,0x5d,0x73,0x1f,0x42,0xd3,0x76,0x64,0xd5,0x2b,0x64,0xe0,0x22,0xd9,0x8a,0x25,0x06,0x5f,0xb1,0xf8,0xbd,0x77,0x85,0x3d,0x7f,0x2b,0xbf,0x07,0xe0, + 0xc9,0x43,0x1b,0x6d,0xed,0xa0,0xc9,0xf9,0x2f,0x36,0x8f,0x7c,0xa1,0x29,0x86,0xf0,0xe0,0x7e,0x01,0x24,0x22,0xb8,0x40,0xc7,0xaa,0x78,0x4a,0x0c,0x71,0x3b,0x50,0x1f, + 0x67,0x2c,0x23,0x39,0xe4,0xc3,0x9e,0x36,0xcf,0xe1,0x3e,0x2c,0xfe,0x35,0x28,0x59,0xe1,0xef,0x66,0x31,0x8f,0xe9,0xf9,0x7d,0xd2,0x6d,0x9d,0x03,0xa9,0x17,0x1f,0x7f, + 0x8c,0xd1,0x13,0x40,0x31,0x3b,0x97,0x8f,0xa3,0x77,0x49,0xf4,0xb3,0x67,0xc0,0x87,0xfd,0x90,0x0f,0x17,0x94,0x10,0x02,0xde,0x22,0xce,0x40,0x29,0xaa,0x55,0x0e,0x7f, + 0x6f,0x1c,0xc2,0xd0,0x7f,0x6e,0xe0,0x7d,0x0b,0x13,0x8b,0x60,0x1c,0x94,0xde,0xb2,0x0a,0xa2,0x34,0xe5,0x26,0xfa,0xb3,0xee,0x4a,0xdc,0x98,0x70,0x70,0x85,0xa7,0x3d, + 0xc2,0x81,0x2e,0xb9,0xb4,0x56,0x29,0x75,0x72,0xe8,0xd8,0x70,0x75,0x4b,0x48,0x48,0x9e,0xa3,0x66,0xf3,0x51,0xf8,0x22,0x75,0x9d,0xe8,0x31,0x72,0x68,0x15,0xe5,0x82, + 0x9c,0xf1,0x68,0x9a,0x01,0x5a,0xc3,0x95,0x8d,0xc9,0x5f,0xc7,0x1c,0xb0,0xd1,0x03,0xe8,0x1b,0x45,0x94,0x68,0x46,0x38,0x93,0x3a,0x5d,0xaa,0xa9,0x9f,0xb3,0xb1,0xfa, + 0x2d,0x60,0x49,0xf8,0xe4,0x6c,0x67,0xc1,0x7d,0xdf,0xc8,0x17,0x8d,0xd9,0x18,0xb2,0x3f,0xd1,0x96,0x9e,0x11,0xc9,0x59,0xb6,0x4e,0xa4,0x2e,0x39,0xc9,0xa8,0x7d,0xea, + 0x9b,0x7f,0x8b,0xe2,0x62,0xb9,0xcd,0x27,0x51,0xef,0x8e,0xae,0x2b,0xad,0x7b,0x1e,0xcf,0x07,0xcb,0x76,0x61,0x3c,0xfe,0x70,0x88,0xcc,0x9b,0xde,0xf1,0xd0,0x44,0x36, + 0x52,0x98,0x0b,0x59,0x80,0xdf,0x38,0xf7,0xc2,0xd5,0x9e,0x4e,0x30,0x7d,0xa2,0x56,0x55,0xd5,0x0c,0x6e,0x03,0x02,0x34,0xb2,0x41,0xc0,0x98,0xc9,0x35,0xa5,0x59,0x6d, + 0x2f,0x1f,0x69,0x90,0xc3,0x01,0x36,0xd6,0xf4,0x4d,0xe8,0x14,0x5f,0x19,0x18,0x40,0xc4,0xb9,0xef,0xbc,0xf8,0x7c,0x39,0xb7,0x99,0x5c,0x26,0x2b,0xdc,0xdf,0x9d,0x40, + 0xaf,0xe5,0xb6,0x0f,0xe3,0xe1,0xdc,0x87,0x3b,0x3f,0x30,0x22,0x89,0x3a,0x35,0x98,0x80,0xe8,0x17,0x53,0x7b,0xeb,0x96,0xb3,0xd4,0x8d,0x37,0x57,0x66,0xab,0x59,0xe6, + 0x33,0x15,0x05,0x38,0x97,0x35,0x10,0x82,0x7c,0xaf,0xdf,0xe9,0x44,0x9e,0x7a,0x5a,0x2e,0x1a,0x79,0x46,0xf4,0xe4,0x85,0xa0,0x0f,0xf2,0x19,0xb2,0xcd,0x58,0xd8,0x01, + 0xb5,0x52,0x3f,0x93,0x82,0xb3,0x5e,0xd9,0xe1,0xc4,0xf2,0xb4,0x20,0xdf,0x9f,0x61,0xe6,0xac,0x8f,0x6d,0x34,0x22,0x13,0xfa,0x4d,0x75,0x45,0x8f,0x5b,0xd8,0x28,0xd1, + 0xad,0x9a,0x53,0xd0,0x53,0x15,0x00,0x9f,0xb1,0x48,0x73,0x69,0xf7,0x2f,0xdc,0x33,0xe6,0xdb,0xba,0x14,0x85,0xef,0xae,0xde,0x29,0x51,0x43,0x35,0x26,0xd2,0xfd,0x0a, + 0xa8,0x8c,0xca,0x88,0xb5,0x9c,0xd8,0x6e,0xdd,0xa2,0x02,0xcb,0x4e,0xa1,0xb2,0xd5,0x41,0xd5,0xc8,0xc2,0x2c,0x06,0x2a,0x08,0xf9,0xdb,0x49,0x6d,0x56,0x25,0x73,0x30, + 0xb7,0xf5,0x31,0xb4,0xa9,0xac,0x00,0x95,0x2b,0xfc,0xf2,0xcb,0xec,0x41,0xe5,0x8b,0x54,0xc4,0xf4,0x12,0xf4,0x64,0xbc,0xf1,0xf1,0xbf,0x10,0xa2,0x4b,0x9b,0x19,0x74, + 0x47,0x34,0x73,0x51,0x8f,0x0e,0x84,0x3d,0x1f,0xb5,0x10,0x5b,0x16,0xfe,0x88,0xed,0xaa,0x41,0x8b,0x39,0x6c,0xab,0x7c,0xb5,0x53,0x24,0x16,0xd1,0x71,0xf2,0xe7,0xbc, + 0xc2,0x56,0x3f,0x49,0xe6,0x23,0xb1,0x39,0xa8,0x3c,0x4c,0xb7,0x1c,0xb7,0x3d,0xeb,0x06,0x45,0x83,0x85,0x65,0x8b,0xf8,0x79,0x6b,0xac,0x0c,0x2e,0xd1,0x2c,0x8a,0x67, + 0x28,0xc2,0x47,0xae,0x91,0xfd,0xac,0x1b,0x29,0x89,0x64,0x15,0xfe,0xc6,0x0f,0x42,0x52,0xfe,0xed,0x9c,0x9f,0xfa,0x02,0x16,0xd3,0x13,0x50,0xd7,0x08,0x64,0x6d,0x89, + 0x76,0xe9,0xe6,0xf1,0x33,0x9b,0xff,0x54,0xb8,0x2a,0x45,0x98,0x07,0x45,0x52,0x6f,0xf9,0x24,0x9e,0x94,0x2b,0x1f,0x83,0x6a,0xab,0x71,0x9f,0xd9,0x59,0xfc,0x80,0x99, + 0x0d,0xe8,0x21,0x77,0xc8,0x0f,0x4e,0x35,0xf3,0xb7,0xa3,0x00,0xe8,0x9a,0xc2,0x88,0xf3,0x0e,0x01,0xa8,0x65,0x89,0x33,0xc1,0x6b,0x8c,0x90,0x60,0x5e,0x35,0xd6,0xc7, + 0xf4,0x1d,0xe3,0xa7,0x75,0x97,0x83,0x5f,0xa9,0x04,0xd1,0xf0,0x54,0x11,0x36,0x8e,0x6e,0x87,0x8a,0xbd,0x04,0x85,0x47,0x7d,0x16,0x2b,0x2c,0x76,0x4e,0xf0,0x45,0xac, + 0xc4,0xdb,0xe3,0xb9,0x4e,0x72,0x9b,0x1e,0x0a,0xe3,0x4f,0xfb,0x0f,0x6b,0x0d,0x95,0xd7,0xe6,0x19,0xab,0x39,0x43,0xaa,0x38,0x36,0xcf,0x1e,0x72,0x1a,0x47,0x0a,0x9e, + 0x83,0xb3,0x10,0x61,0xf1,0xb7,0x01,0x48,0x87,0x0a,0x92,0x82,0xa4,0x64,0x1c,0xc8,0x42,0x89,0x43,0xa3,0xb1,0x0e,0x03,0x01,0x95,0x5f,0x59,0x60,0xc3,0x86,0xfb,0x04, + 0x5f,0x74,0xc0,0x66,0x59,0x5f,0xe9,0xea,0x28,0x32,0x74,0x96,0x4a,0xe8,0x3f,0xba,0x1a,0x73,0xef,0x9d,0x29,0xd2,0x4e,0x66,0x04,0xa4,0xaa,0x08,0x81,0xfe,0x39,0x0d, + 0xc6,0x72,0x60,0x1d,0x95,0x1b,0xdb,0x55,0x0e,0xa9,0xcc,0x58,0xd2,0x03,0x13,0x37,0xdb,0x39,0xa3,0x79,0x9d,0xe2,0x1a,0xf4,0xe5,0xc2,0x3e,0x2f,0xd7,0xf5,0x37,0xda, + 0xb2,0xc2,0xc0,0x05,0x32,0xd4,0x68,0xd2,0x53,0x74,0xae,0x2e,0x6e,0xc9,0xbc,0x52,0xbc,0xb2,0xe8,0xdf,0x20,0xad,0x1a,0x40,0x71,0x9b,0x7d,0x91,0x74,0x6d,0xae,0xab, + 0xe5,0xfe,0x7c,0x96,0x37,0x18,0x78,0xcf,0x86,0xdb,0x42,0x10,0xa4,0x87,0xd7,0xd3,0x3a,0xc4,0xbc,0xc4,0x5b,0x8d,0xf2,0x15,0x2e,0x82,0xaa,0x72,0x28,0xa9,0x91,0xe2, + 0x1b,0xb9,0xa5,0x01,0xab,0x9d,0x21,0x52,0x30,0xcd,0x10,0x72,0x04,0x2b,0x3c,0x82,0x71,0xae,0xc3,0xb2,0xc1,0xda,0x10,0xd1,0xa8,0xc8,0x10,0xfc,0xea,0xed,0x47,0xa4, + 0xfd,0xc1,0x5a,0x26,0xab,0xba,0xde,0x34,0x16,0xe1,0x20,0x1a,0x6d,0x73,0x71,0x28,0xa2,0xf8,0x97,0xf0,0xd8,0x81,0x08,0x64,0x54,0x53,0xa1,0xb3,0xdd,0xd0,0x56,0x88, + 0xe3,0x63,0x48,0xe3,0xa4,0x64,0xbc,0x51,0x83,0x84,0x80,0x6c,0x54,0x8e,0x15,0x6e,0xdd,0x99,0x4c,0xb6,0x94,0x64,0x73,0xc2,0x65,0xa2,0x49,0x14,0xd5,0x55,0x9f,0x1c, + 0x7d,0x65,0x68,0x4b,0xdc,0xe4,0xac,0x95,0xdb,0x00,0x2f,0xba,0x35,0x0d,0xc8,0x9d,0x0d,0x0f,0xc9,0xe1,0x22,0x60,0xd0,0x18,0x68,0x54,0x3f,0x2a,0x6c,0x8c,0x5b,0x8d, + 0x6e,0xc6,0xba,0x23,0x74,0xab,0x0a,0x9a,0xe6,0x63,0xf3,0xf7,0x36,0x71,0x15,0x8a,0xaa,0xba,0xc3,0xac,0x68,0x9d,0x6c,0x27,0x02,0xeb,0xdf,0x41,0x86,0x59,0x7a,0x85, + 0x6d,0x6e,0x87,0x78,0x7d,0x0a,0x94,0x7e,0xcf,0xbf,0x79,0x62,0x14,0x2f,0xde,0x8f,0xf9,0xb5,0x90,0xe4,0x72,0xc0,0xc4,0x6b,0xbc,0x5d,0x39,0x02,0x0e,0x4f,0x78,0xa7, + 0x56,0xea,0x43,0x82,0xf8,0xe1,0xab,0xfc,0xb2,0x11,0x98,0x9f,0x50,0x06,0x76,0x44,0x9a,0xbc,0xeb,0xfe,0x2c,0xd2,0x20,0x4d,0xd8,0x92,0x3d,0xeb,0x53,0x0a,0x6c,0x7b, + 0x2c,0x36,0x2c,0x27,0xb3,0x10,0x7e,0xa8,0xa0,0x42,0xc0,0x5c,0xc5,0x0c,0x4a,0x8d,0xda,0xae,0x8c,0xdc,0x33,0xd0,0x58,0x49,0x29,0x51,0xa0,0x3f,0x8d,0x8f,0x81,0x94, + 0x01,0x88,0xda,0x28,0x9c,0xe8,0x97,0x4a,0x4f,0x44,0x52,0x09,0x60,0xfa,0xe8,0xb3,0x53,0x75,0x0a,0xca,0x78,0x92,0x72,0xe9,0xf9,0x0d,0x12,0x15,0xba,0xcd,0xd8,0x70, + 0xf7,0x8b,0xd7,0xff,0x89,0x9c,0x81,0xb8,0x66,0xbe,0x17,0xc0,0xa9,0x4b,0xec,0x59,0x28,0x38,0xd7,0x8d,0x1f,0x0c,0x0c,0xf5,0x32,0x82,0x9b,0x6c,0x46,0x4c,0x28,0xac, + 0x99,0xf6,0x15,0x1f,0xba,0x28,0x06,0x7e,0xac,0x73,0x35,0x49,0x20,0xfc,0xc1,0xfa,0x17,0xfe,0xa6,0x32,0x25,0xa5,0x83,0x32,0x3c,0xb6,0xc3,0xd4,0x05,0x4e,0xca,0xca, + 0x68,0xca,0x39,0xde,0x0c,0xec,0x22,0x97,0x52,0x9f,0x56,0x87,0x6b,0xc3,0xde,0x7b,0xe3,0x70,0xf3,0x00,0xe8,0x7c,0x2b,0x09,0xcd,0xbb,0x51,0x20,0x38,0x2d,0x69,0x77, + 0x1a,0xf2,0x54,0xaf,0x90,0xc1,0x6d,0xbd,0x21,0x7f,0x33,0x56,0xf7,0xfe,0xf9,0xad,0x53,0x2d,0x49,0x02,0xa6,0xd6,0x72,0x18,0xe3,0x18,0x8a,0x9e,0x84,0x0f,0xc9,0x29, + 0x9e,0x23,0x22,0x23,0xaf,0xd0,0xd5,0x7a,0x7b,0x15,0x0f,0x65,0x70,0x0a,0xc6,0x0a,0x78,0xba,0xe2,0xaa,0xfc,0x0c,0xf9,0xd1,0xa8,0x20,0x45,0x2c,0xa1,0xe5,0x7a,0x14, + 0xec,0x2f,0x75,0x42,0xcc,0x1d,0xf6,0x65,0x76,0x4c,0x5b,0x9b,0xff,0x75,0x12,0x08,0xd6,0x68,0xbe,0x9f,0x3d,0x61,0xcd,0x6c,0x33,0xb3,0x5e,0xd0,0xf4,0xfe,0x5a,0x17, + 0xb0,0x95,0xe9,0xc2,0xf9,0x33,0xa0,0x00,0x53,0xa9,0x57,0x58,0xdc,0x20,0xfe,0x1e,0x72,0xa7,0x98,0x46,0x2f,0x90,0xfd,0x67,0xfa,0xfb,0xbd,0x68,0xd7,0x61,0xdd,0x67, + 0x95,0x48,0x4c,0x55,0x54,0xb5,0x43,0xf8,0xeb,0x2f,0xc2,0x18,0xcc,0x46,0xff,0xe6,0x48,0xa3,0xbf,0xac,0x41,0xe6,0xdf,0xaf,0xca,0x1b,0xa1,0x1f,0x8c,0x53,0xed,0x6e, + 0xf2,0x2e,0xbb,0x68,0x43,0x28,0x1b,0x54,0xb2,0x2a,0x9f,0xf1,0xa9,0x14,0x85,0xc7,0xdb,0x8f,0x95,0xdb,0x4b,0xf8,0xa1,0x13,0x1f,0x89,0x2b,0x3b,0xfc,0xe5,0x66,0x62, + 0x99,0x62,0x3d,0x9f,0x44,0x7b,0x66,0xcb,0x32,0x24,0x88,0xea,0x46,0x3b,0x3e,0x40,0xd5,0x62,0x0f,0x4d,0xf7,0x8f,0x89,0xc6,0x2f,0xe0,0xba,0x8b,0x90,0xff,0x38,0x6e, + 0xd6,0x11,0xaf,0xb4,0x04,0x6c,0x9f,0x4b,0x28,0x87,0xb7,0xdd,0x4d,0x45,0xb8,0x0e,0x95,0x84,0xec,0xa9,0x3f,0x5a,0x85,0x5d,0xc3,0x0e,0x52,0x9e,0xed,0xbf,0x50,0x17, + 0x04,0x38,0x08,0x5a,0xb0,0x10,0x4f,0xb4,0x7c,0x69,0x6b,0xe5,0xc0,0x8f,0x95,0xe3,0x19,0xed,0x55,0x07,0xab,0x78,0x1f,0xe1,0xcd,0xcc,0xd6,0xdd,0xb3,0x4b,0xda,0x67, + 0x32,0x6d,0xba,0xbf,0xfe,0x17,0xc6,0xef,0xc7,0x10,0xbd,0xb8,0xd0,0x4d,0x16,0xc8,0x62,0x4c,0x08,0x3d,0x48,0xbf,0xa6,0xe4,0x41,0x1d,0x22,0x12,0x64,0xd8,0x27,0x7f, + 0xf4,0x7a,0x91,0xe2,0x9e,0xbe,0x69,0xba,0xab,0x6b,0x34,0x0b,0xb6,0x4a,0x6d,0xc3,0x4f,0xca,0x75,0x46,0xfd,0x6e,0xba,0x53,0xf5,0xbb,0xe4,0x1f,0x61,0x78,0xc7,0xc6, + 0xcf,0x83,0x31,0x9c,0x73,0x53,0x48,0xdd,0x13,0xc4,0x4b,0x05,0x5f,0x67,0xa2,0x92,0xf7,0xaf,0xc5,0xd9,0xd2,0xbd,0x07,0x06,0xc9,0x66,0xad,0x76,0x53,0x68,0xd4,0x22, + 0x41,0xee,0x78,0x01,0xcc,0xb7,0x02,0xf2,0xf6,0x33,0xd1,0xd0,0xec,0x20,0xd7,0xc4,0x27,0x93,0x68,0x86,0xdf,0x89,0xad,0x33,0xd1,0x9d,0xbb,0x56,0xf6,0x6a,0x26,0x56, + 0xaf,0x82,0x8d,0x6b,0xc2,0x1a,0xd6,0xb4,0x57,0x0b,0x5f,0x68,0xa6,0x20,0x8d,0x3a,0x2f,0x46,0xed,0xca,0x69,0xb1,0x98,0x0f,0xe5,0x04,0x67,0x92,0xc6,0x8c,0xab,0x80, + 0x4e,0xbf,0x7f,0x17,0x4c,0xdb,0x3f,0xda,0x94,0xf9,0x96,0x98,0x31,0x7f,0xfe,0xf5,0xf4,0xd4,0xfb,0x93,0x3f,0x32,0x92,0xf1,0xaa,0xa7,0x82,0xc3,0x54,0xba,0x03,0xe7, + 0x16,0x49,0xf8,0x3c,0x47,0xa6,0x64,0x0a,0x94,0xb7,0x73,0xab,0x43,0x09,0xbd,0x69,0x64,0x10,0x94,0x33,0xe3,0xf3,0xee,0x5b,0x02,0x4d,0x19,0x15,0xef,0x51,0x39,0xde, + 0xf4,0x34,0xc3,0xff,0xe1,0x09,0x52,0x84,0x56,0xc2,0x3d,0x6c,0xfe,0x51,0xec,0x0b,0x10,0xbe,0x60,0x6d,0x7a,0x26,0x77,0x5f,0xe2,0xff,0x0a,0x9b,0x18,0xf9,0x2f,0x39, + 0xbd,0x02,0xb9,0xdf,0xc8,0xef,0x76,0x07,0x08,0x95,0x0b,0xd9,0x72,0xf2,0xdc,0x24,0x48,0x93,0xb6,0x1b,0x6b,0x46,0xc3,0xb1,0x9b,0xe1,0xb2,0xda,0x7b,0x03,0x4a,0xc5, + 0x41,0x22,0x69,0xbf,0xc1,0x5d,0x8b,0x1f,0xd7,0xf2,0x5d,0xe3,0x3b,0x15,0x15,0xea,0x67,0xf2,0x19,0x4e,0x73,0xba,0x06,0xc8,0x5e,0xf9,0x9b,0xb4,0x27,0x22,0xf9,0x5d, + 0x0a,0xd7,0x55,0x6a,0x62,0x10,0x74,0xa7,0x71,0xbf,0x12,0x91,0x63,0xd0,0x9a,0x2e,0x9d,0x2e,0x17,0x4f,0x2b,0x8a,0x4b,0x69,0x73,0xe8,0x9e,0xa1,0x38,0xc9,0xa6,0x03, + 0x76,0xac,0xc7,0x4d,0xd6,0x08,0x72,0xab,0x29,0xe1,0xbc,0xb9,0x9d,0xd4,0x63,0x65,0xc7,0xc7,0xf7,0x92,0x61,0x9c,0x90,0x1c,0x7b,0xa5,0xc6,0x83,0x78,0xb2,0x33,0xf5, + 0x50,0xe2,0x3b,0x94,0xfc,0xc3,0x3d,0x93,0xdb,0xcd,0x71,0xe9,0x55,0xe1,0x95,0xfe,0x0b,0xf6,0xac,0x9b,0x04,0xb1,0x5f,0x00,0x1e,0x53,0xb5,0xdc,0x7b,0xad,0x15,0x8e, + 0x33,0x24,0xbf,0x2f,0xb3,0x48,0x6b,0x11,0x04,0xff,0xfa,0x35,0xef,0x38,0x97,0x5f,0xaf,0xfb,0xa1,0xeb,0xe4,0x2c,0x54,0x39,0x92,0x06,0xfa,0xce,0x50,0x54,0x48,0xc7, + 0x23,0x5f,0xd3,0xe7,0x21,0x6c,0x92,0xf7,0x38,0x60,0xf0,0xac,0x01,0x21,0xb4,0x26,0x4f,0xf8,0x9d,0x80,0xbc,0x75,0xd5,0x9d,0xd4,0x55,0x29,0x85,0x97,0xc5,0xf2,0xec, + 0x0b,0xf7,0x58,0xde,0x27,0x05,0x23,0x19,0xda,0xc3,0x9b,0x32,0x4a,0x6e,0xa5,0x5e,0x92,0x86,0x03,0xa3,0xef,0x90,0x49,0xad,0x14,0x7f,0x8c,0xa3,0x5f,0x55,0xb6,0x56, + 0x31,0x2e,0xea,0xae,0xe3,0x97,0x22,0x4f,0xc1,0x7d,0xec,0x71,0x91,0xce,0x69,0xce,0xf4,0x0e,0x8f,0xb3,0x73,0x51,0x6c,0x2b,0x1e,0xda,0xda,0x03,0x36,0xc9,0x9c,0x13, + 0xaa,0x16,0x91,0x85,0x8e,0x6a,0x1a,0x06,0xc6,0xdf,0x57,0xce,0x10,0xa4,0xc7,0x30,0x97,0x4c,0x06,0xd1,0xe0,0x10,0x6d,0x1a,0x31,0xb5,0x1b,0x91,0x5c,0xd6,0xb6,0x0e, + 0x57,0x86,0xd6,0xea,0x09,0xff,0xb2,0x1a,0x63,0xad,0xb0,0x20,0xb1,0x17,0x09,0x64,0x84,0xef,0x99,0x5e,0x8c,0x4a,0x72,0xaf,0xa4,0x79,0xcb,0xa9,0x5c,0x95,0x99,0x20, + 0xae,0x0c,0x78,0x45,0xb8,0x29,0x95,0x26,0x3c,0x51,0xe1,0x3e,0x29,0x74,0x12,0xd1,0x7b,0x65,0x0a,0xa8,0x3d,0xce,0x4f,0x55,0xa0,0x69,0xdb,0xee,0x67,0x1c,0x16,0xb8, + 0xe5,0xe7,0x64,0xa3,0x8b,0x73,0x81,0x6f,0x6e,0x11,0xe7,0xcf,0x29,0x8b,0x2b,0xe5,0x4d,0x11,0x24,0x9c,0x61,0x5f,0x0a,0x71,0x49,0x8a,0x0a,0x82,0x1b,0x57,0x36,0xbb, + 0x6a,0xa7,0xe7,0x4a,0x7a,0x83,0x8e,0xfa,0x96,0x07,0xf3,0x58,0x7d,0x41,0x17,0xf1,0x91,0x4c,0x57,0xfa,0x92,0x4b,0x44,0x1c,0x27,0xfb,0x7a,0x7c,0x31,0xfb,0xaa,0xc4, + 0x39,0x1b,0x62,0x4f,0x28,0xeb,0x39,0x81,0x56,0x66,0x6d,0xbe,0xc1,0xd6,0x35,0xf8,0xff,0x17,0x53,0xeb,0x86,0x29,0x79,0x73,0xa1,0xc2,0x83,0x1b,0x10,0x91,0xe2,0xdf, + 0xe3,0xf3,0x9d,0x07,0x1b,0x74,0x3c,0x80,0x41,0x45,0x4d,0x1d,0xac,0xba,0x93,0xdc,0x9f,0x3f,0x12,0xa5,0xae,0x1b,0xfb,0xeb,0xaa,0x59,0xfc,0x4c,0xef,0xee,0x6b,0x82, + 0x09,0xd0,0xd1,0xb9,0x2a,0xf1,0xe7,0x11,0x1d,0x22,0x3b,0xf5,0xef,0xcd,0xfa,0x6d,0xf2,0x62,0x2a,0xb3,0xcf,0x16,0x1a,0xf0,0xeb,0xbf,0x06,0xad,0x00,0xc0,0x9b,0x6e, + 0xa7,0x38,0x72,0x7e,0x0f,0x5b,0x20,0x44,0x80,0x09,0xd1,0x02,0x9c,0xa7,0x27,0xf2,0x38,0x0d,0x2c,0x6e,0x15,0x2a,0x6e,0x2d,0xa8,0xea,0x50,0x53,0x1c,0xe3,0x94,0x99, + 0xa3,0x14,0xe4,0xee,0x9e,0x30,0x3d,0x97,0x0b,0x4e,0x9f,0x0c,0xdc,0x26,0x26,0x57,0xd5,0xc5,0x19,0x2f,0x05,0x54,0x66,0xb9,0xd0,0x9d,0x9c,0x88,0x8d,0x6b,0x72,0x56, + 0x8f,0x4e,0x1b,0xf8,0xe5,0x18,0x2a,0x1f,0xbc,0xde,0xac,0x92,0x4d,0xf1,0xba,0x2f,0x93,0x71,0x62,0xd4,0x8a,0x20,0x67,0x83,0xc4,0x81,0x32,0xcb,0x58,0x2c,0x07,0xdb, + 0x16,0x68,0x2c,0x86,0x2c,0xf5,0x37,0x55,0xb3,0xc2,0x8a,0xdf,0x7d,0xe0,0x52,0xd5,0xcf,0x0e,0x81,0xe5,0xd8,0xac,0xb3,0x46,0x70,0x2a,0x39,0x2b,0xc6,0xb2,0xb1,0xd5, + 0xcc,0x33,0xe8,0x40,0xb5,0x35,0x4b,0xf6,0xe0,0x88,0x04,0x7e,0x76,0xdc,0x16,0x8f,0x15,0xc0,0xc1,0xaa,0x94,0x67,0x31,0x60,0x0f,0x52,0xd6,0xf1,0xc9,0x29,0x9b,0x27, + 0xd7,0xb4,0xf5,0xe2,0xdd,0x1e,0xbe,0xcf,0xc9,0x23,0x18,0xd9,0x20,0x85,0x27,0x1b,0xe4,0x82,0xfe,0x65,0xa0,0x3e,0x83,0xb2,0xe3,0x58,0xa3,0x97,0xa5,0x97,0x44,0x9b, + 0x1d,0x88,0xed,0x8e,0x45,0x79,0xa4,0xc6,0x2f,0xed,0x95,0xea,0xfe,0x15,0x28,0xf8,0xd5,0x05,0x60,0x41,0xfc,0x41,0xf3,0xef,0x06,0x36,0x05,0xdd,0xc9,0x80,0xee,0x09, + 0xa6,0x69,0x85,0x78,0x65,0x0d,0xad,0xb4,0x52,0xd6,0x77,0xc3,0x98,0x3e,0x6b,0x80,0x91,0x52,0xd7,0xd2,0xd8,0xfb,0xa3,0x49,0xce,0xc6,0x86,0xe7,0x2e,0x6f,0x86,0x93, + 0x8e,0x42,0xc3,0x89,0x02,0xb2,0x5f,0xa1,0x38,0xb9,0x5f,0x4f,0x28,0x0b,0x68,0x4c,0x09,0xe1,0x21,0x2c,0x4f,0x06,0xa2,0xbc,0x2c,0x2b,0x2b,0x87,0x90,0x11,0x20,0x34, + 0xa1,0x9f,0x11,0x65,0xd3,0x1c,0x16,0x95,0x35,0x99,0x29,0xde,0xeb,0xcd,0x24,0x84,0x6c,0xcb,0x9a,0x3c,0x2a,0x38,0xc1,0x0b,0xdc,0x7c,0x85,0x5b,0xf8,0xa3,0x2d,0xf7, + 0x0a,0x87,0x93,0x5c,0x03,0x6d,0xe6,0x66,0xb7,0x61,0x9f,0x14,0xec,0x58,0xf9,0xf7,0x86,0x98,0xcc,0x23,0xa6,0x67,0x61,0x6f,0x84,0xc1,0x77,0xf3,0x46,0x61,0xeb,0xe2, + 0x90,0xac,0xcd,0x1c,0x3a,0xf1,0xcd,0x78,0x2e,0xa1,0xe8,0x64,0xa3,0x07,0xaa,0xef,0x6a,0x01,0xfd,0x3a,0x63,0x05,0xa0,0xad,0xae,0x37,0xe7,0x68,0x44,0xb9,0xce,0x10, + 0xe1,0x64,0xd8,0x8f,0xcb,0xd1,0xcc,0xdd,0x65,0x4d,0xe0,0x41,0x5b,0xfb,0xd2,0xa1,0x71,0x59,0x07,0x13,0x01,0x5f,0x4a,0x17,0x55,0x50,0x4e,0x62,0xf7,0xa0,0x38,0x70, + 0xd4,0xb6,0xd4,0x25,0x1a,0xc1,0xf8,0xa0,0xb0,0xc7,0x5b,0xba,0xc3,0x51,0x7a,0x13,0xea,0x0c,0x85,0x7b,0x54,0x99,0xb0,0x3d,0x15,0x3b,0xe6,0x63,0xa8,0x71,0x54,0x80, + 0xf5,0x27,0x0d,0x0c,0x41,0x19,0xf1,0xef,0x46,0x7a,0x37,0x50,0x16,0x88,0xb4,0xbf,0x4a,0x51,0x6e,0x5f,0x58,0xa0,0xf5,0xa4,0x0f,0x23,0xae,0x70,0xee,0x81,0x3c,0x26, + 0x17,0x63,0xeb,0x5b,0xd3,0x67,0x7d,0xe8,0x8e,0x98,0xaa,0xd8,0x40,0x38,0x83,0x84,0x22,0xd6,0xe5,0x56,0x05,0xa1,0x47,0x61,0x78,0x8c,0xf3,0x05,0x67,0x2e,0xb6,0x70, + 0x98,0xc9,0x5e,0xf9,0xfd,0xed,0x24,0x1d,0xa0,0x93,0x92,0x57,0x31,0x44,0xda,0xf4,0x4b,0x03,0x32,0x51,0x8f,0x45,0x81,0x67,0xe0,0x9d,0x67,0x20,0x11,0xea,0x46,0x18, + 0xb0,0xfe,0x8f,0xc6,0xab,0xe8,0x53,0xb1,0xea,0x6a,0xa4,0xf4,0xb4,0x49,0x0b,0xcd,0x94,0xff,0xd3,0x53,0x2c,0x1d,0x7c,0xce,0x36,0xd0,0x59,0xac,0x8f,0x29,0xcd,0x67, + 0x4f,0xdc,0x7c,0xc0,0x4b,0x24,0x59,0xf7,0x3c,0x85,0x60,0x23,0xe8,0x92,0x69,0x9b,0x90,0x18,0xba,0xca,0x1b,0x8e,0x3b,0x04,0x0e,0xc7,0x43,0x24,0x60,0x7c,0x97,0xc5, + 0x56,0x11,0x38,0x97,0x99,0x56,0xfe,0x6a,0x1a,0xea,0xe0,0x62,0x77,0x45,0x6c,0x7e,0x5e,0x7e,0x7d,0x64,0x39,0x10,0xe2,0x47,0xfb,0x24,0x8d,0xd7,0x43,0x56,0x91,0xa0, + 0x06,0xc0,0x6a,0xbb,0x60,0x3b,0xff,0x68,0xf3,0x56,0xce,0x49,0x6c,0x17,0xfc,0xd0,0x66,0x2f,0xa0,0x40,0xeb,0x0c,0xd4,0x5a,0x98,0x11,0x2e,0x6c,0x1e,0xea,0x11,0xdb, + 0x31,0x92,0x97,0xf7,0x7a,0x75,0x38,0x1b,0x65,0xd7,0x31,0x07,0xe8,0x26,0xee,0xa0,0xe6,0x9d,0x85,0x98,0x5d,0xb4,0x56,0x8f,0xea,0x21,0xd1,0x2d,0xda,0x69,0x69,0x21, + 0xc3,0xef,0x6e,0xb9,0x1a,0xad,0x69,0x45,0x6e,0xde,0x51,0x74,0xb0,0xe5,0xe3,0xd6,0x86,0x3c,0x02,0x4a,0xef,0x31,0x85,0xd2,0x25,0x89,0x46,0x36,0x29,0x03,0xe5,0x76, + 0xa1,0x8b,0x1f,0xba,0x4d,0x49,0x64,0x19,0xed,0xe7,0x0c,0xc2,0x3c,0xee,0xd6,0x74,0x52,0x6f,0x34,0x29,0x9e,0x5b,0x09,0xc0,0xee,0x2d,0xd1,0x66,0x96,0x93,0xfe,0xf9, + 0x9f,0xc7,0xff,0xf3,0xbb,0x4d,0x6e,0x5a,0x4d,0x52,0xeb,0x0e,0x3c,0x51,0x3a,0x3c,0x9f,0xa5,0x60,0x14,0xc0,0x30,0x44,0x95,0x46,0xcd,0xa7,0x44,0xaa,0x12,0x6f,0x6e, + 0x61,0xcb,0x2f,0xb9,0x9b,0x69,0x5e,0xcb,0xaf,0x91,0xa9,0x5e,0x6e,0x0c,0x7e,0x24,0x63,0x3b,0xc7,0x61,0x3e,0xbf,0x51,0x8c,0x6f,0x1c,0x81,0x61,0xdc,0x75,0xea,0x5f, + 0xaf,0x30,0x6c,0x99,0x3d,0xee,0x0d,0xcf,0xc4,0x41,0xeb,0xe5,0x33,0x60,0xb5,0x69,0xe2,0x1f,0x18,0x60,0x52,0xdb,0x81,0x97,0xf4,0xa1,0x24,0xfa,0x77,0xb9,0x81,0x48, + 0xaa,0x7f,0xc9,0xfe,0x60,0x44,0x5e,0xac,0x24,0x51,0xec,0x24,0xc1,0xa4,0x49,0x09,0x84,0x2f,0xa1,0x40,0x25,0xf2,0xa1,0xd3,0xdd,0x7f,0x31,0x01,0x9f,0x96,0x2b,0xe5, + 0x08,0x2a,0x43,0xa8,0x41,0x77,0x82,0xa7,0x95,0xc8,0xd4,0xc7,0x0f,0x43,0xed,0xca,0xbb,0xc2,0x45,0xa8,0x82,0x0a,0xc0,0x1b,0xe9,0x0c,0x1a,0xcf,0x03,0x43,0xba,0x91, + 0x70,0x81,0x0b,0x47,0x80,0xa6,0x3c,0x86,0x04,0x27,0xd3,0xa0,0x26,0x9f,0x6c,0x9d,0x3c,0x2e,0xa3,0x34,0x94,0xc5,0x0e,0x58,0xa2,0x0b,0x94,0x80,0x03,0x4b,0xc7,0xa0, + 0xa7,0xd3,0x4e,0xe2,0x5f,0xbb,0x35,0x4f,0x86,0x38,0xd3,0x18,0x50,0xda,0xb4,0x1e,0x4b,0x08,0x68,0x86,0xf7,0xed,0x3f,0x2d,0x6e,0x03,0x5b,0xce,0xb8,0xca,0xb8,0xa0, + 0x3f,0x09,0xcb,0xc1,0x2e,0xd1,0x70,0x1f,0x59,0xdd,0x5a,0xa8,0x3d,0xae,0xf5,0xe6,0x67,0x6a,0xdf,0x7f,0xd2,0x35,0xc5,0x3f,0x69,0xae,0xb5,0xd5,0xb6,0x77,0x99,0xe0, + 0xe0,0x4e,0x88,0x1f,0x41,0x6b,0xb5,0xaa,0x37,0x96,0x40,0x7a,0xa5,0xff,0xdd,0xf8,0xe1,0xb2,0x44,0x6b,0x18,0x5f,0x70,0x0f,0x69,0x53,0x46,0x83,0x84,0xfa,0xaf,0x76, + 0xad,0xac,0xe7,0x1f,0x40,0x00,0x6c,0x04,0x55,0x75,0x40,0xc2,0xed,0x81,0x02,0xd8,0x30,0xc7,0xf6,0x38,0xe2,0x20,0x1e,0xfe,0xb4,0x7d,0x73,0x2d,0xa7,0x9f,0x13,0xd9, + 0xb8,0xcb,0xf0,0x96,0x8f,0xb7,0x0d,0x39,0x10,0x59,0xd0,0x90,0xb3,0x0d,0x1c,0x4e,0xdc,0xd2,0xda,0xd7,0xab,0xbf,0x7a,0xa4,0xad,0x45,0x2f,0x5a,0x46,0x44,0xa7,0xbe, + 0x07,0x25,0x72,0x45,0xda,0x4b,0xc2,0x66,0x96,0xe2,0x45,0x53,0x1c,0x7a,0x97,0xc2,0xb5,0x29,0xf1,0xca,0x2d,0x8c,0x05,0x16,0x26,0x52,0x0e,0x6b,0x83,0xd7,0xfa,0xf2, + 0xd6,0xaa,0x40,0x1b,0x9c,0xe1,0x7e,0xcf,0x7d,0xd7,0xb0,0x86,0x1d,0xfe,0xb3,0x6b,0xb1,0x74,0x9d,0x12,0x53,0x39,0x91,0xe6,0x6c,0x0d,0x94,0x22,0x81,0xae,0x13,0xab, + 0xf4,0x3b,0xfe,0x4e,0xcc,0xc2,0x4e,0xbf,0x6e,0x36,0xc5,0xbc,0xac,0xa4,0x7b,0x77,0x0c,0x17,0xbc,0xb5,0x9e,0xa7,0x88,0xb1,0x5c,0x74,0xae,0x6c,0x9d,0xd0,0x55,0xa1, + 0x00,0x9b,0xc3,0xab,0xb3,0xcf,0x0a,0xca,0x21,0x4f,0x0e,0x8d,0xb5,0x08,0x8d,0x52,0x0b,0x3d,0x4a,0xad,0xb1,0xd4,0x4c,0x4a,0x2b,0xe7,0xf0,0x31,0x46,0x1c,0x94,0x20, + 0x8b,0xcb,0x07,0xa3,0xd0,0xfa,0x82,0xaf,0x60,0xc8,0x8a,0x8d,0x67,0x81,0x0e,0xbc,0xa0,0xea,0x27,0x54,0x83,0x84,0xe9,0x6d,0x34,0x83,0x31,0x02,0x12,0x21,0x93,0x12, + 0xa0,0x9d,0xdc,0x7c,0xfe,0x02,0x3a,0xcd,0x95,0x71,0xef,0x07,0x54,0x01,0x02,0x89,0xc8,0x04,0x67,0x8c,0x04,0x3f,0x90,0x0f,0x26,0x91,0xdd,0x80,0x1b,0x94,0x2e,0xd4, + 0xda,0x98,0x05,0x4d,0x51,0xac,0x96,0x15,0xe9,0xd4,0xf5,0xce,0xda,0x1f,0x1b,0xad,0x40,0x30,0x2a,0xc1,0x16,0x03,0x43,0x1e,0xfe,0xc1,0x3a,0xb5,0x0e,0x32,0xfc,0xf2, + 0xd6,0x07,0x95,0xd8,0xf3,0x10,0xb1,0x55,0x72,0x65,0x34,0xb8,0xbe,0x3d,0x0b,0x8a,0x7b,0xc2,0xce,0xd4,0x68,0xc6,0xe6,0x4c,0x8b,0x9a,0xe0,0x87,0xb3,0x3e,0xe0,0x0b, + 0x67,0x5f,0xef,0x8f,0x56,0x80,0xbf,0x76,0x22,0x0e,0x91,0x36,0x26,0x13,0x94,0x40,0x99,0x04,0x6b,0x0b,0xa0,0x7e,0x58,0x24,0xe9,0x3f,0x3e,0x3c,0xc2,0xcc,0x27,0x58, + 0x76,0xb4,0x39,0xf8,0xea,0x7b,0x42,0xf1,0x1c,0xd5,0x9e,0x6d,0x91,0xb2,0xd2,0xa7,0x25,0x77,0xc1,0x85,0x38,0x6b,0x6a,0xf6,0x63,0x9b,0xe8,0xe3,0x86,0x4a,0x7f,0x27, + 0x56,0xe6,0x3f,0xa7,0x88,0x12,0x1d,0x5e,0xfa,0x0c,0xe3,0xca,0xf4,0x60,0x5a,0xf1,0x8d,0x48,0xc6,0x31,0x49,0x6c,0xdf,0xa8,0x62,0xc4,0x3e,0xcf,0x5e,0x5f,0xc1,0x27, + 0xcf,0xf3,0xb5,0xe1,0x9e,0xd6,0x7e,0x51,0x11,0xdd,0x76,0xe3,0x10,0xa1,0xf1,0x1d,0x7f,0x99,0xa9,0x3f,0xbe,0x9c,0xc5,0xc6,0xf3,0x38,0x40,0x86,0xca,0xcd,0x11,0x42, + 0xe2,0x94,0x83,0x88,0x4a,0x74,0xfb,0x84,0xf4,0x60,0x16,0x54,0x88,0x5a,0x0f,0x57,0x46,0x91,0x39,0x4f,0x06,0x4e,0xa6,0x93,0x7a,0x84,0x61,0x75,0xef,0x08,0x1f,0xc5, + 0x9c,0x6a,0x4b,0xcb,0x2f,0xc0,0x86,0xac,0xa8,0x72,0x6d,0x85,0x0f,0xa7,0x99,0x20,0x21,0x4a,0xf4,0xc1,0x51,0xac,0xea,0x0f,0xcf,0x12,0xa7,0x69,0xad,0x1f,0x35,0x74, + 0x34,0xb7,0xab,0xc3,0xf3,0xe3,0x6e,0x37,0xe2,0xd5,0x72,0x8a,0x87,0x0a,0x29,0x3a,0x16,0x40,0x31,0x46,0xca,0x67,0xff,0x91,0xcb,0xab,0xee,0xe2,0xbb,0x2e,0x03,0x8b, + 0x9b,0xd1,0x28,0x4f,0x1b,0xcb,0x19,0x34,0xd4,0x83,0x83,0x4c,0xae,0x41,0xa7,0x7d,0xb2,0x8c,0xd9,0x55,0x38,0x69,0x38,0x47,0x55,0xb6,0x98,0x3f,0x4f,0x38,0x48,0xa0, + 0x16,0x7e,0x3d,0xb6,0xa9,0x12,0xac,0x61,0x17,0x64,0x45,0x25,0x91,0x1f,0xc8,0x87,0x2e,0xd3,0x3b,0x8e,0x0b,0xbd,0x50,0x07,0x3d,0xd3,0xc1,0x7a,0x74,0x4e,0x61,0xe0, + 0x7c,0x30,0x20,0xe2,0x79,0xcb,0x5a,0xf1,0x41,0x84,0xb4,0x65,0x3c,0xc8,0x7c,0x1d,0xdd,0x7f,0x49,0xcd,0x31,0xcd,0x37,0x1a,0xe8,0x13,0x68,0x1d,0xd6,0x61,0x7d,0x0e, + 0xac,0xfd,0xff,0x56,0x6b,0x8b,0x55,0x31,0x88,0x69,0xfa,0x64,0x6f,0x78,0x9f,0x80,0x36,0xd4,0x0b,0x90,0xf0,0xfc,0x52,0x0a,0xe2,0xa5,0xa2,0x75,0x44,0xf9,0x62,0xc0, + 0x5c,0x6b,0x01,0xcf,0xf4,0xe6,0xce,0x81,0xa6,0x30,0x23,0x8b,0x5d,0xb3,0x66,0x2e,0x77,0xfb,0x88,0xbf,0xfd,0xde,0x61,0x44,0x3a,0x7d,0x85,0x54,0xba,0x00,0x1e,0xf2, + 0xe7,0x28,0x1d,0x12,0xb7,0x4b,0x06,0xee,0xcb,0x27,0x3e,0xc3,0xe0,0xd8,0xfe,0x66,0x3e,0x9e,0xc1,0xd5,0xa5,0x0c,0x2b,0x6c,0x68,0xec,0x8b,0x36,0x93,0xf2,0x3c,0x4c, + 0x80,0x64,0x3e,0xd8,0xb9,0x05,0x2a,0x2e,0x74,0x6a,0x26,0xd9,0x17,0x8f,0xe2,0xcc,0xff,0x35,0xed,0xbb,0x81,0xf6,0x0c,0xd7,0x80,0x04,0xfb,0x8d,0x5f,0x14,0x3a,0xae, + 0x75,0x87,0x3a,0xc5,0x44,0xad,0x69,0xd3,0xdd,0xc5,0xc9,0xcf,0xfe,0x38,0x4d,0x27,0x5e,0x9d,0xa2,0x94,0x9d,0x69,0x82,0xda,0x4b,0x99,0x0f,0x8b,0xf2,0xb7,0x64,0x74, + 0x35,0x5c,0x9f,0xac,0xa2,0x9c,0xf7,0xcc,0x96,0x88,0x53,0xee,0x29,0xff,0xe6,0x2d,0x11,0x27,0xfc,0xc1,0xdc,0x57,0xe9,0xdd,0xaf,0x0e,0x0f,0x44,0x71,0x46,0x06,0x4e, + 0xfc,0x17,0x5a,0x5e,0xf1,0x85,0x95,0xb6,0x9e,0x45,0xbe,0x2c,0xda,0x8a,0xe0,0x0d,0x9c,0x8b,0xdb,0xef,0xbc,0xf7,0xf6,0x92,0xf9,0x1c,0xef,0xdc,0x56,0x0e,0x47,0x22, + 0x46,0x55,0x91,0x46,0xa9,0x3a,0xae,0x90,0x4d,0xbc,0xaa,0xaa,0x07,0xe6,0xcd,0x1b,0xb4,0x50,0xf1,0xb3,0x7c,0x83,0x92,0x9a,0x99,0x4b,0x45,0x79,0x23,0x33,0xd5,0xf6, + 0xc6,0x4b,0x07,0x11,0x90,0x54,0xa3,0x79,0x61,0xc0,0xa1,0x77,0x15,0x82,0x56,0x08,0x1b,0x38,0xb0,0x08,0x7b,0x30,0x7e,0x0c,0xad,0x7e,0x30,0xd7,0x90,0xce,0xb0,0xce, + 0xbe,0xa8,0xcf,0xc0,0xbe,0xe8,0x57,0x1c,0xcf,0x0c,0x52,0x56,0x54,0xef,0x26,0xd1,0xfc,0x78,0x2b,0xb2,0x2d,0xec,0xcf,0x67,0xea,0x4e,0xa0,0x80,0x3d,0xc1,0x5d,0xaf, + 0x60,0x45,0x1d,0xa4,0xad,0xfe,0x5b,0xb3,0x93,0x10,0x90,0x69,0xef,0xdc,0x84,0x41,0x5e,0xc8,0xa2,0xc4,0x29,0x95,0x5c,0xbf,0x22,0xa4,0x34,0x0f,0x8f,0xc4,0x89,0x36, + 0xd6,0x8e,0x74,0x6f,0x3d,0x43,0xfe,0xac,0x5f,0xd4,0x89,0x8d,0xe9,0x43,0xdc,0x38,0x20,0x5a,0xf7,0xe2,0x63,0x1e,0xd7,0x32,0x07,0x9b,0xbf,0xc8,0xab,0x52,0x51,0x1c, + 0x28,0xda,0xea,0xad,0xc6,0x09,0x38,0x6d,0x77,0x0d,0xff,0x4c,0x71,0x20,0xb2,0xa8,0x7c,0xab,0x3e,0x21,0xfd,0xb8,0xa6,0xe4,0xdc,0x12,0x40,0xa5,0x1d,0x12,0xe5,0x5c, + 0xbb,0x41,0x10,0xb7,0x34,0xc8,0xef,0x8a,0x08,0xbb,0x60,0x11,0xac,0xb3,0x5c,0xbd,0xa9,0xae,0x8e,0x2e,0xf6,0xc4,0xd0,0x86,0x25,0x76,0xa6,0x87,0x92,0x66,0x7b,0xb9, + 0xe2,0x5c,0x50,0x03,0x7c,0xa1,0x91,0x38,0x51,0xb9,0x75,0x87,0x52,0x65,0x9f,0xb6,0x1c,0x02,0xd2,0xa7,0xc6,0xb6,0xaa,0xe2,0x9b,0xda,0x30,0x19,0x07,0xd9,0x9f,0x5d, + 0xad,0x25,0x9f,0x01,0xe9,0x53,0x26,0x3f,0x40,0xa3,0x9b,0x14,0xa5,0x38,0xd0,0x76,0x71,0x0c,0x19,0x20,0x7a,0xf9,0x36,0xfe,0xab,0xdf,0x03,0xbd,0xa7,0xf0,0x67,0xa5, + 0x5e,0xc6,0x02,0x5a,0xc7,0xb2,0x5c,0x0f,0x09,0x5f,0x3f,0xde,0xe3,0xe2,0xe5,0x08,0xbd,0x14,0x37,0xb9,0x70,0x5c,0x25,0x43,0xc0,0xe5,0xaf,0x1c,0x1d,0x36,0x3f,0xfd, + 0xa2,0xf9,0x3a,0x84,0x57,0x4a,0x26,0xb4,0x38,0x80,0xcd,0xe6,0xed,0x44,0x0c,0x7f,0x7c,0xc7,0x2c,0x92,0x50,0x4d,0x52,0x71,0x99,0x9a,0x8a,0x78,0xff,0xe3,0x49,0x1d, + 0x8d,0x0c,0xdb,0x49,0x77,0xba,0x76,0x61,0xd4,0x10,0x36,0xae,0xb7,0xa5,0xf2,0xdd,0x20,0x77,0x16,0xd5,0xd7,0x6e,0xeb,0x26,0x62,0x90,0x43,0xc5,0x59,0xec,0x29,0x00, + 0xde,0xfd,0xe4,0xaa,0x48,0xf8,0x9b,0x03,0xf6,0x23,0xea,0x1f,0x94,0x6f,0x1a,0xa9,0x38,0xc5,0xaa,0xb8,0x79,0xca,0x63,0x19,0x59,0x69,0x26,0xf0,0x85,0x57,0x8e,0xdc, + 0xaf,0xe0,0xbf,0xed,0x69,0xa6,0x00,0x16,0x38,0x65,0x40,0x61,0x27,0xa8,0x97,0x2b,0x61,0x32,0x32,0xaa,0x4c,0x93,0x3a,0x06,0xb5,0xa5,0xb5,0xbc,0xff,0x15,0x96,0xf8, + 0xf4,0x9b,0xca,0x7a,0x6a,0x52,0x56,0xdd,0xf7,0x12,0x77,0x59,0x17,0xc3,0x0e,0x48,0x73,0x15,0x34,0x69,0xba,0xe1,0x2f,0xd5,0xc5,0x57,0x10,0x31,0xdb,0x7b,0x12,0x05, + 0x9c,0x88,0xb6,0x11,0xb7,0xf9,0xaa,0xd3,0x3f,0xab,0xb0,0x9c,0xff,0x61,0x8b,0xb1,0xca,0x6f,0xb9,0x04,0xa2,0x89,0xb1,0x48,0x1d,0xa3,0xd1,0xe4,0xe7,0x25,0x89,0xe4, + 0x42,0xf6,0x34,0xc0,0x6c,0x4a,0x0e,0x7e,0x95,0x6d,0xb6,0xe8,0x66,0x66,0x60,0x3d,0x26,0x37,0x4c,0xc7,0x4b,0x11,0x02,0x6f,0x03,0x18,0xd1,0xa2,0x56,0x81,0xa7,0x12, + 0xe2,0xce,0xb9,0x46,0xe7,0x99,0x3f,0x27,0xa4,0x32,0x7a,0xbd,0xf6,0x1d,0x4f,0x06,0x57,0x7e,0x89,0xc6,0x3b,0x62,0xa2,0x4a,0xef,0xbd,0x90,0x57,0x10,0xd1,0x86,0x69, + 0x71,0x63,0x7a,0x5d,0xa2,0x41,0x2a,0x92,0x1f,0x16,0x36,0xc6,0x9a,0x6e,0xe8,0x10,0x83,0xee,0x2b,0x0e,0x13,0x76,0x6a,0xd1,0x22,0x79,0x1e,0xf6,0xf7,0x71,0x89,0x6d, + 0xbd,0x26,0x5e,0xd3,0x07,0x8c,0xa8,0xc7,0x78,0x8f,0x59,0x41,0x87,0xc9,0x6c,0x67,0x5a,0xa6,0x23,0xec,0xd0,0x1b,0xfc,0xad,0x62,0xd7,0x6a,0x78,0x81,0x33,0x4f,0x63, + 0x8d,0x07,0x3f,0xc5,0x92,0xfb,0x7a,0xa6,0xf7,0xb9,0x08,0xed,0x07,0x14,0x8a,0xa7,0xbe,0x5a,0x13,0x5c,0x4b,0x34,0x3e,0xbe,0x29,0x51,0x98,0xcb,0xa7,0x8e,0x71,0xce, + 0xa2,0x6d,0x69,0x8e,0x46,0x13,0x59,0x5a,0xa6,0x1c,0x8e,0x29,0x07,0xd5,0x24,0x1d,0x6d,0x14,0x90,0x97,0x37,0xdf,0x59,0x89,0x58,0x41,0xd0,0x77,0x27,0xbf,0x13,0x48, + 0xa8,0xed,0xc6,0xf9,0xaf,0x6b,0xf7,0x41,0x22,0xc1,0x1c,0xa1,0xa5,0x0a,0xfb,0xc4,0xa3,0xc4,0x98,0x7b,0xd0,0xd1,0xf7,0x32,0x84,0xd2,0xc1,0x37,0x1e,0x61,0x34,0x05, + 0x17,0x96,0x3d,0xe0,0x78,0x99,0x6e,0xb8,0x50,0x3c,0x7c,0xc3,0xe1,0xa2,0xd5,0x14,0x7d,0x7f,0x0b,0xfb,0x25,0x1a,0x02,0x0b,0x43,0x92,0x03,0x30,0x63,0x58,0x7c,0x8d, + 0x06,0x27,0x99,0xa1,0x95,0x45,0xd3,0x1b,0x3e,0xd7,0x22,0x53,0xbc,0xde,0x59,0x76,0x2a,0xa6,0x10,0x4a,0x88,0xac,0x5e,0x2f,0xb6,0x89,0x26,0xb0,0xf7,0x14,0x66,0x98, + 0x9f,0x42,0xdd,0x8f,0xce,0x13,0xf8,0x10,0x3b,0x3b,0x2b,0xc1,0x5e,0x61,0x24,0x2e,0x68,0x20,0xfe,0x13,0x25,0xa2,0x0e,0xf4,0x60,0xfe,0x64,0xd9,0xeb,0x12,0xb2,0x31, + 0xd1,0xb2,0x04,0xe5,0x2d,0x1f,0xac,0x6d,0x50,0x41,0x32,0xc7,0x6c,0xa2,0x33,0xc8,0x7e,0x37,0x7d,0xcc,0x79,0xc8,0x93,0xc9,0x70,0xdd,0xbb,0x9f,0x87,0xb2,0x7f,0xa0, + 0xc8,0xd6,0xbd,0x28,0xc1,0xe6,0x5a,0xe7,0xc7,0xa5,0xde,0xbe,0x67,0xa7,0xdf,0xaf,0x92,0xb4,0x29,0xed,0xe3,0x68,0xef,0xc9,0xda,0x7d,0x57,0x8a,0x53,0x9b,0x70,0x54, + 0x0d,0x1f,0x90,0x5c,0xc7,0x47,0x20,0xbd,0xe6,0x7a,0xe8,0x4f,0x58,0x27,0x28,0x58,0x8c,0x75,0x44,0x4c,0x27,0x3d,0xae,0x41,0x06,0xfa,0x20,0xd1,0xd6,0x94,0x64,0x30, + 0x3f,0x01,0x4e,0x30,0x91,0x92,0x58,0x8f,0xa8,0x3e,0x47,0xd4,0xac,0x96,0x85,0xd2,0x04,0x12,0x04,0xe2,0xea,0xf6,0x33,0xa1,0x31,0x28,0x12,0xe5,0x1a,0xe7,0x4c,0xbd, + 0x68,0xb4,0x04,0xd5,0x56,0xc8,0x20,0x04,0xc6,0xc4,0xbb,0xa4,0x51,0x8e,0xc0,0x0b,0x1d,0x4f,0x11,0x61,0xca,0xfe,0x6c,0x89,0xae,0xb8,0x49,0x4a,0x9b,0xa0,0x9d,0xb5, + 0xc3,0x31,0xad,0xe7,0xa4,0x57,0xdf,0x7f,0x12,0xa2,0xf5,0xc4,0x3d,0x7e,0xa9,0x48,0x6c,0x15,0x63,0xb8,0x1c,0xd8,0xa0,0xf2,0x3f,0x92,0x3c,0x1a,0x9f,0xa6,0x12,0xe3, + 0x17,0xb5,0xc7,0xa3,0x11,0xee,0xa9,0xd2,0xab,0x75,0x71,0xf8,0xb9,0xf8,0x48,0xd4,0x70,0x59,0x97,0xcf,0x3e,0xaf,0x9b,0xdc,0xbe,0x0e,0x34,0xa6,0x70,0xf8,0x1f,0x45, + 0x2f,0x0e,0x4e,0xcc,0xbc,0x45,0x18,0xac,0xe5,0x58,0xe0,0x66,0x04,0xf9,0xbf,0xf4,0x78,0x7f,0x5b,0x01,0x94,0x37,0xb5,0x21,0x95,0xec,0xb6,0xb8,0x21,0x91,0xa6,0xae, + 0x74,0x94,0xd8,0x64,0xcb,0x6e,0xa9,0xc5,0xd9,0x82,0xd4,0x0a,0x5f,0x10,0x37,0x00,0xd0,0x2d,0xc9,0x82,0x63,0x77,0x53,0xcf,0xc7,0xd8,0xaf,0xe1,0xbe,0xaf,0xff,0x70, + 0xa9,0x68,0x73,0xee,0xf5,0xd4,0x38,0xb8,0x07,0x85,0x3b,0x67,0x71,0xc6,0xa5,0x19,0x7e,0x6e,0xef,0x21,0xef,0xef,0xca,0x53,0x8b,0x45,0xe9,0xe9,0x81,0xc0,0x32,0xe5, + 0x91,0x24,0x61,0x89,0x13,0xf2,0x0c,0xdf,0xfa,0x64,0x22,0x07,0xf1,0x92,0xe6,0x7e,0xb8,0x0a,0xde,0x53,0xac,0x55,0x35,0x46,0x9a,0xbe,0x90,0x03,0x6d,0x4a,0xf7,0xe2, + 0x9d,0x8b,0x74,0x88,0x8d,0x94,0x28,0x70,0xb2,0x21,0xde,0x7a,0x64,0x20,0x32,0x89,0x2b,0xc9,0x9e,0x34,0xbd,0x85,0x50,0x19,0x5f,0x6f,0x5f,0x09,0x75,0x47,0x33,0x4a, + 0x16,0x98,0x33,0x77,0xc0,0xf1,0xa9,0xc0,0x04,0x49,0x5b,0x3f,0xd9,0x65,0x83,0x63,0x11,0x6e,0xea,0x64,0x47,0x87,0xd0,0x59,0xd1,0x14,0x0f,0xb9,0x07,0x55,0x5d,0x4a, + 0x08,0x1a,0xf4,0x0a,0x81,0xd4,0x8c,0x6b,0x53,0x01,0x40,0xdb,0x93,0x5e,0x60,0x5b,0xf4,0xcc,0x7b,0x10,0x88,0x5f,0x5b,0x14,0x8f,0x95,0xf1,0xbc,0x8a,0xd2,0xe5,0x2d, + 0x7e,0x4b,0x97,0x3e,0x6d,0x4a,0x35,0x7c,0x40,0x02,0x43,0xa6,0x48,0xc8,0xa0,0xa6,0xa3,0x5c,0xf2,0x31,0x75,0x4a,0xfd,0xef,0x31,0x2d,0x2f,0x4b,0x6a,0xbb,0x98,0x8f, + 0x0f,0x02,0x35,0xda,0x2a,0x06,0xc8,0xd4,0x08,0xc2,0x71,0x51,0xf3,0xf1,0x53,0x42,0xed,0x8c,0x19,0x45,0xaa,0xf8,0x4e,0xd1,0x49,0x93,0x78,0x6d,0x6a,0xc5,0xf5,0x70, + 0x56,0x22,0xc2,0xfb,0xe8,0xaf,0x5a,0xd6,0xce,0xf7,0x2a,0x01,0xbe,0x18,0x6e,0x55,0x48,0x47,0x57,0x61,0x06,0xf8,0x97,0x97,0x72,0xfa,0x56,0x11,0x4d,0x11,0x60,0xab, + 0xbb,0x95,0xe0,0xd0,0xfb,0xaa,0xd8,0x6c,0x5b,0xd8,0x7b,0x95,0x94,0x6c,0x77,0xff,0x1d,0x65,0x32,0x2a,0x17,0x5c,0xcf,0x16,0x41,0x91,0x02,0xc0,0xa1,0x7f,0x5a,0x72, + 0x45,0x10,0x68,0x3c,0x7b,0xfa,0x25,0x1f,0x0c,0xb5,0x6b,0xba,0x7e,0x0a,0xb7,0x4d,0x90,0xf5,0xe2,0xca,0x01,0xe9,0x1e,0x7c,0xa9,0x93,0x12,0xcc,0xff,0x2d,0x90,0xb6, + 0x02,0x54,0x85,0x14,0x2c,0xa1,0xce,0xd7,0x52,0x28,0x9f,0x77,0x21,0x30,0xfc,0x10,0xc7,0x5a,0x45,0x08,0xc4,0x6b,0xff,0xde,0xf9,0x29,0x0a,0xd3,0xe7,0xba,0xf9,0xca, + 0x90,0x67,0x93,0x21,0x50,0x72,0x49,0x65,0xaa,0x47,0x9c,0x1e,0xf1,0xbe,0x55,0x54,0x4b,0xed,0x9f,0xa9,0x45,0x00,0xa3,0xb6,0x78,0x87,0xed,0x91,0xae,0x3b,0x81,0xe5, + 0xf8,0x08,0x4a,0x89,0xad,0xcc,0xdc,0x3a,0xef,0x89,0xe5,0x09,0x1a,0x0f,0x07,0xd6,0x16,0x0a,0x66,0xcb,0x95,0x75,0x24,0x11,0x00,0xc1,0xd3,0x9b,0xf0,0x54,0x9a,0xe2, + 0x44,0x62,0x55,0x8c,0x89,0x90,0x21,0x17,0x05,0x1c,0xb2,0xc5,0x99,0xad,0x66,0xf0,0x08,0x87,0xb5,0x4c,0xae,0x3d,0xa9,0xc0,0x4d,0x31,0x7a,0x5b,0x2a,0xfb,0x46,0x3b, + 0x30,0xb4,0x74,0x1a,0x64,0xf8,0x7d,0x28,0xec,0x00,0x29,0xbd,0x19,0x6b,0x5a,0x74,0x55,0x5f,0x2c,0x9a,0x97,0x6a,0x46,0xd6,0x28,0x57,0x24,0x74,0x46,0x6a,0x63,0x1d, + 0x3a,0xfc,0x04,0xac,0x92,0x11,0x7e,0x50,0xb0,0x91,0x3b,0x09,0xdb,0xbb,0x4e,0x6c,0x78,0x0c,0x05,0x15,0x00,0x20,0x1f,0xad,0x51,0x2b,0x79,0x08,0x0b,0xff,0x39,0xe2, + 0x60,0x96,0x37,0x04,0x85,0x86,0xed,0xc6,0x4c,0xf5,0xf2,0x8f,0x1a,0x50,0x57,0x68,0xc6,0x86,0x47,0x11,0x10,0x07,0x0d,0x78,0x3d,0xe4,0x99,0xff,0xe6,0xfe,0x84,0xda, + 0xb1,0xd4,0xf2,0x7a,0x69,0x83,0xc8,0xee,0x41,0x7e,0xf0,0xf5,0x27,0xd8,0x89,0xd4,0xa1,0xae,0x41,0xd3,0x63,0x92,0x44,0x57,0x8c,0x43,0xd6,0x50,0xc2,0x99,0xfc,0xd1, + 0x00,0x07,0xc9,0xa2,0x7a,0xc5,0x06,0x7c,0x9f,0x0a,0xd1,0xa4,0xd1,0xe6,0x21,0x10,0xda,0x13,0x18,0x89,0x3a,0x65,0x87,0x29,0x71,0x3d,0x82,0xe3,0x33,0x85,0x5b,0x82, + 0x8a,0x3b,0x23,0xa9,0x1f,0x0d,0x5d,0xb8,0x07,0x4a,0x6a,0x88,0x68,0x89,0xee,0x3e,0x19,0xaa,0xf0,0x9b,0x66,0xac,0x9a,0xad,0x2e,0x15,0xc8,0xbd,0xba,0x68,0x08,0x5c, + 0xc2,0xaf,0x76,0x3f,0x41,0x4c,0xb2,0xd7,0xfd,0x46,0x25,0x7f,0x03,0x13,0xb5,0x82,0xc0,0x99,0xb5,0xe2,0x3b,0x73,0xe0,0x73,0xb5,0xab,0x7c,0x23,0x0c,0x45,0xc8,0x83, + 0x34,0x00,0x56,0x94,0xe3,0xca,0xc0,0x93,0x32,0xaa,0x42,0x80,0x7e,0x3a,0xfd,0xc3,0xb3,0xb3,0xbc,0x7c,0x7b,0xe8,0x87,0xd1,0xf9,0x8d,0x76,0x77,0x8c,0x55,0xcf,0xd7, + 0x58,0x41,0xac,0xd3,0xcf,0xf2,0xd6,0x28,0x61,0xbb,0xe1,0x10,0x84,0x73,0x80,0x06,0xd6,0x8c,0xcf,0x35,0xac,0xae,0x61,0x5e,0xe9,0x52,0x47,0x26,0xe9,0x3d,0x0d,0xa5, + 0x43,0x48,0xe4,0xcb,0xa3,0x71,0xea,0xd0,0x39,0x82,0x01,0x8a,0xbc,0x9a,0xac,0xec,0xae,0xbf,0xd6,0x36,0xdd,0xa8,0x2e,0x60,0x9f,0xd2,0x98,0x94,0x7f,0x90,0x7d,0xe8, + 0xe5,0x62,0x21,0xc2,0xb0,0xdc,0x33,0xb9,0x8b,0x90,0xdf,0xd3,0x23,0x9a,0x2c,0x0c,0xb1,0xe4,0xad,0x03,0x99,0xa3,0xaa,0xef,0x3f,0x9d,0x47,0xfb,0x10,0x3d,0xae,0xf0, + 0x5b,0x34,0xa2,0x9b,0x1c,0x4d,0xdc,0xb2,0x10,0x11,0x62,0xd3,0x4b,0xed,0x9f,0x07,0x02,0x36,0x1f,0xe5,0xaf,0x50,0x5d,0xf3,0x15,0xef,0xf7,0xbe,0xfd,0x0e,0x47,0x19, + 0xce,0xce,0x52,0x1b,0x8b,0x5a,0x32,0xbb,0xee,0x38,0x93,0x6b,0xa7,0xd6,0x45,0x82,0x4f,0x23,0x8e,0x56,0x17,0x01,0xa3,0x86,0xfb,0x88,0x8e,0x01,0x0d,0xb5,0x4b,0x2f, + 0x82,0x95,0x21,0xb7,0x9d,0x71,0xf5,0x01,0x1e,0x07,0x97,0x56,0xb8,0x51,0xa0,0xd5,0xc8,0x35,0x57,0x86,0x61,0x89,0xa6,0x25,0x8c,0x1e,0x78,0xa1,0x70,0x0c,0x69,0x04, + 0x8c,0x59,0x34,0x79,0x35,0x05,0xa6,0xa1,0xf8,0x4d,0x41,0x28,0x33,0x41,0x68,0x0c,0x49,0x23,0xf1,0xf4,0xd5,0x62,0x98,0x9a,0x11,0xcc,0x62,0x6f,0xea,0x5e,0xda,0x5a, + 0x35,0x6c,0xae,0xe7,0xe7,0xee,0xe0,0x31,0xa1,0x5e,0x54,0xc3,0xa5,0xc4,0xe7,0x2f,0x9c,0x74,0xbb,0x28,0x7c,0xe6,0x01,0x61,0x9e,0xf8,0x5e,0xb9,0x6c,0x28,0x94,0x52, + 0x09,0xc7,0x33,0x7d,0xf6,0xc2,0xb3,0x5e,0xdf,0x3a,0x21,0x38,0x25,0x11,0xcc,0x5a,0xdd,0x1a,0x71,0xa8,0x4c,0xbf,0x8d,0x33,0x96,0xa5,0xbe,0x54,0x8d,0x92,0xfa,0x67, + 0xd1,0x6c,0xae,0xdd,0x25,0x79,0x36,0x66,0xf9,0xe2,0x6f,0x53,0x31,0x38,0x21,0x06,0xf5,0x40,0x95,0xb3,0xd2,0x0d,0x40,0xc7,0x45,0xb6,0x8c,0xa7,0x6c,0x0e,0x69,0x83, + 0xb8,0xae,0x1e,0x21,0xd8,0xb3,0x4c,0xe4,0xca,0xff,0xed,0x71,0x67,0xa2,0x68,0x68,0xec,0x80,0xa7,0xd4,0xa6,0xa9,0x8b,0x63,0x9d,0x4d,0x05,0xcd,0x22,0x65,0x04,0xde, + 0x02,0x77,0x63,0x15,0xfe,0x14,0x7a,0x36,0xa4,0xb0,0x98,0x74,0x92,0xb6,0x50,0x3a,0xcd,0xea,0x60,0xf9,0x26,0x45,0x0e,0x5e,0xdd,0xb9,0xf8,0x8f,0xc8,0x21,0x78,0xd3, + 0x39,0x88,0xc9,0xc7,0x05,0x0a,0x28,0x79,0x49,0x34,0xe5,0xbd,0x67,0x62,0x9b,0x55,0x6d,0x97,0xa4,0x85,0x8d,0x22,0x81,0x28,0x35,0xf4,0xa3,0x7d,0xca,0x35,0x19,0x43, + 0x34,0x00,0x56,0x94,0xe3,0xca,0xc0,0x93,0x32,0xaa,0x42,0x80,0x7e,0x3a,0xfd,0xc3,0xb3,0xb3,0xbc,0x7c,0x7b,0xe8,0x87,0xd1,0xf9,0x8d,0x76,0x77,0x8c,0x55,0xcf,0xd7, + 0x4b,0x52,0x25,0x7d,0x8b,0x3b,0xa3,0x87,0x79,0x7f,0xdf,0x7a,0x75,0x2f,0x19,0x5d,0xdc,0x4f,0x7d,0x76,0x26,0x3d,0xe6,0x1d,0x0d,0x52,0xa5,0xec,0x14,0xa3,0x6c,0xbf, + 0x38,0x0c,0x53,0xe0,0xa5,0x09,0xeb,0xb3,0xb6,0x33,0x46,0x59,0x81,0x05,0x21,0x9b,0x43,0xd5,0x1a,0xe1,0x96,0xb4,0x55,0x7d,0x59,0xbb,0xd6,0x78,0x24,0x03,0x2d,0xff, + 0x38,0x0c,0x53,0xe0,0xa5,0x09,0xeb,0xb3,0xb6,0x33,0x46,0x59,0x81,0x05,0x21,0x9b,0x43,0xd5,0x1a,0xe1,0x96,0xb4,0x55,0x7d,0x59,0xbb,0xd6,0x78,0x24,0x03,0x2d,0xff, + 0x38,0x0c,0x53,0xe0,0xa5,0x09,0xeb,0xb3,0xb6,0x33,0x46,0x59,0x81,0x05,0x21,0x9b,0x43,0xd5,0x1a,0xe1,0x96,0xb4,0x55,0x7d,0x59,0xbb,0xd6,0x78,0x24,0x03,0x2d,0xff, + 0x38,0x0c,0x53,0xe0,0xa5,0x09,0xeb,0xb3,0xb6,0x33,0x46,0x59,0x81,0x05,0x21,0x9b,0x43,0xd5,0x1a,0xe1,0x96,0xb4,0x55,0x7d,0x59,0xbb,0xd6,0x78,0x24,0x03,0x2d,0xff, + 0x38,0x0c,0x53,0xe0,0xa5,0x09,0xeb,0xb3,0xb6,0x33,0x46,0x59,0x81,0x05,0x21,0x9b,0x43,0xd5,0x1a,0xe1,0x96,0xb4,0x55,0x7d,0x59,0xbb,0xd6,0x78,0x24,0x03,0x2d,0xff, + 0x38,0x0c,0x53,0xe0,0xa5,0x09,0xeb,0xb3,0xb6,0x33,0x46,0x59,0x81,0x05,0x21,0x9b,0x43,0xd5,0x1a,0xe1,0x96,0xb4,0x55,0x7d,0x59,0xbb,0xd6,0x78,0x24,0x03,0x2d,0xff}; + +static const wycheproof_ecdh_testvector testvectors[SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS] = { + /* tcId: 1. normal case */ + {0, 65, 0, 32, 0, 32, 1, 1 }, + /* tcId: 2. compressed public key */ + {65, 33, 0, 32, 32, 32, 1, 2 }, + /* tcId: 3. shared secret has x-coordinate that satisfies x**2 + a = 1 */ + {98, 65, 32, 32, 64, 32, 1, 3 }, + /* tcId: 4. shared secret has x-coordinate that satisfies x**2 + a = 4 */ + {163, 65, 32, 32, 96, 32, 1, 4 }, + /* tcId: 5. shared secret has x-coordinate that satisfies x**2 + a = 9 */ + {228, 65, 32, 32, 128, 32, 1, 5 }, + /* tcId: 6. shared secret has x-coordinate p-3 */ + {293, 65, 32, 32, 160, 32, 1, 6 }, + /* tcId: 7. shared secret has x-coordinate 2**16 + 0 */ + {358, 65, 32, 32, 192, 32, 1, 7 }, + /* tcId: 8. shared secret has x-coordinate 2**32 + 7 */ + {423, 65, 32, 32, 224, 32, 1, 8 }, + /* tcId: 9. shared secret has x-coordinate 2**64 + 1 */ + {488, 65, 32, 32, 256, 32, 1, 9 }, + /* tcId: 10. shared secret has x-coordinate 2**96 + 1 */ + {553, 65, 32, 32, 288, 32, 1, 10 }, + /* tcId: 11. shared secret has x-coordinate that satisfies x**2 + a = -6 */ + {618, 65, 32, 32, 320, 32, 1, 11 }, + /* tcId: 12. shared secret has x-coordinate that satisfies x**2 + a = 2 */ + {683, 65, 32, 32, 352, 32, 1, 12 }, + /* tcId: 13. shared secret has x-coordinate that satisfies x**2 + a = 8 */ + {748, 65, 32, 32, 384, 32, 1, 13 }, + /* tcId: 14. shared secret has x-coordinate that satisfies x**2 = 2**96 + 2 */ + {813, 65, 32, 32, 416, 32, 1, 14 }, + /* tcId: 15. shared secret has x-coordinate with repeating bit-pattern of size 2 */ + {878, 65, 32, 32, 448, 32, 1, 15 }, + /* tcId: 16. shared secret has x-coordinate with repeating bit-pattern of size 2 */ + {943, 65, 32, 32, 480, 32, 1, 16 }, + /* tcId: 17. shared secret has x-coordinate with repeating bit-pattern of size 4 */ + {1008, 65, 32, 32, 512, 32, 1, 17 }, + /* tcId: 18. shared secret has x-coordinate with repeating bit-pattern of size 4 */ + {1073, 65, 32, 32, 544, 32, 1, 18 }, + /* tcId: 19. shared secret has x-coordinate with repeating bit-pattern of size 8 */ + {1138, 65, 32, 32, 576, 32, 1, 19 }, + /* tcId: 20. shared secret has x-coordinate with repeating bit-pattern of size 8 */ + {1203, 65, 32, 32, 608, 32, 1, 20 }, + /* tcId: 21. shared secret has x-coordinate with repeating bit-pattern of size 16 */ + {1268, 65, 32, 32, 640, 32, 1, 21 }, + /* tcId: 22. shared secret has x-coordinate with repeating bit-pattern of size 16 */ + {1333, 65, 32, 32, 672, 32, 1, 22 }, + /* tcId: 23. shared secret has x-coordinate with repeating bit-pattern of size 30 */ + {1398, 65, 32, 32, 704, 32, 1, 23 }, + /* tcId: 24. shared secret has x-coordinate with repeating bit-pattern of size 30 */ + {1463, 65, 32, 32, 736, 32, 1, 24 }, + /* tcId: 25. shared secret has x-coordinate with repeating bit-pattern of size 32 */ + {1528, 65, 32, 32, 768, 32, 1, 25 }, + /* tcId: 26. shared secret has x-coordinate with repeating bit-pattern of size 32 */ + {1593, 65, 32, 32, 800, 32, 1, 26 }, + /* tcId: 27. shared secret has x-coordinate with repeating bit-pattern of size 51 */ + {1658, 65, 32, 32, 832, 32, 1, 27 }, + /* tcId: 28. shared secret has x-coordinate with repeating bit-pattern of size 51 */ + {1723, 65, 32, 32, 864, 32, 1, 28 }, + /* tcId: 29. shared secret has x-coordinate with repeating bit-pattern of size 52 */ + {1788, 65, 32, 32, 896, 32, 1, 29 }, + /* tcId: 30. shared secret has x-coordinate with repeating bit-pattern of size 52 */ + {1853, 65, 32, 32, 928, 32, 1, 30 }, + /* tcId: 31. shared secret has x-coordinate with repeating bit-pattern of size 60 */ + {1918, 65, 32, 32, 960, 32, 1, 31 }, + /* tcId: 32. shared secret has x-coordinate with repeating bit-pattern of size 60 */ + {1983, 65, 32, 32, 992, 32, 1, 32 }, + /* tcId: 33. shared secret has x-coordinate with repeating bit-pattern of size 62 */ + {2048, 65, 32, 32, 1024, 32, 1, 33 }, + /* tcId: 34. shared secret has x-coordinate with repeating bit-pattern of size 62 */ + {2113, 65, 32, 32, 1056, 32, 1, 34 }, + /* tcId: 35. shared secret has x-coordinate with repeating bit-pattern of size 64 */ + {2178, 65, 32, 32, 1088, 32, 1, 35 }, + /* tcId: 36. shared secret has x-coordinate with repeating bit-pattern of size 64 */ + {2243, 65, 32, 32, 1120, 32, 1, 36 }, + /* tcId: 37. shared secret has x-coordinate with repeating bit-pattern of size 112 */ + {2308, 65, 32, 32, 1152, 32, 1, 37 }, + /* tcId: 38. shared secret has x-coordinate with repeating bit-pattern of size 112 */ + {2373, 65, 32, 32, 1184, 32, 1, 38 }, + /* tcId: 39. shared secret has x-coordinate with repeating bit-pattern of size 128 */ + {2438, 65, 32, 32, 1216, 32, 1, 39 }, + /* tcId: 40. shared secret has x-coordinate with repeating bit-pattern of size 128 */ + {2503, 65, 32, 32, 1248, 32, 1, 40 }, + /* tcId: 41. shared secret has an x-coordinate of approx p//3 */ + {2568, 65, 32, 32, 1280, 32, 1, 41 }, + /* tcId: 42. shared secret has an x-coordinate of approx p//5 */ + {2633, 65, 32, 32, 1312, 32, 1, 42 }, + /* tcId: 43. shared secret has an x-coordinate of approx p//7 */ + {2698, 65, 32, 32, 1344, 32, 1, 43 }, + /* tcId: 44. shared secret has an x-coordinate of approx p//9 */ + {2763, 65, 32, 32, 1376, 32, 1, 44 }, + /* tcId: 45. y-coordinate of the public key has many trailing 1's */ + {2828, 65, 32, 32, 1408, 32, 1, 45 }, + /* tcId: 46. y-coordinate of the public key has many trailing 1's */ + {2893, 65, 64, 32, 1440, 32, 1, 46 }, + /* tcId: 47. y-coordinate of the public key is small */ + {2958, 65, 32, 32, 1472, 32, 1, 47 }, + /* tcId: 48. y-coordinate of the public key is small */ + {3023, 65, 32, 32, 1504, 32, 1, 48 }, + /* tcId: 49. y-coordinate of the public key is small */ + {3088, 65, 64, 32, 1536, 32, 1, 49 }, + /* tcId: 50. y-coordinate of the public key is small */ + {3153, 65, 64, 32, 1568, 32, 1, 50 }, + /* tcId: 51. y-coordinate of the public key is large */ + {3218, 65, 32, 32, 1600, 32, 1, 51 }, + /* tcId: 52. y-coordinate of the public key is large */ + {3283, 65, 32, 32, 1632, 32, 1, 52 }, + /* tcId: 53. y-coordinate of the public key is large */ + {3348, 65, 64, 32, 1664, 32, 1, 53 }, + /* tcId: 54. y-coordinate of the public key is large */ + {3413, 65, 64, 32, 1696, 32, 1, 54 }, + /* tcId: 55. y-coordinate of the public key has many trailing 0's */ + {3478, 65, 32, 32, 1728, 32, 1, 55 }, + /* tcId: 56. y-coordinate of the public key has many trailing 0's */ + {3543, 65, 64, 32, 1760, 32, 1, 56 }, + /* tcId: 57. ephemeral key has x-coordinate that satisfies x**2 + a = 1 */ + {3608, 65, 64, 32, 1792, 32, 1, 57 }, + /* tcId: 58. ephemeral key has x-coordinate that satisfies x**2 + a = 4 */ + {3673, 65, 64, 32, 1824, 32, 1, 58 }, + /* tcId: 59. ephemeral key has x-coordinate that satisfies x**2 + a = 9 */ + {3738, 65, 64, 32, 1856, 32, 1, 59 }, + /* tcId: 60. ephemeral key has x-coordinate p-3 */ + {3803, 65, 64, 32, 1888, 32, 1, 60 }, + /* tcId: 61. ephemeral key has x-coordinate 2**16 + 0 */ + {3868, 65, 64, 32, 1920, 32, 1, 61 }, + /* tcId: 62. ephemeral key has x-coordinate 2**32 + 7 */ + {3933, 65, 64, 32, 1952, 32, 1, 62 }, + /* tcId: 63. ephemeral key has x-coordinate 2**64 + 1 */ + {3998, 65, 64, 32, 1984, 32, 1, 63 }, + /* tcId: 64. ephemeral key has x-coordinate 2**96 + 1 */ + {4063, 65, 64, 32, 2016, 32, 1, 64 }, + /* tcId: 65. ephemeral key has x-coordinate that satisfies x**2 + a = -6 */ + {4128, 65, 64, 32, 2048, 32, 1, 65 }, + /* tcId: 66. ephemeral key has x-coordinate that satisfies x**2 + a = 2 */ + {4193, 65, 64, 32, 2080, 32, 1, 66 }, + /* tcId: 67. ephemeral key has x-coordinate that satisfies x**2 + a = 8 */ + {4258, 65, 64, 32, 2112, 32, 1, 67 }, + /* tcId: 68. ephemeral key has x-coordinate that satisfies x**2 = 2**96 + 2 */ + {4323, 65, 64, 32, 2144, 32, 1, 68 }, + /* tcId: 69. ephemeral key has x-coordinate with repeating bit-pattern of size 2 */ + {4388, 65, 64, 32, 2176, 32, 1, 69 }, + /* tcId: 70. ephemeral key has x-coordinate with repeating bit-pattern of size 2 */ + {4453, 65, 64, 32, 2208, 32, 1, 70 }, + /* tcId: 71. ephemeral key has x-coordinate with repeating bit-pattern of size 4 */ + {4518, 65, 64, 32, 2240, 32, 1, 71 }, + /* tcId: 72. ephemeral key has x-coordinate with repeating bit-pattern of size 4 */ + {4583, 65, 64, 32, 2272, 32, 1, 72 }, + /* tcId: 73. ephemeral key has x-coordinate with repeating bit-pattern of size 8 */ + {4648, 65, 64, 32, 2304, 32, 1, 73 }, + /* tcId: 74. ephemeral key has x-coordinate with repeating bit-pattern of size 8 */ + {4713, 65, 64, 32, 2336, 32, 1, 74 }, + /* tcId: 75. ephemeral key has x-coordinate with repeating bit-pattern of size 16 */ + {4778, 65, 64, 32, 2368, 32, 1, 75 }, + /* tcId: 76. ephemeral key has x-coordinate with repeating bit-pattern of size 16 */ + {4843, 65, 64, 32, 2400, 32, 1, 76 }, + /* tcId: 77. ephemeral key has x-coordinate with repeating bit-pattern of size 30 */ + {4908, 65, 64, 32, 2432, 32, 1, 77 }, + /* tcId: 78. ephemeral key has x-coordinate with repeating bit-pattern of size 30 */ + {4973, 65, 64, 32, 2464, 32, 1, 78 }, + /* tcId: 79. ephemeral key has x-coordinate with repeating bit-pattern of size 32 */ + {5038, 65, 64, 32, 2496, 32, 1, 79 }, + /* tcId: 80. ephemeral key has x-coordinate with repeating bit-pattern of size 32 */ + {5103, 65, 64, 32, 2528, 32, 1, 80 }, + /* tcId: 81. ephemeral key has x-coordinate with repeating bit-pattern of size 51 */ + {5168, 65, 64, 32, 2560, 32, 1, 81 }, + /* tcId: 82. ephemeral key has x-coordinate with repeating bit-pattern of size 51 */ + {5233, 65, 64, 32, 2592, 32, 1, 82 }, + /* tcId: 83. ephemeral key has x-coordinate with repeating bit-pattern of size 52 */ + {5298, 65, 64, 32, 2624, 32, 1, 83 }, + /* tcId: 84. ephemeral key has x-coordinate with repeating bit-pattern of size 52 */ + {5363, 65, 64, 32, 2656, 32, 1, 84 }, + /* tcId: 85. ephemeral key has x-coordinate with repeating bit-pattern of size 60 */ + {5428, 65, 64, 32, 2688, 32, 1, 85 }, + /* tcId: 86. ephemeral key has x-coordinate with repeating bit-pattern of size 60 */ + {5493, 65, 64, 32, 2720, 32, 1, 86 }, + /* tcId: 87. ephemeral key has x-coordinate with repeating bit-pattern of size 62 */ + {5558, 65, 64, 32, 2752, 32, 1, 87 }, + /* tcId: 88. ephemeral key has x-coordinate with repeating bit-pattern of size 62 */ + {5623, 65, 64, 32, 2784, 32, 1, 88 }, + /* tcId: 89. ephemeral key has x-coordinate with repeating bit-pattern of size 64 */ + {5688, 65, 64, 32, 2816, 32, 1, 89 }, + /* tcId: 90. ephemeral key has x-coordinate with repeating bit-pattern of size 64 */ + {5753, 65, 64, 32, 2848, 32, 1, 90 }, + /* tcId: 91. ephemeral key has x-coordinate with repeating bit-pattern of size 112 */ + {5818, 65, 64, 32, 2880, 32, 1, 91 }, + /* tcId: 92. ephemeral key has x-coordinate with repeating bit-pattern of size 112 */ + {5883, 65, 64, 32, 2912, 32, 1, 92 }, + /* tcId: 93. ephemeral key has x-coordinate with repeating bit-pattern of size 128 */ + {5948, 65, 64, 32, 2944, 32, 1, 93 }, + /* tcId: 94. ephemeral key has x-coordinate with repeating bit-pattern of size 128 */ + {6013, 65, 64, 32, 2976, 32, 1, 94 }, + /* tcId: 95. ephemeral key has an x-coordinate of approx p//3 */ + {6078, 65, 64, 32, 3008, 32, 1, 95 }, + /* tcId: 96. ephemeral key has an x-coordinate of approx p//5 */ + {6143, 65, 64, 32, 3040, 32, 1, 96 }, + /* tcId: 97. ephemeral key has an x-coordinate of approx p//7 */ + {6208, 65, 64, 32, 3072, 32, 1, 97 }, + /* tcId: 98. ephemeral key has an x-coordinate of approx p//9 */ + {6273, 65, 64, 32, 3104, 32, 1, 98 }, + /* tcId: 99. edge case for Jacobian and projective coordinates */ + {6338, 65, 96, 32, 3136, 32, 1, 99 }, + /* tcId: 100. edge case for Jacobian and projective coordinates */ + {6403, 65, 96, 32, 3168, 32, 1, 100 }, + /* tcId: 101. edge case for Jacobian and projective coordinates */ + {6468, 65, 96, 32, 3200, 32, 1, 101 }, + /* tcId: 102. edge case for Jacobian and projective coordinates */ + {6533, 65, 128, 32, 3232, 32, 1, 102 }, + /* tcId: 103. edge case for Jacobian and projective coordinates */ + {6598, 65, 128, 32, 3264, 32, 1, 103 }, + /* tcId: 104. edge case for Jacobian and projective coordinates */ + {6663, 65, 128, 32, 3296, 32, 1, 104 }, + /* tcId: 105. edge case for Jacobian and projective coordinates in left to right addition chain */ + {6728, 65, 96, 32, 3328, 32, 1, 105 }, + /* tcId: 106. edge case for Jacobian and projective coordinates in left to right addition chain */ + {6793, 65, 96, 32, 3360, 32, 1, 106 }, + /* tcId: 107. edge case for Jacobian and projective coordinates in left to right addition chain */ + {6858, 65, 96, 32, 3392, 32, 1, 107 }, + /* tcId: 108. edge case for Jacobian and projective coordinates in left to right addition chain */ + {6923, 65, 96, 32, 3424, 32, 1, 108 }, + /* tcId: 109. edge case for Jacobian and projective coordinates in left to right addition chain */ + {6988, 65, 96, 32, 3456, 32, 1, 109 }, + /* tcId: 110. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7053, 65, 96, 32, 3488, 32, 1, 110 }, + /* tcId: 111. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7118, 65, 96, 32, 3520, 32, 1, 111 }, + /* tcId: 112. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7183, 65, 96, 32, 3552, 32, 1, 112 }, + /* tcId: 113. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7248, 65, 96, 32, 3584, 32, 1, 113 }, + /* tcId: 114. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7313, 65, 96, 32, 3616, 32, 1, 114 }, + /* tcId: 115. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7378, 65, 96, 32, 3648, 32, 1, 115 }, + /* tcId: 116. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7443, 65, 96, 32, 3680, 32, 1, 116 }, + /* tcId: 117. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7508, 65, 96, 32, 3712, 32, 1, 117 }, + /* tcId: 118. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7573, 65, 96, 32, 3744, 32, 1, 118 }, + /* tcId: 119. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7638, 65, 96, 32, 3776, 32, 1, 119 }, + /* tcId: 120. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7703, 65, 96, 32, 3808, 32, 1, 120 }, + /* tcId: 121. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7768, 65, 128, 32, 3840, 32, 1, 121 }, + /* tcId: 122. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7833, 65, 128, 32, 3872, 32, 1, 122 }, + /* tcId: 123. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7898, 65, 128, 32, 3904, 32, 1, 123 }, + /* tcId: 124. edge case for Jacobian and projective coordinates in left to right addition chain */ + {7963, 65, 128, 32, 3936, 32, 1, 124 }, + /* tcId: 125. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8028, 65, 128, 32, 3968, 32, 1, 125 }, + /* tcId: 126. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8093, 65, 128, 32, 4000, 32, 1, 126 }, + /* tcId: 127. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8158, 65, 128, 32, 4032, 32, 1, 127 }, + /* tcId: 128. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8223, 65, 128, 32, 4064, 32, 1, 128 }, + /* tcId: 129. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8288, 65, 128, 32, 4096, 32, 1, 129 }, + /* tcId: 130. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8353, 65, 128, 32, 4128, 32, 1, 130 }, + /* tcId: 131. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8418, 65, 128, 32, 4160, 32, 1, 131 }, + /* tcId: 132. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8483, 65, 128, 32, 4192, 32, 1, 132 }, + /* tcId: 133. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8548, 65, 128, 32, 4224, 32, 1, 133 }, + /* tcId: 134. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8613, 65, 128, 32, 4256, 32, 1, 134 }, + /* tcId: 135. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8678, 65, 128, 32, 4288, 32, 1, 135 }, + /* tcId: 136. edge case for Jacobian and projective coordinates in left to right addition chain */ + {8743, 65, 128, 32, 4320, 32, 1, 136 }, + /* tcId: 137. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {8808, 65, 128, 32, 4352, 32, 1, 137 }, + /* tcId: 138. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {8873, 65, 128, 32, 4384, 32, 1, 138 }, + /* tcId: 139. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {8938, 65, 128, 32, 4416, 32, 1, 139 }, + /* tcId: 140. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9003, 65, 128, 32, 4448, 32, 1, 140 }, + /* tcId: 141. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9068, 65, 128, 32, 4480, 32, 1, 141 }, + /* tcId: 142. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9133, 65, 128, 32, 4512, 32, 1, 142 }, + /* tcId: 143. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9198, 65, 128, 32, 4544, 32, 1, 143 }, + /* tcId: 144. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9263, 65, 128, 32, 4576, 32, 1, 144 }, + /* tcId: 145. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9328, 65, 128, 32, 4608, 32, 1, 145 }, + /* tcId: 146. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9393, 65, 128, 32, 4640, 32, 1, 146 }, + /* tcId: 147. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9458, 65, 128, 32, 4672, 32, 1, 147 }, + /* tcId: 148. edge case for Jacobian and projective coordinates in precomputation or right to left addition chain */ + {9523, 65, 128, 32, 4704, 32, 1, 148 }, + /* tcId: 149. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9588, 65, 128, 32, 4736, 32, 1, 149 }, + /* tcId: 150. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9653, 65, 128, 32, 4768, 32, 1, 150 }, + /* tcId: 151. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9718, 65, 128, 32, 4800, 32, 1, 151 }, + /* tcId: 152. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9783, 65, 128, 32, 4832, 32, 1, 152 }, + /* tcId: 153. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9848, 65, 128, 32, 4864, 32, 1, 153 }, + /* tcId: 154. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9913, 65, 128, 32, 4896, 32, 1, 154 }, + /* tcId: 155. edge case for Jacobian and projective coordinates in right to left addition chain */ + {9978, 65, 128, 32, 4928, 32, 1, 155 }, + /* tcId: 156. edge case for Jacobian and projective coordinates in right to left addition chain */ + {10043, 65, 128, 32, 4960, 32, 1, 156 }, + /* tcId: 157. edge case for Jacobian and projective coordinates in right to left addition chain */ + {10108, 65, 128, 32, 4992, 32, 1, 157 }, + /* tcId: 158. edge case for Jacobian and projective coordinates in right to left addition chain */ + {10173, 65, 128, 32, 5024, 32, 1, 158 }, + /* tcId: 159. edge case for computation of x with projective coordinates */ + {10238, 65, 128, 32, 5056, 32, 1, 159 }, + /* tcId: 160. edge case for computation of x with projective coordinates */ + {10303, 65, 128, 32, 5088, 32, 1, 160 }, + /* tcId: 161. edge case for computation of x with projective coordinates */ + {10368, 65, 128, 32, 5120, 32, 1, 161 }, + /* tcId: 162. edge case for computation of x with projective coordinates */ + {10433, 65, 128, 32, 5152, 32, 1, 162 }, + /* tcId: 163. edge case for computation of x with projective coordinates */ + {10498, 65, 128, 32, 5184, 32, 1, 163 }, + /* tcId: 164. edge case for computation of x with projective coordinates */ + {10563, 65, 128, 32, 5216, 32, 1, 164 }, + /* tcId: 165. edge case for computation of x with projective coordinates */ + {10628, 65, 128, 32, 5248, 32, 1, 165 }, + /* tcId: 166. edge case for computation of x with projective coordinates */ + {10693, 65, 128, 32, 5280, 32, 1, 166 }, + /* tcId: 167. edge case for computation of x with projective coordinates */ + {10758, 65, 128, 32, 5312, 32, 1, 167 }, + /* tcId: 168. edge case for computation of x with projective coordinates in left to right addition chain */ + {10823, 65, 128, 32, 5344, 32, 1, 168 }, + /* tcId: 169. edge case for computation of x with projective coordinates in left to right addition chain */ + {10888, 65, 128, 32, 5376, 32, 1, 169 }, + /* tcId: 170. edge case for computation of x with projective coordinates in left to right addition chain */ + {10953, 65, 128, 32, 5408, 32, 1, 170 }, + /* tcId: 171. edge case for computation of x with projective coordinates in left to right addition chain */ + {11018, 65, 128, 32, 5440, 32, 1, 171 }, + /* tcId: 172. edge case for computation of x with projective coordinates in left to right addition chain */ + {11083, 65, 128, 32, 5472, 32, 1, 172 }, + /* tcId: 173. edge case for computation of x with projective coordinates in left to right addition chain */ + {11148, 65, 128, 32, 5504, 32, 1, 173 }, + /* tcId: 174. edge case for computation of x with projective coordinates in left to right addition chain */ + {11213, 65, 128, 32, 5536, 32, 1, 174 }, + /* tcId: 175. edge case for computation of x with projective coordinates in left to right addition chain */ + {11278, 65, 128, 32, 5568, 32, 1, 175 }, + /* tcId: 176. edge case for computation of x with projective coordinates in left to right addition chain */ + {11343, 65, 128, 32, 5600, 32, 1, 176 }, + /* tcId: 177. edge case for computation of x with projective coordinates in left to right addition chain */ + {11408, 65, 128, 32, 5632, 32, 1, 177 }, + /* tcId: 178. edge case for computation of x with projective coordinates in left to right addition chain */ + {11473, 65, 128, 32, 5664, 32, 1, 178 }, + /* tcId: 179. edge case for computation of x with projective coordinates in left to right addition chain */ + {11538, 65, 128, 32, 5696, 32, 1, 179 }, + /* tcId: 180. edge case for computation of x with projective coordinates in left to right addition chain */ + {11603, 65, 128, 32, 5728, 32, 1, 180 }, + /* tcId: 181. edge case for computation of x with projective coordinates in left to right addition chain */ + {11668, 65, 128, 32, 5760, 32, 1, 181 }, + /* tcId: 182. edge case for computation of x with projective coordinates in left to right addition chain */ + {11733, 65, 128, 32, 5792, 32, 1, 182 }, + /* tcId: 183. edge case for computation of x with projective coordinates in left to right addition chain */ + {11798, 65, 128, 32, 5824, 32, 1, 183 }, + /* tcId: 184. edge case for computation of x with projective coordinates in left to right addition chain */ + {11863, 65, 128, 32, 5856, 32, 1, 184 }, + /* tcId: 185. edge case for computation of x with projective coordinates in left to right addition chain */ + {11928, 65, 128, 32, 5888, 32, 1, 185 }, + /* tcId: 186. edge case for computation of x with projective coordinates in left to right addition chain */ + {11993, 65, 128, 32, 5920, 32, 1, 186 }, + /* tcId: 187. edge case for computation of x with projective coordinates in left to right addition chain */ + {12058, 65, 128, 32, 5952, 32, 1, 187 }, + /* tcId: 188. edge case for computation of x with projective coordinates in left to right addition chain */ + {12123, 65, 128, 32, 5984, 32, 1, 188 }, + /* tcId: 189. edge case for computation of x with projective coordinates in left to right addition chain */ + {12188, 65, 128, 32, 6016, 32, 1, 189 }, + /* tcId: 190. edge case for computation of x with projective coordinates in left to right addition chain */ + {12253, 65, 128, 32, 6048, 32, 1, 190 }, + /* tcId: 191. edge case for computation of x with projective coordinates in left to right addition chain */ + {12318, 65, 128, 32, 6080, 32, 1, 191 }, + /* tcId: 192. edge case for computation of x with projective coordinates in left to right addition chain */ + {12383, 65, 128, 32, 6112, 32, 1, 192 }, + /* tcId: 193. edge case for computation of x with projective coordinates in left to right addition chain */ + {12448, 65, 128, 32, 6144, 32, 1, 193 }, + /* tcId: 194. edge case for computation of x with projective coordinates in left to right addition chain */ + {12513, 65, 128, 32, 6176, 32, 1, 194 }, + /* tcId: 195. edge case for computation of x with projective coordinates in left to right addition chain */ + {12578, 65, 128, 32, 6208, 32, 1, 195 }, + /* tcId: 196. edge case for computation of x with projective coordinates in left to right addition chain */ + {12643, 65, 128, 32, 6240, 32, 1, 196 }, + /* tcId: 197. edge case for computation of x with projective coordinates in left to right addition chain */ + {12708, 65, 128, 32, 6272, 32, 1, 197 }, + /* tcId: 198. edge case for computation of x with projective coordinates in left to right addition chain */ + {12773, 65, 128, 32, 6304, 32, 1, 198 }, + /* tcId: 199. edge case for computation of x with projective coordinates in left to right addition chain */ + {12838, 65, 128, 32, 6336, 32, 1, 199 }, + /* tcId: 200. edge case for computation of x with projective coordinates in left to right addition chain */ + {12903, 65, 128, 32, 6368, 32, 1, 200 }, + /* tcId: 201. edge case for computation of x with projective coordinates in left to right addition chain */ + {12968, 65, 128, 32, 6400, 32, 1, 201 }, + /* tcId: 202. edge case for computation of x with projective coordinates in left to right addition chain */ + {13033, 65, 128, 32, 6432, 32, 1, 202 }, + /* tcId: 203. edge case for computation of x with projective coordinates in left to right addition chain */ + {13098, 65, 128, 32, 6464, 32, 1, 203 }, + /* tcId: 204. edge case for computation of x with projective coordinates in left to right addition chain */ + {13163, 65, 128, 32, 6496, 32, 1, 204 }, + /* tcId: 205. edge case for computation of x with projective coordinates in left to right addition chain */ + {13228, 65, 128, 32, 6528, 32, 1, 205 }, + /* tcId: 206. edge case for computation of x with projective coordinates in left to right addition chain */ + {13293, 65, 128, 32, 6560, 32, 1, 206 }, + /* tcId: 207. edge case for computation of x with projective coordinates in left to right addition chain */ + {13358, 65, 128, 32, 6592, 32, 1, 207 }, + /* tcId: 208. edge case for computation of x with projective coordinates in left to right addition chain */ + {13423, 65, 128, 32, 6624, 32, 1, 208 }, + /* tcId: 209. edge case for computation of x with projective coordinates in left to right addition chain */ + {13488, 65, 128, 32, 6656, 32, 1, 209 }, + /* tcId: 210. edge case for computation of x with projective coordinates in left to right addition chain */ + {13553, 65, 128, 32, 6688, 32, 1, 210 }, + /* tcId: 211. edge case for computation of x with projective coordinates in left to right addition chain */ + {13618, 65, 128, 32, 6720, 32, 1, 211 }, + /* tcId: 212. edge case for computation of x with projective coordinates in left to right addition chain */ + {13683, 65, 128, 32, 6752, 32, 1, 212 }, + /* tcId: 213. edge case for computation of x with projective coordinates in left to right addition chain */ + {13748, 65, 128, 32, 6784, 32, 1, 213 }, + /* tcId: 214. edge case for computation of x with projective coordinates in left to right addition chain */ + {13813, 65, 128, 32, 6816, 32, 1, 214 }, + /* tcId: 215. edge case for computation of x with projective coordinates in left to right addition chain */ + {13878, 65, 128, 32, 6848, 32, 1, 215 }, + /* tcId: 216. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {13943, 65, 128, 32, 6880, 32, 1, 216 }, + /* tcId: 217. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14008, 65, 128, 32, 6912, 32, 1, 217 }, + /* tcId: 218. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14073, 65, 128, 32, 6944, 32, 1, 218 }, + /* tcId: 219. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14138, 65, 128, 32, 6976, 32, 1, 219 }, + /* tcId: 220. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14203, 65, 128, 32, 7008, 32, 1, 220 }, + /* tcId: 221. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14268, 65, 128, 32, 7040, 32, 1, 221 }, + /* tcId: 222. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14333, 65, 128, 32, 7072, 32, 1, 222 }, + /* tcId: 223. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14398, 65, 128, 32, 7104, 32, 1, 223 }, + /* tcId: 224. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14463, 65, 128, 32, 7136, 32, 1, 224 }, + /* tcId: 225. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14528, 65, 128, 32, 7168, 32, 1, 225 }, + /* tcId: 226. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14593, 65, 128, 32, 7200, 32, 1, 226 }, + /* tcId: 227. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14658, 65, 128, 32, 7232, 32, 1, 227 }, + /* tcId: 228. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14723, 65, 128, 32, 7264, 32, 1, 228 }, + /* tcId: 229. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14788, 65, 128, 32, 7296, 32, 1, 229 }, + /* tcId: 230. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14853, 65, 128, 32, 7328, 32, 1, 230 }, + /* tcId: 231. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14918, 65, 128, 32, 7360, 32, 1, 231 }, + /* tcId: 232. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {14983, 65, 128, 32, 7392, 32, 1, 232 }, + /* tcId: 233. edge case for computation of x with projective coordinates in precomputation or right to left addition chain */ + {15048, 65, 128, 32, 7424, 32, 1, 233 }, + /* tcId: 234. edge case for computation of x with projective coordinates in right to left addition chain */ + {15113, 65, 128, 32, 7456, 32, 1, 234 }, + /* tcId: 235. edge case for computation of x with projective coordinates in right to left addition chain */ + {15178, 65, 128, 32, 7488, 32, 1, 235 }, + /* tcId: 236. edge case for computation of x with projective coordinates in right to left addition chain */ + {15243, 65, 128, 32, 7520, 32, 1, 236 }, + /* tcId: 237. edge case for computation of x with projective coordinates in right to left addition chain */ + {15308, 65, 128, 32, 7552, 32, 1, 237 }, + /* tcId: 238. edge case for computation of x with projective coordinates in right to left addition chain */ + {15373, 65, 128, 32, 7584, 32, 1, 238 }, + /* tcId: 239. edge case for computation of x with projective coordinates in right to left addition chain */ + {15438, 65, 128, 32, 7616, 32, 1, 239 }, + /* tcId: 240. edge case for computation of x with projective coordinates in right to left addition chain */ + {15503, 65, 128, 32, 7648, 32, 1, 240 }, + /* tcId: 241. edge case for computation of x with projective coordinates in right to left addition chain */ + {15568, 65, 128, 32, 7680, 32, 1, 241 }, + /* tcId: 242. edge case for computation of x with projective coordinates in right to left addition chain */ + {15633, 65, 128, 32, 7712, 32, 1, 242 }, + /* tcId: 243. edge case for computation of x with projective coordinates in right to left addition chain */ + {15698, 65, 128, 32, 7744, 32, 1, 243 }, + /* tcId: 244. edge case for computation of x with projective coordinates in right to left addition chain */ + {15763, 65, 128, 32, 7776, 32, 1, 244 }, + /* tcId: 245. edge case for computation of x with projective coordinates in right to left addition chain */ + {15828, 65, 128, 32, 7808, 32, 1, 245 }, + /* tcId: 246. edge case for computation of x with projective coordinates in right to left addition chain */ + {15893, 65, 128, 32, 7840, 32, 1, 246 }, + /* tcId: 247. edge case for computation of x with projective coordinates in right to left addition chain */ + {15958, 65, 128, 32, 7872, 32, 1, 247 }, + /* tcId: 248. edge case for computation of x with projective coordinates in right to left addition chain */ + {16023, 65, 128, 32, 7904, 32, 1, 248 }, + /* tcId: 249. edge case for computation of y with projective coordinates */ + {16088, 65, 128, 32, 7936, 32, 1, 249 }, + /* tcId: 250. edge case for computation of y with projective coordinates */ + {16153, 65, 128, 32, 7968, 32, 1, 250 }, + /* tcId: 251. edge case for computation of y with projective coordinates */ + {16218, 65, 128, 32, 8000, 32, 1, 251 }, + /* tcId: 252. edge case for computation of y with projective coordinates in left to right addition chain */ + {16283, 65, 128, 32, 8032, 32, 1, 252 }, + /* tcId: 253. edge case for computation of y with projective coordinates in left to right addition chain */ + {16348, 65, 128, 32, 8064, 32, 1, 253 }, + /* tcId: 254. edge case for computation of y with projective coordinates in left to right addition chain */ + {16413, 65, 128, 32, 8096, 32, 1, 254 }, + /* tcId: 255. edge case for computation of y with projective coordinates in left to right addition chain */ + {16478, 65, 128, 32, 8128, 32, 1, 255 }, + /* tcId: 256. edge case for computation of y with projective coordinates in left to right addition chain */ + {16543, 65, 128, 32, 8160, 32, 1, 256 }, + /* tcId: 257. edge case for computation of y with projective coordinates in left to right addition chain */ + {16608, 65, 128, 32, 8192, 32, 1, 257 }, + /* tcId: 258. edge case for computation of y with projective coordinates in left to right addition chain */ + {16673, 65, 128, 32, 8224, 32, 1, 258 }, + /* tcId: 259. edge case for computation of y with projective coordinates in left to right addition chain */ + {16738, 65, 128, 32, 8256, 32, 1, 259 }, + /* tcId: 260. edge case for computation of y with projective coordinates in left to right addition chain */ + {16803, 65, 128, 32, 8288, 32, 1, 260 }, + /* tcId: 261. edge case for computation of y with projective coordinates in left to right addition chain */ + {16868, 65, 128, 32, 8320, 32, 1, 261 }, + /* tcId: 262. edge case for computation of y with projective coordinates in left to right addition chain */ + {16933, 65, 128, 32, 8352, 32, 1, 262 }, + /* tcId: 263. edge case for computation of y with projective coordinates in left to right addition chain */ + {16998, 65, 128, 32, 8384, 32, 1, 263 }, + /* tcId: 264. edge case for computation of y with projective coordinates in left to right addition chain */ + {17063, 65, 128, 32, 8416, 32, 1, 264 }, + /* tcId: 265. edge case for computation of y with projective coordinates in left to right addition chain */ + {17128, 65, 128, 32, 8448, 32, 1, 265 }, + /* tcId: 266. edge case for computation of y with projective coordinates in left to right addition chain */ + {17193, 65, 128, 32, 8480, 32, 1, 266 }, + /* tcId: 267. edge case for computation of y with projective coordinates in left to right addition chain */ + {17258, 65, 128, 32, 8512, 32, 1, 267 }, + /* tcId: 268. edge case for computation of y with projective coordinates in precomputation or right to left addition chain */ + {17323, 65, 128, 32, 8544, 32, 1, 268 }, + /* tcId: 269. edge case for computation of y with projective coordinates in precomputation or right to left addition chain */ + {17388, 65, 128, 32, 8576, 32, 1, 269 }, + /* tcId: 270. edge case for computation of y with projective coordinates in precomputation or right to left addition chain */ + {17453, 65, 128, 32, 8608, 32, 1, 270 }, + /* tcId: 271. edge case for computation of y with projective coordinates in precomputation or right to left addition chain */ + {17518, 65, 128, 32, 8640, 32, 1, 271 }, + /* tcId: 272. edge case for computation of y with projective coordinates in precomputation or right to left addition chain */ + {17583, 65, 128, 32, 8672, 32, 1, 272 }, + /* tcId: 273. edge case for computation of y with projective coordinates in precomputation or right to left addition chain */ + {17648, 65, 128, 32, 8704, 32, 1, 273 }, + /* tcId: 274. edge case for computation of y with projective coordinates in right to left addition chain */ + {17713, 65, 128, 32, 8736, 32, 1, 274 }, + /* tcId: 275. edge case for computation of y with projective coordinates in right to left addition chain */ + {17778, 65, 128, 32, 8768, 32, 1, 275 }, + /* tcId: 276. edge case for computation of y with projective coordinates in right to left addition chain */ + {17843, 65, 128, 32, 8800, 32, 1, 276 }, + /* tcId: 277. edge case for computation of y with projective coordinates in right to left addition chain */ + {17908, 65, 128, 32, 8832, 32, 1, 277 }, + /* tcId: 278. edge case for computation of y with projective coordinates in right to left addition chain */ + {17973, 65, 128, 32, 8864, 32, 1, 278 }, + /* tcId: 279. point with coordinate x = 1 */ + {3608, 65, 128, 32, 8896, 32, 1, 279 }, + /* tcId: 280. point with coordinate x = 1 */ + {18038, 65, 128, 32, 8928, 32, 1, 280 }, + /* tcId: 281. point with coordinate x = 1 */ + {18103, 65, 128, 32, 8960, 32, 1, 281 }, + /* tcId: 282. point with coordinate x = 1 in left to right addition chain */ + {18168, 65, 128, 32, 8992, 32, 1, 282 }, + /* tcId: 283. point with coordinate x = 1 in left to right addition chain */ + {18233, 65, 128, 32, 9024, 32, 1, 283 }, + /* tcId: 284. point with coordinate x = 1 in left to right addition chain */ + {18298, 65, 128, 32, 9056, 32, 1, 284 }, + /* tcId: 285. point with coordinate x = 1 in left to right addition chain */ + {18363, 65, 128, 32, 9088, 32, 1, 285 }, + /* tcId: 286. point with coordinate x = 1 in left to right addition chain */ + {18428, 65, 128, 32, 9120, 32, 1, 286 }, + /* tcId: 287. point with coordinate x = 1 in left to right addition chain */ + {18493, 65, 128, 32, 9152, 32, 1, 287 }, + /* tcId: 288. point with coordinate x = 1 in left to right addition chain */ + {18558, 65, 128, 32, 9184, 32, 1, 288 }, + /* tcId: 289. point with coordinate x = 1 in left to right addition chain */ + {18623, 65, 128, 32, 9216, 32, 1, 289 }, + /* tcId: 290. point with coordinate x = 1 in left to right addition chain */ + {18688, 65, 128, 32, 9248, 32, 1, 290 }, + /* tcId: 291. point with coordinate x = 1 in left to right addition chain */ + {18753, 65, 128, 32, 9280, 32, 1, 291 }, + /* tcId: 292. point with coordinate x = 1 in left to right addition chain */ + {18818, 65, 128, 32, 9312, 32, 1, 292 }, + /* tcId: 293. point with coordinate x = 1 in left to right addition chain */ + {18883, 65, 128, 32, 9344, 32, 1, 293 }, + /* tcId: 294. point with coordinate x = 1 in left to right addition chain */ + {18948, 65, 128, 32, 9376, 32, 1, 294 }, + /* tcId: 295. point with coordinate x = 1 in left to right addition chain */ + {19013, 65, 128, 32, 9408, 32, 1, 295 }, + /* tcId: 296. point with coordinate x = 1 in left to right addition chain */ + {19078, 65, 128, 32, 9440, 32, 1, 296 }, + /* tcId: 297. point with coordinate x = 1 in left to right addition chain */ + {19143, 65, 128, 32, 9472, 32, 1, 297 }, + /* tcId: 298. point with coordinate x = 1 in precomputation or right to left addition chain */ + {19208, 65, 128, 32, 9504, 32, 1, 298 }, + /* tcId: 299. point with coordinate x = 1 in precomputation or right to left addition chain */ + {19273, 65, 128, 32, 9536, 32, 1, 299 }, + /* tcId: 300. point with coordinate x = 1 in precomputation or right to left addition chain */ + {19338, 65, 128, 32, 9568, 32, 1, 300 }, + /* tcId: 301. point with coordinate x = 1 in precomputation or right to left addition chain */ + {19403, 65, 128, 32, 9600, 32, 1, 301 }, + /* tcId: 302. point with coordinate x = 1 in precomputation or right to left addition chain */ + {19468, 65, 128, 32, 9632, 32, 1, 302 }, + /* tcId: 303. point with coordinate x = 1 in precomputation or right to left addition chain */ + {19533, 65, 128, 32, 9664, 32, 1, 303 }, + /* tcId: 304. point with coordinate x = 1 in right to left addition chain */ + {19598, 65, 128, 32, 9696, 32, 1, 304 }, + /* tcId: 305. point with coordinate x = 1 in right to left addition chain */ + {19663, 65, 128, 32, 9728, 32, 1, 305 }, + /* tcId: 306. point with coordinate x = 1 in right to left addition chain */ + {19728, 65, 128, 32, 9760, 32, 1, 306 }, + /* tcId: 307. point with coordinate x = 1 in right to left addition chain */ + {19793, 65, 128, 32, 9792, 32, 1, 307 }, + /* tcId: 308. point with coordinate x = 1 in right to left addition chain */ + {19858, 65, 128, 32, 9824, 32, 1, 308 }, + /* tcId: 309. point with coordinate x = 2 */ + {3673, 65, 128, 32, 9856, 32, 1, 309 }, + /* tcId: 310. point with coordinate x = 2 */ + {19923, 65, 128, 32, 9888, 32, 1, 310 }, + /* tcId: 311. point with coordinate x = 2 */ + {19988, 65, 128, 32, 9920, 32, 1, 311 }, + /* tcId: 312. point with coordinate x = 2 in left to right addition chain */ + {20053, 65, 128, 32, 9952, 32, 1, 312 }, + /* tcId: 313. point with coordinate x = 2 in left to right addition chain */ + {20118, 65, 128, 32, 9984, 32, 1, 313 }, + /* tcId: 314. point with coordinate x = 2 in left to right addition chain */ + {20183, 65, 128, 32, 10016, 32, 1, 314 }, + /* tcId: 315. point with coordinate x = 2 in left to right addition chain */ + {20248, 65, 128, 32, 10048, 32, 1, 315 }, + /* tcId: 316. point with coordinate x = 2 in left to right addition chain */ + {20313, 65, 128, 32, 10080, 32, 1, 316 }, + /* tcId: 317. point with coordinate x = 2 in left to right addition chain */ + {20378, 65, 128, 32, 10112, 32, 1, 317 }, + /* tcId: 318. point with coordinate x = 2 in left to right addition chain */ + {20443, 65, 128, 32, 10144, 32, 1, 318 }, + /* tcId: 319. point with coordinate x = 2 in left to right addition chain */ + {20508, 65, 128, 32, 10176, 32, 1, 319 }, + /* tcId: 320. point with coordinate x = 2 in left to right addition chain */ + {20573, 65, 128, 32, 10208, 32, 1, 320 }, + /* tcId: 321. point with coordinate x = 2 in left to right addition chain */ + {20638, 65, 128, 32, 10240, 32, 1, 321 }, + /* tcId: 322. point with coordinate x = 2 in left to right addition chain */ + {20703, 65, 128, 32, 10272, 32, 1, 322 }, + /* tcId: 323. point with coordinate x = 2 in left to right addition chain */ + {20768, 65, 128, 32, 10304, 32, 1, 323 }, + /* tcId: 324. point with coordinate x = 2 in left to right addition chain */ + {20833, 65, 128, 32, 10336, 32, 1, 324 }, + /* tcId: 325. point with coordinate x = 2 in left to right addition chain */ + {20898, 65, 128, 32, 10368, 32, 1, 325 }, + /* tcId: 326. point with coordinate x = 2 in left to right addition chain */ + {20963, 65, 128, 32, 10400, 32, 1, 326 }, + /* tcId: 327. point with coordinate x = 2 in left to right addition chain */ + {21028, 65, 128, 32, 10432, 32, 1, 327 }, + /* tcId: 328. point with coordinate x = 2 in precomputation or right to left addition chain */ + {21093, 65, 128, 32, 10464, 32, 1, 328 }, + /* tcId: 329. point with coordinate x = 2 in precomputation or right to left addition chain */ + {21158, 65, 128, 32, 10496, 32, 1, 329 }, + /* tcId: 330. point with coordinate x = 2 in precomputation or right to left addition chain */ + {21223, 65, 128, 32, 10528, 32, 1, 330 }, + /* tcId: 331. point with coordinate x = 2 in precomputation or right to left addition chain */ + {21288, 65, 128, 32, 10560, 32, 1, 331 }, + /* tcId: 332. point with coordinate x = 2 in precomputation or right to left addition chain */ + {21353, 65, 128, 32, 10592, 32, 1, 332 }, + /* tcId: 333. point with coordinate x = 2 in precomputation or right to left addition chain */ + {21418, 65, 128, 32, 10624, 32, 1, 333 }, + /* tcId: 334. point with coordinate x = 2 in right to left addition chain */ + {21483, 65, 128, 32, 10656, 32, 1, 334 }, + /* tcId: 335. point with coordinate x = 2 in right to left addition chain */ + {21548, 65, 128, 32, 10688, 32, 1, 335 }, + /* tcId: 336. point with coordinate x = 2 in right to left addition chain */ + {21613, 65, 128, 32, 10720, 32, 1, 336 }, + /* tcId: 337. point with coordinate x = 2 in right to left addition chain */ + {21678, 65, 128, 32, 10752, 32, 1, 337 }, + /* tcId: 338. point with coordinate x = 2 in right to left addition chain */ + {21743, 65, 128, 32, 10784, 32, 1, 338 }, + /* tcId: 339. point with coordinate x = 3 */ + {3738, 65, 128, 32, 10816, 32, 1, 339 }, + /* tcId: 340. point with coordinate x = 3 */ + {21808, 65, 128, 32, 10848, 32, 1, 340 }, + /* tcId: 341. point with coordinate x = 3 */ + {21873, 65, 128, 32, 10880, 32, 1, 341 }, + /* tcId: 342. point with coordinate x = 3 in left to right addition chain */ + {21938, 65, 128, 32, 10912, 32, 1, 342 }, + /* tcId: 343. point with coordinate x = 3 in left to right addition chain */ + {22003, 65, 128, 32, 10944, 32, 1, 343 }, + /* tcId: 344. point with coordinate x = 3 in left to right addition chain */ + {22068, 65, 128, 32, 10976, 32, 1, 344 }, + /* tcId: 345. point with coordinate x = 3 in left to right addition chain */ + {22133, 65, 128, 32, 11008, 32, 1, 345 }, + /* tcId: 346. point with coordinate x = 3 in left to right addition chain */ + {22198, 65, 128, 32, 11040, 32, 1, 346 }, + /* tcId: 347. point with coordinate x = 3 in left to right addition chain */ + {22263, 65, 128, 32, 11072, 32, 1, 347 }, + /* tcId: 348. point with coordinate x = 3 in left to right addition chain */ + {22328, 65, 128, 32, 11104, 32, 1, 348 }, + /* tcId: 349. point with coordinate x = 3 in left to right addition chain */ + {22393, 65, 128, 32, 11136, 32, 1, 349 }, + /* tcId: 350. point with coordinate x = 3 in left to right addition chain */ + {22458, 65, 128, 32, 11168, 32, 1, 350 }, + /* tcId: 351. point with coordinate x = 3 in left to right addition chain */ + {22523, 65, 128, 32, 11200, 32, 1, 351 }, + /* tcId: 352. point with coordinate x = 3 in left to right addition chain */ + {22588, 65, 128, 32, 11232, 32, 1, 352 }, + /* tcId: 353. point with coordinate x = 3 in left to right addition chain */ + {22653, 65, 128, 32, 11264, 32, 1, 353 }, + /* tcId: 354. point with coordinate x = 3 in left to right addition chain */ + {22718, 65, 128, 32, 11296, 32, 1, 354 }, + /* tcId: 355. point with coordinate x = 3 in left to right addition chain */ + {22783, 65, 128, 32, 11328, 32, 1, 355 }, + /* tcId: 356. point with coordinate x = 3 in left to right addition chain */ + {22848, 65, 128, 32, 11360, 32, 1, 356 }, + /* tcId: 357. point with coordinate x = 3 in left to right addition chain */ + {22913, 65, 128, 32, 11392, 32, 1, 357 }, + /* tcId: 358. point with coordinate x = 3 in precomputation or right to left addition chain */ + {22978, 65, 128, 32, 11424, 32, 1, 358 }, + /* tcId: 359. point with coordinate x = 3 in precomputation or right to left addition chain */ + {23043, 65, 128, 32, 11456, 32, 1, 359 }, + /* tcId: 360. point with coordinate x = 3 in precomputation or right to left addition chain */ + {23108, 65, 128, 32, 11488, 32, 1, 360 }, + /* tcId: 361. point with coordinate x = 3 in precomputation or right to left addition chain */ + {23173, 65, 128, 32, 11520, 32, 1, 361 }, + /* tcId: 362. point with coordinate x = 3 in precomputation or right to left addition chain */ + {23238, 65, 128, 32, 11552, 32, 1, 362 }, + /* tcId: 363. point with coordinate x = 3 in precomputation or right to left addition chain */ + {23303, 65, 128, 32, 11584, 32, 1, 363 }, + /* tcId: 364. point with coordinate x = 3 in right to left addition chain */ + {23368, 65, 128, 32, 11616, 32, 1, 364 }, + /* tcId: 365. point with coordinate x = 3 in right to left addition chain */ + {23433, 65, 128, 32, 11648, 32, 1, 365 }, + /* tcId: 366. point with coordinate x = 3 in right to left addition chain */ + {23498, 65, 128, 32, 11680, 32, 1, 366 }, + /* tcId: 367. point with coordinate x = 3 in right to left addition chain */ + {23563, 65, 128, 32, 11712, 32, 1, 367 }, + /* tcId: 368. point with coordinate x = 3 in right to left addition chain */ + {23628, 65, 128, 32, 11744, 32, 1, 368 }, + /* tcId: 369. point with coordinate y = 1 */ + {23693, 65, 128, 32, 11776, 32, 1, 369 }, + /* tcId: 370. point with coordinate y = 1 */ + {23758, 65, 128, 32, 11808, 32, 1, 370 }, + /* tcId: 371. point with coordinate y = 1 */ + {23823, 65, 128, 32, 11840, 32, 1, 371 }, + /* tcId: 372. point with coordinate y = 1 */ + {23888, 65, 128, 32, 11872, 32, 1, 372 }, + /* tcId: 373. point with coordinate y = 1 */ + {23953, 65, 128, 32, 11904, 32, 1, 373 }, + /* tcId: 374. point with coordinate y = 1 */ + {24018, 65, 128, 32, 11936, 32, 1, 374 }, + /* tcId: 375. point with coordinate y = 1 */ + {24083, 65, 128, 32, 11968, 32, 1, 375 }, + /* tcId: 376. point with coordinate y = 1 */ + {24148, 65, 128, 32, 12000, 32, 1, 376 }, + /* tcId: 377. point with coordinate y = 1 */ + {24213, 65, 128, 32, 12032, 32, 1, 377 }, + /* tcId: 378. point with coordinate y = 1 in left to right addition chain */ + {24278, 65, 128, 32, 12064, 32, 1, 378 }, + /* tcId: 379. point with coordinate y = 1 in left to right addition chain */ + {24343, 65, 128, 32, 12096, 32, 1, 379 }, + /* tcId: 380. point with coordinate y = 1 in left to right addition chain */ + {24408, 65, 128, 32, 12128, 32, 1, 380 }, + /* tcId: 381. point with coordinate y = 1 in left to right addition chain */ + {24473, 65, 128, 32, 12160, 32, 1, 381 }, + /* tcId: 382. point with coordinate y = 1 in left to right addition chain */ + {24538, 65, 128, 32, 12192, 32, 1, 382 }, + /* tcId: 383. point with coordinate y = 1 in left to right addition chain */ + {24603, 65, 128, 32, 12224, 32, 1, 383 }, + /* tcId: 384. point with coordinate y = 1 in left to right addition chain */ + {24668, 65, 128, 32, 12256, 32, 1, 384 }, + /* tcId: 385. point with coordinate y = 1 in left to right addition chain */ + {24733, 65, 128, 32, 12288, 32, 1, 385 }, + /* tcId: 386. point with coordinate y = 1 in left to right addition chain */ + {24798, 65, 128, 32, 12320, 32, 1, 386 }, + /* tcId: 387. point with coordinate y = 1 in left to right addition chain */ + {24863, 65, 128, 32, 12352, 32, 1, 387 }, + /* tcId: 388. point with coordinate y = 1 in left to right addition chain */ + {24928, 65, 128, 32, 12384, 32, 1, 388 }, + /* tcId: 389. point with coordinate y = 1 in left to right addition chain */ + {24993, 65, 128, 32, 12416, 32, 1, 389 }, + /* tcId: 390. point with coordinate y = 1 in left to right addition chain */ + {25058, 65, 128, 32, 12448, 32, 1, 390 }, + /* tcId: 391. point with coordinate y = 1 in left to right addition chain */ + {25123, 65, 128, 32, 12480, 32, 1, 391 }, + /* tcId: 392. point with coordinate y = 1 in left to right addition chain */ + {25188, 65, 128, 32, 12512, 32, 1, 392 }, + /* tcId: 393. point with coordinate y = 1 in left to right addition chain */ + {25253, 65, 128, 32, 12544, 32, 1, 393 }, + /* tcId: 394. point with coordinate y = 1 in left to right addition chain */ + {25318, 65, 128, 32, 12576, 32, 1, 394 }, + /* tcId: 395. point with coordinate y = 1 in left to right addition chain */ + {25383, 65, 128, 32, 12608, 32, 1, 395 }, + /* tcId: 396. point with coordinate y = 1 in left to right addition chain */ + {25448, 65, 128, 32, 12640, 32, 1, 396 }, + /* tcId: 397. point with coordinate y = 1 in left to right addition chain */ + {25513, 65, 128, 32, 12672, 32, 1, 397 }, + /* tcId: 398. point with coordinate y = 1 in left to right addition chain */ + {25578, 65, 128, 32, 12704, 32, 1, 398 }, + /* tcId: 399. point with coordinate y = 1 in left to right addition chain */ + {25643, 65, 128, 32, 12736, 32, 1, 399 }, + /* tcId: 400. point with coordinate y = 1 in left to right addition chain */ + {25708, 65, 128, 32, 12768, 32, 1, 400 }, + /* tcId: 401. point with coordinate y = 1 in left to right addition chain */ + {25773, 65, 128, 32, 12800, 32, 1, 401 }, + /* tcId: 402. point with coordinate y = 1 in left to right addition chain */ + {25838, 65, 128, 32, 12832, 32, 1, 402 }, + /* tcId: 403. point with coordinate y = 1 in left to right addition chain */ + {25903, 65, 128, 32, 12864, 32, 1, 403 }, + /* tcId: 404. point with coordinate y = 1 in left to right addition chain */ + {25968, 65, 128, 32, 12896, 32, 1, 404 }, + /* tcId: 405. point with coordinate y = 1 in left to right addition chain */ + {26033, 65, 128, 32, 12928, 32, 1, 405 }, + /* tcId: 406. point with coordinate y = 1 in left to right addition chain */ + {26098, 65, 128, 32, 12960, 32, 1, 406 }, + /* tcId: 407. point with coordinate y = 1 in left to right addition chain */ + {26163, 65, 128, 32, 12992, 32, 1, 407 }, + /* tcId: 408. point with coordinate y = 1 in left to right addition chain */ + {26228, 65, 128, 32, 13024, 32, 1, 408 }, + /* tcId: 409. point with coordinate y = 1 in left to right addition chain */ + {26293, 65, 128, 32, 13056, 32, 1, 409 }, + /* tcId: 410. point with coordinate y = 1 in left to right addition chain */ + {26358, 65, 128, 32, 13088, 32, 1, 410 }, + /* tcId: 411. point with coordinate y = 1 in left to right addition chain */ + {26423, 65, 128, 32, 13120, 32, 1, 411 }, + /* tcId: 412. point with coordinate y = 1 in left to right addition chain */ + {26488, 65, 128, 32, 13152, 32, 1, 412 }, + /* tcId: 413. point with coordinate y = 1 in left to right addition chain */ + {26553, 65, 128, 32, 13184, 32, 1, 413 }, + /* tcId: 414. point with coordinate y = 1 in left to right addition chain */ + {26618, 65, 128, 32, 13216, 32, 1, 414 }, + /* tcId: 415. point with coordinate y = 1 in left to right addition chain */ + {26683, 65, 128, 32, 13248, 32, 1, 415 }, + /* tcId: 416. point with coordinate y = 1 in left to right addition chain */ + {26748, 65, 128, 32, 13280, 32, 1, 416 }, + /* tcId: 417. point with coordinate y = 1 in left to right addition chain */ + {26813, 65, 128, 32, 13312, 32, 1, 417 }, + /* tcId: 418. point with coordinate y = 1 in left to right addition chain */ + {26878, 65, 128, 32, 13344, 32, 1, 418 }, + /* tcId: 419. point with coordinate y = 1 in left to right addition chain */ + {26943, 65, 128, 32, 13376, 32, 1, 419 }, + /* tcId: 420. point with coordinate y = 1 in left to right addition chain */ + {27008, 65, 128, 32, 13408, 32, 1, 420 }, + /* tcId: 421. point with coordinate y = 1 in left to right addition chain */ + {27073, 65, 128, 32, 13440, 32, 1, 421 }, + /* tcId: 422. point with coordinate y = 1 in left to right addition chain */ + {27138, 65, 128, 32, 13472, 32, 1, 422 }, + /* tcId: 423. point with coordinate y = 1 in left to right addition chain */ + {27203, 65, 128, 32, 13504, 32, 1, 423 }, + /* tcId: 424. point with coordinate y = 1 in left to right addition chain */ + {27268, 65, 128, 32, 13536, 32, 1, 424 }, + /* tcId: 425. point with coordinate y = 1 in left to right addition chain */ + {27333, 65, 128, 32, 13568, 32, 1, 425 }, + /* tcId: 426. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27398, 65, 128, 32, 13600, 32, 1, 426 }, + /* tcId: 427. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27463, 65, 128, 32, 13632, 32, 1, 427 }, + /* tcId: 428. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27528, 65, 128, 32, 13664, 32, 1, 428 }, + /* tcId: 429. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27593, 65, 128, 32, 13696, 32, 1, 429 }, + /* tcId: 430. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27658, 65, 128, 32, 13728, 32, 1, 430 }, + /* tcId: 431. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27723, 65, 128, 32, 13760, 32, 1, 431 }, + /* tcId: 432. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27788, 65, 128, 32, 13792, 32, 1, 432 }, + /* tcId: 433. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27853, 65, 128, 32, 13824, 32, 1, 433 }, + /* tcId: 434. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27918, 65, 128, 32, 13856, 32, 1, 434 }, + /* tcId: 435. point with coordinate y = 1 in precomputation or right to left addition chain */ + {27983, 65, 128, 32, 13888, 32, 1, 435 }, + /* tcId: 436. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28048, 65, 128, 32, 13920, 32, 1, 436 }, + /* tcId: 437. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28113, 65, 128, 32, 13952, 32, 1, 437 }, + /* tcId: 438. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28178, 65, 128, 32, 13984, 32, 1, 438 }, + /* tcId: 439. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28243, 65, 128, 32, 14016, 32, 1, 439 }, + /* tcId: 440. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28308, 65, 128, 32, 14048, 32, 1, 440 }, + /* tcId: 441. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28373, 65, 128, 32, 14080, 32, 1, 441 }, + /* tcId: 442. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28438, 65, 128, 32, 14112, 32, 1, 442 }, + /* tcId: 443. point with coordinate y = 1 in precomputation or right to left addition chain */ + {28503, 65, 128, 32, 14144, 32, 1, 443 }, + /* tcId: 444. point with coordinate y = 1 in right to left addition chain */ + {28568, 65, 128, 32, 14176, 32, 1, 444 }, + /* tcId: 445. point with coordinate y = 1 in right to left addition chain */ + {28633, 65, 128, 32, 14208, 32, 1, 445 }, + /* tcId: 446. point with coordinate y = 1 in right to left addition chain */ + {28698, 65, 128, 32, 14240, 32, 1, 446 }, + /* tcId: 447. point with coordinate y = 1 in right to left addition chain */ + {28763, 65, 128, 32, 14272, 32, 1, 447 }, + /* tcId: 448. point with coordinate y = 1 in right to left addition chain */ + {28828, 65, 128, 32, 14304, 32, 1, 448 }, + /* tcId: 449. point with coordinate y = 1 in right to left addition chain */ + {28893, 65, 128, 32, 14336, 32, 1, 449 }, + /* tcId: 450. point with coordinate y = 1 in right to left addition chain */ + {28958, 65, 128, 32, 14368, 32, 1, 450 }, + /* tcId: 451. point with coordinate y = 1 in right to left addition chain */ + {29023, 65, 128, 32, 14400, 32, 1, 451 }, + /* tcId: 452. point with coordinate y = 1 in right to left addition chain */ + {29088, 65, 128, 32, 14432, 32, 1, 452 }, + /* tcId: 453. point with coordinate y = 1 in right to left addition chain */ + {29153, 65, 128, 32, 14464, 32, 1, 453 }, + /* tcId: 454. point with coordinate y = 1 in right to left addition chain */ + {29218, 65, 128, 32, 14496, 32, 1, 454 }, + /* tcId: 455. point with coordinate y = 1 in right to left addition chain */ + {29283, 65, 128, 32, 14528, 32, 1, 455 }, + /* tcId: 456. point with coordinate y = 1 in right to left addition chain */ + {29348, 65, 128, 32, 14560, 32, 1, 456 }, + /* tcId: 457. point with coordinate y = 1 in right to left addition chain */ + {29413, 65, 128, 32, 14592, 32, 1, 457 }, + /* tcId: 458. point with coordinate y = 1 in right to left addition chain */ + {29478, 65, 128, 32, 14624, 32, 1, 458 }, + /* tcId: 459. edge case private key */ + {29543, 65, 160, 32, 14656, 32, 1, 459 }, + /* tcId: 460. edge case private key */ + {29543, 65, 192, 32, 14688, 32, 1, 460 }, + /* tcId: 461. edge case private key */ + {29543, 65, 224, 32, 14720, 32, 1, 461 }, + /* tcId: 462. edge case private key */ + {29543, 65, 256, 32, 14752, 32, 1, 462 }, + /* tcId: 463. edge case private key */ + {29543, 65, 288, 32, 14784, 32, 1, 463 }, + /* tcId: 464. edge case private key */ + {29543, 65, 320, 32, 14816, 32, 1, 464 }, + /* tcId: 465. edge case private key */ + {29543, 65, 352, 32, 14848, 32, 1, 465 }, + /* tcId: 466. edge case private key */ + {29543, 65, 384, 32, 14880, 32, 1, 466 }, + /* tcId: 467. edge case private key */ + {29543, 65, 416, 32, 14912, 32, 1, 467 }, + /* tcId: 468. edge case private key */ + {29543, 65, 448, 32, 14944, 32, 1, 468 }, + /* tcId: 469. edge case private key */ + {29543, 65, 480, 32, 14976, 32, 1, 469 }, + /* tcId: 470. edge case private key */ + {29543, 65, 512, 32, 15008, 32, 1, 470 }, + /* tcId: 471. edge case private key */ + {29543, 65, 544, 32, 15040, 32, 1, 471 }, + /* tcId: 472. edge case private key */ + {29543, 65, 576, 32, 15072, 32, 1, 472 }, + /* tcId: 473. edge case private key */ + {29543, 65, 608, 32, 15104, 32, 1, 473 }, + /* tcId: 474. edge case private key */ + {29543, 65, 640, 32, 15136, 32, 1, 474 }, + /* tcId: 475. point is not on curve */ + {29608, 65, 672, 32, 15168, 0, 0, 475 }, + /* tcId: 476. point is not on curve */ + {29673, 65, 672, 32, 15168, 0, 0, 476 }, + /* tcId: 477. point is not on curve */ + {29738, 65, 672, 32, 15168, 0, 0, 477 }, + /* tcId: 478. point is not on curve */ + {29803, 65, 672, 32, 15168, 0, 0, 478 }, + /* tcId: 479. point is not on curve */ + {29868, 65, 672, 32, 15168, 0, 0, 479 }, + /* tcId: 480. point is not on curve */ + {29933, 65, 672, 32, 15168, 0, 0, 480 }, + /* tcId: 481. point is not on curve */ + {29998, 65, 672, 32, 15168, 0, 0, 481 }, + /* tcId: 482. point is not on curve */ + {30063, 65, 672, 32, 15168, 0, 0, 482 }, + /* tcId: 483. point is not on curve */ + {30128, 65, 672, 32, 15168, 0, 0, 483 }, + /* tcId: 484. point is not on curve */ + {30193, 65, 672, 32, 15168, 0, 0, 484 }, + /* tcId: 485. point is not on curve */ + {30258, 65, 672, 32, 15168, 0, 0, 485 }, + /* tcId: 486. point is not on curve */ + {30323, 65, 672, 32, 15168, 0, 0, 486 }, + /* tcId: 487. point is not on curve */ + {30388, 65, 672, 32, 15168, 0, 0, 487 }, + /* tcId: 488. point is not on curve */ + {30453, 65, 672, 32, 15168, 0, 0, 488 }, + /* tcId: 489. point is not on curve */ + {30518, 65, 672, 32, 15168, 0, 0, 489 }, + /* tcId: 490. point is not on curve */ + {30583, 65, 672, 32, 15168, 0, 0, 490 }, + /* tcId: 491. */ + {30648, 0, 672, 32, 15168, 0, 0, 491 }, + /* tcId: 494. public point not on curve */ + {30648, 65, 704, 32, 15168, 0, 0, 494 }, + /* tcId: 495. public point = (0,0) */ + {29608, 65, 704, 32, 15168, 0, 0, 495 }, + /* tcId: 498. order = 1 */ + {30713, 65, 704, 32, 15168, 32, 1, 498 }, + /* tcId: 499. order = 26959946667150639794667015087019630673536463705607434823784316690060 */ + {30713, 65, 704, 32, 15200, 32, 1, 499 }, + /* tcId: 500. generator = (0,0) */ + {30713, 65, 704, 32, 15232, 32, 1, 500 }, + /* tcId: 501. generator not on curve */ + {30713, 65, 704, 32, 15264, 32, 1, 501 }, + /* tcId: 506. cofactor = None */ + {30713, 65, 704, 32, 15296, 32, 1, 506 }, + /* tcId: 508. using secp224r1 */ + {30778, 57, 704, 32, 15328, 0, 0, 508 }, + /* tcId: 509. using secp256r1 */ + {30835, 65, 704, 32, 15328, 0, 0, 509 }, + /* tcId: 510. a = 0 */ + {30713, 65, 704, 32, 15328, 32, 1, 510 }, + /* tcId: 511. public key of order 3 */ + {30900, 65, 704, 32, 15360, 0, 0, 511 }, + /* tcId: 528. invalid public key */ + {30965, 33, 736, 32, 15360, 0, 0, 528 }, + +}; diff --git a/src/wycheproof/ecdh_secp256k1_test.json b/src/wycheproof/ecdh_secp256k1_test.json new file mode 100644 index 00000000..16db6189 --- /dev/null +++ b/src/wycheproof/ecdh_secp256k1_test.json @@ -0,0 +1,8441 @@ +{ + "algorithm" : "ECDH", + "schema" : "ecdh_test_schema.json", + "generatorVersion" : "0.9rc5", + "numberOfTests" : 752, + "header" : [ + "Test vectors of type EcdhTest are intended for", + "testing an ECDH implementations using X509 encoded", + "public keys and integers for private keys.", + "Test vectors of this format are useful for testing", + "Java providers." + ], + "notes" : { + "AdditionChain" : { + "bugType" : "KNOWN_BUG", + "description" : "The private key has an unusual bit pattern, such as high or low Hamming weight. The goal is to test edge cases for addition chain implementations." + }, + "CompressedPoint" : { + "bugType" : "UNKNOWN", + "description" : "The point in the public key is compressed. Not every library supports points in compressed format." + }, + "CompressedPublic" : { + "bugType" : "FUNCTIONALITY", + "description" : "The public key in the test vector is compressed. Some implementations do not support compressed points." + }, + "EdgeCaseDoubling" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains an EC point that hits an edge case (e.g. a coordinate 0) when doubled. The goal of the test vector is to check for arithmetic errors in these test cases.", + "effect" : "The effect of such arithmetic errors is unclear and requires further analysis." + }, + "EdgeCaseEphemeralKey" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains an ephemeral public key that is an edge case." + }, + "EdgeCaseSharedSecret" : { + "bugType" : "EDGE_CASE", + "description" : "The test vector contains a public key and private key such that the shared ECDH secret is a special case. The goal of this test vector is to detect arithmetic errors.", + "effect" : "The seriousness of an arithmetic error is unclear. It requires further analysis to determine if the bug is exploitable." + }, + "InvalidAsn" : { + "bugType" : "UNKNOWN", + "description" : "The public key in this test uses an invalid ASN encoding. Some cases where the ASN parser is not strictly checking the ASN format are benign as long as the ECDH computation still returns the correct shared value." + }, + "InvalidCompressedPublic" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The test vector contains a compressed public key that does not exist. I.e., it contains an x-coordinate that does not correspond to any points on the curve. Such keys should be rejected " + }, + "InvalidCurveAttack" : { + "bugType" : "CONFIDENTIALITY", + "description" : "The point of the public key is not on the curve. ", + "effect" : "If an implementation does not check whether a point is on the curve then it is likely that the implementation is susceptible to an invalid curve attack. Many implementations compute the shared ECDH secret over a curve defined by the point on the public key. This curve can be weak and hence leak information about the private key." + }, + "InvalidEncoding" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The test vector contains a public key with an invalid encoding." + }, + "InvalidPublic" : { + "bugType" : "CAN_OF_WORMS", + "description" : "The public key has been modified and is invalid. An implementation should always check whether the public key is valid and on the same curve as the private key. The test vector includes the shared secret computed with the original public key if the public point is on the curve of the private key.", + "effect" : "Generating a shared secret other than the one with the original key likely indicates that the bug is exploitable." + }, + "LargeCofactor" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The cofactor is larger than the limits specified in FIPS-PUB 186-4 table 1, p.36." + }, + "Modified curve parameter" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The parameters a and b of the curve have been modified. The parameters haven been chosen so that public key or generator still are also valid points on the new curve." + }, + "ModifiedCofactor" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The cofactor has been modified. ", + "effect" : "The seriousness of accepting a key with modified cofactor depends on whether the primitive using the key actually uses the cofactor." + }, + "ModifiedGenerator" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The generator of the EC group has been modified.", + "effect" : "The seriousness of the modification depends on whether the cryptographic primitive uses the generator. In the worst case such a modification allows an invalid curve attack." + }, + "ModifiedGroup" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The EC curve of the public key has been modified. EC curve primitives should always check that the keys are on the expected curve." + }, + "ModifiedPrime" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The modulus of the public key has been modified. The public point of the public key has been chosen so that it is both a point on both the curve of the modified public key and the private key." + }, + "ModifiedPublicPoint" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The public point of the key has been modified and is not on the curve.", + "effect" : "Not checking that a public point is on the curve may allow an invalid curve attack." + }, + "NegativeCofactor" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The cofactor of the curve is negative." + }, + "Normal" : { + "bugType" : "BASIC", + "description" : "The test vector contains a pseudorandomly generated, valid test case. Implementations are expected to pass this test." + }, + "UnnamedCurve" : { + "bugType" : "UNKNOWN", + "description" : "The public key does not use a named curve. RFC 3279 allows to encode such curves by explicitly encoding, the parameters of the curve equation, modulus, generator, order and cofactor. However, many crypto libraries only support named curves. Modifying some of the EC parameters and encoding the corresponding public key as an unnamed curve is a potential attack vector." + }, + "UnusedParam" : { + "bugType" : "MALLEABILITY", + "description" : "A parameter that is typically not used for ECDH has been modified. Sometimes libraries ignore small differences between public and private key. For example, a library might ignore an incorrect cofactor in the public key. We consider ignoring such changes as acceptable as long as these differences do not change the outcome of the ECDH computation, i.e. as long as the computation is done on the curve from the private key." + }, + "WeakPublicKey" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The vector contains a weak public key. The curve is not a named curve, the public key point has order 3 and has been chosen to be on the same curve as the private key. This test vector is used to check ECC implementations for missing steps in the verification of the public key." + }, + "WrongCurve" : { + "bugType" : "CONFIDENTIALITY", + "description" : "The public key and private key use distinct curves. Implementations are expected to reject such parameters.", + "effect" : "Computing an ECDH key exchange with public and private keys can in the worst case lead to an invalid curve attack. Hence, it is important that ECDH implementations check the input parameters. The severity of such bugs is typically smaller if an implementation ensures that the point is on the curve and that the ECDH computation is performed on the curve of the private key. Some of the test vectors with modified public key contain shared ECDH secrets, that were computed over the curve of the private key." + }, + "WrongOrder" : { + "bugType" : "MODIFIED_PARAMETER", + "description" : "The order of the public key has been modified.", + "effect" : "If this order is used in a cryptographic primitive instead of the correct order then an invalid curve attack is possible and the private keys may leak. E.g. ECDHC in BC 1.52 suffered from this." + } + }, + "testGroups" : [ + { + "type" : "EcdhTest", + "curve" : "secp256k1", + "encoding" : "asn", + "tests" : [ + { + "tcId" : 1, + "comment" : "normal case", + "flags" : [ + "Normal" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b396812ea1686e7472e9692eaf3e958e50e9500d3b4c77243db1f2acd67ba9cc4", + "private" : "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", + "shared" : "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", + "result" : "valid" + }, + { + "tcId" : 2, + "comment" : "compressed public key", + "flags" : [ + "CompressedPublic", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a03220002d8096af8a11e0b80037e1ee68246b5dcbb0aeb1cf1244fd767db80f3fa27da2b", + "private" : "00f4b7ff7cccc98813a69fae3df222bfe3f4e28f764bf91b4a10d8096ce446b254", + "shared" : "544dfae22af6af939042b1d85b71a1e49e9a5614123c4d6ad0c8af65baf87d65", + "result" : "acceptable" + }, + { + "tcId" : 3, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 1", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004965ff42d654e058ee7317cced7caf093fbb180d8d3a74b0dcd9d8cd47a39d5cb9c2aa4daac01a4be37c20467ede964662f12983e0b5272a47a5f2785685d8087", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000000001", + "result" : "valid" + }, + { + "tcId" : 4, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 4", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000406c4b87ba76c6dcb101f54a050a086aa2cb0722f03137df5a922472f1bdc11b982e3c735c4b6c481d09269559f080ad08632f370a054af12c1fd1eced2ea9211", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000000002", + "result" : "valid" + }, + { + "tcId" : 5, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 9", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bba30eef7967a2f2f08a2ffadac0e41fd4db12a93cef0b045b5706f2853821e6d50b2bf8cbf530e619869e07c021ef16f693cfc0a4b0d4ed5a8f464692bf3d6e", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000000003", + "result" : "valid" + }, + { + "tcId" : 6, + "comment" : "shared secret has x-coordinate p-3", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046da9eb2cdac02122d5f05cf6a8cd768e378f664ea4a7871d10e25f57eb1ee1cc5b2b5abf9c6c6596f8f383ddbcb3bcc2d5a7cc605984931239ca9669946032ee", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c", + "result" : "valid" + }, + { + "tcId" : 7, + "comment" : "shared secret has x-coordinate 2**16 + 0", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f2976154c4f53ce392d1fe39a891a4611ba8cf046023cd8f1bcd9fdd2e921191b25cf31caedfbb415381637bc3f599a34fba3e1413f644cb1668469f4558a772", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000000010000", + "result" : "valid" + }, + { + "tcId" : 8, + "comment" : "shared secret has x-coordinate 2**32 + 7", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045e422fea67cca5ebaeac87745c81b10ef807030367e6fce012254176ec8cf199881592f42c264371e19e3037388ab64f32fa8870e62905e7af205e43b02aad12", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000000000000100000007", + "result" : "valid" + }, + { + "tcId" : 9, + "comment" : "shared secret has x-coordinate 2**64 + 1", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bb57b9a1231be042d185c03eda6926a6def177fe6745eda000c520d66581f0cdf1d73c80453f2fe30725adf951390c739e36fc8677691db107881342613d00ab", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000000000000010000000000000001", + "result" : "valid" + }, + { + "tcId" : 10, + "comment" : "shared secret has x-coordinate 2**96 + 1", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045563c76c19377638f7d517bdbe0ace467eb5d4dd9fb4bf18332bab8f07b1d80c261332d46e316711278bacccd88005ee4c115fa84089fd190674626e5ed1ebfe", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000000000000000000000000001000000000000000000000001", + "result" : "valid" + }, + { + "tcId" : 11, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = -6", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048983aae8c002f2b555acb2370adb9b50ba4cac1bfcc9039a125c70ca7c5fc0d1f6efeb8ae4ba8c69429d93244382447ac534891c66090025282655719bd72512", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0b7beba34feb647da200bed05fad57c0348d249e2a90c88f31f9948bb65d5207", + "result" : "valid" + }, + { + "tcId" : 12, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000423556564850c50fba51f1e64ef98378ef5c22feafa29499ca27600c473cace889d5679e917daa7f4c7899517d37826284f031de01a60bc813696414d04531a21", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f7", + "result" : "valid" + }, + { + "tcId" : 13, + "comment" : "shared secret has x-coordinate that satisfies x**2 + a = 8", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ddbf807e22c56a19cf6c472829150350781034a5eddec365694d4bd5c865ead14e674127028c91d3394cac37293a866055d10f0f40a3706ad16b64fc9d5998bd", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "result" : "valid" + }, + { + "tcId" : 14, + "comment" : "shared secret has x-coordinate that satisfies x**2 = 2**96 + 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000464688eae7aabd248f6f44a0d6e2c438e4100001813eb71f9f082fad3dfe43e287dab3dabe7d436001a0fb763015dedbb90f811000ec8f5f29953e3af42f92065", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "39f883f105ac7f09f4e7e4dcc84bc7ff4b3b74f301efaaaf8b638f47720fdaec", + "result" : "valid" + }, + { + "tcId" : 15, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c404e17141d102bba2f1cb16bb954a208798b04dca8dd139a8ab7f01f0dbef39c7b8e55f2257a480077e4190570a004cbe668200c9c78eaa53b61b20fce4c685", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "5555555555555555555555555555555555555555555555555555555555555550", + "result" : "valid" + }, + { + "tcId" : 16, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e160e87c0a562a1dbb59b4c2f614720e7753608672eb8d883b91e25f8cfc58474623cba584e1324bc49bcdf0891166b545b7704e2bbda705d0d73b7530e47952", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "result" : "valid" + }, + { + "tcId" : 17, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045d4d182b18782a02685dcc7b671ec742ce308c7acc8e6260f67e81516eb546e8a38f0756074eea4857953398b6d05597c7ceb5e65e4e8cee31e81c5658824ce4", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "3333333333333333333333333333333333333333333333333333333333333333", + "result" : "valid" + }, + { + "tcId" : 18, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048ecd6a2576f42626792076935e2fe961599e484cd212bce2623b83aa22f546d2a7f855b09bef286bcbe9e8bab17fd56d7055df64f344310c3522e8f227e472c8", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccb", + "result" : "valid" + }, + { + "tcId" : 19, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046826f79ef84da803460aed09198d2bbb42d7892ed608aacbb281a95acae11465a25809191aa5bdfa61b8963beacb4eb133266a90f33d1b2ca4f6152d37a94fd8", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0c", + "result" : "valid" + }, + { + "tcId" : 20, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a54bb2ae80086053a5fa4fdb1836a8c6ac41783650b0f79a5428c98ff64d078a12bbb4cb8af20ca75ec15b2e0d47a83ca93fc78cd92640a02e8002966f1fe80b", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0", + "result" : "valid" + }, + { + "tcId" : 21, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bace46eed492743c693e1a33adb046b7722c55ce369d1438e67f9c5b3412783145262dd4a86c8a527b23f4114b8a9b9f36f9701835f50b678b24d2a9155ebc2c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff", + "result" : "valid" + }, + { + "tcId" : 22, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000401055147863aa060c0e104e243ec01eda2b0e0c6814e232d671abcba9715d5ce0c13006aa7960c54fe3f20220bef766756c910fd05764afc318375540cef2d5c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00", + "result" : "valid" + }, + { + "tcId" : 23, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004595e46ee7c2d7183ff2ea760ffd8472fb834ec89c08b6ef48ff92b44a13a6e1ae563e23953c97c26441323d2500c84e8cee04c15d4d5d2cc458703d1f2d02d31", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "7fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff", + "result" : "valid" + }, + { + "tcId" : 24, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046a40adc811b09e83ba0fb8a94fea50591ca9e58bb7d47304950dbff78dad777ee3bd08f742d7e8e30cff31bc6a6cc02c8717ee25838aabffa6e48f65cce74d81", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000fffe0003fff8000fffe0003fff8000fffe0003fff8000fffe0003fff7fff", + "result" : "valid" + }, + { + "tcId" : 25, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045a33fe91d7e35db7875208bee77f4cc0006f1439cc845f695b6a12673dcd03d18f86ee121c5ea0da3eb0210509e12db845296225ca973e2e19ce3e3d01486090", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffd", + "result" : "valid" + }, + { + "tcId" : 26, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f6ebaab62c35fd4b8bec9d95bcfc433e6bde7c0f0d5ef75d6fd326aaf28f23b0b2f4d1c2e891706b7bada59fb0f6a32b5463982a9c8c2d8ea38954418183b634", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffefffe", + "result" : "valid" + }, + { + "tcId" : 27, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004524392416f8cfc5f84dc9b72f2887c684e4bd24796f0065078e18d16bc43b56ea02178311799eb61ad3b3e7dcda10404dc4541c13e3de0ceb40c9aa7afabc53b", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000003ffffff0000007fffffe000000ffffffc000001ffffff8000003fffffd", + "result" : "valid" + }, + { + "tcId" : 28, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000499965c477a240aebbd19cd094c8b62852de8663d0cc9f06eeb395ffc92d121f64811882f406080d7d04ea4f339bddd2e5ef0345b5834142f75b562154d5ec7ae", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "7fffffe000000ffffffc000001ffffff8000003ffffff0000007fffffdfffffe", + "result" : "valid" + }, + { + "tcId" : 29, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ad3d179877e74ee258ba6f8e128bc2a0045c06a3d3c30fcce01ca8d9e1afee4ea3fe47156fb727fc1c55ef9db516df665cbb073405c2c301a8fe1d10f3b9b300", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "000003ffffff0000003ffffff0000003ffffff0000003ffffff0000003fffffc", + "result" : "valid" + }, + { + "tcId" : 30, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044bb19deae638fc5fa7070cc90e969bac3f8384a59ea11cb01bc091edf1a4cbd677ed6bdf8971d3e63c903d9acabc28b75af661a03457261c5a8d5940ad02c509", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "fffffc000000ffffffc000000ffffffc000000ffffffc000000ffffffbfffffe", + "result" : "valid" + }, + { + "tcId" : 31, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000424175c078e305d3139e5dab727a6ab8587b26daa470a529a23c10585cb56c038bf1f2b937ae074ff94b15f5cb5e60eb5d32afba2077539db794294bcaab71a81", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff", + "result" : "valid" + }, + { + "tcId" : 32, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ef691afe2ee4aa18a8485a71c0e20eff1337ae0622acc09ccda10f49574ae840b82730bb2eef59a17ab095acd131e5fcf8ba11150a9421bbab6b9f146aa78ffb", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000fffffffc0000000fffffffc0000000fffffffc0000000fffffffbffffffd", + "result" : "valid" + }, + { + "tcId" : 33, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004067e7df09f5e38f2b2823f65a6b1135c3290586fef6eceffa6d59595748879f66932b3f70d603229e10a57344ecde503a2df930651046c2f1d2b719bfc93e0a1", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ff00000001fffffffc00000007fffffff00000001fffffffc00000007ffffffd", + "result" : "valid" + }, + { + "tcId" : 34, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b8722ecdde7c85317e486b03656b83910ac3c88687a4291e8bb9a4b6a52cc6e02e4158a5a88de023d6a135bd04c1585ef46741890376135453ec562da5b3760b", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00fffffffe00000003fffffff80000000fffffffe00000003fffffff80000000", + "result" : "valid" + }, + { + "tcId" : 35, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004728e15d578212bc42287c0118c82c84b126f97d549223c10ad07f4e98af912385d23b1a6e716925855a247b16effe92773315241ac951cdfefdfac0ed16467f6", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", + "result" : "valid" + }, + { + "tcId" : 36, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c3ef35fd4cda66e8e850095e1e697aee56decc29484aa463f879c7b6dd7669e625945351276719c5e3bb8e514f69305b6085b7c782a07b26a842887c33a93dc6", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffffffff00000000ffffffff00000000ffffffff00000000fffffffeffffffff", + "result" : "valid" + }, + { + "tcId" : 37, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004784907c6be6202770b98d01f1ffe11b9ed2c97515843f57c2c06363a9dadc7011de5fbaa7356cf3ba28cb7b932a07c8321007c7c45396751fe70724343d2b19f", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffffffff00000000000000ffffffffffffff00000000000000fffffffffffffe", + "result" : "valid" + }, + { + "tcId" : 38, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047c016dee8b5411f8e95184daf8e318119e844b8bdc70d75efb99b8d0ff10ab745e905103d57d6537908e6e9864aee4f0917f5b920d06f980aa823f043ef9139e", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "00000000ffffffffffffff00000000000000ffffffffffffff00000000000000", + "result" : "valid" + }, + { + "tcId" : 39, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000436e1e76ffdbe8577520b0716eb88c18ea72a49e5a4e5680a7d290093f841cb6e7310728b59c7572c4b35fb6c29c36ebabfc53553c06ecf747fcfbefcf6114e1c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 40, + "comment" : "shared secret has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047a19501d646fc9332a8525af4cc79523b57d736b69bb24b06270c1b1dadf88ce834efa1bce854ff5bcade40cbcee9f40154bc26036adc5cf87e50ea388af2987", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "ffffffffffffffff0000000000000000fffffffffffffffefffffffffffffff5", + "result" : "valid" + }, + { + "tcId" : 41, + "comment" : "shared secret has an x-coordinate of approx p//3", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f43b610a2a5c5f6e2b395567489657059e3351c6f9a7e2ebde52638abfea006ab2d690513e9187c0cc903ceee022ee421c594a8bd7610c68cd8143adfc741dde", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "55555555555555555555555555555555555555555555555555555554fffffebc", + "result" : "valid" + }, + { + "tcId" : 42, + "comment" : "shared secret has an x-coordinate of approx p//5", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d93bfdaa797cd4bd81dea80d7c72a24923ce50e94bfc4ee1bd5f5f10eea3f8ecc0b5941890a26e88e5029c283e0fadeccc0b980f8a5098aa7835c5c958d471e5", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "33333333333333333333333333333333333333333333333333333332ffffff3c", + "result" : "valid" + }, + { + "tcId" : 43, + "comment" : "shared secret has an x-coordinate of approx p//7", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040ac1ea7a29f7ace8a38b2fedbfe4d0d9ae45344432ab3eb5e0a5b66716f61c6aaaa39a5f098fd4472587d14bdf72b3dd3e966b5f0b6e400fff6e0e9c8453fc79", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "249249249249249249249249249249249249249249249249249249246db6dae2", + "result" : "valid" + }, + { + "tcId" : 44, + "comment" : "shared secret has an x-coordinate of approx p//9", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf2e8a61a21d96e74a296b397e53044f373acb73a6ea4a398d89c56549e96b7fe846fd0df239691d0682b067a50a2423d88b4d970b1d3d8141a066d13c186f96", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "1c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c555554e8", + "result" : "valid" + }, + { + "tcId" : 45, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000456baf1d72606c7af5a5fa108620b0839e2c7dd40b832ef847e5b64c86efe1aa563e586a667a65bbb5692500df1ff8403736838b30ea9791d9d390e3dc6689e2c", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 46, + "comment" : "y-coordinate of the public key has many trailing 1's", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004800000000000000000000000009fa2f1ffffffffffffffffffffffffffffffff07ed353c9f1039edcc9cc5336c034dc131a4087692c2e56bc1dd1904e3ffffff", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "7c07b199b6a62e7ac646c7e1dee94aca55de1a97251ddf92fcd4fe0145b40f12", + "result" : "valid" + }, + { + "tcId" : 47, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa05a5e4af11cf63ceaaa42a6dc9e4ccb394852cf84284e8d2627572fbf22c0ba88", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 48, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a48307eb78d38770fea1a44f4da72c26f85b17f3501a4f9394fe29856ccbf15fd284", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 49, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037effffffffffffffffffffffffffffffff0000031a6bf344b86730ac5c54a7751aefdba135759b9d535ca64111f298a38d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", + "result" : "valid" + }, + { + "tcId" : 50, + "comment" : "y-coordinate of the public key is small", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff0000013bc6f08431e729ed2863f2f4ac8a30279695c8109c340a39fa86f451cd", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", + "result" : "valid" + }, + { + "tcId" : 51, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045e4c2cf1320ec84ef8920867b409a9a91d2dd008216a282e36bd84e884726fa0a5a1b50ee309c31555bd592361b334c6b7ad307bd7b172d9d8a8d03fdd3f41a7", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "80000000000000000000000000a3037effffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 52, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000402a30c2fabc87e6730625dec2f0d03894387b7f743ce69c47351ebe5ee98a483f814872c788f015e5bb0b258d3d907a4e80cafe5b06c6b01d67a93330ea029ab", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "8000000000000000000000000124dcb0ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 53, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000000a3037efffffffffffffffffffffffffffffffffffffce5940cbb4798cf53a3ab588ae510245eca8a6462aca359beed0d6758a2", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5206c3de46949b9da160295ee0aa142fe3e6629cc25e2d671e582e30ff875082", + "result" : "valid" + }, + { + "tcId" : 54, + "comment" : "y-coordinate of the public key is large", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000000000000000000000000124dcb0fffffffffffffffffffffffffffffffffffffec4390f7bce18d612d79c0d0b5375cfd8696a37ef63cbf5c604790baa62", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "8a8c18b78e1b1fcfd22ee18b4a3a9f391a3fdf15408fb7f8c1dba33c271dbd2f", + "result" : "valid" + }, + { + "tcId" : 55, + "comment" : "y-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCaseSharedSecret" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045450cace04386adc54a14350793e83bdc5f265d6c29287ecd07f791ad2784c4cebd3c24451322334d8d51033e9d34b6bb592b1995d07867863d1044bd59d7501", + "private" : "00a2b6442a37f8a3764aeff4011a4c422b389a1e509669c43f279c8b7e32d80c3a", + "shared" : "80000000000000000000000001126b54ffffffffffffffffffffffffffffffff", + "result" : "valid" + }, + { + "tcId" : 56, + "comment" : "y-coordinate of the public key has many trailing 0's", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480000000000000000000000001126b54ffffffffffffffffffffffffffffffff4106a369068d454ea4b9c3ac6177f87fc8fd3aa240b2ccb4882bdccbd4000000", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "e59ddc7646e4aef0623c71c486f24d5d32f7257ef3dab8fa524b394eae19ebe1", + "result" : "valid" + }, + { + "tcId" : 57, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 1", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "12c2ad36a59fda5ac4f7e97ff611728d0748ac359fca9b12f6d4f43519516487", + "result" : "valid" + }, + { + "tcId" : 58, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 4", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "45aa9666757815e9974140d1b57191c92c588f6e5681131e0df9b3d241831ad4", + "result" : "valid" + }, + { + "tcId" : 59, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 9", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "b90964c05e464c23acb747a4c83511e93007f7499b065c8e8eccec955d8731f4", + "result" : "valid" + }, + { + "tcId" : 60, + "comment" : "ephemeral key has x-coordinate p-3", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2c0e994b14ea72f8c3eb95c71ef692575e775058332d7e52d0995cf8038871b67d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "e97fb4c4fb33d6a114da6e0d180e54f99ec1ece9ff558871054e99d221930d16", + "result" : "valid" + }, + { + "tcId" : 61, + "comment" : "ephemeral key has x-coordinate 2**16 + 0", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000100003c81e87241d9451d286ddbe65b14d47234307b80ce74b8921af7d4935707549d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1eea9c2756a3305bb5178f2c37436e7b41cf3805cd0a1087d2d02407fc553c09", + "result" : "valid" + }, + { + "tcId" : 62, + "comment" : "ephemeral key has x-coordinate 2**32 + 7", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000010000000715098598dc12cf294ea5ac1eb5eeae9139f5cfd3d0ffdcfa7297a01dce1ee9df", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "2f1c5c590f97f79351fb9d36c597d1c61f1c409fcdedaeae795112fa1a2c7453", + "result" : "valid" + }, + { + "tcId" : 63, + "comment" : "ephemeral key has x-coordinate 2**64 + 1", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000001000000000000000161bd3a38f707713b97eaf8d0184e0079e2a62cfba75d428b1326ea861aade950", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "82b8e90e6b6441b7164c9725ac1a35f098788096af95c276fac3c5a383d6b56c", + "result" : "valid" + }, + { + "tcId" : 64, + "comment" : "ephemeral key has x-coordinate 2**96 + 1", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000100000000000000000000000115820e7e26670c6b45c1e0caa951eab312754180baa9fcff9f7e7bf46deea7fc", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "8a955b6cf4d518558e59372444d3fd9b78933e2d3229dfdfa6f5f66403290e19", + "result" : "valid" + }, + { + "tcId" : 65, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = -6", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040b7beba34feb647da200bed05fad57c0348d249e2a90c88f31f9948bb65d52077435a6bef91b92ae32cf51d7149cad0353a46513851427c34436536ec7eae483", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5626bbf79f10827e23fa5aef9a26533f5f4e7472934ed9759b7b3a77cda04b82", + "result" : "valid" + }, + { + "tcId" : 66, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f75f450dbbf718a4f6582d7af83953170b3037fb81a450a5ca5acbec74ad6cac89", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1908ae936f53b9a8a2d09707ae414084090b175365401425479b10b8c3e8d1ba", + "result" : "valid" + }, + { + "tcId" : 67, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 + a = 8", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee37269a64bbcf3a3f227631c7a8ce532c77245a1c0db4343f16aa1d339fd2591a", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "5e13b3dc04e33f18d1286c606cb0191785f694e82e17796145c9e7b49bc2af58", + "result" : "valid" + }, + { + "tcId" : 68, + "comment" : "ephemeral key has x-coordinate that satisfies x**2 = 2**96 + 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000439f883f105ac7f09f4e7e4dcc84bc7ff4b3b74f301efaaaf8b638f47720fdaec24f50efd39b8ae7536e8806927eac6fd52210a239fb4129e0bfed333476575ea", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "a995572ad174897ff1971e6d1e39f908448a5878da1e60f3901f57cacd49e5f6", + "result" : "valid" + }, + { + "tcId" : 69, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045555555555555555555555555555555555555555555555555555555555555550134a74fc6e7d7acef5bb20e969abb6f026ec0cb04dff34f7916ca64b07fff511", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "cd8427ea93f9fede38a70d0c39dbd96759613ba00f27b9db3971c80aec07e2d6", + "result" : "valid" + }, + { + "tcId" : 70, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 2", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa769afe397a5709201bda50ce2d31a13fde4076722a857719924009cc28159869", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "766b0752cd895b4b8543d44c9a348868ffff12aed632f8070e731d450d8a8c94", + "result" : "valid" + }, + { + "tcId" : 71, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433333333333333333333333333333333333333333333333333333333333333330434e877eaa71340aa5e57e58a01f0b0aec8d24b5c64aa77ef95fae9b4958c5d", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "09b0aa839893b7ad37cc83160e6f3c5506bbe323497c21505ae9937c75d943c8", + "result" : "valid" + }, + { + "tcId" : 72, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 4", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccb2e808a8b6c6e5bc068f96348d68171e66159a0ee27073c82fc3f9581a4a1fb28", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "3c2a61121f094d5eecddf7d3b0016c170b90fd3f2fea0b12e31db04ae7c279a2", + "result" : "valid" + }, + { + "tcId" : 73, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0c1d854210f797c547bd3b3feccde1ce3e67c61c3400141da2068520e2bae9bf90", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "9a641d5efa8be7dc723aa58e2e52a150c8efced2fa1084041249773c7562c66d", + "result" : "valid" + }, + { + "tcId" : 74, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 8", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f022bcbf40d658bf3ff02d98aea5ae45d43ed85f6de9268f0eae85210f2fed81c6", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "d32977eca64d223ea90f10f72f810ec64d661833acc4c839591da813ef86f736", + "result" : "valid" + }, + { + "tcId" : 75, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff210a46304881329c9807b71b6393ba104b9f27d976065e852429fd664de98eee", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "55137fecb21eb3ebed1b41fb2f7e1ca337009465f855f3f920bc7d0b73c2da32", + "result" : "valid" + }, + { + "tcId" : 76, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 16", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff007011d6e851e5a53fde41c1f348690c0188f24c105d5cfca5b6ff3c93dbfdef99", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "0bde659ed89281e6c8a5fbdab764d0499b86d19d33f4c978e260bbae587d4057", + "result" : "valid" + }, + { + "tcId" : 77, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047fff0001fffc0007fff0001fffc0007fff0001fffc0007fff0001fffc0007fff4b66003c7482d0f2fd7b1cb2b0b7078cd199f2208fc37eb2ef286ccb2f1224e7", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "3135a6283b97e7537a8bc208a355c2a854b8ee6e4227206730e6d725da044dee", + "result" : "valid" + }, + { + "tcId" : 78, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 30", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000fffe0003fff8000fffe0003fff8000fffe0003fff8000fffe0003fff7fff0a2331880cb3f8f9004bf68fc379beb6e3affadcbe81bd4f9bf76e4ac5ab2c37", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "2a3d29ce049fc50b00fab50e7581b84d441d297be6515fbe83dc485bdf32b6dc", + "result" : "valid" + }, + { + "tcId" : 79, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffd3b6a2629d598a045be28a1687288cc4d0c389cc6fe627c5cc3aa2ab963db7495", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "03c202a64e60ff5948d29816d68420c64c0518a7522a929381365b1245770a02", + "result" : "valid" + }, + { + "tcId" : 80, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 32", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000fffefffe35e39d53d101a6aa4ab434c55a70b03d244b6a2025a18d4d549dea451c031392", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "d07fcf7b89bd1ba24194caf977db68a5503a471a37d374e0917a5fe31d48c99e", + "result" : "valid" + }, + { + "tcId" : 81, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048000003ffffff0000007fffffe000000ffffffc000001ffffff8000003fffffd3aa774f4d29fefddd9546ad1f7b2b79cf42634284fbb1d7c702e9fca3fe049af", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "ea9f3a53ab4053df0bae0156767a62ec5ba0de4373ef12cbfb19aa80c6bcd904", + "result" : "valid" + }, + { + "tcId" : 82, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 51", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047fffffe000000ffffffc000001ffffff8000003ffffff0000007fffffdfffffe23e4bca0984da424a6120a13dc676c777607562d16ed9b8fa94c21fff7151d4e", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "f0557be2b26ddb56d44d2cb852224a291de771418fe148a730a76dadf5882f18", + "result" : "valid" + }, + { + "tcId" : 83, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000003ffffff0000003ffffff0000003ffffff0000003ffffff0000003fffffc2a95c81253ac554846812d2a4415f6edcf954209008d260a806b85aba759ff72", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "c68f07233efd0745d8bcd51a89158717c2dc532f75a9e4de2076e1b830654ec8", + "result" : "valid" + }, + { + "tcId" : 84, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 52", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffc000000ffffffc000000ffffffc000000ffffffc000000ffffffbfffffe031537fcabe5d5e25165a18b1bd408212cb523efea0fc0fd1eac46e83b0d0b52", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "6eec8a68eb5f9caf2ab3053a3047bbc08412a1d433d79eea65effc5e0cd583bf", + "result" : "valid" + }, + { + "tcId" : 85, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffff00000003fffffff00000003fffffff00000003fffffff00000003fffffff63a88b2e0c8987c6310cf81d0c935f00213f98a3dad2f43c8128fa313a90d55b", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "bbd9d305b99ff3db56f77fea9e89f32260ee7326040067ce05dd15e0dcc13ed8", + "result" : "valid" + }, + { + "tcId" : 86, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 60", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000fffffffc0000000fffffffc0000000fffffffc0000000fffffffbffffffd2407bddc5a50b2a7b96a288efb838bf768c6066e60b72f08a9782da2e39bd34f", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1f81aa3d70f8756b9495fba82921717d4006206a4451d8d59f3c9b8d95b548e8", + "result" : "valid" + }, + { + "tcId" : 87, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff00000001fffffffc00000007fffffff00000001fffffffc00000007ffffffd4af9cc406a46943ffe0fe630bd21f205eefa05355f3a13c9943d58e16e880435", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "66e707faf954d1ec84fe0f68f829beb2fe95058271b636362e3eb5c5d492cbf8", + "result" : "valid" + }, + { + "tcId" : 88, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 62", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400fffffffe00000003fffffff80000000fffffffe00000003fffffff800000002796cf7bde36dc6b1950001228b7249d3438a35fe5be98661255bf63a879b3a5", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "42dd6d83bbce6afab5045e1393838a97a46161c25ae91db0143e985d29162faa", + "result" : "valid" + }, + { + "tcId" : 89, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff73b0886496aed70db371e2e49db640abba547e5e0c2763b73a0a42f84348a6b1", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "ab43917a64c1b010159643c18e2eb06d25eedae5b78d02fa9b3debacbf31b777", + "result" : "valid" + }, + { + "tcId" : 90, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 64", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000ffffffff00000000ffffffff00000000fffffffeffffffff0013a9be0cbaaacf4e0f53ee45bc573eaa44dbf48d5fafc26856b44d6d00e2be", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "f39bf49011cb323ee00f77e0344a9b9da1256db92646dda0e342f8c1ad3741c5", + "result" : "valid" + }, + { + "tcId" : 91, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffff00000000000000ffffffffffffff00000000000000fffffffffffffe6e563bca873bd591c9663391c826150795e3c42cedd269e68ff0e56dc971d554", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "27860fa0679edd4556f0423a21cc21e1e3f1701da3e62a544974ae94f15f91a0", + "result" : "valid" + }, + { + "tcId" : 92, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 112", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000ffffffffffffff00000000000000ffffffffffffff000000000000005b5b2ec553be67fd73add4cc2bced4ebe6d04a05b0e926e312037b3951667847", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "2bcfc95bba84524d8093dce1092bc157ca1fa42a37aaca9b0759437f940c3e7d", + "result" : "valid" + }, + { + "tcId" : 93, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000ffffffffffffffff0000000000000000ffffffffffffffff31cf13671b574e313c35217566f18bd2c5f758c140d24e94e6a4fda7f4c7b12b", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1a32749dcf047a7e06194ccb34d7c9538a16ddabeeede74bea5f7ef04979f7f7", + "result" : "valid" + }, + { + "tcId" : 94, + "comment" : "ephemeral key has x-coordinate with repeating bit-pattern of size 128", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ffffffffffffffff0000000000000000fffffffffffffffefffffffffffffff53a54141598334650d1f99a12850769f53d34529b07ae591244c6ed702f1aa171", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "119aa477afad550e98db77bfb4e71a4b6ec79ec4fe17b7283f9b8bb7b9fdb5ec", + "result" : "valid" + }, + { + "tcId" : 95, + "comment" : "ephemeral key has an x-coordinate of approx p//3", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000455555555555555555555555555555555555555555555555555555554fffffebc7c976bddab1d1a302cfa176c25434558ec7cac238e739ca9849aa104323b106c", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "21edb700cf62c1bb816a877988ee8c5bc16a8464bcb6454adb8abf8b5cef7ceb", + "result" : "valid" + }, + { + "tcId" : 96, + "comment" : "ephemeral key has an x-coordinate of approx p//5", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433333333333333333333333333333333333333333333333333333332ffffff3c7b2bf3716a9e336e162966597e5c423bb9d3d0d0c3c02b9e2dc4aabad17bfdcb", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "1ba54571d1d280f5fa2d0c5846ec392c721acd4ba7e4aadc3dc2353957abd80b", + "result" : "valid" + }, + { + "tcId" : 97, + "comment" : "ephemeral key has an x-coordinate of approx p//7", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004249249249249249249249249249249249249249249249249249249246db6dae22817588aa19f910e8bed1f89a6b5ea6cde4800dd9beb28d1336bb46075118144", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "9d422ce42f74aa0272e5530b5dd094225f11d1100fed954ff714a2d471559cef", + "result" : "valid" + }, + { + "tcId" : 98, + "comment" : "ephemeral key has an x-coordinate of approx p//9", + "flags" : [ + "EdgeCaseEphemeralKey" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c71c555554e83c4d16ba6991011cf3f94feeff3f48ad29ed9a22bcef8fac40d9b2af25e2b909", + "private" : "2bc15cf3981eab61e594ebf591290a045ca9326a8d3dd49f3de1190d39270bb8", + "shared" : "a5ab2cc5bb6881f7e734d7ccc9d448127d9465fd342d81c8381572059b3aa2b7", + "result" : "valid" + }, + { + "tcId" : 99, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000459294e8bc54e76d48b5594f01fe4729566d9b6df6385982fbb533183921f1a124543e4110bf4cd22e1d444d83e24c5ecdb328a98f2f93e8edcb99b07d5d9fafc", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "e976057e8a322dfdb2debd55d8e58802fb54425950b2dbfd00f0813de27105e4", + "result" : "valid" + }, + { + "tcId" : 100, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000429b579690264954985187aaa9ea313d39b5c828e022afce8fd0cb764ed693473ba8cde1b2be1749cf4d5bc0df578009c9650e44b6c385c5ee2621ffffc205cb7", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "09fa5a510558a12110daf75117af1e175f93d7c4d8ba41c5bf3efe95d829ff50", + "result" : "valid" + }, + { + "tcId" : 101, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044150a111e0489cc82d43ba66f404ba0df2b1fa13ffea361442f7854f9abb381465627e96f372fd0400eca42113890cb110c11eda22405bcd295b1caab9d93af7", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "98bc618faef7c4311c3d8fd37b39e9baad780e14f0527fa69a3f4c2b66ac6394", + "result" : "valid" + }, + { + "tcId" : 102, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a74646c798fd5a0af442da69c822cdf1134adba361f90663d626481aa10e0004567160696818286b72f01a3e5e8caca736249160c7ded69dd51913c303a2fa97", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8a0b2ddef3a1108f6ea367ed08079a0ec98494fe46cfad584bdc98e99e6d7f99", + "result" : "valid" + }, + { + "tcId" : 103, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004611c65eecd9e3de528f639e8b6698688db1f4fc8c11650a601fe6daeca5c59665fa45a23400633ba3630244aa6b0144de2ab3b6295e3dfa15f586e40a84053af", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "89b86329f0f13aab07a48d0d3b7afe530ad260a90de6c25ec3da8b6905502551", + "result" : "valid" + }, + { + "tcId" : 104, + "comment" : "edge case for Jacobian and projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b49c6791647937568c7570064856420835d44af1ceddd682967fbd44fc97294cd135651bd7ee3aab957eba10ed4b7a5c40ca00d959ca663080c4eaf0e189bc21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "751b521de6384a017caafa10419fc35d58f6dbace86f6b533c117e38dab1d689", + "result" : "valid" + }, + { + "tcId" : 105, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c73c71d856cb949a31c249c1e99b11ffb698cbc1dbf4002e956cdeb655f84045716e98dec10a9905fa1d3a851f4f1fe617356cb56d5643a148eec376237a27f1", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "f282a78942218fac638eeb0eb15098f5aabae15b3ddb7abdd40a8ad3b5540c8e", + "result" : "valid" + }, + { + "tcId" : 106, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004acabedbe760e9330af3508209ba0081b9ce061327d1ea0b6ffdc577dbaf28e269cd00176358828215d30ade0cff8cdc0856c84fcdb424feb93ce58a2554a9bcd", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "6aeb7004f6cf6b05f30bf481e8b32a1e25fc66d96a4a53165727bb304cc27baa", + "result" : "valid" + }, + { + "tcId" : 107, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044cc9197bfdef17d33a9ea743bf83747b564d6ad11e6080957a9d3ac44165fa793ce20d13d431071be367e592f8a22f88edee1cd51cadb0845ebea64b11c45708", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "67b5a9926bc58025c8bc2b9504b72c3a8465173d70f5d5ec1580fe88c5a4887b", + "result" : "valid" + }, + { + "tcId" : 108, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fbf411afc88358dff2ba156ce273d7b15d0ba3980a60a82eb38bfa58995e163d57c62e53070e8e6cb1df4ef509eb2598dbdb07a5ffd71301eaa2892ad1238f4a", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "12182c05568a6b18a98ea19110330146e7dbc49274f324b5edef4eb861f72bec", + "result" : "valid" + }, + { + "tcId" : 109, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cd7863adddaf0099647139ce64ca0b39dbd312ccf96c15a62f2c49e628248235999f82afd0f76e744afd0fca2aab36f22ff7ebefd8e541fcb6e972704b8ac521", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "f75920e61e7d05c3cf4107e5e81f3c1be7ffb0637f0ac8b895d87361345d9a87", + "result" : "valid" + }, + { + "tcId" : 110, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd4fd857640a6bdf5da42ffc5c2c1755c4c125a99d380a5935eb1c4c3a9c2a3a4760df25ca561724a82e3f9c9d782536db4310d6c9c769f51b733de44a9c02f1", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "373aca70b036b70cf8e46fc9457a8e19c6821be2f2d6c16edadd20d7b30eb3ba", + "result" : "valid" + }, + { + "tcId" : 111, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000445654b3b66065743ac86854daa77c9e5cf713a402fbd4ada365f4f96bf1717cd63cf23ba035de430a2128dab0d2c7b939d44c66624f6979275cd37cd02370669", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "caec9de4a74d76603c5d5d07de2df0d435bef2b9063b5123305d2fcbd5dbb318", + "result" : "valid" + }, + { + "tcId" : 112, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dda793fe7fdea5c7481c756f59fbff48481777a54218d95eaa24e7b86d8a5858fdac18590cd96e193db51c50307d2606674d5b8afcc82d1b672dd8e09719a6ac", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "27980511f433feea84475b82281b1fa6b946c97c646738d5ac3345250f86037d", + "result" : "valid" + }, + { + "tcId" : 113, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042e043b851fc5a5f12deb76fe94182b99bbce727b476783f9d868ad3ab7ac7a251462b469c2e02491e05a3a4523e09a6be8e5b2d10419cb7760a8503ae4eb7e7b", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "20b27f84ae128f674e144d82bcd1544146bfd0150b0843ea585314f59cc54aae", + "result" : "valid" + }, + { + "tcId" : 114, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043d8fddf41e52320c8081e0d60f5397993abdfa979c4b5e832ac61bf3cc2e6fd94504fe3207dbd18ebad2b921a52a16a33659939c16fbb9186caf5e2cf3170346", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "92592791ff90b595dd2ae7ec039bf6b7bfeae7f044761f5e7fa86564ebc46b2b", + "result" : "valid" + }, + { + "tcId" : 115, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000465106fdca0c408738c2316f3ec2238d459157bab2c2855323b95bd271c91dedcd9fc2d685446789829251d293a50d150df5f1fc1a0604e4defaa9a8e3f8c9169", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "8e61b2e072bd1401da12a3f3d8164daedab0bf0ca795bcf56aff81d07caf7281", + "result" : "valid" + }, + { + "tcId" : 116, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004320c813548183aadb0e7d21a0ffe472bfa9b4ffe815adefd09180a3ae2d15fbcd0ca20611d2232847aa80e7f7691c008ff886dfce550f90c4c19982ed779b466", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "a41170f616c5499e289b4893b3973e1155f66ff354ae6a812bcd0e33bd7dd5cc", + "result" : "valid" + }, + { + "tcId" : 117, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a0e2b1a92a6afa9fe68424bc63dcad620b7dc844e4571f5404ab9d18bf08545ccba1c1ff49bf7baa9be1fc0ac4bba63b41ba7a374e15fc39b884d80a75b07092", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "b8cbc27d4ea1b25f2292292ae53a3bb954b7ca77ccca5b4dccf1b958b0aad163", + "result" : "valid" + }, + { + "tcId" : 118, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dc97139a3dd1411d74616154aa0d6bce787cfafbd8fd060b680b04b422b0d22f6ab50e5c68e027805953bf7c3be40a8f7c9b56c6dbbe86337e6163ada01d9d63", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "4baaee93a752397bf2ad0be72ac82b0ad2417e167bfdfce4904f012d4c33fea6", + "result" : "valid" + }, + { + "tcId" : 119, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040978d42e1594569589b578266cedb6088a84c9cc9baff0070dc1d934342605e62ce80a966b5ca0344981f4229c7ab622a853bd9bc59b662ecd92df238e4e46ed", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "3b3d86187d05a0012d83be280987dc95b1c0c9b57f253b64530d1d4220aa4abf", + "result" : "valid" + }, + { + "tcId" : 120, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a8630a7bdb78a970a01b20c3e7b95d25d3eebdc8e94ecfe0f508e4136eca49afa5eb12114b50ac77d68d410cd5ef5107b2e68f08600e5e6938c452d51d6993ba", + "private" : "00938f3dbe37135cd8c8c48a676b28b2334b72a3f09814c8efb6a451be00c93d23", + "shared" : "472d4b34f5be6b499f76b0d9e439e115f6a89b725d9e9e811185a615f14007d0", + "result" : "valid" + }, + { + "tcId" : 121, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c4ea8ed31ab4a8c994a965efd4770bbb5e26ee54cb7217ffd31fa888c108feca063c415201329dda130f43973f442ad320da0ccf289cd1b71489ca0a7201d5a6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "fa67f4a9ea34fde196a7dff6bc1a2917b1526d54950335bea2abe22e1edab410", + "result" : "valid" + }, + { + "tcId" : 122, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000491780d1905316105d6a6aca94a0d4488d134f985f7e29adecb1bc6cd0c211a788035b06e495d1e58b085bfb6720bca84557b670de34587df0d7e3aad5bbc803a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "95c131de0c89e5b17f91e56779c1571de2c8a20794084fa274eccc8eed1d3d65", + "result" : "valid" + }, + { + "tcId" : 123, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041961a1a4b29671f1d835b313ffeba4d8203d8414cdc0ea11e47d619b47038b1de50a63b89cbc8956a5870c6c4830e2102d5281b9b5dc127b1052fe7b3e11c438", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5bae6d6d23a68f283fe0de46f1d74c0f52e278cb181f55c4353f768ba162aac7", + "result" : "valid" + }, + { + "tcId" : 124, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000429a9e7f25109a8c4bd80dbea05fbb46aade58797c3b2fa5f00f0f081669ae39d2c78fb1160de6eda50f472ba659d4f1db4ea6e297244b6ae68a051d96e62e75e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b4fe1201a8647be6d6d59f406fa970cc858f5a46a50a6ae9d992c0e23f5e2ad3", + "result" : "valid" + }, + { + "tcId" : 125, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041617dc03d3eea42e8ea2c5bd034a38c5a3d74165a548074b7b5765ccd8465b7f61089d6dde53430f34cf8285ddbc584d1543fdc70c2333fc315eed4e930ac3a1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b721ebc7eb1b09438d754ae80302b2a2bf40f866ec507540ab5120b22f868886", + "result" : "valid" + }, + { + "tcId" : 126, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000420e7a1358436f675f3774d60954b5621145b8f5260b5503636f54878ecaaff8dccaf2fffcb7c7084e325dae5e24bff5a34e37980d1722016dd6667da71f164c4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b8da5d1bf9419e2b876e708871a9a29574686689bae8d87985d72a4e573dded4", + "result" : "valid" + }, + { + "tcId" : 127, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042759bf4c336501340cbc67afb4a8f5744f9131d973966a9de50ded60fbe045121b67a9e81e53b064adeddd16a4c030dbb189ccd7019b329d67a527c311723469", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "39aa2bbc4b6f30c268b19909d5070155c39c60649b7a2ebec266bdd18fff8cbf", + "result" : "valid" + }, + { + "tcId" : 128, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000419b8a10f5021f11e29e18611fa8284b7e9a3f67cf36eec8ecc4d7a5b54803411311a8a4e199d98eb358e19a27e80cda6af142d6091ddaa9370ed610453abc6c8", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e40396a908c2cca4504f4f40be394a12244ae184f6909ec725ce723485bbbb97", + "result" : "valid" + }, + { + "tcId" : 129, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049ba841f41245ac08955966470425593290b9e1d87bda8f47df19048db8e3d83097f68905f360ced26801872a7ff124c3637b02c4a596b83abafe7bce567ca177", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "13a21dc50cdfaeabd572f2d94dc0f3f768f17f990ee59d7f16ace9bfad8a705c", + "result" : "valid" + }, + { + "tcId" : 130, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000468af761d053dee64aca5e98f547feb2dfb6f5edb8138011c7f5c33809b4b9e00466dd76cb8ceeb5132862052ad3e08bfea245ef16ca0d00ed0c4b45fb6bd3028", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a82fb3bbdf6d69c7398ee9020fe006d5b28c632f2da357393fe58deb8d27fd08", + "result" : "valid" + }, + { + "tcId" : 131, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000405dc8b18bc286f203213b1319413dfa4911d6c2e30f3c778c55e4e5f5d9bfdbacd0b3b209e76049895ae80ff63c0225a563228cd99243f628a9dbae70d773c66", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8fa44f09cfddef86aa9007cd4bea6f0bc9b5b2115256303df09f8a20909c5271", + "result" : "valid" + }, + { + "tcId" : 132, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bacb606384b1930bb4b74ded236d03d3bb1739a51b73f20dc3349ec3b383180a6896ed59fa0b654a9c404b34fee2c767be2383f4b8b171d2359806b04b502d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ef762992d22bacaf06aa1e482c0711046b52e0e40de2a21d4e38df0109ad67c0", + "result" : "valid" + }, + { + "tcId" : 133, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000448ab89b2a312de510a6d3c9ac9e4c4f5b46e04d3f858433b7646e46273d94dce4a0c7da616388f1eb8d55ece64ab695e5405d779c92f3bc2595c27d65def8db9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3b0936f22337ece971ee102178f37bca3cb69b50b8ec9c9b47334c68b5d4320b", + "result" : "valid" + }, + { + "tcId" : 134, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fd9de304ea5f18dd641510b9809473d39a2373ed5a470ffc5ea7c83093911b4540baabb9d912279aeea44379110abec75ab7994a6183c6294bad27bab5bbf821", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ec571878fb1e3b1f5d4f66b8b080bd4e50410b6eeea4dcd3cedd4622bf876160", + "result" : "valid" + }, + { + "tcId" : 135, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf8976a28221000d7f5219fa8d06f9f8ae47be626f89c2bb6c4d0323bf02f8490c78bc948c6bf82a191f1de972e57db35b05918594ccfbe8da19bd46facbda78", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9f3d9de87d9cc5099ff4f56d913b98b5eb1260e2b3a2d7a3c5e01a7e68219d10", + "result" : "valid" + }, + { + "tcId" : 136, + "comment" : "edge case for Jacobian and projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c3229c9b4f409a6539484152b39535c512a66748972025165fd888c388369fb3298cc41dda36fcb15a0d97cabf757bf0737dae70829f4b9a1d499d9e9911673a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "23adda6571d4ad7e940c21023af3ffedef9d8f64e83cc1cf6e992d1da1451d91", + "result" : "valid" + }, + { + "tcId" : 137, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046f2c3dd84b44daca936a2edaf43adc8c1bd5f42801231718fce6f5e94d144717a247598c11eaa2c507b0e96dfdd03294cba4472ae8a2128e36f1eabd315aeb25", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "91e70bd8bf85bc6311b2cd7791b7edf00e22f9cb8bfd72571ec9a03bbf716f37", + "result" : "valid" + }, + { + "tcId" : 138, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a511b09334f032cc33ee4ddbb839304f6bbf1daa4a80de524ca24ebb65a0a92e4ea48243cf7e26deaf4de7779ca71f76d9dc6c8c1b7f44cf190fddbe82c2c940", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a7d2f3e3faa772d7a86026e2f183dbe7a298ae3d1bc3abcea0df3c11cae4ca60", + "result" : "valid" + }, + { + "tcId" : 139, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047cf4a6ec110db892e45a7b2ab38b411a6c41e86fd21a6455ca1a4c2e2220681309b3e399ae30098bf872c9aed5db69d14cb71149abb05cf5227a620c4b16b740", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c611d27e7cb52e7c56cfa9062e59f3defe7c1e225727b9049384a180bd1688a8", + "result" : "valid" + }, + { + "tcId" : 140, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000436c7dcd152fb7e53fd16228465ea0c419da29cc6c79fd4266303b3bd06aa0b9036363a959f8c0b400da525ad7674677f829092ae7f7e8dbf88397fcd19047af5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "661f5d36b57af48982e44ff89ae75f849a08b1daed6417a20212bea88c7f2f8a", + "result" : "valid" + }, + { + "tcId" : 141, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b61d3cd27bfa1269234a777e118f7db10a3844e8c7d1162c099a8099d887dfb849520e9a038f8ba8804d44f22b37452514f0aefea93bab7bdf180db54485aada", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "540e255f6cb58d237990a7437cc7aae770428796deb607bc29fbf0a4d11873c8", + "result" : "valid" + }, + { + "tcId" : 142, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ac9cbc8bd917192928d9a065fb1f89be4bea850186fd466a7a9014066ce002c51a906c90eee55cb5692f0ac046746ee4bd2205fe5f435d1e71f19a8cb8550f3e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ac6705af9d059cac9977967c0ce514d70dc51d88fde684123a921244933ba8ec", + "result" : "valid" + }, + { + "tcId" : 143, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c050d058aada9e43767f1f760abdbc421ae220fd01e832ae81c628bfb1277c99d35483fe6aea51dea9c017c326ba7bbd4175687a72dc5c4f449eed0c53a08052", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f7a5b69bc39a976bfa6644a152789c3149352093b1dcc4b6b06f6c4c7c90fdf3", + "result" : "valid" + }, + { + "tcId" : 144, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004399542882ca4d5fae3282c4edffc3c7eda7c451e46adee4219015e91c8c69cf8b123f8ede48ab76fe2c9218326cb06542a832d0a32b7ac0d485b4629bfaf0d76", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f0587fbd10e332ad297b5e463d4f09d2167c8589c46dc6680c13b044a34485ea", + "result" : "valid" + }, + { + "tcId" : 145, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bfc304fd88ad8f11801d35286a49505cf349403d8100efe903d078efd5d3a66ebf05d6fe2a14c069902f0d8eb6800460731d48395efac4428ed87b00f3fc6fb0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2fb4991332a5d648df5ca6bbd08575c7553773a97312303440cfe7e43d3a268c", + "result" : "valid" + }, + { + "tcId" : 146, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046881678d6c6d8ceb01de5d6664a0b57b470f149492e8e7513e121fad849aba1b2ad34db024ccd2694e497f6adf4d3cf5adbf518c768a4628bc2e159d0949f2aa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cb65082df5f54cdc668625017cdf45f22f305a8f34ad91fabf36c071496c84cc", + "result" : "valid" + }, + { + "tcId" : 147, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e38dac9ca4ef5b35da77d846093e0d29c1ca350e72b5a6ce901bed9f472ea199f805fc3202920782f49f4b6e7257a4364dd5451d982f29b62d5d4b8e07a33068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6441ac7be81c2fb6472655528f21454d40236a878fbac2ce31e4358ab4ed02cc", + "result" : "valid" + }, + { + "tcId" : 148, + "comment" : "edge case for Jacobian and projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042d8c6732e3d0e1822193243bb9ec3fc2c7f264e94ee61b295de5b3c10db937f135343453838114a4752a5514bcfb9dce10f83e0190c540fef10675cb42584a05", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0b586c442eaf016f382199729f60240ce50c0f7107c488a423d42794db5f6663", + "result" : "valid" + }, + { + "tcId" : 149, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000420bec8d2b5aae1f955b7992198bcfe20880494150058cf6151fe14f6071bad3132dc1ce503969b824c5a9e23aeb472255dd23f97d02f68281ad0269818b17e49", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b376d9bc1909eef92953cebc3bd6f2bc0cd6cca620c190141740f62239579334", + "result" : "valid" + }, + { + "tcId" : 150, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f456946770af5d069d60b279ae519ea18e719abaf5787476873a5e61f969074d47eb27520d72fce10650d312a5431bbd6b3f37cd46755b7a8e1ef1a796f90908", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ae739f624ccb1f0ec964b2d1896d2df83ca1969ad6ca26b334342013d83282aa", + "result" : "valid" + }, + { + "tcId" : 151, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1390a944d24f300fdab9bd272bbaca056feb71c0c37468e0327b08504d55f3a80a4b240565aa43be8f3e2089b4788049c5d378b667e987e01aa8a08a4cd2c95", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3c25126ece58ad8e93ebfe6e7547b05b39c6d9858e559fc01ff6b6e50b0a22ac", + "result" : "valid" + }, + { + "tcId" : 152, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043e61ff2443d10b1e25fb0ce19f57ae39223d33fbb0e5ee2b4740fa19384b7d0e1408119a70aa9b230d9f18269c065c53d4c2619673b49377af4cdd536c931aae", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e47d658df5c1f9599d4e560954ab860e9a6377decb0b56ef3c13dee36185b2f3", + "result" : "valid" + }, + { + "tcId" : 153, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b06028d729039617f912e86d1d1f44e93e63aa216ab0641813d06c16a3edaee979d21572f9540d7b07b0a6667f7e0a9452f6f9f3671e522e2b497eec138a46ea", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d8279c1ec95189fe63d75d1c6d7fc312e411a3d11e4d671a49fa17fa36c3cee1", + "result" : "valid" + }, + { + "tcId" : 154, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040a8f74cee50d1e853a38c026f627fe47d81fc11f886268b35379a32ada249bb91d63cf0198e1c926bcb65ce21813e4d72118b7092a5e8bc152909222ac19603a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "077c7a4e606099d781cbe5a89caf7bdf4f448b1c0d7d3097263a045170275a3a", + "result" : "valid" + }, + { + "tcId" : 155, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040edb7020cf4d6ab14b5a3f8f698d66eff983588846d718b4845d674e7bbfc0edd92a27e40e5ab2e0cd2d0ac1ab679402ce36f16d3ebfc0fd9df817dab17292d9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2025808c609ab0b07924444ea4aa0fa52563858a53221f719c91b15576f49ea2", + "result" : "valid" + }, + { + "tcId" : 156, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f06c77cac24a6ee51421863a0d1469418f0a6430e062da18f27dd57401c0b612032b7e0591455ca33b4e49e53facf5864410ba046ba5d4fc6bacfea9a0782ff3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9832405d565c97ba1d6ff46e1d8fe33886222cbaa69963868d12a8be07abac6d", + "result" : "valid" + }, + { + "tcId" : 157, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cb2b9df4ddc430df7b0befcb5a826da1589a15bef1b6b25f1201daab5b2fa4ac3801e27d112f0f3276722dcb58b8b4f4844a2e614de49db440b7cc7620812734", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c4bbf44547e8128b9a46ed92ceb07df691e2e91d0b47dac0dc2afd14121e7a80", + "result" : "valid" + }, + { + "tcId" : 158, + "comment" : "edge case for Jacobian and projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000445206b62e4a3c4404c74ae8695cdb905a8e6a9456da09c72c72eb7712d9d52e81ddc2d56b634e4ab66b798cdb4db86cf94f02208f747304ab3d5aa2bb125e137", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "170a91aa8196df6f0d09ec197fc526996ffcb6792880f01018b3327a096fe638", + "result" : "valid" + }, + { + "tcId" : 159, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004584d2dc258bd4650e6fa04fe9d3d2a5e768d795945ed2323f844d0a8fa0c6fbd5f96256b9e1b7263fa00fa758cd6be15d9f6157fad66c729ab0dad694564e834", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ed527e31223f175aa786f146b3fe0561a41b1051d5eb32249790481eab1ef381", + "result" : "valid" + }, + { + "tcId" : 160, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046c5527898ae8067da56ac82caf338c9e7f40ee4489115daf0aba923a8b6e501e430f5970ce9d01d03ec076f8daf685cf4d5a9ccd5eb9e849d43ae2f36f2e80e5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5a74555732d8541d2f73e3a59eb31a131c8d41464a1f2c37531a25f4a6d3bfe4", + "result" : "valid" + }, + { + "tcId" : 161, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000452cd9924795fe2a251af7cb569f66d9141db894545d798a0db3d30e50f100fe204ea81c808587c90f3f2c94d993c2d0cc4be64dd6aeb9dc81c70d78885b2f776", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f2750c996f22762629a3f808da6eedd7cc72af4fb0bd816c86e636264bf57664", + "result" : "valid" + }, + { + "tcId" : 162, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bbad8da4c018bdc15a5af8f3da4b384c530ea75560cdfd242bfa3235d8d3595f734cbd866487b83fcb84a4ac74ac548f2535b79b57d02f03a1a37e2791a096e4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5d2163ca850749991cf782c3852e86b05e6b05ec8662905b60cc7b7e37434fbd", + "result" : "valid" + }, + { + "tcId" : 163, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004389aa52235043bbd759868898bbe277ab996ea9387bd7098b0072442bd2b42f5b823364e9144a1eef1f10093fda0c30168f3004e2c2ea74fde4978f3aa1a31c0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f8cf2cccdcb53b3d3c6d1990ae16c71ad9d141ca49f8574a72047ce6c2da950b", + "result" : "valid" + }, + { + "tcId" : 164, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fd1bac144354cfe1cd4c64aa3a2f77f0aefa26cc5141082676370a0f1ec92cd8fee66992d2d2fcb87f90da0a6743378466655519bc782dd7b0ab570f6ed451d8", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ccf6e14d1add6e4b5a4228e5aad0b31fac4b45e2112c1c767e933c6a0c3f2edb", + "result" : "valid" + }, + { + "tcId" : 165, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000478c926b0ee01c000c25a83631219f08d8b34745d2ea2fdc9ebdc5a2288fa9b0306bc00ab3790508e5705eeabfbaa0744719c9bd7b467ca4a37a06f6fdbe6d86c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "57556459e9d32b75a13776bddc8f547cb64708133e7917b61e3697c392003de7", + "result" : "valid" + }, + { + "tcId" : 166, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044cae5606bad6013f7f36190d7254cbf0d5a92b338e4a47702a3c97a3371d7ec280d273dd598c20392c540e58bec9b180406f3fa6e6c529a851bcf2b96d8f3809", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e5490cb494bc6ab2108da2cb0b926cd878712f54bfa72b59f702c180c62b0c91", + "result" : "valid" + }, + { + "tcId" : 167, + "comment" : "edge case for computation of x with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000408ccbd74f297fe71ca3115c0b1ef4e0421b99ce91ffcd4b72a530b22993e18e9ba0ae1bdbe1c2836ffe9a61ae5a899f152c90b42823638be4d51dc3afa99e6a0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b3ca753c1e1067b550736a66c0d6b6f47e9394c56bb80b5d4204fbec9e59b490", + "result" : "valid" + }, + { + "tcId" : 168, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aaccef834f57e6c5526fe92748cd8cdc1375c2ac71139f5d2587305bd3fdd3cd965dd5374b6a319850c23ebc2ec7a2deb7ff3e428679d4afc9df7e75f2e06e4d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0cf8c178ad95952520264d0f4a24389bf1b23dc7ac1b65d4e8fe822dcf20d67", + "result" : "valid" + }, + { + "tcId" : 169, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a585e1ed6e47224a472cf4ed4ff34e6251c62ac682e4b70992d5002f08d9e203e9b7b28895b9db4016e5d94a9f59385c16db738a83b84e6d43ecef820c55d462", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "15e40dc49ed62d35e8c91999b05068f419238a222deba206df47d909d3a1f40f", + "result" : "valid" + }, + { + "tcId" : 170, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b104d0cc4a987771655105cfc840f195746e112334c54801fd93f4be8b114a1d3cd8cbcf4b274166f82cfe57393042e3534e68df2f4c3dad1b7ce72b47cad256", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e9458064d3bfc444417486ac1334a93c9aa4468031134ee0196ca6e31713956c", + "result" : "valid" + }, + { + "tcId" : 171, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000482bed3d552098d2fc9e02f1f3cc32f5f31cf6cd101bbb8b42bc6f732badc1976229257d92b241f2031ecaeba10f1ac154d8a3bea309328231272eb6aa01aa65f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f4446e98a63b0598011baaa4f930513218e8370abfbd46f721c8dbf37e170d85", + "result" : "valid" + }, + { + "tcId" : 172, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045c4fb681213bf39b68e7ca914d2830b12a7a32c96a9c788ad2987c009e08d0a376a02ccf594c28995cfcb285ed5d91dded92921108a0b40928487cd07180ab21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "dca827687aa24f2fcbcab5c38069f4860dee6698fc23908b06c7dae713a141f9", + "result" : "valid" + }, + { + "tcId" : 173, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046b29f8c006869ab6be793ea72b970aceebb7a4c4b6fbafecd1e35713a28bf284c76b07dc14f1dc533f1c4ccb0973eb53e53023f0b0f1a8914c7708c2d73d4817", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "19714f1d4aaf8bd61520b647633a8e53099499ac368c3dd6f1b084891619b0c0", + "result" : "valid" + }, + { + "tcId" : 174, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046e6849c2b07a37c4f36be911b323e4ce70c18b15902612c4fc0fe6d91e7c180de925544363c68035498cbb2236f5c1ecd0e4b2cbb5801a8cac4d0883f651bbd0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d7a2da8de2434e2ad264f9706b30d0657c727606d8285d2179800a970b4faee3", + "result" : "valid" + }, + { + "tcId" : 175, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433649a1e74c7ffb5edc3949c58b7a7f4b5348288f621c50fbbdb714fa42aa793cbfd969e077b00ead21082f0980009868f79e430ef1c216394bb0e9eda135e9c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "853d4e01d4dd4c9d6e7820adc16f32ce7bfeec0d578deaf28af9cbb3315e8f1b", + "result" : "valid" + }, + { + "tcId" : 176, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf976ef204532bf67443e8b8d9987a683184ec26420329ba268e54e90b480de0beb108df26eda91eb4fd23d26af6f2d78a4281d5ede075c2c715fb1c4f876784", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "35715befcfded16e67fc0dcebe945c6264ca0d91b3663bd3ec0722b585e5d652", + "result" : "valid" + }, + { + "tcId" : 177, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042c435d9faa598070b4920277506c100de62a7df05c34a39317785d628d74dde3c7f5d0bedf54af1c7d21ff955128002fd5296237384723fef1fb806c2a6d8ea9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2baf108668e82b7fcaf3f5e3272637b426c551d8af0e55f5d74bc317a4474767", + "result" : "valid" + }, + { + "tcId" : 178, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043819dfaab5537863c8dbf406ac18dd675619c9a7a554620ad8a14492bba425a3d68e8c68181555e22362415c95a31724ebfe8b2bf1764e209eae9e53b3f462a0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bba443b160997aa8b7fb2748911dc2154c0f6b986fbe9a49e0a2934fa5f32954", + "result" : "valid" + }, + { + "tcId" : 179, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000470ad3a9c9a9db71d420abae84ccdb12768851bac6a82ffd03d89621a50a7c311bfff7c664c211f93768f84b5255d95c7f67887c3305d789d7fcedc2d29989f9a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b4831736601e7387050ba3d401aea241c3506b56a0473886c408b366c8696429", + "result" : "valid" + }, + { + "tcId" : 180, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000458391361fbc8115c978e82037814d31aa3a88873ed6c74c4aaea9727e300d94542924c67b5cf828be827e581dafcbd16e653e72a4f2d4d0550805387b9417e77", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ecd0c9e1acb90ff8bde88f7757a089cc86cba27f0d15fdf737ab3b8ecf9fd9c8", + "result" : "valid" + }, + { + "tcId" : 181, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000423a2be684b0b5f04bef5c6ca8a991bf752f5964f6fdf36d7129100daf80f1434b6f3ca2a5e85ce005e1cb6d2b13094c434fdc1c095a3ae5e53f64949ca56691b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6b9ee618598f33c184cd63cf8930a4db3a2d4ea022d50e63cdfff85734a77ab4", + "result" : "valid" + }, + { + "tcId" : 182, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004147b8a2fb4f6e85eead81ca0b3f230b8d8cc230de73107d9cabcbc5b39e4e7eadaa44ec1ed0b95f6109223bc480e917419d860f9b9a75f81d6f8ca3ada377533", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d801dc9354cb756e6c27de5a7cc88ed5cb214ac5091b4090624ee8afbcba35f9", + "result" : "valid" + }, + { + "tcId" : 183, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042b3fe64bb142789e89e1092db46b613012bcfae57759ea908165c0362f804f36c0053faf3266ad7eecedcb24636b99c935f1c8e73168f0eeb3ddfb660801e55b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "03307ea557024686910d2d1d2d2760d82664413b8feec66ae8d2dbf1025f0c45", + "result" : "valid" + }, + { + "tcId" : 184, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c4ed72445465cdb44f58b0e1af0823226ea79eb2e1bc3f27fb8e4ce7b85f4a30c237e574c59a992406fd517f4d905e03d7a2b0a40ef85aa3c73bd46a1a06a918", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "dc2cd94321643e89dcc92acb0128d886b28cb7d66a0eaa5b96194465708780d6", + "result" : "valid" + }, + { + "tcId" : 185, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000418ef4e2fadaac1b982a7d2d12e9d5148ecf336b1d3775da2f7df822ad49a1324bd07046a3f8e949e7a0d960fe9d9a1de0f61497cb4e7b2f39aee6844396f997f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b831f4a0fb75927bdd2945c0081f11cce871c9d6dbf83b7895748c3f46375ac7", + "result" : "valid" + }, + { + "tcId" : 186, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004398ca1a944210a10b1f5732071259528df87d42d3d7b006bc6fd9e1e09f6fa30fed379db3f1bd915db2ba27384ec13715417446ee84fb5fd0a4bf6431cfd3f15", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ed607a9e6d41a4bc0535c5161c98613edac6b519590b481420fb2ba1ed2c35e6", + "result" : "valid" + }, + { + "tcId" : 187, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1c182adb101ebe5fec3910f80058e091d1325433d4fd3bbb38eb75bcaf2698a21218f7544ce84dcfe52e817ec0ba6bf84460f49932b3ec5ed27682d337f270d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "64a68fad2378591a18f8f2a4e346faf59da29446ec16b3fb8c37aef2d79faea5", + "result" : "valid" + }, + { + "tcId" : 188, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043f68c4e412c57da015568e0a9fcc3db499b77e6c0f55050828c50c35493af5e3d0b53fe30b0c6cf42cdf9f4f01d5c9058f8169b241bdea225932f9033f8bc5eb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0fddd50bb27666d4d38e6ec18c8ae1be3d763be7dd11067213e997fa4059c67a", + "result" : "valid" + }, + { + "tcId" : 189, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000456dd4c2b1d7a1a2d6559b5203fcb8974fa81be7d64cf0ae7a14fd965dfd69cddebe1ca78d5583fda3487040dcd94764f8dc619e8d74aae8d9665f340693c21b3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9c412023b7a66ebc9579a8d16bfd3109ba085c42f3fd395e07534529ad2340a4", + "result" : "valid" + }, + { + "tcId" : 190, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e1e5053b6f43b8714a025acfb86a8f51195488099b1f5d63310a6becd7ccb47ef0d16bc0c3234470ffa8d45f582fcb65ff9ccaaa6ae0cd6b572bebaa50c17741", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "28717726dc3674abb4f82b66837e8685ede16cb0cd965824352ac0a2f9d893a7", + "result" : "valid" + }, + { + "tcId" : 191, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041a46571a1438ca23dc7912a8a7b2245d70c852a6e9f4d385dd608427ec3c41e7fe06e2dedfbaa376a614657ce61701a7db181e5b1f3139045b8424ee54964b7a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2e74661109f0cbc6d587790330d67988658bcfabf1f7498a2b3279212828e207", + "result" : "valid" + }, + { + "tcId" : 192, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048ce5a3c8bd2544695a005841612a7c5d05beb07cf7bca1027172b030acf7d275fba0c339f74ce36d104fffbd5ae1c9c72588693190ed2b3687433087213b5bdf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d202df6662ba06d3088363c60e341283f7b6300104d58cf6d707262be6972b59", + "result" : "valid" + }, + { + "tcId" : 193, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a0abcdb1ef035e186e720606b07fd615532039275ac1b6f22720b756c0f857cf76e465cfdef30602b2e055a303bc6e176dfe972d06cc6f3821780387bd6357c1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a54a81c18f4b7ab0f3702013678566ce29e91c4142114d62f867a5278f89cfff", + "result" : "valid" + }, + { + "tcId" : 194, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004859b6beb70671b3e64991bb661180dbbe835f63c0a5878c3f83f0922660a7c093389bf4ce6b5c1c2f801c84c54391d53aa953ead5e51b7757b3508345bb4cdeb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9a954112f52d76709d64739dc75e9ce7a76aa19242b306391fcf25ff92b76901", + "result" : "valid" + }, + { + "tcId" : 195, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000435510d43f4d1a173a0467d5cb35a4170c3fc407e55b416b4dfce28650f8802afe8ef2adbde8b40a1714286176d674489bf9acb2e4a8353a7dae1a9e97cbb4150", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8763cb235f2780c1bbd35fe6c387d5505f72eb0a77b104c775c2b3b42786d7c9", + "result" : "valid" + }, + { + "tcId" : 196, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fa4af089c14d6a8be1881135989411607160d141a7a8cb4546f358a797d2aafdbe0086796436344daeec063f4f4a414a8779e72a960892335acdfbfd452f727a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b9309ddc5eb64a4d819a8a332b061a59f163a5f50d4865697e4d123efc9b2b29", + "result" : "valid" + }, + { + "tcId" : 197, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043cdcaa086427023bbd91b5b2e212be77de5591a1a0c210d54f0482f27c426558f8e1f4fe6e3bf037c0e03d4043c1d9b25436e0803b1a42b6de2e40d99e839c68", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "87e9f5ec4a9091d94ac22a6a71408213f444be094c618d459682e17357631939", + "result" : "valid" + }, + { + "tcId" : 198, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d7adbe30a5682acf9d398f58da8fd3b583283d9eda74ae067b9b533cd6c0824cfe50d0371c0e7b59043ffad25e17445cfbdfb3fea40e55bc7de19ac5f27c64a2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c69a00017184a13c713cc0a70e89c60174361d07dea5085fd707f4b5ed3faead", + "result" : "valid" + }, + { + "tcId" : 199, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004029e1c6eb37c383fb4e27ebb3197688f8d8af755db83b7628e17579cb3f90f058a2bf57857f5ff6331cdcf87440b6e69cc1b6e444ce540b8222b955c98a99955", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c139b75615e1010c920b07d14f6a1980ff4c97a0a9bb8a097aec2a456b6bc4ed", + "result" : "valid" + }, + { + "tcId" : 200, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043a35de213b2dc33eb348948a22ed5a93600fad071bb017a6a250e6609b13f7cafbec06b663a5f54689d0ee6709fd0da46acfd26038935935f749d6d4bc21060f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "70aab5e96e4991321faf440ca2dea861ba007df08ee46c6f579731ead51636da", + "result" : "valid" + }, + { + "tcId" : 201, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046b910d9e9943cbeff717ca9546aa5677e06118f5f04a0246b5bab73505775d65c87a4c1fd7bc584c56991119699b90b4b3a568e508eaa83f118332da9152b13a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e2ae03b844b3f279d5cd16bff20ab5cad07e4c984f21cbe73e1997a02bd2c291", + "result" : "valid" + }, + { + "tcId" : 202, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f102b90ad378725fb7ffe3fc3fe6efb320a728a03ce09a88ee25bab2cf133c04af2cfee528f3913c83504498ca8b3b6deb9e284241b8d01c678ab79ad8091888", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0aab6b19e4205548f929362e72b077f2365667bdd81d93a404343e7a5f84c6ba", + "result" : "valid" + }, + { + "tcId" : 203, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047f420fcef93b0b9d0a9f86b2c65e18938e17aa84eade2a7a6440adec914cb2f6ec1663baab8af308333399adceff908ee33c8f86b3df9ef93a51520931f851ec", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d96cdd08e6eeeca690989b659024f324e18c2faf5c50958da6985f70826095c5", + "result" : "valid" + }, + { + "tcId" : 204, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046b83adf58bbf00da4b77b6c4615925cf5a8f7b72997ad96904855490834bcf82224db940bba028dbddaf3cba949dc41b0db795515e34549fac11a183b89d5bb7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "434bd68e45630ca1b3484517da080e3c3198ddec5ef1f7e9d2e3425df214b90d", + "result" : "valid" + }, + { + "tcId" : 205, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000404102367dc53576a8385fc58ee2337e2b9af547e69934fe3ec797a84c225df0c621cecc727669f2e558762b65b33b3cf3f228fe9a9c22223ab71e77f904d6aa9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "aea47444c897f7157f336c77b7401979066d6617b59a01988f78f6c9a98feedf", + "result" : "valid" + }, + { + "tcId" : 206, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004258340105842ebe760c4fde13e31eefd52e51aaef938c4477d148bbac6d37412301f4b4d1bfe0e7046cb1f993a359f9191fd7bca7c53e039fa51db8a117efaa3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "486cf8959f7d939c4c79a0715ba7bbf0cc3fa7b2a1d60e86ad097c91e5612e24", + "result" : "valid" + }, + { + "tcId" : 207, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d9a521d8147c1e83df82b9db62b25e6ff1417ddd41aef3ffb182ad23f27822f7b0ad917462cd2a5abce2ec2c4a4f7456ebdb65db10d962056e75f6f8853d2a4c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5a1f0674b1397b6e653ff6e473d641da4fb9e7bc90a73802739a0349148500fa", + "result" : "valid" + }, + { + "tcId" : 208, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040b58006e371570686658d458f26faa34ccf8b49fba8234ebd7304cbba3ab1b2468787e9c7ea3043e0bf27aa9730a5abe473060b77c53bddc70e201d7f5b1d89c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9a907514a9ecc85f9659b9e97909a38f972b0c9a7c009778b8190438a8ebc00a", + "result" : "valid" + }, + { + "tcId" : 209, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044ab8f5ac88eecfcb0394f6cfe5528596b6b4c4fdac8247fd62957289133e620e1af51852e11b19d6137852e218fd64d2ebb567f8fa92a1ed43a5e34f5694a94b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "941685fe4de816261157b2fe3d3ac28195d81fac6225fd3103ee60a0c24df472", + "result" : "valid" + }, + { + "tcId" : 210, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004903201ba08353ba6158c06e66df0b413b771d21acc0832213bd03d589575e67677a90ccf2f3079cd2ac6c59cc0256a612c079b8a91b59ece1efd076f53bf5b04", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b203eb0365a40624a442572e0bad80e1f0c9958e5709512e76b28f4e0bfb2291", + "result" : "valid" + }, + { + "tcId" : 211, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c8021be2269a2ee83853e4a12bb0680825088d9ac0e56fb505109f4708dd9d5dd802ad690d8e8b817a815de607865afabfbed7650988f925ecf23fe5654d0c9c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e09d25f822471e647064b5b68cd2ae42d6be7b8765cdc026bb7696a524c83f49", + "result" : "valid" + }, + { + "tcId" : 212, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a53f7c412c11ad6a362bd2be2e7d1f20440297be86594abbcbea2594ddf9372379db08ad87b536939a70582682cb7570263655cc25a2979f845fd68be3d82953", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "97e3c29f69d9032e676933edb152f2438ec7dffb17641442ce9342e138f81667", + "result" : "valid" + }, + { + "tcId" : 213, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000446feed4e522963192cbd6c6edabd5175d10f93999a585a045a3026b69bb4d528ed7f6abd7b39e40e08e2126991ed410394bfdabea990abb7b2ca5eb9f048fa4f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cd7874612d68c907b434bd81bf1b1a83cf9429b24cee753cc228ecbdd6657388", + "result" : "valid" + }, + { + "tcId" : 214, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000467db11ee0b73071bf3b815864a178581ada3d100918365e7120d9bdec9cd9c3325f5eb5a1b66ad104a5c9e43b07afa4b152a75fa22a3e429af41e459e7993e45", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "621ddb1893137c12147e909dff830859dcd73ddb00acdb4097f1d66e14fe366e", + "result" : "valid" + }, + { + "tcId" : 215, + "comment" : "edge case for computation of x with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000414cdc4f16c07d6e6074caa8ecca26a0186347e723dcedf9aff9dc6fc8c3815bf5d64fe2d7e6abc20802a1c158040cebd614deda0347987e0cdcfd41e09618cf5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "19ad362ef44a36342cf9143b88470d5659fca6a3a30c904271f6d6bdc05e9407", + "result" : "valid" + }, + { + "tcId" : 216, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000424193c3501ffa77ebf1ee62f7c118b28c05a1c0a946f442b208a8305c6a745f8863603299dfdf5d2bda19230007d0e03ae61fe1caeafa584ddad4cea6dc7d76a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "43bd8cf370257bc88f38b0ded68af2f9d93977234a19fbf67abf2e0a4c09c120", + "result" : "valid" + }, + { + "tcId" : 217, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004081ceab1d3cd5317fc782c9c8dc33399705aba6899c0b804efa96ed4ee944da900adf51cd31b5000f2d175695d48a12213ae1595b98372643ec0eb400ef79d41", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9d920e7a6f61fe4140bbe56f4317e3892d21a80fb480a091a3c16a0a67a7a97d", + "result" : "valid" + }, + { + "tcId" : 218, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000413e56b207855eabb4b8a27dfe8d1ec89644be7c096f6c2f3a122c9cd0b8b508bb5b7970e3a1411f4ffe3711405ec65ef98db12a2b37d8c18c8d1984134e85492", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0796221792860298f1b4c5aa1561ec5db01ad876c3552bd96b00aa23ef47b71d", + "result" : "valid" + }, + { + "tcId" : 219, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045cf95e23e681059f008b32df326ffb7795bdf74bb337f77cff5052de7826794b5cb038ec1fdefde51f6c68dc5e12a198a51ce86b92167883687b253415d6d37a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8cec890842617de7789c3c2909e2d38031d5aad957d995bdec622b010ce9e0b7", + "result" : "valid" + }, + { + "tcId" : 220, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049c49754a4c45d97e5b70d0931b98f60b3a99f51a95497537bd85ede7e9879429dcadfe273a4086c30dde4755667923e58c463e8d94cbb7d56c9e0f4de79e6d21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1d4c7c7aa359140edf907c8234ef16b92f201f562c2237aa32adbcbdc0cabd0c", + "result" : "valid" + }, + { + "tcId" : 221, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fc7fd984dd0dc3c93846f8b41b07296ea854401325f155f1236f2e4414a9b9da473f38a5f84d08c0ac7a1dab8a568eac21066074947449a8c3d16f055a379bff", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b15134b9e91996e228ea7ba6cb4500a117983c8eeb687174657354e59961e521", + "result" : "valid" + }, + { + "tcId" : 222, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004337e2e260a3565ff81e0be900c8dafb2ce2310688c3eeb6c025cac208b08a18a4484fc5fb01c2d404da99b56a4dc226420dc3e676fd0223ba3a45d43cdcf3562", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "906acb96120ec7684e391100cf0bb747691678eb3e147f53db886ba0fc5aa70d", + "result" : "valid" + }, + { + "tcId" : 223, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e2b170d1dc4d9e329514a54f10dc81d902f3752c3a6e2f8be5d820fafefa9d8be087dbd390152ebb04c73b8c504b994a768372d3f920a5cedc4242bf834ccc6f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "73dd087b1cb3c5a07acdb9b0a4a02c64b7087ae97836e943439dbfdf41eac833", + "result" : "valid" + }, + { + "tcId" : 224, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046702ab6b257c24440bf719c02d2161e4e31e22d55ed8ad0f33e5af9568ac4a9abf87accc758577389042f5b650c37db6b0c7682203156de73728a582bed6a6d4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f73c49f6da537b2ff30ead7538c04726bc74152535d22b6baf92d06adb45e676", + "result" : "valid" + }, + { + "tcId" : 225, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040cec0aa4de0c143f5d4c3d36de3db4cd72e8fe0fbd336de879a562ac87e628d8e75d0d0ae3d7b4d869e7f6ff564e21efc30a15ff2d4c87618104fbd42ef5e00b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f4a757ceb0ba6cb9618acd8fef68d2c8fe9901fff14177f27b6e6b8c6bd34cb7", + "result" : "valid" + }, + { + "tcId" : 226, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049276151fb999ff3f7fcf542491fb62479fd1eae93fc2e7d22c38d944867c447ef0e7185e4d55a1c2eafa2cf8d262636d6e4b353fe71ae3d3cce6b158d86cf5fe", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3eb4a634d0090175347613b7eed6d49b9b5944e70acc3ed98474989d30a4c299", + "result" : "valid" + }, + { + "tcId" : 227, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e657a91abdcb67bffa8f78565ec796b4901f2991c12722d27bca6a0217f2b00c9bb2cf5f6c5780c70fa8f03159bcb0d56096aeecf53ea5e28d1058c3a50d2091", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "520dff4d04085871cff69b3a20a75b8f3b103da0e468365e8c9287c0a7ad7d9e", + "result" : "valid" + }, + { + "tcId" : 228, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047c051c1eebc76746eb267e8e91a47d8ab81b89bd3b3a9de6f1c3e6b98db81c7b75df088882150b97e20146547ee07b6b5620bcece4d40a53eeed84e5d4779a1f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c80ac13c5d2e6723e848edb023fc17ecae553781a4aac90f2577fae7511711cf", + "result" : "valid" + }, + { + "tcId" : 229, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d890400f1230fa80d8d4c95173924e9e7b3458f7e54680ab1834e505a2dccb26f714374c9978432830b8e1b82742ca86777f9b8b686b1924ee55e7c572c2b119", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0c28a9938cf095a4b0ebf3daa6a16e19e3f4199e3475ca3aa58746f651b921e", + "result" : "valid" + }, + { + "tcId" : 230, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f44866b8ee1b937d182ff79aade41b549b71ff1bfa882a192ec90dc87a51774d5e335f19880e8438b9f205932664512cd6dd53d5a40a7008fc5c98124a7d9554", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "78dbfec6b4aad2d0a99bdde7b90996324c0f7b9d136a6ede5c2995197d0d412a", + "result" : "valid" + }, + { + "tcId" : 231, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fd298ab944a08702816a7395f84e45ed782968b701838b67fa2528111cd4f4148599867c89174f00ccf30627815e6618bd2845f35819db0754180535bb4d4b2f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "36a2e77f56c3e5b11e35bf4ba5de1885cf0264643cac5d6f7bfb1ae01e39a6c0", + "result" : "valid" + }, + { + "tcId" : 232, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047b78d59967ed07c83f0ed7f8f0b26388db76b0863b64ac14b7ecbed8e3a1bda24b49dae1adf948860741376c919cfd50ffcf749672f19f78ad565e88f6096df6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9f4e92d9a959c09eeddd152f6d95ff2c3157446f477fbed214a00621d014f936", + "result" : "valid" + }, + { + "tcId" : 233, + "comment" : "edge case for computation of x with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004791c9017b3a93ca2f2d03fcf18b4230331fdc3de5785e847c9f51d22caf50cdbedc729c92f0a88233a29a2259e7e6265b92a1438c0b5959167fbe2aa4a65a6c0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d0b16561349f182ef2792d0c2dd585601ce4e032754b7628b3d801f187c14fd4", + "result" : "valid" + }, + { + "tcId" : 234, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004475786ce215a1873e04a0c67642c319a6d24dffb06a4cffbb15a8256d2c811ec5a1bba7f661e38d694d9a11564b511af6c6632a5efc933732642dd5c4928a41b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5fd6d7f0ba317a36434e1a995bed54a42898d940ee5fa4578373e8d4c23f5567", + "result" : "valid" + }, + { + "tcId" : 235, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004759ae77233b119fb3789059760112f38e8d9e69f431cf0e8f0bbe6a06e23bc5b18d69b80980f53b7e8c76c9b82dc61f05cdc03826c2c9637cc02af2a6db0e4fa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bbe559b77e83905b08954dc3736a2752d56a5bc366a5fcd84e042a78c8af68d3", + "result" : "valid" + }, + { + "tcId" : 236, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043af2b8629a3475294ee0d5437321fcd5fa4554c780b6b18b86242d3edf36f551ede37c4ea319d42f8fc3cf97cfe7dd17e85ba6e11ba260ed991c22ee891abc2b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e62429b8eb322d24e4bdb9a72bf6e9c94d82962b26d99f633e1f21709b7eddbe", + "result" : "valid" + }, + { + "tcId" : 237, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ca2df3b3d7d958b0d46ed6e0ffe3b7488f2e13660951eb821c24246d6c7f2ec2055e780e6a534f9ff469b0ba3c8d38962ac0acdc7b4b3dc057c07ead3f4b7aa0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5822c168aab9bb6ffe00b7c4c7be5551daa8304b8d2c0696e2d77fe50b9d8d8d", + "result" : "valid" + }, + { + "tcId" : 238, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ef17ac084abad12496df80d80dbe21dfade58e302ac0398002c5349d852528ccef34500266a5dd3fb454828ed85684a62e6eb142f65f5497e64d23148f757976", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bae26fa69da00aa03fd9028fa84d46b92c13d5e555b2e7b3db0d09bb95d41486", + "result" : "valid" + }, + { + "tcId" : 239, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004624cf7459a3e097f114383a125c7cdec33b947c5bc0a2679d7aae508b5d46479408cac791f2ed71d9bd594bd66f6ce70d928d3b20fe02b5b66cf743b51739a74", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "97ce8c4b6e031776b19fc7c9577cb26f085274a58407267bca35a97692a2e8e6", + "result" : "valid" + }, + { + "tcId" : 240, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e41ec556bb3f85cef6651a2db1816dab3bc82898871482dbf1cc801407ce4d1dedeafe8c33721250bf75cdb9181e990492d37080e7dab41da1673d62a8b835df", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5eb5722f98aad0622097d944bb120e09e7a122498b20ae2bfff91c8b362daad2", + "result" : "valid" + }, + { + "tcId" : 241, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b5c3cb146d30fecfd7fed0093dcba01846a28aa50c7fe3c0cf4b8c5aa837d5b0b21b7605cadbc7b6206e5dd4289e1de9cc36bc98094fb18223be636e6d36e0fa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f5c9b88d48112041334c574f93313670cdecbe0c0b6c2655778df8ff62025d3f", + "result" : "valid" + }, + { + "tcId" : 242, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b3c62848beb063fc8f285c0da7207e707c71460b8f792ae0890f2362fc8f02109cf80c0e0d75d2f54a6bffe3fef39441ed0cbf29c8397b76a824ff9ecf4c772b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "effa362fce62e271016d50a0e35c031455fca280b80ed2cce87c83e57e3cfd36", + "result" : "valid" + }, + { + "tcId" : 243, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000407ad8cd055528feb4b3a53d354c7c7cc0616ca3ff787bbb0bf79909606d27e8a70b4d271ebd8363d9ad910cf4d84e52171b5b359792f7ff8a89c4427fb6afa21", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "59b8dcdc6676029109871fc67b466a7fb622225cd6c77bbc21b1b628464798a2", + "result" : "valid" + }, + { + "tcId" : 244, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047c66fd67b79f88531a0747288726dbeb299dd8e1159612bff2d979fe4bd1060c15c54c5cf40b7a6b36f4400bdbaa2b6dd0669c3b45a55925635287116aaaff1c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "42dd3a8e14dfe9fe2ebf80746989ba66f28e5460116a02bce24c549d117d6b0f", + "result" : "valid" + }, + { + "tcId" : 245, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000494064698280e7eb6e14dd81efa9f0ab527fe6ceeded60cd4d422162c397d5bad163a63342b44629e57c09bb490118b1daf06bc0bd1de48a98ea7ac3e893e4470", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0e1025b39c5481a748a0461aa7773a6b342adead4b4587521a1953d4ff0296b", + "result" : "valid" + }, + { + "tcId" : 246, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b454039384abb191e593463976dea937428b76a2f21f8553a994e0e23a0de3282888d4e22eaa986dfcd20e5a4c9666a2a341eaadcdf86b6e137660c95561566f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9dd7118006ee56fccf307a31a6334be7e19db2deca68fd45b3f4f94f100de6a4", + "result" : "valid" + }, + { + "tcId" : 247, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d43b704bcda6ed2cd8cacd64a67191da2f68f25a6a983dd79010b1066942730f2eaa0d0933f710917e3223f2feb23388add3fed3a2a7de18af50803b0b20d6c9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1fb16336393ba603fb2eb701fed0e982ad32964afae7dbbfbc5a8112382e51e3", + "result" : "valid" + }, + { + "tcId" : 248, + "comment" : "edge case for computation of x with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049ea3db44d3c1e09715ec330d3607a06cfdc1b0baf4f570fbad15d63e1a8d190bdae78a1a46ed6fdaa02ea2785c2bad33aace95397b290eb7c26428ef68494abf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9a6d03a17e68561a105da66d2fb1d9ec9e3ca6c686f65d9da926849d7af4fcb7", + "result" : "valid" + }, + { + "tcId" : 249, + "comment" : "edge case for computation of y with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e4cb3b67d62108687c74b36a081c3adb9fc4e188b5e611727312b70886e81a795edba4df71b9c4b06f7b052b5b48d9e0be855ffcc2f27926524cb22ffbb9e865", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3c03077e0098a845f7c9b22b73eecd495a2d6a0b34d211154ee3898634f823b4", + "result" : "valid" + }, + { + "tcId" : 250, + "comment" : "edge case for computation of y with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046e833dc786039cb081ca12034adfae41e3454cad0976a09612f1af4c390d589f16f499bb679ce63d15bd4b821392e6c3deb9ac2163d0211a68a6167bcb5dd0e2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b8454bcf8463c2bd59f7538b65f11b9c98c18c13438417cc08a39c8842a0b7ed", + "result" : "valid" + }, + { + "tcId" : 251, + "comment" : "edge case for computation of y with projective coordinates", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000493b0cf66e6c51ec9f5b02589607443bab7b97b18f3dd2c9cc831c0a356b60c21f960bebf79b0c295794237c60576d6a74e5f694d9fccdc2c4a469e00b18115ac", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b4df5f335a0461a38852205ac73bc51512b5c7f6a8305f1a8d4f191cb6fd3b2a", + "result" : "valid" + }, + { + "tcId" : 252, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000467f4d7cf5b8574fa36ec8d3d4caa369efe0521ff9e25760cf99894c64f064ca34db1597fbd96d7b7e319236e0660b05800ed99099c8c1022d55be3a8fd231e96", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a9de6e92af14bf4eb11d7533bbcb28cf622ec5e52e4a2f4cde4ddc3d21babcee", + "result" : "valid" + }, + { + "tcId" : 253, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004439638adcda870137436eeb09e27c32637307921974b64b9f73e266d8e95393094cfcf350b98282437974db3e402fd86e3ebdddc5e23fcd07303a0a5cf282ba4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "edcd8e48df11aa67a90c75614983466d244e4b5473f8ac01a41c146db13c4827", + "result" : "valid" + }, + { + "tcId" : 254, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf32693dd77e182d8b2650382832f37f6770090132aa77a7ebc18215e00c44c04642ea3461ff10e2e1800dc392738d7d01174679c9d2e382a80ed4961fe48b6b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2c8dd74792ced281f9cb161d2f64d238cbac2d18f8661b0f5674d79cd5c6edb8", + "result" : "valid" + }, + { + "tcId" : 255, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d20a02a6d0424820f7c2ed6afd1b7c149f6762bf8ce4dba50ded9792368dceacc574cc6298fa1d96edd178309f7508ce8aabf69fc0c49b85299baf91239e6665", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "503fb9bf4b57b00e0c239b3e8371f24660aa01cbf79f4c499e4fe1a155528ff9", + "result" : "valid" + }, + { + "tcId" : 256, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004afd321e9ff7b24d856bf14bbc5afef1952744867cae4a9f3e38f6673da908aed714966dfee5af5b7ddfc1779db74987e9e87f532bea76a2cbed717a36c9100e7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e61ad5f80632382b626f9a77fb7f5db020dbc084c888c6b09993e12fe4d31604", + "result" : "valid" + }, + { + "tcId" : 257, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cfd6d84113fc920b44bf6d67cb841691dbae07bd6732e5dec045e60d90b98f7110cbf8c9ffaef36f3d53132b1c10db5672acd5df5b87cb98d19daf87b0de3573", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "51c10b8332b33faf529c58cc2da45a23bbfecc1d4e0aa4ea54fd819b7e31e555", + "result" : "valid" + }, + { + "tcId" : 258, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f09616827b93b6017d770c75e35b0162c5455ce2380ef2fec54e336dfe94cbbcf3d01b7b102bec4ff0245db8c943c68c23cf1172c65544aa1174e44cd524f049", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "98d67822c318db0653a470a6ed96e7c22a046a2a25664c19539af62ae1d3a96b", + "result" : "valid" + }, + { + "tcId" : 259, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bfeb62d5cdb7333e0976fad3a259ddb9cb525aeee68327657aed59285352f3476e88bc9799df4d0c142bc632c81d40486fe2376392e0180af93debcb82c639cd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7c4648cd808df9a54f992b294a3ece562ba5efbeba7e1760f1f107ed1af8c187", + "result" : "valid" + }, + { + "tcId" : 260, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046d864a7cb7f8e3a1fe1c8094e3852f8f43cc4ca6a9039512b2ade5f040e3b4237c908ec1cb9fbc1f6d49460ac19f2d4526f66e00db60d207408bd46c95bffff0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "41b89b46f018a3ac884ad921e49fcf5d9677ae84e39e6ea8de844acc337d8481", + "result" : "valid" + }, + { + "tcId" : 261, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004feb68f41e806a239f62445d23d1b925978a9b696d6f0caa9dc29f40539b073cc2c902affb20066d2c2c920ceb8a453e42cd2454988c332cf0db907bb4fe95943", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d155b0e0e37da1a19af0e85e68e7bb4180aab55b1e95501a1a3ae0cd95404aee", + "result" : "valid" + }, + { + "tcId" : 262, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000457d04c653325a6cb998f61ce347109eca0efff9a16a734134a69cd1e0b081aceb43aea4f71b1f2802fbe4107d0bfb9f6fbbda464501b87ff73c47103e372f635", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "12bd72e952e6b81255ad79af19310da2e0ef9772003384a1f35753e6beab71d6", + "result" : "valid" + }, + { + "tcId" : 263, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004605fd33a42d921e01ee7f75806106de72cb5039f65ff31d6ca2e1efd6aa81a1c95789f0923d705fd19d5a8ae18b66687cb29091e17944b37d27f398bd5546bdb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3514b8362ee1e70e846ede7ed57283f5d5891fdb9b0c5605da45dbc5c6f44e53", + "result" : "valid" + }, + { + "tcId" : 264, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004303ce896aa570cf8f97954ba48fcc25f5f252867f01a9b9edeceaa6bfccedf561134d6290e1649bb028a16c6f54eb06c7e724a947a6248274a4bf6a6aa139096", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f6c829ed9ca3dfdd1f165a204461e1c16620e752216e2b6e3aab6197f3dd2b3b", + "result" : "valid" + }, + { + "tcId" : 265, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041c2ca67311dc5c454dc830386b7997e50bc67e3d5ff522d3e8a39f144998f884862c975f548a5f55dd8504dab5c9e88f0ed3123688d475b211da5a4d6920dd63", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3719f7afe82c3fa54c0c1260476246441d387970935e4c76965ced96da3a07de", + "result" : "valid" + }, + { + "tcId" : 266, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045633cbcfdf74327de0883f59e1788eed76bb0b9e0f9e55e2769ec9aa365a30e1d913bd531f4a61c2d07b847d318ee96482d2f8fa7a12aab3b303c10851ce7fcd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0a368c74c56c61aab02440e64b2699c24cdacb4dfbcdebe0b3cf801e86f1f74f", + "result" : "valid" + }, + { + "tcId" : 267, + "comment" : "edge case for computation of y with projective coordinates in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000419d53e44b058c317fbedbf106c98f31832cdfb84f21add753cf213ba5de9026a614cf7b7b60e759a15a6c7d864eddec6dc253519975df7f3e9bc0c77fd80e510", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "de5b6c29f2f4f17f8ed925f129159410e4557dffc5472944b8862c42bd2b180a", + "result" : "valid" + }, + { + "tcId" : 268, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041c96cc2b22e5bdb195b2a47187fad5ee6736bd96dcefef20259a551e9847b5e0c5ab052c8836e4f7cc7b65545775d55b0c7b0c7f830c6539915cb624a507dbfe", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8fca30fc5d731f42d37664d52b64e022d98a25065fb1f8bd77853d7f2bbf07e0", + "result" : "valid" + }, + { + "tcId" : 269, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004733242cc4afb82271034111b81309e156ae4466e7f2fc5fc1042f4f6e3c44f435c6f614d4be18a73170c85a6b68a9614052934e1d612466dd4921989474ff513", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c9431b6deda0c9f92f368f7ca12986f0e07e012422b840c7aa784a0c713b501f", + "result" : "valid" + }, + { + "tcId" : 270, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041a24b6520af4f028824beece59b603d15d6d15cde0719ad2f7b8e3fcb6c1342c7ed702a30e875b2436db2f2d3687d9580d3bd7b3f8d1280a81071f3ccd6b407d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "672c2339e4c39e36cfe13e2cfe352859e1ef66318fe9f97dd26d9d03a9171f7f", + "result" : "valid" + }, + { + "tcId" : 271, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044ade6fa13e59117e054ac1bca3ca52f414035493ac2ee7b1a811f1fb52521e8116ad612cd7ab0c21ef78938945d870dac827becb5b873c84225c4aef159ee4bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8cd11340313b978fa37749f4b367c087fd900f17941002de22ce4029aa550e7f", + "result" : "valid" + }, + { + "tcId" : 272, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000434b2ac5a3e4916d081d1ed404b5bccfe076aa7f41e29d0362390f7f08458b44c25987b7f7a214323763e1aa1044a8779bbffc5e22be628138a1d80268364698e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6f1cc2d07f6ee07d0b138b601c94deb20aa234e526fab3ee4adc98707085a73d", + "result" : "valid" + }, + { + "tcId" : 273, + "comment" : "edge case for computation of y with projective coordinates in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000458c25f4047782b815b41001dea636c86ef19d67ec056324127225aaf6ff10832761325c4a70307dceb9bf451c7405e42580868e665f3f259995f8c358eb0799d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c2812eb9b456297572e8d870754b48489ea366f351f822759de831726815e582", + "result" : "valid" + }, + { + "tcId" : 274, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e3d05f1aff72acff70e4d51b4207880ec06b4c269db02753d6d858aa5e6d561e7c756f6b0cd106bb732e5f20c91ddde4f24a3699df1125206fcc47449abb7d1e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9cf1689a015ac3958dc95fc71cb0d103e81b4594684638933a5daaa99fb3b1fa", + "result" : "valid" + }, + { + "tcId" : 275, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000475638ca9ef9fa252429d21243c778be355bd130c1ef626593ca0c244cf2b6ef253b88766230ce8ded7900956a5291a6967c2a54279844cb07d7c585d87d40661", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2d6049f8e46c67c17ddfc8178dd918b23fd1969e11c959b64ea42e39c9a87dea", + "result" : "valid" + }, + { + "tcId" : 276, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000444682e437448730f594a820ead232c4443f7e784370bfb031304b85199c4159f7151eceaa0a698d15785cc7a2e812aeda12f9ba4238a7f5e76e930f3905015aa", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9b7f8be262b9cd2751ef8eae2bad7b1ecf07cb76613cfe7088cc9bdef1d04436", + "result" : "valid" + }, + { + "tcId" : 277, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c98b01fe92feae441d9f4de50d4dfbe9789711d911be6ef7cd9c55f4b3e8cabdd9e3aaf16605b0ab50632df6c00ec8554f36ecf427d31df930d4458fe1cbaf11", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "52980b5980df38f7c2d59e4e307da25655d50c6e030234b241c098c935a5596d", + "result" : "valid" + }, + { + "tcId" : 278, + "comment" : "edge case for computation of y with projective coordinates in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049173ae014b645724587ee26e17bfeb61f91253fe8653dafbda4381da9fa57e9815a9166e1dfc2a81cbe126a2594e51fb98fbee7b3d6588ad86a86431141444f4", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2f1f6990c30136d6f44de8145f191840c4b9efbcf87c39b7995c262bdcdf9d40", + "result" : "valid" + }, + { + "tcId" : 279, + "comment" : "point with coordinate x = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000014218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "afe5b60fe3e1dc873b3f3022893a359880e817537beb96b3d48d375766ab59e6", + "result" : "valid" + }, + { + "tcId" : 280, + "comment" : "point with coordinate x = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e4102f16fa7f386e912d3a7f77dcc7dc9f8af54cae117ddba10a3d09620eff8c689c20e12ce8f78412945e1d3acbf9935e4653fb0dce02b14a7d526a114f1387", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "33150538973510827cafdfe9449e7a5a2e1a7946f4e485a00ff219b2cd58d801", + "result" : "valid" + }, + { + "tcId" : 281, + "comment" : "point with coordinate x = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047aa67d0033226fb2b1bf975d4568e1f2299e82f2e459ff0b6ee3c0c57dbd40417c20634644993bd84aa361037ce8bf3fb72286dfdf4482458b076a7a5f46d1dd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b5523f9382b35ed9e1c4f2b420df9f61e6ac8f6d342213fa4d75458f5bd828d1", + "result" : "valid" + }, + { + "tcId" : 282, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000480694ba7d6ad6efa8ad5ce0435a1bd225e0288b6fc22a11e7013aa0d4e9a496b316d67d1c70e6c130420f57cb6e0d60cda154c737f0118007cfea5c2d5b4e397", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ad9a53d05315009fb1487369f72fdc33e6dbba1485efaede2951433526d2fd0a", + "result" : "valid" + }, + { + "tcId" : 283, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000406c66970e539d9ae0f8f67a72f426c100b3b2cf2e276e9b0aea75b4efc98832524eeab2b413ba17db811f740f9fb9fc3c73b5ce51f1e74e7e08bcd8ab48dae83", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a88cca88b59cd86edda202cb4ea1b2d541d5c8c22c062a08f9db496d56257330", + "result" : "valid" + }, + { + "tcId" : 284, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000441277a6f20d855af6acec53e9923216d74ee2aed18a4140591ebbb0b3455072669bc7f19d64647e74ff00d0c89bbfe508e322b4397ddb8564ed2832eaa5b2d92", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b7f531b4a9ac00952bfcf2cbec41e58b54c4f412f464bcf1f1bf10a24b9b1974", + "result" : "valid" + }, + { + "tcId" : 285, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004146dee2bcaa5cc0817fe191b6d10def6259df744afdc9e5b0dde523b348aaab445b1546f79b7a6aadfa547bfa416f62b54f7a476d6d888056b9c05c72e0139f1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "473473518f0e843d1fb5105b16fe88edaa418b396cab7cb5532416d171f2e7bc", + "result" : "valid" + }, + { + "tcId" : 286, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c48ee90f8fe800664086ed5ba12930cacdfa175a67a2c4398168f626699deb8dd78c35a48042aafbc6c7caf3a68385ddb5d406acee86d96403e75baffece00e3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c2563f49e623b139a83c4cb71cb73deb06458385658bf8796bac0c2ed12c8a67", + "result" : "valid" + }, + { + "tcId" : 287, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004737d92f5dad51d58261a77e755678ab02b107912041c5d295f5829cbd10cd8c59b55dd084f84937c27565a9075fe108745e17001666743db551436e691ea818d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "28c247ae91fdac1b29896415fec60f4252feed9c9ffa0216d31350d708646d89", + "result" : "valid" + }, + { + "tcId" : 288, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000459efed747303891baab0e1dfdc32d69906e0fc6815b056dae0eda2080957a3ebf205fd299c63e549d24c153935d950141c3dc2699afe8731a46304e203cac15d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "76e9e6f1339bff54b82a45980745526ff9249e942b1f836aab719fd959fc8099", + "result" : "valid" + }, + { + "tcId" : 289, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048ef9a7997b717fdbc5d2a7f9a67f705e5dee4c82ca383b7ee2d07c24850396d072c98f7dc1658f9dc3c434a9fddc2f986cc0e3e3ef409827537617ee67105f2b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0de82177c80f4e35f3b7a300e89ac288f30e01a8658933c16b8c90605e35d6c7", + "result" : "valid" + }, + { + "tcId" : 290, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000404569ec9fb3d6bcedc059e7fd04ab7d3f6bac730b1b75a11749e4346458f9296a051c84d558dbd2957c15907477776af660ac01582c001dc1f868ebfc6b3b264", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f41de3a77597835fa904d1f05411368e6e878abd0485477d162b2c764ef045ac", + "result" : "valid" + }, + { + "tcId" : 291, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044b298a3eba6a09fcd8415976e0faea997fd519ffd3363bd20107752123e101466abb70c013ba2389c371be19dd3296f0600e64f05755e15cf89320ac7ffb25d6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c4dbe3b94e729b1e0ae34ffb0f6b0d95d7e619ab3943aa3836cf1e721a470a9e", + "result" : "valid" + }, + { + "tcId" : 292, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000418bde07952d7be8914d2b2544c65a3debdddd9e7ce8a9c46a03d124acfb8548b01a4a175a2a81af98e6028770d055e22f1016df15462b65f55a2d4850cc415e5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "83b31061f1b70148870a9282a4641cc8428943a3b10e0301955f5960c386fb04", + "result" : "valid" + }, + { + "tcId" : 293, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004002beb755f694a09f60bce5b34dc347c5c3aa236de9007bcdd0707e9bc8071694f443b0045999f2f5899ca793424a9b423b0ec0a3edcbbf4afb9e66526cf89b2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5f74c066595fe9ea283274964ae83fba1a73ef9d29d24e6604a4aa0881fe390d", + "result" : "valid" + }, + { + "tcId" : 294, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004957e5bcd11fc450bffcefe636c0b73f10fe8585e04c6c7aa7fa0b603d24162d99e553e940956aa04a237a0c2570a0c7bc3712172b8f78c7b470a042ae31f3223", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c672601d951bdb550ea9cc58d2031337db39a3799de21af4e5c23e2fd7f537da", + "result" : "valid" + }, + { + "tcId" : 295, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c43b1b4099da70f8d33fbb61b68d9b0e9c7aedd4f4761c6722996666974e298e978c02ea7899cdd46a47405ac0d89fd6a4d66718a4502438ad45463260976841", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b2c2c00532d468d25374ae2e6ec9bc52bcb2e8df20ad1a40719b7d91746daeab", + "result" : "valid" + }, + { + "tcId" : 296, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004deb85f604be1930dbac6629cb96210f6fbc87ce2b260b66cc7d661861806afe1120bbcf8356dcfbf1de4bbb7d2066c3dddfbaf330af754c57859137a9cc4a68e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e5fe7c96371878cf86db4210a487d7d33ac4bcc45b8df2152e82aa7228a991e2", + "result" : "valid" + }, + { + "tcId" : 297, + "comment" : "point with coordinate x = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000427899fe24811adc869d49ac451cb210631d19aff8971ac7c3dd2fe826262507fd9ddffef4cc9cd81bdd3eab8acdd5c287a8934f82dfc255dded1ac1f1100aa17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1bb9a501ab9d215230cd1072042b3c8271aec3b2c1da10d1a8c810fceaed47a4", + "result" : "valid" + }, + { + "tcId" : 298, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044301f54b3592d1ea2a40989c94261d2b1d1fe297ed6ed64125ee241de05d004bc79014f156e9b7bfb36b8ad2d66d55f3a753829a9ddb86055bb9166dd3aff457", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "fdc15a26abbade3416e1201a6d737128a2f897f0d88108645453a1b3ddd05688", + "result" : "valid" + }, + { + "tcId" : 299, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000436b0f66bf5f9fd4b2df9cdae2af873a075c55497d7fec4737a7c9643c2c76fe5da9f7287b3cd4e5f05b9a1a4f64e8a8d96c316e452594d02a4592a2107ece90b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e36348e3a464bc518384806c548e156edd994cb6946473c265a24914d5559f1c", + "result" : "valid" + }, + { + "tcId" : 300, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000482abb58afb62d261878bdee12664df1499b824f1d60fb02811642cb02f4aff5d30719835d96f32dc03c49d815ffa21285733137f507ce316cec65ca562ce2ad0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7d65684bdce4ac95db002fba350dc89d0d0fc9e12260d01868543f2a6c8c5b8d", + "result" : "valid" + }, + { + "tcId" : 301, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047de7b7cf5c5ff4240daf31a50ac6cf6b169aad07d2c5936c73b83ee3987e22a1940c1bd78e4be6692585c99dc92b47671e2ccbcf12a9a9854c6607f98213c108", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6ec6ba2374ab0a9ae663f3f73671158aaabac3ac689d6c2702ebdf4186597a85", + "result" : "valid" + }, + { + "tcId" : 302, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000406fa93527294c8533aa401ce4e6c8aeb05a6921bc48798a8e20a0f84a5085af4ec4828f8394d22de43043117b8595fb113245f7285cb35439389e8547a105039", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6d6e87787d0a947ecfbf7962142fde8ff9b590e472c0c46bbc5d39020e4f78a7", + "result" : "valid" + }, + { + "tcId" : 303, + "comment" : "point with coordinate x = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048a4f625210b448dc846ad2399b31cd1bc3f1788c7bed69cc1cb7aac8ab28d5393007c6f11f3e248de651c6622de308ee5576be84ef1ed8ed91fd244f14fc2053", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "56ea4382f8e1abfcb211989f500676449abcebfe2cd2204dd8923deb530a6c7b", + "result" : "valid" + }, + { + "tcId" : 304, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004885e452cbb0e4b2a9768b7596c153198a922dabbb8d0ca1dc3faf4f097f09113be9aaa630918d5056053ecf7388f448b912d9ccfbed80d7ca23c0e7991a34901", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2c362c27b3107ea8a042c05cc50c4a8ddaae8cdc33d058492951a03f8d8f8194", + "result" : "valid" + }, + { + "tcId" : 305, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e226df1fcf7c137a41c920ff74d6204faa2093eeffc4a9ee0a23fb2e994041c3457107442cc4b3af631c4dfb5f53e2c5608bed04ff6653b771f7cd4670f81034", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0188da289ce8974a4f44520960fae8b353750aca789272e9f90d1215bacdd870", + "result" : "valid" + }, + { + "tcId" : 306, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f53ead9575eebba3b0eb0d033acb7e99388e8590b4ad2db5ea4f6bd9bde16995b5f3ab15f973ca9e3aa9dfe2914eebbd2e11010b455513907908800396fb9d1a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f78bd7ff899c81b866be17c0a94bec592838d78d1f0c0cf532829b6c464c28ac", + "result" : "valid" + }, + { + "tcId" : 307, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004882773ec7e10605c8f9e2e3b8700943be26bcc4c9d1fedf2bdcfb36994f23c7f8e5d05b2fdd2954b6188736ebe3f5646602a58d978b716b5304ea56777691db3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "99f6151fba28067eac73354920fcc1fa17fea63225a583323cb6c3d4054ecaca", + "result" : "valid" + }, + { + "tcId" : 308, + "comment" : "point with coordinate x = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a60b6458256b38d4644451b490bd357feade7bb6b8453c1fc89794d5a45f768d81eee90548a59e5d2cecd72d4b0b5e6574d65a9d837c7c590d1d125ee37c4d51", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "68ca39de0cec2297529f56876bc3de7be370f300e87c2b09cdbb5120382d6977", + "result" : "valid" + }, + { + "tcId" : 309, + "comment" : "point with coordinate x = 2", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004000000000000000000000000000000000000000000000000000000000000000266fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1af254af90c16dbd217f3356f7fef9ad532d4902a6d67218e3188a9e840fc929", + "result" : "valid" + }, + { + "tcId" : 310, + "comment" : "point with coordinate x = 2", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000452d9a44bf0bc729e5f3ffc8a73a4da332e2962b22013391b60eb66de6e1b83431eb0d9c6e92a424bc24ab23caf99e3cda830263689653626f8be91590fb75cbd", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9e232223afd0d57a7b150f65700ac60a78bae2aafc0cf9d1a820452ca1e57a14", + "result" : "valid" + }, + { + "tcId" : 311, + "comment" : "point with coordinate x = 2", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000478a99dfcb7df4d9277f97b5e24e979f48a8aa8983ef9dd86765dccc33d8ade9f9857dccce2a7ff0ac41b255eb8df45df61b4db58fb5e997614bf0d5ab217dd90", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ec2f7542cc1df665764c5b9bff751208d668be9f3d61cd6c33b35ed0f4fe5a17", + "result" : "valid" + }, + { + "tcId" : 312, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041162424aa9fa0d42bf60e06a16b7e7ea45ac0e2f07f1e36735bd0d98c70b8850693f2ac128f47f213322c5f8872dde9261affe614e3f364a792d17b0e8421840", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b095e9c2f933a00053a95758dc20fe1e72a798462f90fd67fafbbd68d761dd67", + "result" : "valid" + }, + { + "tcId" : 313, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000430d2d42a85385b64817d0900bc8c984716934529056da032d5fde844915d669b0e5ef40d566f5b23992132c4ae588017ebd160e5dbf4804f936cb0f257a93446", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "95484c5554b543f8eb2fc218cc46ffe648a3bfac41e6dfafca1ba11f8c53ed6e", + "result" : "valid" + }, + { + "tcId" : 314, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a77a259a55ed98d643e1a3e13804c95e543c1557e6141e4ed47dcf13b941a6fa8bfa5f879ab14aeba7b2ac06e5a719c86f4a2ed391160380aa3b6f74141cd354", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f22ebb6843281b54b22a9ff1a91485c7db8f95db4bf8a1131f892b3bfce56662", + "result" : "valid" + }, + { + "tcId" : 315, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f89454593dba5720164d17bc1ca32f10ddd1a7d37b7bf02e5ec0d59794f4d63d34268de3f6a2c108514a52702f7e67d27829fa0340b3c4710651291483c8b213", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "99623d9f447b66cb322488ea463b3e40d5620f4df78f89c62fe0ba8b90ff386e", + "result" : "valid" + }, + { + "tcId" : 316, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b00befcb868eeb5d558ef2ec2ec679dc082ec15a57c5899311178424674b8f50588742728a6384a180506b8739a79c4ce95e1055c0d0eab2254ca55b18a3e7b2", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d611afb4046c9f4b2887b7dd4d45b80e9584eca93f5a855dc30e529eedbf5017", + "result" : "valid" + }, + { + "tcId" : 317, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b3e2f9c7f9f068c5da8882fd581e7112e538aa01feb5f017433c00fc8a828fccc56a3f692e3b237b7caf49869009e6743e35ec5aed19d814cfc13869f78eb895", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0438085ab0104fb47c696be5c08f95e319ed5507ab781fe1cdccd6ddb34bda67", + "result" : "valid" + }, + { + "tcId" : 318, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e5dae9779e0c168e60b842508e253d2ac80e7e504daed9fac077b9b449c368b57bd8661bbbccef478f050f4ffec8aa47ed7f98e89514d9083facf0a7f2f7b70f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "326dbabffe17c6efc710bdb8d04d16c8624c083d48bfa6e4411d221264d8277f", + "result" : "valid" + }, + { + "tcId" : 319, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004420e10bb81b379d728879fe600e6f1bf2b85d8023848a040c7654a9734da1ac4cbee561571a616b094a38436e02c6d7b54b4279a234193a828e86e21e6b71d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f47a91e29ebe69baab6b340bb64a6dc34fca7546fd6eba53f5bbe41f6178c7c6", + "result" : "valid" + }, + { + "tcId" : 320, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048dbf1ba87597004af552317225916abf3d71dff90fe9e61f9d2863a6de218d4a0897e334000139b0849d772757b150e5d86b55d7a00a744bccbb7cb8d1a6b07b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cf83319c735348dd13c44b055f67a292f7afc5d9d2bd0706c966ad765368d422", + "result" : "valid" + }, + { + "tcId" : 321, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041accb85b612d32d58459caec0bb6768f05ce8094e3862422a7c12340dd31bd7397e0377d33ccdce8bd872f898be6cbcf7274b3beefb5dd7cadddf027d0c02c2e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "41ee7801ccb702f2f633d1d0ec20d7c427936886df89ad33d19dbb56f66a2656", + "result" : "valid" + }, + { + "tcId" : 322, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000414eef41b67c17b1d4a040554287cd6a9e6b3080335ea4e16821dbd643ec67dba6d67cadcbd1a3f0227b7caf2c0604d2b3507aeb96ed98c32e2350fe295ed8998", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "af828d6bc21ad6b4570b5f68a6208d3a2f46edca69b1980fe5046792c68cab80", + "result" : "valid" + }, + { + "tcId" : 323, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a99af5dec3c995080ddcc15d7994daff266aa53f181fba4bcdd504d206bfca2f3739588f071e4192b615361ec81735fe2ef2923c4056c432f4c2782e5d722215", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4ebf7f174cdb3fda94f99698317ffef5f4d4fb933f3292f1aaa782c354ba03e7", + "result" : "valid" + }, + { + "tcId" : 324, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a355d8d17d50f6428e0af345921662587e2b6249eed1e326abb7c8605036b1db1fd72efaca9082bb6fab44359fa7f6ef8a45d036852832e2ade9d41f28219144", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1649f83c47a6640a94b773ab4309bd6964109433e3f3ee5b024d1915ef5139de", + "result" : "valid" + }, + { + "tcId" : 325, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fa53e5b58d55ebf517d8db07b021d80918d1f260f9e0b3d00bd47b24a91ae6ab85ab2adcc31b98caaec2681a841d50bc0eda875561fab70c979463ffb6a1d74c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f434c3ffe109528456c23d6cfe51ec0b10be606d7a26775fe2ff0a9b18f92f39", + "result" : "valid" + }, + { + "tcId" : 326, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000433fe37949375debd9734f54b7036b7a978bc8fc4ae3fe927a521f940d9e35dd38f81a9160c05df04e34290db40c3e045b832373941ca85b433854e43caed323d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bd02b9dfc8ef760708950bd972f2dc244893b61b6b46c3b19be1b2da7b034ac5", + "result" : "valid" + }, + { + "tcId" : 327, + "comment" : "point with coordinate x = 2 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b9ba8445067d0e81bd32dd99e6b4ea3d442d063a8eb9873518ee3bb18c053706099964b6889105784d9d6d9d9aa79c76b6a3d3376315953afdcb5a7439e7c706", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "412269bfc15d8b1fd7f25de33b1515ea67f2194e73ba06c85ef99bb42722f95d", + "result" : "valid" + }, + { + "tcId" : 328, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000478b248634270a7a6640bd0c64595dc4e98adfe6bdb8112593a4173e36d4a9b4969a1f3d19b325898e36459c41eba1de99229b0ba2cf1337461c84391d9aea1fc", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0ad7556a621074a771bf129163d09a2e9d2e174f2b8a4b6973e89ea138c9a603", + "result" : "valid" + }, + { + "tcId" : 329, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c788884ac868593db241f5b3ea7013810d3ce28a02680a96ff357b261fad611bef353b0e82c1c68c471ff1ed5c4749e168e7af8591a5e6dab599b96620de0ede", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "76acc74dd60872ab29e1bcb99dd46365c7c7f792619c901c7ba5c68378b233f5", + "result" : "valid" + }, + { + "tcId" : 330, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041864e373ac60c23543fea9e1f237950a8169e07c817db69d500e5592d1df9d5a10da4651efccc46d37e7eae16c36ac86a9a86b88ad08751a8dcd15060019704b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "50e23b94fcc33d93dbcd71e955e195fe0bf6ac9b04b15f001e53b5dc7bad158e", + "result" : "valid" + }, + { + "tcId" : 331, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dd7308d2a6757f924dc979066e75ee6fa52b03393d2892f59788effa553b690d1fef00c1c22ba80b95d529782dbef55a63046179fb4ef00fdccf5b62ce55c136", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3324bf2fb3486b1104fffa35ef38975faffba1ebe42c54399206face505448c7", + "result" : "valid" + }, + { + "tcId" : 332, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004575d51be2bddf5bf1ab42431ba7e3b5f2947bc574df9f60a448b8db5ca28c92cd836f55c556440a7df125de6599b21ae68f15d5b9f422d6eec88ab2f65406bf9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "235fd3e7216c92f73860f0ac0121b4264ff89d80bc75d59dd455298597c5f2ec", + "result" : "valid" + }, + { + "tcId" : 333, + "comment" : "point with coordinate x = 2 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c7422a80aebdb518bd2daba691d39a25ea2fe49a35cdfb2a0f94bdfbadc6629ae55ac7c400afd2976b7c3b24f7126807a5a0afb931cfa5c6ada1f4ff984ea5a7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0bf758de27052319dac39b324a6ea55e928603a3ef9049ad147f8ca35f55b656", + "result" : "valid" + }, + { + "tcId" : 334, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ad4062216f84ffd66e326497bcbcab982283493392ec0f739cef8cd7eaf3453414c5a289a846e28bf2042ea5dc7b15e252f48d3cf980e7c4751cc35493a1c328", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "312eeaaee397224fc17dec7191ce69cef40e8fb373516c2b1edada0336c99c13", + "result" : "valid" + }, + { + "tcId" : 335, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ccacd1bf7c7f4ea9c7e59bd802804a9d335262716ac288c6eefd7a7135349a4f7b8612e2bdbd43b3fc4fa6941ac15a8f37e34fe7810a0c0d43c05afafb6480ef", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "aa1691858e6a1a06c6df57ce10a4c730974c06d1e0106d1a31b51b915cd6b60e", + "result" : "valid" + }, + { + "tcId" : 336, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049aa7f1f93474fa370c4df3805bd2839328895880dce197a06cf9052e6ab7a6938c9a208b335bfda6b01321f029a0d83c8bb96561208481f7af6c6cf1d2657843", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5786d6ea09ffb21a63adb020b117096484ef995e8c4a72afa479cba95c959920", + "result" : "valid" + }, + { + "tcId" : 337, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000483b7affcec11685d15614e2d53c1e73504e3d98344bbd5fc0ad86dc4c36704323a7f73a09533d1a1076aa9c4af22a6bab92f3f0d766798db7aa4183c037f86e6", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ae0c7845b82995263c51e13e297412d17b650aa83dce4f55a069dbee671c16b8", + "result" : "valid" + }, + { + "tcId" : 338, + "comment" : "point with coordinate x = 2 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aeebdd971cf4e988fabd8070c75c64aab90a83a36735fecfb385605979c008ae8c39888f0daf74f98cebbb08f6b91a5193f684a56761b9f2b63d87d3f60491ed", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e5e764a38b73816f6e11e7cf298b2be54d11249c615f0a71498a0a821b5736bb", + "result" : "valid" + }, + { + "tcId" : 339, + "comment" : "point with coordinate x = 3", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000032f233395c8b07a3834a0e59bda43944b5df378852e560ebc0f22877e9f49bb4b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "6aa7e74a7a838efa9607f3587d4117f1914c57fa924b441c27fb7a7c31fbaac4", + "result" : "valid" + }, + { + "tcId" : 340, + "comment" : "point with coordinate x = 3", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e38eec4c1a4d81a5d994b0d7780305af651892cbf07f3a07628f4e2473a8ab754bda96622462880d3536d390132a85db6147f814c62efb580a6f529598b0dd1e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "391b624f28eb398156666dbec1d635f8ff1753eb86297973a1c2831b1091e2df", + "result" : "valid" + }, + { + "tcId" : 341, + "comment" : "point with coordinate x = 3", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000410f02d496e9a8758c831389892a45ed009282ea1eb201ab8caf09e6f2de9fa4acc126becc204c41a94aff4f2ead7552ec23fc68f0005147625a95622b521090d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e3f39d071b743c8041454d1dacba93dc9f3f12a5ae1bfbebaa59fc4cefee6b82", + "result" : "valid" + }, + { + "tcId" : 342, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044c859aff342c56a9508b859ab1509edcabf66e044e2026cc293474389b3d58c16bc06cf99dd6d8249c5d24386a55a97214ea0cda270ad9470986c3a3d023cb07", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "09d0d1b92af1e7111d223bf5efcdfa6df2622ab3cf161af0ebbf06ad00c09b6e", + "result" : "valid" + }, + { + "tcId" : 343, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1eb4f7c680a247a14f3d67f85cdb1c4c6f13d44821fc456c9247a606622afec4952cf05ff06f06d7030e88904737096cbf8dd90e478a3b5dfed2ee487a0835c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a738727e0f5b20448009d1029ca727f2380d2c6e152a6e2da8ea50531ce39499", + "result" : "valid" + }, + { + "tcId" : 344, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043bf79d6c1a20d85115e973079707f5131eed2f83be5683c34d0fb3eee1ae40dfd2ea4f1b735cf62341835a5721c25daa0dc1a3886ab75ef653f472d8f3aa1e97", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a314e4ee9e303d970b4e9f0cdc262657d5c5192f055466b9d09d9c888d6b7256", + "result" : "valid" + }, + { + "tcId" : 345, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b1f808286a42eeee85d585e54dc28aba2aebfb956805f5c01127bcdf435154cb5b178fda5896d9e7508661fee7ee55fa9623610b3d9f4a59156b76d8877b4ef1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8f4e1bf8e5182a1fbcdeac924df1ba2f937162d48a206783c48132cb582c07db", + "result" : "valid" + }, + { + "tcId" : 346, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a21e80d09e11acbccbc909de6c9f1159addbb5dd477211b90a370f8c7548e60d1d7aacb6e455bcdc230331d79ad9464a77b702c858400900cb4488cb6c28bd61", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "16682c862cf53755b3c28adf7de052d5cf0e81e5d8acb346702a392bc6b2b1d5", + "result" : "valid" + }, + { + "tcId" : 347, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045055a8c45e81385f4144c7b6fb32119395a94dbd07665ed7bc1cce1e62dc47c8b6d50a39a55d3b8e996624fb6ec2f2960c7c2bc0bc94b2a63d65096fd99ca41a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cc33e840b5354bf6e088047e76dc168f15c0c1aa946731600f52d6f1c9299b27", + "result" : "valid" + }, + { + "tcId" : 348, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004af522fc0a61440173945b914d6404b1940b547a6f768550280fe28bd331c9c661d282429f2911298f9c5b82f87c7f5044706748c19035689b216d64474bf5ad0", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d7b4f5e2dd1ebecfc92318d92085271be482fe65a03e83b2e358a397a597449b", + "result" : "valid" + }, + { + "tcId" : 349, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ec1a88652de714d21fddb54db4a3423521aead5828b843bdde9a42cf4a8bf124a69568c664e2d9317ac732c98c435548dcec0eeb8ab31027ee5f1693ccd97c68", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1d88ed8e4579a4c62fed95eafe1528f8d5056041fc41f3ef063605ddc980ee09", + "result" : "valid" + }, + { + "tcId" : 350, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000448e4c9cc88a601eb639f81ffa679540bf1d7bcbe876a955e73bfade055384160bae130243ef5fd328f65278e00cad6001327ab42fdf3b9654aad6f260542b02b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a6698578650dadb452d677c3983e6b809152d7d2d8fba349cec686e72e6f8693", + "result" : "valid" + }, + { + "tcId" : 351, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e861379f1c1b07540155bbfef4a69a84be81b1441d43e7850c7ac1005a804238bb33c7981d383a06d1b795552a7b31f49145fba937876fdc9f0d138aa5b3f322", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8e42c38902b25fa138b95f4f280b684c09e1212c4f06a2bc2c2b2b8790112034", + "result" : "valid" + }, + { + "tcId" : 352, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b4489cd499168bd48cd2c31167edad246c63859bf8b48398617a7a0556341e3c0b0f66f665038baa29db8c296d4f2ae07b9ab9193bfc00981d7df0599ce0648d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a19f1165d31c1695359929deebcd24846ccb9a3c2a38c10bdc7c855bf8a32df7", + "result" : "valid" + }, + { + "tcId" : 353, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004884e74885ea450f5aab0cc8f06c006630e8b183a06bda509322fcd97ba5d2d2b00e1373d533bd5920427d106b7f33eeb53d21b5cf46ca0151e91859e811a39cb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0a87935c036de666b7619f14ec58f9f78698cc23a667616f84c177f34661ebe2", + "result" : "valid" + }, + { + "tcId" : 354, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c50224a8cf3a19da6133e746d00217285df85589ed334b54d95b005b8f033f7df7bc6a5ddc59d033f0c66bed57149a160f25723117a2fcd413aff8c9ada43bf9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "90accd1c3af1cd782ea1e864a307aaef6a01fd3a6305a0adae37e76844b9ce10", + "result" : "valid" + }, + { + "tcId" : 355, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c66a917fc435c9f41c47428e718a3017b3c5c992b4d94a663602f73fd825d043a03cb9f58174cffb359e2f541cfb5e551c50fd811b82362eadb216a4cfd0f8c3", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e164d88fcbd1ccdd654de0415bfbd2a171590713015f4a1755504e62f7a03870", + "result" : "valid" + }, + { + "tcId" : 356, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004f55a451e6e0d8f7600c7bf7c05741c5e5985b8ffe4eab62d4ffc04aedb725a66e942cf486efcf3b85488cf3cd4fb0248b820703b938ce77a074a2f9286af03bf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d4b6d4251ac1f8a0b0c75bbac3517a13ea0c857b5499b03d153be663a8715480", + "result" : "valid" + }, + { + "tcId" : 357, + "comment" : "point with coordinate x = 3 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a96aa25bee8c8cb6f6aaf40be98ca047da245e8d4cae28fc892a0369b299cba3ef5f54bb59f4ad58a84332a00d89a1cf3d56c4e6ec9c3a467a4a2a04ad3bce97", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f5270d0c4119f1ef467a37501688b4bf4a516e5f58a0f5a40f23ae70ee813c26", + "result" : "valid" + }, + { + "tcId" : 358, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000449f572fa8cdf6750adabc3ab0e46bf23dd7ad7114bf319f35afa6a2ccbe2e7d343c44f018f8efc9f52691b274a8c89283d13ce93d1b58aea11d62c88599c309c", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "1763eb5bd3677de88e98aad84038838422d6e55605a14761788cf305672eb670", + "result" : "valid" + }, + { + "tcId" : 359, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b36f6b02bf1d213d9abcfc98c25fc81ab3b98cb13d678da871310aa093ab7b58a50b134818321a48ffc1ef9f8624e371ddf078d8983fda6c4eb27dfb255174e9", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "98c95ef9fded241da09392573144daf44b0332518f458167e09d672011ea4618", + "result" : "valid" + }, + { + "tcId" : 360, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000474f57ff3da8d60ec0b382e6866be4502f695688384b405e2179aab61066196d7d24064185d68de95bd72b219c0c0a93879324f299fb19214b33a3ed2f1bf4823", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b0fe8fc6abe853b1ea6aa4f4b4490bcd94ffd3532c1d7cce36d059ac8f29cd67", + "result" : "valid" + }, + { + "tcId" : 361, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004924fe3439d35427e2ad9b1f6e67877ed3441d74bdd0eb9f82ae360434bc20624537e3400007cd2d140f2caa0f7b61c7118abb9ac5c766ecab3f8f72ea5d96cdf", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4fdc7cc04b2459f73c856023e892699b9018baca1b8e3b040ec74324607c97c5", + "result" : "valid" + }, + { + "tcId" : 362, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fb0e48a3815a2b80e9e725036a239757e9c5987850a941c5f5d2b89b776aac683adb5481fcd85f0013feb20505ebbaff27edf8474a7cf4d985ec567365ecbc1d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "561138979956fe6a1aeae06277456c7e5e7e7d643910e247fb248dd7435691a0", + "result" : "valid" + }, + { + "tcId" : 363, + "comment" : "point with coordinate x = 3 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e669915ee160694e8559d7965f7cff945c1cb076f194ec9894b1a38b10726fb0389675e3155b069b3862da3d1112179a04accbe7dbb70b3cc48bedb7591d2eac", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "06c06abb603bff68f356ce496c17fcd0662fa040eb0cd45a98112e6c1eea11db", + "result" : "valid" + }, + { + "tcId" : 364, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b760dfff4c5c200aec18b930b18df34297bb421b96017ef902139fe6b12349f6ccb8cf83d2837c7520300f197b491c0368470ee86f74ca0381682bb6ad80344f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "319297f77a75381b65d73107e826eea0e69d85985db4568fea21d12dda696921", + "result" : "valid" + }, + { + "tcId" : 365, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b0e4de914fe71b61636e61391528efac8b6c11edcd41c9766af8693dbb6e41f2517293725552f22dd6e1db7c2c243f80c10713f6aa48fc5e395bd9ec51f1e9c5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c3ef6eb91aad69456ede5174b0e5e3d6863c024aef3185d2258946362903e576", + "result" : "valid" + }, + { + "tcId" : 366, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048eb6ee2ee9e061acb9312ad015b1954ea47ca304a2cebb77f3bf6c78678c1149d93fc6e80561f3110fd0e95fdc0ce8da2c3f32f7f581f9b666d74900b3760b9f", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a18b1fba4d496419ede70cc23ceed674526f34299e5b09c0ee2dd1669693fef9", + "result" : "valid" + }, + { + "tcId" : 367, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000490121021546a96e7879d53e7b85c21f4047df49b9ad85020104f216d010f520d1bba6e765742395b4c894fd0eaaf87275d1c77494c01cce882de2805d1922c0b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9fc7fff3bb4d6e5a4d52eb0e3c513a3c9fa56014c030449546cda744aa126f6e", + "result" : "valid" + }, + { + "tcId" : 368, + "comment" : "point with coordinate x = 3 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000464c1712e3e9ef440c7ea8faf0540d2e6a05adccbd53a7fb24ff16a9502a818f747cfafd2209430eb7794f5da91d6c5e2db505ba287bc6ef397bf7f30c747536a", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "61cb2fb99b695ecbaf91a95e6e0c7e24633bc7613ebf518c6f1c8161dc75ea5f", + "result" : "valid" + }, + { + "tcId" : 369, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cbb0deab125754f1fdb2038b0434ed9cb3fb53ab735391129994a535d925f6730000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "af306c993dee0dcfc441ebe53360b569e21f186052db8197f4a124fa77b98148", + "result" : "valid" + }, + { + "tcId" : 370, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000424800deac3fe4c765b6dec80ea299d771ada4f30e4e156b3acb720dba37394715fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "aa7fc9fe60445eac2451ec24c1a44909842fa14025f2a1d3dd7f31019f962be5", + "result" : "valid" + }, + { + "tcId" : 371, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048f33652f5bda2c32953ebf2d2eca95e05b17c8ab7d99601bee445df844d46a369cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "082a43a8417782a795c8d4c70f43edcabbc245a8820ac01be90c1acf0343ba91", + "result" : "valid" + }, + { + "tcId" : 372, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004146d3b65add9f54ccca28533c88e2cbc63f7443e1658783ab41f8ef97c2a10b50000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "70810b4780a63c860427d3a0269f6c9d3c2ea33494c50e58a20b9480034bc7a0", + "result" : "valid" + }, + { + "tcId" : 373, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b0344418a4504c07e7921ed9f00714b5d390e5cb5e793bb1465f73174f6c26fe5fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a7d34ee25fbb354f8638d31850dab41e4b086886f7ed3f2d6e035bceb8cab8a0", + "result" : "valid" + }, + { + "tcId" : 374, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048a98c1bc6be75c5796be4b29dd885c3485e75e37b4ccac9b37251e67175ff0d69cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3f09cbc12ed1701f59dd5aa83daef5e6676adf7fd235c53f69aeb5d5b67799e0", + "result" : "valid" + }, + { + "tcId" : 375, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041fe1e5ef3fceb5c135ab7741333ce5a6e80d68167653f6b2b24bcbcfaaaff5070000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e04e881f416bb5aa3796407aa5ffddf8e1b2446b185f700f6953468384faaf76", + "result" : "valid" + }, + { + "tcId" : 376, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042b4badfc97b16781bcfff4a525cf4dd31194cb03bca56d9b0ce96c0c0d2040c05fe4c64bb0648e26d05cb9cc98ac86d4e97b8bf12f92b9b2fdc3aecd8ea6648b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "adace71f40006c04557540c2ed8102d830c7f638e2201efeb47d732da79f13d9", + "result" : "valid" + }, + { + "tcId" : 377, + "comment" : "point with coordinate y = 1", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e633d914383e7775d402f5a8f3ad0deb1f00d91ccd99f348da96839ea3cb9d529cf5ac007711bdbe5c0333dc0c0636a64823ee48019464940d1f27e05c4208de", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b8cbf0968fb70d391059d090b30d1c4edcd2dad7abbf7aa4ad452f5a4644a7be", + "result" : "valid" + }, + { + "tcId" : 378, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d1c1b509c9ddb76221a066a22a3c333fee5e1d2d1a4babde4a1d33ec247a7ea30162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "07257245da4bc26696e245531c7a97c2b529f1ca2d8c051626520e6b83d7faf2", + "result" : "valid" + }, + { + "tcId" : 379, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004755d8845e7b4fd270353f6999e97242224015527bf3f94cc2c693d1b6ba12298604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d6aa401b9ce17ecf7dd7b0861dfeb36bb1749d12533991e66c0d942281ae13ab", + "result" : "valid" + }, + { + "tcId" : 380, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c6f9fc8644ba5c9ea9beb12ce2cb911c5487e8b1be91d5a168318f4ae44d66807bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f43bfe4eccc24ebf6e36c5bcaca47b770c17bcb59ea788b15c74ae6c9dd055a1", + "result" : "valid" + }, + { + "tcId" : 381, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d3179fce5781d0c49ce8480a811f6f08e3f123d9f6010fbf619b5d868a8ea833ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "009bc3abb3cf0aca214f0e8db5088d520b3d4aadb1d44c4a2be7f031461c9420", + "result" : "valid" + }, + { + "tcId" : 382, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049e098095463c91ac7107a920ccb276d45e1f7240ef2b93b957ee09393d32e001503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8bcb07a3d0fa82af60c88a8d67810ebca0ea27548384e96d3483310212219312", + "result" : "valid" + }, + { + "tcId" : 383, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bf3034a9935182da362570315011544ac2ce8a9c22777c2fc767ac9c5c0daeebcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a09ddc7cfe023acd9571ef0754010289c804678c043f900f2691dd801b942ed4", + "result" : "valid" + }, + { + "tcId" : 384, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004709c7179c2bb27ce3985ba42feb870f069dacead9294c80557be882fb57790481e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "da98054d51ac9615e9d4f5ceda1f1bad40302ac11603431efec13ab50e32fcf2", + "result" : "valid" + }, + { + "tcId" : 385, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004264c00a2d92514a6dbe655de3c71a5740cec4fcb251aa48ca6745dbea6f5f7cfc1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d60795d8f310b155726534b8be3d0b8a7bc2ced468c6e64c8b9ae087b33ee00b", + "result" : "valid" + }, + { + "tcId" : 386, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a12124606bcbbb33cecec7fc8d78b3897192ca851560c539e47dd276c63bd3c2f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "675fef8f5680bf76220e91362613944099046b0ba07e5824e93f3e3cc2cc2758", + "result" : "valid" + }, + { + "tcId" : 387, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004244b7afe7f31289f9d6aaeb7f70d29a7b49a228c7bb202764aba94daaaa3332270c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "76b439f8ea7b42f11cd59e6d91b2d2a72577c185386b6af6639be8e3864a7f27", + "result" : "valid" + }, + { + "tcId" : 388, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042ac29db2ebc4fa9473b42bd335a60226579cc186b2c676a3b01bc60e589616165aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "56e63fa788121d5efa0ce3caf4605af18d48c631496cdfa862c43ecf5e5fc127", + "result" : "valid" + }, + { + "tcId" : 389, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e62aee5205a8063e3ae401d53e9343001e55eb5f4e4d6b70e2b84159cf3157e64ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "cff3b5e19ed67e5111dd76e310a1f11d7f99a93fbe9cc5c6f3384086cacd1142", + "result" : "valid" + }, + { + "tcId" : 390, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000431dce6de741f10267f2e8f3d572a4f49be5fe52ff7bff3c3b4646f38076c06752702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e29483884a74fb84f4601654885a0f574691394f064ea6937a846175ef081fc5", + "result" : "valid" + }, + { + "tcId" : 391, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046518cd66b1d841e689d5dc6674c7cc7d964574d1490fff7906bd373494791599104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9c6a4bcb2fc086aca8726d850fa79920214af4c151acea0fcf12a769ad1f3574", + "result" : "valid" + }, + { + "tcId" : 392, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004952a88ce31ad4cb086978e6c5621c3d8023b2c11418d6fd0dcef8de72123efc15d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "34b7abc3f3e36e37e2d5728a870a293a16403146ca67ff91cbabeee2bb2e038b", + "result" : "valid" + }, + { + "tcId" : 393, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042a43f33573b619719099cf54f6cccb28d16df3992239fadf79c7acb9c64f7af0f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9bd1284f1bcb1934d483834cae41a77db28cd9553869384755b6983f4f3848a0", + "result" : "valid" + }, + { + "tcId" : 394, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041b1b0c75408785e84727b0e55e4ba20d0f2599c4ed08482dc1f3b5df545691380162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "167e3db6a912ac6117644525911fc8872ed33b8e0bbd50073dd3c17a744e61e0", + "result" : "valid" + }, + { + "tcId" : 395, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200044dd1283bccd36cc3402f3a81e2e9b0d6a2b2b1debbbd44ffc1f179bd49cf0a7e604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7c3020e279cb5af14184b4653cc87c1ddd7f49cd31cd371ae813681dd6617d0e", + "result" : "valid" + }, + { + "tcId" : 396, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a499dbf732e438be0eb084b9e6ad879dd7a2904bbb004b40027969a171f2d4267bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "acfdff566b8b55318869fa646f789f8036d40b90f0fc520ae2a5a27544f962c0", + "result" : "valid" + }, + { + "tcId" : 397, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004adcf0ffba9cb6ef0c8031c4291a434b18d78f42e45e62ba01fbe91f9273f0ad1ddf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5c6b01cff4e6ce81a630238b5db3662e77fb88bffdde61443a7d8554ba001ef2", + "result" : "valid" + }, + { + "tcId" : 398, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000421712725d9806acf54d3a6c82bf93c0fe249268ca9f42eceac19e93a5eab8056503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e7281d12b74b06eecb273ec3e0d8fe663e9ec1d5a50c2b6c68ec8b3693f23c4c", + "result" : "valid" + }, + { + "tcId" : 399, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041e02176824bd31eabdce03a9403c7d3c2ac631f9b0e88d9a924701c1b2f29b85cf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "80643ed8b9052a2e746a26d9178fe2ccff35edbb81f60cd78004fb8d5f143aae", + "result" : "valid" + }, + { + "tcId" : 400, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000463e7a1af36d6b540a49276aac3fec9cb45ed6bab167c06b0419a77b91399f6181e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "75873ac544ad69d3ddc5c9cffe384d275e9da2949d6982da4b990f8bf2b76474", + "result" : "valid" + }, + { + "tcId" : 401, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041e265ab5b7f7199470e532653d2a7b9a8b728970b838137c9692ed0692897b2ac1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "355c9faca29cf7cc968853ee29ffe62d1127fcc1dc57e9ddaf0e0f447146064e", + "result" : "valid" + }, + { + "tcId" : 402, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000454d2a4394c109fcbd3cb9886fec3add51ba4d2e44e1d5676e4b98f0c13655fc5f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "fc175a5ef18595b69e45be2cda8ae00d9c8bdbefbcf7f692f91cefdc560e4722", + "result" : "valid" + }, + { + "tcId" : 403, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000493f1459207fb09c6f0a88c398ac80d1052a4cd33e7eef5687da99ab97c6024b770c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "46559146a93aae904dbcaaaa07e6cd1bb450f1b37c83929a994b45792333d5f6", + "result" : "valid" + }, + { + "tcId" : 404, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200041fa049a1892b679857c6dff08af19db70cbc99b6f2d7bc51a341fe79d1647f4a5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c64b07119054a37961c0a177158256081b38b0087b307e0cad7e30d790ceb0ce", + "result" : "valid" + }, + { + "tcId" : 405, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000484e0b192d60abf531e828e887d366d869e1033a16e9c7f1167458c8134c10fba4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bea8cfc0bee8571ccf0c525654ef26d1fc782bb22deccf67ea4ea0803dc15daf", + "result" : "valid" + }, + { + "tcId" : 406, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042f9707c67118724111efbbbbf06b623ab2ffd9259ddc354fcaaf81ba01f6fa7b2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "60451da4adfe5bb393109069efdc84415ec8a2c429955cbf22a4340f8fc48936", + "result" : "valid" + }, + { + "tcId" : 407, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ac1fbbe42293a9f9ae104ee2da0b0a9b3464d5d8b1e854df19d3c4456af8f9a6104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d68e746f3d43feac5fd4898de943dc38205af7e2631ed732079bbfc8ab52511c", + "result" : "valid" + }, + { + "tcId" : 408, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bae10cf93ff7b72d6ed98519602e9f03aa40303fa0674fb3ddee7d2db1c92bb25d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "28daeaadc609386d770dff4c7120b2a87cab3e21fdb8a6e4dc1240a51d12e55c", + "result" : "valid" + }, + { + "tcId" : 409, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004edb4288cf5567673d50a1cd9e6bea45317823f30383f60d9bc3b9ee42ac29871f4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bb4110b734c8ef8a08bb6011acb35cbda9ae8e2ef6c4d0862576a68792667bb9", + "result" : "valid" + }, + { + "tcId" : 410, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000413233e80f59ac2b59737e87877782ab3027c490df8ac0bf3f3ef1633872eec540162f954534eadb1b4ea95c57d40a10214e5b746ee6aa4194ed2b2012b72f97d", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e25c50037ca1913851b9758752659fb61c02d2a7c6b6aae29bda301907d99f5d", + "result" : "valid" + }, + { + "tcId" : 411, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043cd14f7e4b779615bc7ccee47e7f2b07394bf8f98503263411a549264a8fcf19604f8174e3605b8f18bed3742b6871a8cffce006db31b8d7d836f50cfcda7d16", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "ad259f01e953263f40a39b14a538d076710c19207af936feabdf03bda7f067a5", + "result" : "valid" + }, + { + "tcId" : 412, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004946c278288616aa34790ca193686e745d3d58702866ddf1e95550711a9bfbdb87bc337a1c82e3c5f7a2927987b8fae13627237d220fafb4013123bfbd95f0ba5", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5ec6025ac7b25c0f095f3fdee3e2e508bd1437b9705c2543c0e5af1c1d363ffd", + "result" : "valid" + }, + { + "tcId" : 413, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047f195035feb2c04a9b149bb2ed3c5c458e95e7f7c418c4a07ea6107e4e32455addf9a666bf0015b20e4912f70f655ef21b82087596aa1e2f1e2865350d159185", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a2f93a84574a26b43880cde6ed440c7f7cc72c92504d5271999a8a78ffe3491d", + "result" : "valid" + }, + { + "tcId" : 414, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000440855844e04303843a24b01707544d1bbf97673266e03d77fbf80d8b64219bd8503af4a2e3b26279564fed8e772a043e75630e4e3859976ede88ffcf16f5ca71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8d0cdb4977ba7661d41036aeb7a5f2dd207716d5d76eeb26629043c559ec2900", + "result" : "valid" + }, + { + "tcId" : 415, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000422cdb3ee47f14b3b0c0c8c256fb22e79126b436a2c9ff635a65151a0f0ffb1bfcf333562f3e018892374353674de8490fc9d30426598eb600779154baf2aec17", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "defde4aa48f89b03f623ea1f946f1aa938c5aab879ca6319596926f085578edc", + "result" : "valid" + }, + { + "tcId" : 416, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042b7becd7066e22f121e7cf123d48c5445037c5a756ef314a66a7001636ee75cf1e6fe2c1a715163efaf86ea8b1e55ea5742d6b042e6cbf8acc69c99f8271a902", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "afe0bfed69a600163865406127a8972b613232aa4c933a06b5a5b5bcff1596f8", + "result" : "valid" + }, + { + "tcId" : 417, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bb8da4a76ee3d1c4b33477bc8663def167a126c422ad47f6c2f8b539c6808936c1d5ee9fc3ce49fd4509d33c4dcfcc1a20a660529fa9ebd6e6afc3d5c84c72bb", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f49bca7a6a5256ddf712775917c30e4873153469bae12fd5c5571031db7b1205", + "result" : "valid" + }, + { + "tcId" : 418, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040a0c37664823a5005d659f7c73c39ea172c862969c81e44f36c89e7c265ec8a8f20a0ca618ba0131a2e373f31f73b3f55e9188d46fddbc6387e32aefb9f3ba12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9c88b611b7f9aad33fabb09cff618bb1ca6fb904a289b1481da3d1e4e72589e4", + "result" : "valid" + }, + { + "tcId" : 419, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000447c33f6f78d3cd9971ecc50e7e2ac947f8c1103f9c5f0821379bd06ad8fca45670c60975748f0c749a8b0f8fc1e222ddcbd3384f6d68f0b6b6ff679b435cdcb1", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "42f634c06c4a0e7e956db6e86666603d26374cc74b11026f0318d1a25681a712", + "result" : "valid" + }, + { + "tcId" : 420, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b59d18ab8b0f9dd33484f43c3f6860229ba6a4c25a61cd0aaca23b76d60566cf5aa9c0d1b240e6dd4211e3235425634b278ad88fede0337d5acf3136587d8413", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "e2ceb946e7993f27a4327abdf61d4f06577e89c63b62a24aefbd905710d18669", + "result" : "valid" + }, + { + "tcId" : 421, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000494f4601b244d3a6ea6996fa244364f794399e0ff4316157db6023222fc0d90be4ba2e420cabc43b6e8e86590fc2383d17827dd99a60c211f190a74269100c141", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "71637a5da2412a921f1636c69a6ee81083ee2b0e13766ad122791ef6f771896d", + "result" : "valid" + }, + { + "tcId" : 422, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200049e8c115b1ac87d986ee1b506b86a4e7b8ea041aa6a63d6ec80ec0f0cf69cfb3f2702a515a9a50db1d86fd42aea0834daeb62be03d0cd9033f84b9c4b56a19f12", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bd265ed3078ca8c7788f594187c96c675aa623ecd01bfcad62d76a7881334f63", + "result" : "valid" + }, + { + "tcId" : 423, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004eec776b52b94141fc819d4b6b12d28e73555b5560507aba7df6f0484008de91f104277170692fa6bf2270580d56d1bc81b54f477d8ab6c3f5842650ac7176d71", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8d073fc592fb7aa6f7b908ed07148aa7be5a135c4b343ebe295198cba78e71ce", + "result" : "valid" + }, + { + "tcId" : 424, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aff46a388e5afc220a8eec7a49af9d245384a3af1e0b407b4521f4e92d12dceb5d367688fde5e082f097855a0c0adc305dd6cf46f50ca75859bb243b70249605", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a26d698e4613595aa61c8e2907d5241d6d14909737df59895841d07727bf1348", + "result" : "valid" + }, + { + "tcId" : 425, + "comment" : "point with coordinate y = 1 in left to right addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e807e43d96f3701a9a5c13d122749084170fcd36a586a446c9fcb4600eede4fdf4d1d22af7187c8de1b992a4046c419b801cde57d638d30f2e1ac49353117a20", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a8edc6f9af6bf74122c11ca1a50afbc4a3c4987bd0d1f73284d2c1371e613405", + "result" : "valid" + }, + { + "tcId" : 426, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004798868a56916d341e7d6f96359ae3658836e221459f4f7b7b63694de18a5e9247713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "17963de078996eb8503c7cc3e1a2d5147d7f0bfb251a020b4392033063587c8d", + "result" : "valid" + }, + { + "tcId" : 427, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ff419909d8a8ce0a9416051f4e256208c1dc035581a53312d566137e22104e9877421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "062799a19545d31b3ed72253bcde59762aa6104a88ac5e2fb68926b0f7146698", + "result" : "valid" + }, + { + "tcId" : 428, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200048b48119d7089d3b95cd2eaf8c85584fa8f5e56c4c4ccee7037d74cdbf88e571714c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9f42dd8fce13f8103b3b2bc15e61242e6820fe1325a20ef460fe64d9eb12b231", + "result" : "valid" + }, + { + "tcId" : 429, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e2888119379b5b2151bd788505def1d6bd786329431caf39705d9cbf96a42ea43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "d1b204e52d1fac6d504132c76ca233c87e377dcc79c893c970ddbb9f87b27fa0", + "result" : "valid" + }, + { + "tcId" : 430, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200046dcc3971bd20913d59a91f20d912f56d07e7f014206bef4a653ddfe5d12842c39b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c8d6bd28c1e65ae7c7a5debe67a7dfaf92b429ede368efc9da7d578a539b7054", + "result" : "valid" + }, + { + "tcId" : 431, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200047ebea45854569a1f7ea6b95b82d6befefbf6296ebc87c810b6cba93c0c1220b23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0d1f905cc74720bde67ae84f582728588c75444c273dae4106fa20d1d6946430", + "result" : "valid" + }, + { + "tcId" : 432, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ceab5937900d34fa88378d371f4acaa7c6a2028b6143213413f16ba2dc7147877713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3f014e309192588fa83e47d4ac9685d2041204e2eaf633a1312812e51ae74cbd", + "result" : "valid" + }, + { + "tcId" : 433, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004a4ffea5e25f75e4f689c81084a35c1220e8e6b914c482f4a2e8f93cffca6964777421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "68b404d556c82004c6c4bba4518ec00b1d4f1161cafe6c89aeb8494a9ba09db5", + "result" : "valid" + }, + { + "tcId" : 434, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004de8809ea0ecce1d24a0431429510383a6f6e5a1c51cea32d830c6c353042603e14c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c331ade7a457df7f12a2f5c43d7ea9486c1563b81cd8a0f23f923c1a9fa612e3", + "result" : "valid" + }, + { + "tcId" : 435, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004566209f174d6bf79720b70edb27e51350beeb2b0bcd083bbae7214f71cf824d43bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "17b5c7a311eea9d2ab7571f8b9f848d4705997cf3eaf9bdcbe0e34a670f81f45", + "result" : "valid" + }, + { + "tcId" : 436, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004cc3181c0127137536ceec94fd45996657df72e0f97c44b9dad14763ce506e9dc9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "2f0e4eccbc4518ace558e06604f9bff4787f5b019437b52195ecb6b82191a6ae", + "result" : "valid" + }, + { + "tcId" : 437, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d7052a1eeafc0e78d79e7f26003aa0a409287cf476007df28d281b142be1a0e23f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7494d864cb6ea9c5d982d40a5f103700d02dc982637753cfc7d8afe1beafff70", + "result" : "valid" + }, + { + "tcId" : 438, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004b7cc3e2306dbf7c38ff179658706feffb5efdb6044c7e71435d7ff7d0ae8c7b37713fdb03a8de8c6d29ca38a9fbaa82e5e02bead2f9eec69b6444b7adb05333b", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "a96873eef5d438b807853b6771c6a5197e6eef21efefca538b45e9e981c032e5", + "result" : "valid" + }, + { + "tcId" : 439, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200045bbe7c98015fd3a6034d79d867a4dcd52f95911932129da2fc0a58afe149137f77421ab01e00e83841b946dae5bb5a23973daa98fe1a8172883abcbedced7021", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9124618913f20cdffa642207f192e67eb80ade53ac5535469abe90036d4af7e2", + "result" : "valid" + }, + { + "tcId" : 440, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004962fe47880a94a745928e3c4a29a42cb01334f1ee9646e62451c46ecd72f410914c1aac5f0bf1b48a4abcf1d9291b9a8776a004380546a5a1c1f294690f61969", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9d8b74888d942870b221de7a642032892bc99e34bd8550195f6f5f097547334a", + "result" : "valid" + }, + { + "tcId" : 441, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c71574f5538de5653c37168d47a2bcf43698ea260012cd0ae1304e474c63a4e63bb7328839d2aecac64b1cdb182f08adccaac327ed008987a10edc9732413ced", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "16983377c0f1a9c004495b3fd9658363116eea644787d059d1140fb907555d4a", + "result" : "valid" + }, + { + "tcId" : 442, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c60244ce306e376f3968178f5293742d7a20e1dc47cfc517edada9db49d0cbbf9b51b17b76ea6cc137eebd93c811e636d8ae26c70d064650f7205a865d01a6ee", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "081af40a81d48c6b530140db935e605bf4cc7b10885f5b148f95f1bc8ad2e52d", + "result" : "valid" + }, + { + "tcId" : 443, + "comment" : "point with coordinate y = 1 in precomputation or right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004aa3c3188c0ad5767a9bac77e7ceea05cfae1599ccd77b9fcbc0c3badc80c36ca3f1874fa08a693b086643ef21eb59d75562da9422d13d9a39b0b17e241b04d32", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "7e4b973e6d4a357c400243a648c8a0a6a35cf231754afdef312d2f4b6abb988f", + "result" : "valid" + }, + { + "tcId" : 444, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200042cce8ddfe4827dc030ddf38f998b3f2ed5e0621d0b3805666daf48c8c31e75e5198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0f0235da2a06c8d408c27151f3f15342ed8c1945aaf84ed14993786d6ac5f570", + "result" : "valid" + }, + { + "tcId" : 445, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000414bfc3e5a46b69881a9a346d95894418614ed91476a1ddce48676b7cbab9ba02f334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "5622c2fbe8af5ad6cef72a01be186e554847576106f8979772fa56114d1160ab", + "result" : "valid" + }, + { + "tcId" : 446, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd442fa5a2a8d72e13e44fd2222c85a006f03375e0211b272f555052b03db750be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "bb95e0d0fbaad86c5bd87b95946c77ff1d65322a175ccf16419102c0a17f5a72", + "result" : "valid" + }, + { + "tcId" : 447, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040d7a3ff49bda6a587ed07691450425aa02d253ba573a16ad86c61af412dd3c770b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4510683c7bfa251f0cb56bba7e0ab74d90f5e2ca01e91e7ca99312ccff2d90b6", + "result" : "valid" + }, + { + "tcId" : 448, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bdea5d2a3adde7df2e839ff63f62534b3f27cb191bb54dfa1d39cbff713ba9ed307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "025485142ca1ced752289f772130fc10c75a4508c46bffdef9290ad3e7baf9ca", + "result" : "valid" + }, + { + "tcId" : 449, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004d4c063e3c036f47c92f6f5470a26a835e1a24505b14d1b29279062a16cf6f489198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "9067932150724965aa479c1ef1be55544bed9fa94500a3b67887ed91ae3b81e5", + "result" : "valid" + }, + { + "tcId" : 450, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200043cb9f07997756859e9b9a85b681fa50ee20357f535c1b311c4637d16b76b9ebff334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "f8084a89adccdc3aef89e5091a0f07d6160a66cb9575241100c1d39bf0549ae2", + "result" : "valid" + }, + { + "tcId" : 451, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004793412ff636c08a2d0f6d60cc608e9a9098349a2501f91c95f692010bc1238b2be345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "4462558c89902117051cb2c599ad66f00887b54cae3da9c04d317a5b2afb463b", + "result" : "valid" + }, + { + "tcId" : 452, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004bd1eb0849e2e6a13d54b76518f11ba8775c2d7634d85152534bc7c3af4161efa0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "30b4741a64f87d28ec0029bd196b5a74555f2c9a976a46d628572474466a631d", + "result" : "valid" + }, + { + "tcId" : 453, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004624b3b4ba993a8b938125689f6cf757392ee390d14a90fea6db944b5a8deb8d0307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "3afc04ac92117e50b0913b09dbbb4e6c780c051500201fad512b79080bff39e2", + "result" : "valid" + }, + { + "tcId" : 454, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fe710e3c5b468dc33c2b17295c4e189b487d58dd437adf706ac05493cfea8df0198d9ef4e973b6bdebe119a35faae86191acd758c1ed8accaf1e706ad55d83d7", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "609637048586edc64cf5f28f1a505768c686471110070d783de499ffe6fe84da", + "result" : "valid" + }, + { + "tcId" : 455, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004ae864ba0c41f2e1dfbac2337025716d8bcadcef6539c6f1ff335176b8ddaa36ef334d64f2caf561b063bc1f7889e937302a455ff685d8ae57cb2444a17dad068", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "b1d4f27a6983c8ee417ef0f527d889d4a1ae41d3639244578c43d650c299fcd1", + "result" : "valid" + }, + { + "tcId" : 456, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004c987bd5af9eb202f1b24da2117ca90b6ef8c82e7cfbf530f71418f9a93b0085cbe345737f7c6b5e70e97d9fe9dc4ca94fb185f4b9d2a00e086c1d47273b33602", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "0007c9a27ac5067c9f0ad1a4d1e62110da1318893a658729713d82e333855b82", + "result" : "valid" + }, + { + "tcId" : 457, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000435670f86c5f72b93abe4131d2bea1fce876ad4e25b40d42d447d68cff90ca0be0b6d3b9e570ba004877c9a69e481fe215de03a70126305a452826e66d9b5583e", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "8a3b23a91f0d5db8074a6a886889ee3e19aaf09b66ac9aad2e15c8bdba68085c", + "result" : "valid" + }, + { + "tcId" : 458, + "comment" : "point with coordinate y = 1 in right to left addition chain", + "flags" : [ + "EdgeCaseDoubling" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004dfca678a1b8e6f67996a097fc9ce37412de9fbd9cfa1a21b750cef48e5e595a1307d8f1d02c6f07146655e6383b0ef3035bee7067c336fdb91365e197a97b616", + "private" : "00c1781d86cac2c052b865f228e64bd1ce433c78ca7dfca9e8b810473e2ce17da5", + "shared" : "c2af763f414cb2d7fd46257f0313b582c099b5e23b73e073b5ab7c230c45c883", + "result" : "valid" + }, + { + "tcId" : 459, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "03", + "shared" : "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", + "result" : "valid" + }, + { + "tcId" : 460, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "shared" : "5841acd3cff2d62861bbe11084738006d68ccf35acae615ee9524726e93d0da5", + "result" : "valid" + }, + { + "tcId" : 461, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "0100000000000000000000000000000000000000000000000000000000000000", + "shared" : "4348e4cba371ead03982018abc9aacecaebfd636dda82e609fd298947f907de8", + "result" : "valid" + }, + { + "tcId" : 462, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "shared" : "e56221c2b0dc33b98b90dfd3239a2c0cb1e4ad0399a3aaef3f9d47fb103daef0", + "result" : "valid" + }, + { + "tcId" : 463, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "008000000000000000000000000000000000000000000000000000000000000000", + "shared" : "5b34a29b1c4ddcb2101162d34bed9f0702361fe5af505df315eff7befd0e4719", + "result" : "valid" + }, + { + "tcId" : 464, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03abfd25e8cd0364141", + "shared" : "cece521b8b5a32bbee38936ba7d645824f238e561701a386fb888e010db54b2f", + "result" : "valid" + }, + { + "tcId" : 465, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfc25e8cd0364141", + "shared" : "829521b79d71f5011e079756b851a0d5c83557866189a6258c1e78a1700c6904", + "result" : "valid" + }, + { + "tcId" : 466, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfca5e8cd0364141", + "shared" : "8c5934793505a6a1f84d41283341680c4923f1f4d562989a11cc626fea5eda5a", + "result" : "valid" + }, + { + "tcId" : 467, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8bd0364141", + "shared" : "356caee7e7eee031a15e54c3a5c4e72f9c74bb287ce601619ef85eb96c289452", + "result" : "valid" + }, + { + "tcId" : 468, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03640c3", + "shared" : "09c7337df6c2b35edf3a21382511cc5add1a71a84cbf8d3396a5be548d92fa67", + "result" : "valid" + }, + { + "tcId" : 469, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364103", + "shared" : "d16caedd25793666f9e26f5331382106f54095b3d20d40c745b68ca76c0e6983", + "result" : "valid" + }, + { + "tcId" : 470, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364123", + "shared" : "b8ae1e21d8b34ce4caffed7167a26868ec80a7d4a6a98b639d4d05cd226504de", + "result" : "valid" + }, + { + "tcId" : 471, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364133", + "shared" : "02776315fe147a36a4b0987492b6503acdea60f926450e5eddb9f88fc82178d3", + "result" : "valid" + }, + { + "tcId" : 472, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413b", + "shared" : "3988c9c7050a28794934e5bd67629b556d97a4858d22812835f4a37dca351943", + "result" : "valid" + }, + { + "tcId" : 473, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e", + "shared" : "34005694e3cac09332aa42807e3afdc3b3b3bc7c7be887d1f98d76778c55cfd7", + "result" : "valid" + }, + { + "tcId" : 474, + "comment" : "edge case private key", + "flags" : [ + "AdditionChain" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000432bdd978eb62b1f369a56d0949ab8551a7ad527d9602e891ce457586c2a8569e981e67fae053b03fc33e1a291f0a3beb58fceb2e85bb1205dacee1232dfd316b", + "private" : "00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413f", + "shared" : "4b52257d8b3ba387797fdf7a752f195ddc4f7d76263de61d0d52a5ec14a36cbf", + "result" : "valid" + }, + { + "tcId" : 475, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 476, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 477, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 478, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 479, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 480, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 481, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 482, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a034200040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 483, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 484, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e0000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 485, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 486, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 487, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000000", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 488, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f0000000000000000000000000000000000000000000000000000000000000001", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 489, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 490, + "comment" : "point is not on curve", + "flags" : [ + "InvalidCurveAttack" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 491, + "comment" : "", + "flags" : [ + "InvalidEncoding" + ], + "public" : "3015301006072a8648ce3d020106052b8104000a030100", + "private" : "00c6cafb74e2a50c83b3d232c4585237f44d4c5433c4b3f50ce978e6aeda3a4f5d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 492, + "comment" : "public key has invalid point of order 2 on secp256r1. The point of the public key is a valid on secp256k1.", + "flags" : [ + "WrongCurve" + ], + "public" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004ffffffff00000001000000000000000000000000ffffffffffffffffffffffff32d98e0d77dd0e543770ec994c0ae837e7bb36eb1d910b58a14a2a08dc182f83", + "private" : "3b25129f3410ec89cc6dc539fd7601873ba6abf72a6d023f1aa9041765430ee6", + "shared" : "1d3fc2b2e48b3e96c6323380fadb467825e69f5b9078a9e02173b477bc232cc1", + "result" : "invalid" + }, + { + "tcId" : 493, + "comment" : "public key has invalid point of order 2 on FRP256v1. The point of the public key is a valid on secp256k1.", + "flags" : [ + "WrongCurve" + ], + "public" : "305b301506072a8648ce3d0201060a2a817a01815f6582000103420004f1fd178c0b3ad58f10126de8ce42435b3961adbcabc8ca6de8fcf353d86e9c03247e9edb2a633201dfc68fbd34556690db38ef76732f8a9052ee40d84e2ec35b", + "private" : "485dea32cd245db99d88e1852587c161b81abeabb151ad3fc1e4dd2f591e9936", + "shared" : "0a373d77057a50e3aad60b1e51bc017523dc2bdfef1c07cf4ed8393839224d0a", + "result" : "invalid" + }, + { + "tcId" : 494, + "comment" : "public point not on curve", + "flags" : [ + "ModifiedPublicPoint", + "InvalidPublic" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e4", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 495, + "comment" : "public point = (0,0)", + "flags" : [ + "ModifiedPublicPoint", + "InvalidPublic" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a0342000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 496, + "comment" : "order = -115792089237316195423570985008687907852837564279074904382605163141518161494337", + "flags" : [ + "WrongOrder", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80221ff000000000000000000000000000000014551231950b75fc4402da1732fc9bebf0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 497, + "comment" : "order = 0", + "flags" : [ + "WrongOrder", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201000201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 498, + "comment" : "order = 1", + "flags" : [ + "WrongOrder", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201133081cc06072a8648ce3d02013081c0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b80201010201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 499, + "comment" : "order = 26959946667150639794667015087019630673536463705607434823784316690060", + "flags" : [ + "WrongOrder", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "3082012f3081e806072a8648ce3d02013081dc020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8021d00fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8c0201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 500, + "comment" : "generator = (0,0)", + "flags" : [ + "ModifiedGenerator", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 501, + "comment" : "generator not on curve", + "flags" : [ + "ModifiedGenerator", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4ba022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 502, + "comment" : "cofactor = -1", + "flags" : [ + "NegativeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201ff0342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 503, + "comment" : "cofactor = 0", + "flags" : [ + "NegativeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 504, + "comment" : "cofactor = 2", + "flags" : [ + "ModifiedCofactor", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201020342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 505, + "comment" : "cofactor = n", + "flags" : [ + "LargeCofactor", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201553082010d06072a8648ce3d020130820100020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "invalid" + }, + { + "tcId" : 506, + "comment" : "cofactor = None", + "flags" : [ + "ModifiedCofactor", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201303081e906072a8648ce3d02013081dd020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 507, + "comment" : "modified prime", + "flags" : [ + "ModifiedPrime", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fb524ac7055bebf603a4e216abaa6a9ef8eb2bbea2cd820e59d46d8501f6268b304404200000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000000070441040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101034200040000000000000000000006597fa94f5b8380000000000000000000000000000f229ba06e5c03dbcba0eec01b4bcca549cda86e507e8813b5bb2b42df88f12f47", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "c5956b8cf7244e3c0457658a214210b358205cab12374d523ecf57895cecfeb0", + "result" : "invalid" + }, + { + "tcId" : 508, + "comment" : "using secp224r1", + "flags" : [ + "ModifiedGroup", + "InvalidPublic" + ], + "public" : "304e301006072a8648ce3d020106052b81040021033a0004074f56dc2ea648ef89c3b72e23bbd2da36f60243e4d2067b70604af1c2165cec2f86603d60c8a611d5b84ba3d91dfe1a480825bcc4af3bcf", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 509, + "comment" : "using secp256r1", + "flags" : [ + "ModifiedGroup", + "InvalidPublic" + ], + "public" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cbf6606595a3ee50f9fceaa2798c2740c82540516b4e5a7d361ff24e9dd15364e5408b2e679f9d5310d1f6893b36ce16b4a507509175fcb52aea53b781556b39", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 510, + "comment" : "a = 0", + "flags" : [ + "Modified curve parameter", + "UnusedParam", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f3044042000000000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000000704410449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641410201010342000449c248edc659e18482b7105748a4b95d3a46952a5ba72da0d702dc97a64e99799d8cff7a5c4b925e4360ece25ccf307d7a9a7063286bbd16ef64c65f546757e2", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "380c53e0a509ebb3b63346598105219b43d51ae196b4557d59bbd67824032dff", + "result" : "acceptable" + }, + { + "tcId" : 511, + "comment" : "public key of order 3", + "flags" : [ + "WeakPublicKey", + "InvalidPublic", + "UnnamedCurve" + ], + "public" : "308201333081ec06072a8648ce3d02013081e0020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f304404209234b518bfe789f01e2389571299e39b4596c63a14d598659341dd313c65e08a04209d569a9efeeb4362b094d096024cba7b53d51dbc33818c8cdf37b9315d2e7bab044104fb6075d26c3501c014e48c79b3463cd768378c390d7e6eeb379717d490c4e63487fbca88e6867877e98f43ec02f4a0f45ef0f94310d8ee3d70a10280ce2ae6b3022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414102010103420004fb6075d26c3501c014e48c79b3463cd768378c390d7e6eeb379717d490c4e63478043577197987881670bc13fd0b5f0ba10f06bcef2711c28f5efd7e31d5157c", + "private" : "00cfe75ee764197aa7732a5478556b478898423d2bc0e484a6ebb3674a6036a65d", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 512, + "comment" : "Public key uses wrong curve: secp224r1", + "flags" : [ + "WrongCurve" + ], + "public" : "304e301006072a8648ce3d020106052b81040021033a000450eb062b54940a455719d523e1ec106525dda34c2fd95ace62b9b16d315d323f089173d10c45dceff155942431750c00ca36f463828e9fab", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 513, + "comment" : "Public key uses wrong curve: secp256r1", + "flags" : [ + "WrongCurve" + ], + "public" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000406372852584037722a7f9bfaad5661acb623162d45f70a552c617f4080e873aa43609275dff6dcaaa122a745d0f154681f9c7726867b43e7523b7f5ab5ea963e", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 514, + "comment" : "Public key uses wrong curve: secp384r1", + "flags" : [ + "WrongCurve" + ], + "public" : "3076301006072a8648ce3d020106052b81040022036200040ef5804731d918f037506ee00b8602b877c7d509ffa2c0847a86e7a2d358ba7c981c2a74b22401ac615307a6deb275402fa6c8218c3374f8a91752d2eff6bd14ad8cae596d2f37dae8aeec085760edf4fda9a7cf70253898a54183469072a561", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 515, + "comment" : "Public key uses wrong curve: secp521r1", + "flags" : [ + "WrongCurve" + ], + "public" : "30819b301006072a8648ce3d020106052b81040023038186000400921da57110db26c7838a69d574fc98588c5c07a792cb379f46664cc773c1e1f6fa16148667748ede232d1a1f1cea7f152c5d586172acbeaa48416bcbd70bb27f0f01b4477e1ae74bf4f093184a9f26f103712ccf6ceb45a0505b191606d897edaf872b37f0f90a933000a80fc3207048323c16883a3d67a90aa78bcc9c5e58d784b9b9", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 516, + "comment" : "Public key uses wrong curve: secp224k1", + "flags" : [ + "WrongCurve" + ], + "public" : "304e301006072a8648ce3d020106052b81040020033a000456dd09f8a8c19039286b6aa79d099ff3e35ff74400437d2072fd9faa7f2901db79d793f55268980f7d395055330a91b46bf4a62c3a528230", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 517, + "comment" : "Public key uses wrong curve: brainpoolP224r1", + "flags" : [ + "WrongCurve" + ], + "public" : "3052301406072a8648ce3d020106092b2403030208010105033a00042c9fdd1914cacdb28e39e6fc24b4c3c666cc0d438acc4529a6cc297a2d0fdecb3028d9e4d84c711db352379c080c78659969bdc5d3218901", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 518, + "comment" : "Public key uses wrong curve: brainpoolP256r1", + "flags" : [ + "WrongCurve" + ], + "public" : "305a301406072a8648ce3d020106092b240303020801010703420004120e4db849e5d960741c7d221aa80fe6e4fcd578191b7f845a68a6fcb8647719a6fffb6165d8ec39389eecc530839c321b2e9040027fba5d9cb9311df7cd3d4d", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 519, + "comment" : "Public key uses wrong curve: brainpoolP320r1", + "flags" : [ + "WrongCurve" + ], + "public" : "306a301406072a8648ce3d020106092b2403030208010109035200040efb1c104938f59a931fe6bf69f7ead4036d2336075a708e66b020e1bc5bb6d9cdc86d4e8fa181d7c7ea1af28353044e8cec12eec75a6dd87a5dc902024d93f8c8d9bf43b453fd919151f9bd7bb955c7", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 520, + "comment" : "Public key uses wrong curve: brainpoolP384r1", + "flags" : [ + "WrongCurve" + ], + "public" : "307a301406072a8648ce3d020106092b240303020801010b036200043e96d75b79214e69a4550e25375478bdc9c2a9d0178a77b5700bd5f12e3ce142f50c93dc1ee7268456d7eae2d44b718d6f159e896ae14fbe3aba397801a95e2bb6a9a761e865b289dd9db64aa07c794cedf77328543b94c9b54ce0cf04c60ac8", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 521, + "comment" : "Public key uses wrong curve: brainpoolP512r1", + "flags" : [ + "WrongCurve" + ], + "public" : "30819b301406072a8648ce3d020106092b240303020801010d03818200044f191130740f1b75ae13402960eb22ea801db80ed51a461e06a7b3ba60c9bddd132a6465bbee8afd70cfb4495efbda4f1567b958e6e305bfcb4ac8f05172688e0f2f175aa12425be3ab7271b42f258639e868677d1163c12e641229f1e6427761c9e294de51db564151b21a051d2f7a13661852799557a556a5f3c51d36d083a", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 522, + "comment" : "Public key uses wrong curve: brainpoolP224t1", + "flags" : [ + "WrongCurve" + ], + "public" : "3052301406072a8648ce3d020106092b2403030208010106033a00044964b948cefa39cd769e3480d4840a3c58e966161be80df02d9aab33b4a318a32f30130224edcefe0dd64342404e594aa334995b179f641f", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 523, + "comment" : "Public key uses wrong curve: brainpoolP256t1", + "flags" : [ + "WrongCurve" + ], + "public" : "305a301406072a8648ce3d020106092b24030302080101080342000411157979c08bcd175d34572209a85f3f5d602e35bdc3b553b0f19307672b31ba69d0556bce48c43e2e7e6177055221a4c4b7eb17ee9708f49216de76d6e92ab8", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 524, + "comment" : "Public key uses wrong curve: brainpoolP320t1", + "flags" : [ + "WrongCurve" + ], + "public" : "306a301406072a8648ce3d020106092b240303020801010a035200048bb517e198930eba57293419876a8793f711de37c27f200e6fb2c2b13e9fabd4fbc42ad61751ca583031ba76cbc6d745d115addc74eab63bf415c4fa20dbbecae98ac3c3da1a041705cf8959e2ccf453", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 525, + "comment" : "Public key uses wrong curve: brainpoolP384t1", + "flags" : [ + "WrongCurve" + ], + "public" : "307a301406072a8648ce3d020106092b240303020801010c036200045eb38d0261b744b03abef4ae7c17bc886b5b426bd910958f8a49ef62053048f869541b7a05d244315fc9cd74271ec3d518d94114b6006017f4ed5e3c06322baa1c75809a1057ba6fa46d1e1a9927a262e627940d5da538b5a3d1d794d9c866a4", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 526, + "comment" : "Public key uses wrong curve: brainpoolP512t1", + "flags" : [ + "WrongCurve" + ], + "public" : "30819b301406072a8648ce3d020106092b240303020801010e0381820004035fc238e57d980beae0215fb89108f9c6c4afda5d920f9d0583ee7d65f8778ecfff24a31d4f32deb6ea5f7e3adb6affb9327a5e62e09cba07c88b119fd104a83b7811e958e393971a5c9417412070b9f18b03be37e81e0bca5d3ff0873ed1f3113ed0fc57a0344321fb4d6c43f2f6e630a3d3883efe4c21df3e0f0b1208226b", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 527, + "comment" : "Public key uses wrong curve: FRP256v1", + "flags" : [ + "WrongCurve" + ], + "public" : "305b301506072a8648ce3d0201060a2a817a01815f6582000103420004375e9438d4ab14e298a75eab1e2d51a9248c8ee0bbb24397cbd4651517faedd26d4ded568d2348a473aa5a7570107dc6fc60a2ce0c4143446b5b09ab3fcc7bb4", + "private" : "00dafa209e0f81119a4afa3f1bc46e2f7947354e3727c608b05c4950b10386643a", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 528, + "comment" : "invalid public key", + "flags" : [ + "InvalidCompressedPublic", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a03220002977cb7fb9a0ec5b208e811d6a0795eb78d7642e3cac42a801bcc8fc0f06472d4", + "private" : "00d09182a4d0c94ba85f82eff9fc1bddb0b07d3f2af8632fc1c73a3604e8f0b335", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 529, + "comment" : "public key is a low order point on twist", + "flags" : [ + "WrongCurve", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a032200020000000000000000000000000000000000000000000000000000000000000000", + "private" : "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb300", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 530, + "comment" : "public key is a low order point on twist", + "flags" : [ + "WrongCurve", + "CompressedPoint" + ], + "public" : "3036301006072a8648ce3d020106052b8104000a032200030000000000000000000000000000000000000000000000000000000000000000", + "private" : "0098b5c223cf9cc0920a5145ba1fd2f6afee7e1f66d0120b8536685fdf05ebb2ff", + "shared" : "", + "result" : "invalid" + }, + { + "tcId" : 531, + "comment" : "length of sequence uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "308156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 532, + "comment" : "length of sequence uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "305730811006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 533, + "comment" : "length of sequence contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "30820056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 534, + "comment" : "length of sequence contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583082001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 535, + "comment" : "length of sequence uses 87 instead of 86", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 536, + "comment" : "length of sequence uses 85 instead of 86", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 537, + "comment" : "uint32 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30850100000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 538, + "comment" : "uint32 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3085010000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 539, + "comment" : "uint64 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3089010000000000000056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 540, + "comment" : "uint64 overflow in length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f308901000000000000001006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 541, + "comment" : "length of sequence = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "30847fffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 542, + "comment" : "length of sequence = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a30847fffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 543, + "comment" : "length of sequence = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "3084ffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 544, + "comment" : "length of sequence = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a3084ffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 545, + "comment" : "length of sequence = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "3085ffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 546, + "comment" : "length of sequence = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3085ffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 547, + "comment" : "length of sequence = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "3088ffffffffffffffff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 548, + "comment" : "length of sequence = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3088ffffffffffffffff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 549, + "comment" : "incorrect length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30ff301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 550, + "comment" : "incorrect length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305630ff06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 551, + "comment" : "replaced sequence by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 552, + "comment" : "replaced sequence by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056308006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 553, + "comment" : "removing sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 554, + "comment" : "removing sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "304403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 555, + "comment" : "lonely sequence tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "30", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 556, + "comment" : "lonely sequence tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "30453003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 557, + "comment" : "appending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 558, + "comment" : "appending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 559, + "comment" : "prepending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30580000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 560, + "comment" : "prepending 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012000006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 561, + "comment" : "appending unused 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 562, + "comment" : "appending unused 0's to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 563, + "comment" : "appending null value to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 564, + "comment" : "appending null value to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 565, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b4981773056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 566, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a25003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 567, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3015498177301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 568, + "comment" : "prepending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a30142500301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 569, + "comment" : "appending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 570, + "comment" : "appending garbage to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3012301006072a8648ce3d020106052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 571, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305eaa00bb00cd003056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 572, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3018aa00bb00cd00301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 573, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3018260faa00bb00cd0006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 574, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301806072a8648ce3d0201260daa00bb00cd0006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 575, + "comment" : "including undefined tags", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301006072a8648ce3d020106052b8104000a234aaa00bb00cd0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 576, + "comment" : "truncated length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3081", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 577, + "comment" : "truncated length of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3046308103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 578, + "comment" : "including undefined tags to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305caa02aabb3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 579, + "comment" : "including undefined tags to sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c3016aa02aabb301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 580, + "comment" : "Replacing sequence with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "0500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 581, + "comment" : "Replacing sequence with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "3046050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 582, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "2e56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 583, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "2f56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 584, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3156301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 585, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3256301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 586, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "ff56301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 587, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30562e1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 588, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30562f1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 589, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056311006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 590, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056321006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 591, + "comment" : "changing tag value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056ff1006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 592, + "comment" : "dropping value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 593, + "comment" : "dropping value of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3046300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 594, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 595, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30551006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 596, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06072a8648ce3d020106052b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 597, + "comment" : "truncated sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 598, + "comment" : "sequence of size 4183 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "30821057301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 599, + "comment" : "indefinite length", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 600, + "comment" : "indefinite length", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058308006072a8648ce3d020106052b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 601, + "comment" : "indefinite length with truncated delimiter", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326700", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 602, + "comment" : "indefinite length with truncated delimiter", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057308006072a8648ce3d020106052b8104000a0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 603, + "comment" : "indefinite length with additional element", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326705000000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 604, + "comment" : "indefinite length with additional element", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a308006072a8648ce3d020106052b8104000a0500000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 605, + "comment" : "indefinite length with truncated element", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267060811220000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 606, + "comment" : "indefinite length with truncated element", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c308006072a8648ce3d020106052b8104000a06081122000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 607, + "comment" : "indefinite length with garbage", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000fe02beef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 608, + "comment" : "indefinite length with garbage", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c308006072a8648ce3d020106052b8104000a0000fe02beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 609, + "comment" : "indefinite length with nonempty EOC", + "flags" : [ + "InvalidAsn" + ], + "public" : "3080301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670002beef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 610, + "comment" : "indefinite length with nonempty EOC", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a308006072a8648ce3d020106052b8104000a0002beef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 611, + "comment" : "prepend empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583000301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 612, + "comment" : "prepend empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012300006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 613, + "comment" : "append empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32673000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 614, + "comment" : "append empty sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000a300003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 615, + "comment" : "append garbage with high tag number", + "flags" : [ + "InvalidAsn" + ], + "public" : "3059301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267bf7f00", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 616, + "comment" : "append garbage with high tag number", + "flags" : [ + "InvalidAsn" + ], + "public" : "3059301306072a8648ce3d020106052b8104000abf7f0003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 617, + "comment" : "append null with explicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267a0020500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 618, + "comment" : "append null with explicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d020106052b8104000aa002050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 619, + "comment" : "append null with implicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267a000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 620, + "comment" : "append null with implicit tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106052b8104000aa00003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 621, + "comment" : "sequence of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 622, + "comment" : "sequence of sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 623, + "comment" : "truncated sequence: removed last 1 elements", + "flags" : [ + "InvalidAsn" + ], + "public" : "3012301006072a8648ce3d020106052b8104000a", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 624, + "comment" : "truncated sequence: removed last 1 elements", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f300906072a8648ce3d020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 625, + "comment" : "repeating element in sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "30819a301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 626, + "comment" : "repeating element in sequence", + "flags" : [ + "InvalidAsn" + ], + "public" : "305d301706072a8648ce3d020106052b8104000a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 627, + "comment" : "length of sequence uses 17 instead of 16", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301106072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 628, + "comment" : "length of sequence uses 15 instead of 16", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056300f06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 629, + "comment" : "sequence of size 4113 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "308210593082101106072a8648ce3d020106052b8104000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 630, + "comment" : "length of oid uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "305730110681072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 631, + "comment" : "length of oid uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d02010681052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 632, + "comment" : "length of oid contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012068200072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 633, + "comment" : "length of oid contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d0201068200052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 634, + "comment" : "length of oid uses 8 instead of 7", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006082a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 635, + "comment" : "length of oid uses 6 instead of 7", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006062a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 636, + "comment" : "uint32 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3015068501000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 637, + "comment" : "uint32 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301506072a8648ce3d0201068501000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 638, + "comment" : "uint64 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906890100000000000000072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 639, + "comment" : "uint64 overflow in length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906072a8648ce3d020106890100000000000000052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 640, + "comment" : "length of oid = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406847fffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 641, + "comment" : "length of oid = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d020106847fffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 642, + "comment" : "length of oid = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a30140684ffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 643, + "comment" : "length of oid = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d02010684ffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 644, + "comment" : "length of oid = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b30150685ffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 645, + "comment" : "length of oid = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301506072a8648ce3d02010685ffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 646, + "comment" : "length of oid = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e30180688ffffffffffffffff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 647, + "comment" : "length of oid = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301806072a8648ce3d02010688ffffffffffffffff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 648, + "comment" : "incorrect length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006ff2a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 649, + "comment" : "incorrect length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106ff2b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 650, + "comment" : "replaced oid by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006802a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 651, + "comment" : "replaced oid by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106802b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 652, + "comment" : "removing oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "304d300706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 653, + "comment" : "lonely oid tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "304e30080606052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 654, + "comment" : "lonely oid tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3050300a06072a8648ce3d02010603420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 655, + "comment" : "appending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206092a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 656, + "comment" : "appending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106072b8104000a000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 657, + "comment" : "prepending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012060900002a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 658, + "comment" : "prepending 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d0201060700002b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 659, + "comment" : "appending unused 0's to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d0201000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 660, + "comment" : "appending null value to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206092a8648ce3d0201050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 661, + "comment" : "appending null value to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301206072a8648ce3d020106072b8104000a050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 662, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b3015260c49817706072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 663, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a3014260b250006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 664, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301506072a8648ce3d0201260a49817706052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 665, + "comment" : "prepending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d02012609250006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 666, + "comment" : "appending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e3018260906072a8648ce3d02010004deadbeef06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 667, + "comment" : "appending garbage to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301806072a8648ce3d0201260706052b8104000a0004deadbeef03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 668, + "comment" : "truncated length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f3009068106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 669, + "comment" : "truncated length of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3051300b06072a8648ce3d0201068103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 670, + "comment" : "including undefined tags to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c3016260daa02aabb06072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 671, + "comment" : "including undefined tags to oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c301606072a8648ce3d0201260baa02aabb06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 672, + "comment" : "Replacing oid with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f3009050006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 673, + "comment" : "Replacing oid with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "3051300b06072a8648ce3d0201050003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 674, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301004072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 675, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301005072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 676, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301007072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 677, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301008072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 678, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "30563010ff072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 679, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020104052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 680, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020105052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 681, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020107052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 682, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020108052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 683, + "comment" : "changing tag value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d0201ff052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 684, + "comment" : "dropping value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "304f3009060006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 685, + "comment" : "dropping value of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3051300b06072a8648ce3d0201060003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 686, + "comment" : "modifying first byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305630100607288648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 687, + "comment" : "modifying first byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d02010605298104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 688, + "comment" : "modifying last byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d028106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 689, + "comment" : "modifying last byte of oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104008a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 690, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06062a8648ce3d0206052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 691, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06068648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 692, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06072a8648ce3d020106042b81040003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 693, + "comment" : "truncated oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055300f06072a8648ce3d020106048104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 694, + "comment" : "oid of size 4104 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082105b30821013068210082a8648ce3d0201000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 695, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3054300e06052b0e03021a06052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 696, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "30583012060960864801650304020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 697, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b0e03021a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 698, + "comment" : "wrong oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d0201060960864801650304020103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 699, + "comment" : "longer oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106082a8648ce3d02010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 700, + "comment" : "longer oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d020106062b8104000a0103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 701, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d021106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 702, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a3014060b2a8648ce3d02888080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 703, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104001a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 704, + "comment" : "oid with modified node", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301406072a8648ce3d020106092b810400888080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 705, + "comment" : "large integer in oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906102a8648ce3d028280808080808080800106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 706, + "comment" : "large integer in oid", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301906072a8648ce3d0201060e2b8104008280808080808080800a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 707, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106082a8648ce3d0201e006052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 708, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106082a808648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 709, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d020106062b8104000ae003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 710, + "comment" : "oid with invalid node", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301106072a8648ce3d020106062b808104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 711, + "comment" : "oid with 263 nodes", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082015b30820113068201082a8648ce3d0201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 712, + "comment" : "length of oid uses 6 instead of 5", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106062b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 713, + "comment" : "length of oid uses 4 instead of 5", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106042b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 714, + "comment" : "oid of size 4102 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082105b3082101306072a8648ce3d0201068210062b8104000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 715, + "comment" : "oid with 262 nodes", + "flags" : [ + "InvalidAsn" + ], + "public" : "3082015b3082011306072a8648ce3d0201068201062b8104000a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010103420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 716, + "comment" : "length of bit string uses long form encoding", + "flags" : [ + "InvalidAsn" + ], + "public" : "3057301006072a8648ce3d020106052b8104000a0381420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 717, + "comment" : "length of bit string contains a leading 0", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a038200420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 718, + "comment" : "length of bit string uses 67 instead of 66", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 719, + "comment" : "length of bit string uses 65 instead of 66", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 720, + "comment" : "uint32 overflow in length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301006072a8648ce3d020106052b8104000a038501000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 721, + "comment" : "uint64 overflow in length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305f301006072a8648ce3d020106052b8104000a03890100000000000000420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 722, + "comment" : "length of bit string = 2**31 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a03847fffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 723, + "comment" : "length of bit string = 2**32 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a0384ffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 724, + "comment" : "length of bit string = 2**40 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301006072a8648ce3d020106052b8104000a0385ffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 725, + "comment" : "length of bit string = 2**64 - 1", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301006072a8648ce3d020106052b8104000a0388ffffffffffffffff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 726, + "comment" : "incorrect length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03ff0004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 727, + "comment" : "replaced bit string by an indefinite length tag without termination", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03800004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 728, + "comment" : "lonely bit string tag", + "flags" : [ + "InvalidAsn" + ], + "public" : "3013301006072a8648ce3d020106052b8104000a03", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 729, + "comment" : "appending 0's to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 730, + "comment" : "prepending 0's to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a034400000004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 731, + "comment" : "appending null value to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3058301006072a8648ce3d020106052b8104000a03440004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 732, + "comment" : "prepending garbage to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305b301006072a8648ce3d020106052b8104000a234749817703420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 733, + "comment" : "prepending garbage to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a2346250003420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 734, + "comment" : "appending garbage to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305e301006072a8648ce3d020106052b8104000a234403420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670004deadbeef", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 735, + "comment" : "truncated length of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3014301006072a8648ce3d020106052b8104000a0381", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 736, + "comment" : "including undefined tags to bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305c301006072a8648ce3d020106052b8104000a2348aa02aabb03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 737, + "comment" : "Replacing bit string with NULL", + "flags" : [ + "InvalidAsn" + ], + "public" : "3014301006072a8648ce3d020106052b8104000a0500", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 738, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a01420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 739, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a02420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 740, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a04420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 741, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a05420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 742, + "comment" : "changing tag value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000aff420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 743, + "comment" : "dropping value of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3014301006072a8648ce3d020106052b8104000a0300", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 744, + "comment" : "modifying first byte of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420204e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 745, + "comment" : "modifying last byte of bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32e7", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 746, + "comment" : "truncated bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a03410004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 747, + "comment" : "truncated bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3055301006072a8648ce3d020106052b8104000a034104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 748, + "comment" : "bit string of size 4163 to check for overflows", + "flags" : [ + "InvalidAsn" + ], + "public" : "30821059301006072a8648ce3d020106052b8104000a038210430004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da32670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 749, + "comment" : "declaring bits as unused in bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03420104e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 750, + "comment" : "unused bits in bit string", + "flags" : [ + "InvalidAsn" + ], + "public" : "305a301006072a8648ce3d020106052b8104000a03462004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da326701020304", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 751, + "comment" : "unused bits in empty bit-string", + "flags" : [ + "InvalidAsn" + ], + "public" : "3015301006072a8648ce3d020106052b8104000a030103", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + }, + { + "tcId" : 752, + "comment" : "128 unused bits", + "flags" : [ + "InvalidAsn" + ], + "public" : "3056301006072a8648ce3d020106052b8104000a03428004e03faca42a8b811759211d49b69dd0e0a686b28ff7b5817789a2f80050791335bf34cf495029075de25603fd56dd3cef36ee8503b9f3b0c1340c8e4012da3267", + "private" : "0495800a83e6c1d61886d332e2613aa3f70df22865b0387ca6ca195cfcd2b2b1", + "shared" : "ebdca74dbf2c8ef63af8d86e0e0ee4511399bc08a395c4ea050bab43a29d2646", + "result" : "acceptable" + } + ] + } + ] +} diff --git a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h index 736737fd..556c2356 100644 --- a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h +++ b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h @@ -1,4 +1,4 @@ -/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */ +/* Note: this file was autogenerated using tests_wycheproof_generate_ecdsa.py. Do not edit. */ #define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS (463) typedef struct { diff --git a/tools/tests_wycheproof_generate_ecdh.py b/tools/tests_wycheproof_generate_ecdh.py new file mode 100755 index 00000000..97551d01 --- /dev/null +++ b/tools/tests_wycheproof_generate_ecdh.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 Random "Randy" Lattice and Sean Andersen +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php. +''' +Generate a C file with ECDH testvectors from the Wycheproof project. +''' + +import json +import sys + +from binascii import hexlify, unhexlify +from wycheproof_utils import to_c_array + +def should_skip_flags(test_vector_flags): + # skip these vectors because they are for ASN.1 encoding issues and other curves. + # for more details, see https://github.com/bitcoin-core/secp256k1/pull/1492#discussion_r1572491546 + flags_to_skip = {"InvalidAsn", "WrongCurve"} + return any(flag in test_vector_flags for flag in flags_to_skip) + +def should_skip_tcid(test_vector_tcid): + # We skip some test case IDs that have a public key whose custom ASN.1 representation explicitly + # encodes some curve parameters that are invalid. libsecp256k1 never parses this part so we do + # not care testing those. See https://github.com/bitcoin-core/secp256k1/pull/1492#discussion_r1572491546 + tcids_to_skip = [496, 497, 502, 503, 504, 505, 507] + return test_vector_tcid in tcids_to_skip + +# Rudimentary ASN.1 DER public key parser. +# This should not be used for anything other than parsing Wycheproof test vectors. +def parse_der_pk(s): + tag = s[0] + L = int(s[1]) + offset = 0 + if L & 0x80: + if L == 0x81: + L = int(s[2]) + offset = 1 + elif L == 0x82: + L = 256 * int(s[2]) + int(s[3]) + offset = 2 + else: + raise ValueError("invalid L") + value = s[(offset + 2):(L + 2 + offset)] + rest = s[(L + 2 + offset):] + + if len(rest) > 0 or tag == 0x06: # OBJECT IDENTIFIER + return parse_der_pk(rest) + if tag == 0x03: # BIT STRING + return value + if tag == 0x30: # SEQUENCE + return parse_der_pk(value) + raise ValueError("unknown tag") + +def parse_public_key(pk): + der_pub_key = parse_der_pk(unhexlify(pk)) # Convert back to str and strip off the `0x` + return hexlify(der_pub_key).decode()[2:] + +def normalize_private_key(sk): + # Ensure the private key is at most 64 characters long, retaining the last 64 if longer. + # In the wycheproof test vectors, some private keys have leading zeroes + normalized = sk[-64:].zfill(64) + if len(normalized) != 64: + raise ValueError("private key must be exactly 64 characters long.") + return normalized + +def normalize_expected_result(er): + result_mapping = {"invalid": 0, "valid": 1, "acceptable": 1} + return result_mapping[er] + +filename_input = sys.argv[1] + +with open(filename_input) as f: + doc = json.load(f) + +num_vectors = 0 +offset_sk_running, offset_pk_running, offset_shared = 0, 0, 0 +test_vectors_out = "" +private_keys = "" +shared_secrets = "" +public_keys = "" +cache_sks = {} +cache_public_keys = {} + +for group in doc['testGroups']: + assert group["type"] == "EcdhTest" + assert group["curve"] == "secp256k1" + for test_vector in group['tests']: + if should_skip_flags(test_vector['flags']) or should_skip_tcid(test_vector['tcId']): + continue + + public_key = parse_public_key(test_vector['public']) + private_key = normalize_private_key(test_vector['private']) + expected_result = normalize_expected_result(test_vector['result']) + + # // 2 to convert hex to byte length + shared_size = len(test_vector['shared']) // 2 + sk_size = len(private_key) // 2 + pk_size = len(public_key) // 2 + + new_sk = False + sk = to_c_array(private_key) + sk_offset = offset_sk_running + + # check for repeated sk + if sk not in cache_sks: + if num_vectors != 0 and sk_size != 0: + private_keys += ",\n " + cache_sks[sk] = offset_sk_running + private_keys += sk + new_sk = True + else: + sk_offset = cache_sks[sk] + + new_pk = False + pk = to_c_array(public_key) if public_key != '0x' else '' + + pk_offset = offset_pk_running + # check for repeated pk + if pk not in cache_public_keys: + if num_vectors != 0 and len(pk) != 0: + public_keys += ",\n " + cache_public_keys[pk] = offset_pk_running + public_keys += pk + new_pk = True + else: + pk_offset = cache_public_keys[pk] + + + shared_secrets += ",\n " if num_vectors and shared_size else "" + shared_secrets += to_c_array(test_vector['shared']) + wycheproof_tcid = test_vector['tcId'] + + test_vectors_out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n" + test_vectors_out += f" {{{pk_offset}, {pk_size}, {sk_offset}, {sk_size}, {offset_shared}, {shared_size}, {expected_result}, {wycheproof_tcid} }},\n" + if new_sk: + offset_sk_running += sk_size + if new_pk: + offset_pk_running += pk_size + offset_shared += shared_size + num_vectors += 1 + +struct_definition = """ +typedef struct { + size_t pk_offset; + size_t pk_len; + size_t sk_offset; + size_t sk_len; + size_t shared_offset; + size_t shared_len; + int expected_result; + int wycheproof_tcid; +} wycheproof_ecdh_testvector; +""" + +print("/* Note: this file was autogenerated using tests_wycheproof_ecdh.py. Do not edit. */") +print(f"#define SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})") + +print(struct_definition) + +print("static const unsigned char wycheproof_ecdh_private_keys[] = { " + private_keys + "};\n") +print("static const unsigned char wycheproof_ecdh_public_keys[] = { " + public_keys + "};\n") +print("static const unsigned char wycheproof_ecdh_shared_secrets[] = { " + shared_secrets + "};\n") + +print("static const wycheproof_ecdh_testvector testvectors[SECP256K1_ECDH_WYCHEPROOF_NUMBER_TESTVECTORS] = {") +print(test_vectors_out) +print("};") diff --git a/tools/tests_wycheproof_generate.py b/tools/tests_wycheproof_generate_ecdsa.py similarity index 95% rename from tools/tests_wycheproof_generate.py rename to tools/tests_wycheproof_generate_ecdsa.py index b26dfa89..91ff9e31 100755 --- a/tools/tests_wycheproof_generate.py +++ b/tools/tests_wycheproof_generate_ecdsa.py @@ -9,6 +9,8 @@ Generate a C file with ECDSA testvectors from the Wycheproof project. import json import sys +from wycheproof_utils import to_c_array + filename_input = sys.argv[1] with open(filename_input) as f: @@ -16,12 +18,6 @@ with open(filename_input) as f: num_groups = len(doc['testGroups']) -def to_c_array(x): - if x == "": - return "" - s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2])) - return "0x" + s - num_vectors = 0 offset_msg_running, offset_pk_running, offset_sig = 0, 0, 0 @@ -101,7 +97,7 @@ typedef struct { """ -print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */") +print("/* Note: this file was autogenerated using tests_wycheproof_generate_ecdsa.py. Do not edit. */") print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})") print(struct_definition) diff --git a/tools/wycheproof_utils.py b/tools/wycheproof_utils.py new file mode 100644 index 00000000..e8d2edd0 --- /dev/null +++ b/tools/wycheproof_utils.py @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Random "Randy" Lattice and Sean Andersen +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php. +''' +Utility functions for generating C files for testvectors from the Wycheproof project. +''' + +def to_c_array(x): + if x == "": + return "" + s = ',0x'.join(a + b for a, b in zip(x[::2], x[1::2])) + return "0x" + s From d73ed994799ef632ca4a26b4e73f51ec5cfaad79 Mon Sep 17 00:00:00 2001 From: RandomLattice <128569685+RandomLattice@users.noreply.github.com> Date: Tue, 13 May 2025 19:43:09 +0900 Subject: [PATCH 149/383] tests: update wycheproof files Wycheproof ownership was recently moved to C2SP (https://github.com/C2SP/wycheproof). This PR updates all references to the new URL and bumps to the latest version of the vector files. This commit does not change the content of processed .h testvector files. To test: ``` make clean-testvectors testvectors ``` See: https://github.com/bitcoin-core/secp256k1/pull/1492#discussion_r1572443456 Co-authored-by: Sean Andersen <6730974+andozw@users.noreply.github.com> --- CHANGELOG.md | 2 +- src/wycheproof/WYCHEPROOF_COPYING | 12 ++++++------ src/wycheproof/ecdh_secp256k1_test.json | 5 ++++- .../ecdsa_secp256k1_sha256_bitcoin_test.json | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70421711..12abd357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,7 +115,7 @@ We strongly recommend updating to 0.3.1 if you use or plan to use Clang >=14 to - Fix "constant-timeness" issue with Clang >=14 that could leave applications using libsecp256k1 vulnerable to a timing side-channel attack. The fix avoids secret-dependent control flow and secret-dependent memory accesses in conditional moves of memory objects when libsecp256k1 is compiled with Clang >=14. #### Added - - Added tests against [Project Wycheproof's](https://github.com/google/wycheproof/) set of ECDSA test vectors (Bitcoin "low-S" variant), a fixed set of test cases designed to trigger various edge cases. + - Added tests against [Project Wycheproof's](https://github.com/C2SP/wycheproof/) set of ECDSA test vectors (Bitcoin "low-S" variant), a fixed set of test cases designed to trigger various edge cases. #### Changed - Increased minimum required CMake version to 3.13. CMake builds remain experimental. diff --git a/src/wycheproof/WYCHEPROOF_COPYING b/src/wycheproof/WYCHEPROOF_COPYING index efe3e8bf..26957043 100644 --- a/src/wycheproof/WYCHEPROOF_COPYING +++ b/src/wycheproof/WYCHEPROOF_COPYING @@ -1,12 +1,12 @@ * The file `ecdsa_secp256k1_sha256_bitcoin_test.json` in this directory - comes from Google's project Wycheproof with git commit - `b063b4aedae951c69df014cd25fa6d69ae9e8cb9`, see - https://github.com/google/wycheproof/blob/b063b4aedae951c69df014cd25fa6d69ae9e8cb9/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json + comes from project Wycheproof with git commit + `df4e933efef449fc88af0c06e028d425d84a9495`, see + https://github.com/C2SP/wycheproof/blob/df4e933efef449fc88af0c06e028d425d84a9495/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json * The file `ecdh_secp256k1_test.json` in this directory - comes from Google's project Wycheproof with git commit - `d9f6ec7d8bd8c96da05368999094e4a75ba5cb3d`, see - https://github.com/google/wycheproof/blob/d9f6ec7d8bd8c96da05368999094e4a75ba5cb3d/testvectors_v1/ecdh_secp256k1_test.json + comes from project Wycheproof with git commit + `df4e933efef449fc88af0c06e028d425d84a9495`, see + https://github.com/C2SP/wycheproof/blob/df4e933efef449fc88af0c06e028d425d84a9495/testvectors_v1/ecdh_secp256k1_test.json * The file `ecdsa_secp256k1_sha256_bitcoin_test.h` is generated from `ecdsa_secp256k1_sha256_bitcoin_test.json` using the script diff --git a/src/wycheproof/ecdh_secp256k1_test.json b/src/wycheproof/ecdh_secp256k1_test.json index 16db6189..71da9472 100644 --- a/src/wycheproof/ecdh_secp256k1_test.json +++ b/src/wycheproof/ecdh_secp256k1_test.json @@ -1,7 +1,6 @@ { "algorithm" : "ECDH", "schema" : "ecdh_test_schema.json", - "generatorVersion" : "0.9rc5", "numberOfTests" : 752, "header" : [ "Test vectors of type EcdhTest are intended for", @@ -124,6 +123,10 @@ "testGroups" : [ { "type" : "EcdhTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.9rc5" + }, "curve" : "secp256k1", "encoding" : "asn", "tests" : [ diff --git a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json index 9c907479..aa0cc8a4 100644 --- a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json +++ b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json @@ -10,7 +10,7 @@ "notes" : { "ArithmeticError" : { "bugType" : "EDGE_CASE", - "description" : "Some implementations of ECDSA have arithmetic errors that occur when intermediate results have extreme values. This test vector has been constructed to test such occurences.", + "description" : "Some implementations of ECDSA have arithmetic errors that occur when intermediate results have extreme values. This test vector has been constructed to test such occurrences.", "cves" : [ "CVE-2017-18146" ] @@ -95,7 +95,7 @@ }, "SignatureMalleabilityBitcoin" : { "bugType" : "SIGNATURE_MALLEABILITY", - "description" : "\"BitCoins\"-curves are curves where signature malleability can be a serious issue. An implementation should only accept a signature s where s < n/2. If an implementation is not meant for uses cases that require signature malleability then this implemenation should be tested with another set of test vectors.", + "description" : "\"BitCoins\"-curves are curves where signature malleability can be a serious issue. An implementation should only accept a signature s where s < n/2. If an implementation is not meant for uses cases that require signature malleability then this implementation should be tested with another set of test vectors.", "effect" : "In bitcoin exchanges, it may be used to make a double deposits or double withdrawals", "links" : [ "https://en.bitcoin.it/wiki/Transaction_malleability", From 05445377f4a1d5837b9e1616c8f1abfdf72ad9c2 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 27 Mar 2025 00:46:30 +0100 Subject: [PATCH 150/383] bench_ecmult: add benchmark for ecmult_const_xonly --- src/bench_ecmult.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 172292d5..b2bab65d 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -56,6 +56,7 @@ typedef struct { /* Benchmark output. */ secp256k1_gej* output; + secp256k1_fe* output_xonly; } bench_data; /* Hashes x into [0, POINTS) twice and store the result in offset1 and offset2. */ @@ -123,6 +124,32 @@ static void bench_ecmult_const_teardown(void* arg, int iters) { bench_ecmult_teardown_helper(data, &data->offset1, &data->offset2, NULL, iters); } +static void bench_ecmult_const_xonly(void* arg, int iters) { + bench_data* data = (bench_data*)arg; + int i; + + for (i = 0; i < iters; ++i) { + const secp256k1_ge* pubkey = &data->pubkeys[(data->offset1+i) % POINTS]; + const secp256k1_scalar* scalar = &data->scalars[(data->offset2+i) % POINTS]; + int known_on_curve = 1; + secp256k1_ecmult_const_xonly(&data->output_xonly[i], &pubkey->x, NULL, scalar, known_on_curve); + } +} + +static void bench_ecmult_const_xonly_teardown(void* arg, int iters) { + bench_data* data = (bench_data*)arg; + int i; + + /* verify by comparing with x coordinate of regular ecmult result */ + for (i = 0; i < iters; ++i) { + const secp256k1_gej* pubkey_gej = &data->pubkeys_gej[(data->offset1+i) % POINTS]; + const secp256k1_scalar* scalar = &data->scalars[(data->offset2+i) % POINTS]; + secp256k1_gej expected_gej; + secp256k1_ecmult(&expected_gej, pubkey_gej, scalar, NULL); + CHECK(secp256k1_gej_eq_x_var(&data->output_xonly[i], &expected_gej)); + } +} + static void bench_ecmult_1p(void* arg, int iters) { bench_data* data = (bench_data*)arg; int i; @@ -171,6 +198,8 @@ static void run_ecmult_bench(bench_data* data, int iters) { run_benchmark(str, bench_ecmult_gen, bench_ecmult_setup, bench_ecmult_gen_teardown, data, 10, iters); sprintf(str, "ecmult_const"); run_benchmark(str, bench_ecmult_const, bench_ecmult_setup, bench_ecmult_const_teardown, data, 10, iters); + sprintf(str, "ecmult_const_xonly"); + run_benchmark(str, bench_ecmult_const_xonly, bench_ecmult_setup, bench_ecmult_const_xonly_teardown, data, 10, iters); /* ecmult with non generator point */ sprintf(str, "ecmult_1p"); run_benchmark(str, bench_ecmult_1p, bench_ecmult_setup, bench_ecmult_1p_teardown, data, 10, iters); @@ -319,6 +348,7 @@ int main(int argc, char **argv) { data.pubkeys_gej = malloc(sizeof(secp256k1_gej) * POINTS); data.expected_output = malloc(sizeof(secp256k1_gej) * (iters + 1)); data.output = malloc(sizeof(secp256k1_gej) * (iters + 1)); + data.output_xonly = malloc(sizeof(secp256k1_fe) * (iters + 1)); /* Generate a set of scalars, and private/public keypairs. */ secp256k1_gej_set_ge(&data.pubkeys_gej[0], &secp256k1_ge_const_g); @@ -361,6 +391,7 @@ int main(int argc, char **argv) { free(data.pubkeys); free(data.pubkeys_gej); free(data.seckeys); + free(data.output_xonly); free(data.output); free(data.expected_output); From 3a4f448cb46eae2aec991b95e4c686de2a4ba906 Mon Sep 17 00:00:00 2001 From: "Peter.Dettman" Date: Tue, 20 May 2025 17:48:22 +0700 Subject: [PATCH 151/383] Assert field magnitude at control-flow join --- src/ecmult_const_impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index 0d78f7c3..4f662091 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -373,6 +373,8 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, } } + SECP256K1_FE_VERIFY_MAGNITUDE(&g, 2); + /* Compute base point P = (n*g, g^2), the effective affine version of (n*g, g^2, v), which has * corresponding affine X coordinate n/d. */ secp256k1_fe_mul(&p.x, &g, n); From 3af71987a8f18b96dd21d8a4642df6f9e6e4c9c7 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 30 May 2025 11:59:31 +0100 Subject: [PATCH 152/383] cmake: Bump minimum required CMake version to 3.22 Ubuntu 20.04 LTS has reached the end of standard support. There no longer appear to be compelling reasons to maintain compatibility with CMake 3.16. The new suggested minimum, CMake 3.22, is shipped with Ubuntu 22.04 LTS, which is supported until April 2027. This change also introduces new CMake policies, from CMP0098 to CMP0128. --- CMakeLists.txt | 13 +------------ CMakePresets.json | 1 - src/CMakeLists.txt | 20 ++++++-------------- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b773714..b51576c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.22) #============================= # Project / Package metadata @@ -15,17 +15,6 @@ project(libsecp256k1 enable_testing() list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) -if(CMAKE_VERSION VERSION_LESS 3.21) - # Emulates CMake 3.21+ behavior. - if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - set(PROJECT_IS_TOP_LEVEL ON) - set(${PROJECT_NAME}_IS_TOP_LEVEL ON) - else() - set(PROJECT_IS_TOP_LEVEL OFF) - set(${PROJECT_NAME}_IS_TOP_LEVEL OFF) - endif() -endif() - # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html diff --git a/CMakePresets.json b/CMakePresets.json index b35cd805..6ed52b8f 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,5 +1,4 @@ { - "cmakeMinimumRequired": {"major": 3, "minor": 21, "patch": 0}, "version": 3, "configurePresets": [ { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f31b8c8f..0e2a27b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,20 +48,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION} ) elseif(APPLE) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) - math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1") - set_target_properties(secp256k1 PROPERTIES - MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version} - MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION} - ) - unset(${PROJECT_NAME}_compatibility_version) - elseif(BUILD_SHARED_LIBS) - message(WARNING - "The 'compatibility version' and 'current version' values of the DYLIB " - "will diverge from the values set by the GNU Libtool. To ensure " - "compatibility, it is recommended to upgrade CMake to at least version 3.17." - ) - endif() + math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1") + set_target_properties(secp256k1 PROPERTIES + MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version} + MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION} + ) + unset(${PROJECT_NAME}_compatibility_version) elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(${PROJECT_NAME}_windows "secp256k1") if(MSVC) From c32715b2a0f574dba7bb2a953b97bdb0e3e9b2b0 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 4 Jun 2025 13:13:33 +0100 Subject: [PATCH 153/383] cmake, move-only: Move module option processing to `src/CMakeLists.txt` This change simplifies the following commit. --- CMakeLists.txt | 34 ---------------------------------- src/CMakeLists.txt | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b51576c8..02abaa97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,40 +52,6 @@ option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON) option(SECP256K1_ENABLE_MODULE_MUSIG "Enable musig module." ON) option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON) -# Processing must be done in a topological sorting of the dependency graph -# (dependent module first). -if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) -endif() - -if(SECP256K1_ENABLE_MODULE_MUSIG) - if(DEFINED SECP256K1_ENABLE_MODULE_SCHNORRSIG AND NOT SECP256K1_ENABLE_MODULE_SCHNORRSIG) - message(FATAL_ERROR "Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.") - endif() - set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) - add_compile_definitions(ENABLE_MODULE_MUSIG=1) -endif() - -if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - if(DEFINED SECP256K1_ENABLE_MODULE_EXTRAKEYS AND NOT SECP256K1_ENABLE_MODULE_EXTRAKEYS) - message(FATAL_ERROR "Module dependency error: You have disabled the extrakeys module explicitly, but it is required by the schnorrsig module.") - endif() - set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON) - add_compile_definitions(ENABLE_MODULE_SCHNORRSIG=1) -endif() - -if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) - add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1) -endif() - -if(SECP256K1_ENABLE_MODULE_RECOVERY) - add_compile_definitions(ENABLE_MODULE_RECOVERY=1) -endif() - -if(SECP256K1_ENABLE_MODULE_ECDH) - add_compile_definitions(ENABLE_MODULE_ECDH=1) -endif() - option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF) if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS) add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e2a27b5..c3cdd959 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,40 @@ # Must be included before CMAKE_INSTALL_INCLUDEDIR is used. include(GNUInstallDirs) +# Processing must be done in a topological sorting of the dependency graph +# (dependent module first). +if(SECP256K1_ENABLE_MODULE_ELLSWIFT) + add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) +endif() + +if(SECP256K1_ENABLE_MODULE_MUSIG) + if(DEFINED SECP256K1_ENABLE_MODULE_SCHNORRSIG AND NOT SECP256K1_ENABLE_MODULE_SCHNORRSIG) + message(FATAL_ERROR "Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.") + endif() + set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) + add_compile_definitions(ENABLE_MODULE_MUSIG=1) +endif() + +if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) + if(DEFINED SECP256K1_ENABLE_MODULE_EXTRAKEYS AND NOT SECP256K1_ENABLE_MODULE_EXTRAKEYS) + message(FATAL_ERROR "Module dependency error: You have disabled the extrakeys module explicitly, but it is required by the schnorrsig module.") + endif() + set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON) + add_compile_definitions(ENABLE_MODULE_SCHNORRSIG=1) +endif() + +if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) + add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1) +endif() + +if(SECP256K1_ENABLE_MODULE_RECOVERY) + add_compile_definitions(ENABLE_MODULE_RECOVERY=1) +endif() + +if(SECP256K1_ENABLE_MODULE_ECDH) + add_compile_definitions(ENABLE_MODULE_ECDH=1) +endif() + add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL precomputed_ecmult.c precomputed_ecmult_gen.c From 6f67151ee2e94a0ce14522632edcc153f1cde7e6 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:46:10 +0100 Subject: [PATCH 154/383] cmake: Use `PUBLIC_HEADER` target property This change simplifies the installation logic. --- src/CMakeLists.txt | 47 ++++++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c3cdd959..bed1b533 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,15 @@ -# Must be included before CMAKE_INSTALL_INCLUDEDIR is used. -include(GNUInstallDirs) +add_library(secp256k1) + +set_property(TARGET secp256k1 PROPERTY PUBLIC_HEADER + ${PROJECT_SOURCE_DIR}/include/secp256k1.h + ${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h +) # Processing must be done in a topological sorting of the dependency graph # (dependent module first). if(SECP256K1_ENABLE_MODULE_ELLSWIFT) add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_ellswift.h) endif() if(SECP256K1_ENABLE_MODULE_MUSIG) @@ -13,6 +18,7 @@ if(SECP256K1_ENABLE_MODULE_MUSIG) endif() set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) add_compile_definitions(ENABLE_MODULE_MUSIG=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_musig.h) endif() if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) @@ -21,18 +27,22 @@ if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) endif() set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON) add_compile_definitions(ENABLE_MODULE_SCHNORRSIG=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h) endif() if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h) endif() if(SECP256K1_ENABLE_MODULE_RECOVERY) add_compile_definitions(ENABLE_MODULE_RECOVERY=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h) endif() if(SECP256K1_ENABLE_MODULE_ECDH) add_compile_definitions(ENABLE_MODULE_ECDH=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h) endif() add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL @@ -42,7 +52,7 @@ add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL # Add objects explicitly rather than linking to the object libs to keep them # from being exported. -add_library(secp256k1 secp256k1.c $) +target_sources(secp256k1 PRIVATE secp256k1.c $) add_library(secp256k1_asm INTERFACE) if(SECP256K1_ASM STREQUAL "arm32") @@ -68,7 +78,6 @@ set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE target_include_directories(secp256k1 INTERFACE # Add the include path for parent projects so that they don't have to manually add it. $>:${PROJECT_SOURCE_DIR}/include>> - $ ) # This emulates Libtool to make sure Libtool and CMake agree on the ABI version, @@ -136,36 +145,16 @@ if(SECP256K1_BUILD_CTIME_TESTS) endif() if(SECP256K1_INSTALL) + include(GNUInstallDirs) + target_include_directories(secp256k1 INTERFACE + $ + ) install(TARGETS secp256k1 EXPORT ${PROJECT_NAME}-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) - set(${PROJECT_NAME}_headers - "${PROJECT_SOURCE_DIR}/include/secp256k1.h" - "${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h" - ) - if(SECP256K1_ENABLE_MODULE_ECDH) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h") - endif() - if(SECP256K1_ENABLE_MODULE_RECOVERY) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h") - endif() - if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h") - endif() - if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h") - endif() - if(SECP256K1_ENABLE_MODULE_MUSIG) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_musig.h") - endif() - if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ellswift.h") - endif() - install(FILES ${${PROJECT_NAME}_headers} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install(EXPORT ${PROJECT_NAME}-targets From 3f31ac43e09df14e19ea1d90684f757bed17d299 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 4 Jun 2025 19:13:49 +0100 Subject: [PATCH 155/383] doc: Promote "Building with CMake" to standard procedure The CMake-based build system has demonstrated its maturity through its use in Bitcoin Core 29.0. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f7a59b2b..5f35b37b 100644 --- a/README.md +++ b/README.md @@ -108,8 +108,8 @@ Building with Autotools To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. -Building with CMake (experimental) ----------------------------------- +Building with CMake +------------------- To maintain a pristine source tree, CMake encourages to perform an out-of-source build by using a separate dedicated build tree. From 37dd422b5cecad54db40a7304f03bff552d8d9fb Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 11 Jun 2025 01:01:34 +0100 Subject: [PATCH 156/383] cmake: Emulate Libtool's behavior on FreeBSD --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e2a27b5..97b5b592 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,7 +43,7 @@ math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${ set_target_properties(secp256k1 PROPERTIES SOVERSION ${${PROJECT_NAME}_soversion} ) -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") +if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$") set_target_properties(secp256k1 PROPERTIES VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION} ) From 819210974bd91bbbe6cc2e691b12c3e6130aa9d5 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sat, 7 Jun 2025 16:15:29 +0200 Subject: [PATCH 157/383] README: add link to musig example, generalize module enabling hint Co-authored-by: Jonas Nick --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f35b37b..3d3118ad 100644 --- a/README.md +++ b/README.md @@ -151,8 +151,9 @@ Usage examples can be found in the [examples](examples) directory. To compile th * [Schnorr signatures example](examples/schnorr.c) * [Deriving a shared secret (ECDH) example](examples/ecdh.c) * [ElligatorSwift key exchange example](examples/ellswift.c) + * [MuSig2 Schnorr multi-signatures example](examples/musig.c) -To compile the Schnorr signature and ECDH examples, you also need to configure with `--enable-module-schnorrsig` and `--enable-module-ecdh`. +To compile the examples, make sure the corresponding modules are enabled. Benchmark ------------ From 145ae3e28d587dd04866ec5893be9270bc99289a Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Tue, 3 Jun 2025 18:17:33 +0000 Subject: [PATCH 158/383] cmake: add a helper for linking into static libs Parent projects (Bitcoin Core in this case) may wish to include secp256k1 in another static library (libbitcoinkernel) so that users are not forced to bring their own static libsecp256k1. Unfortunately, CMake lacks the machinery to link (combine) one static lib into another. To work around this, secp256k1_objs is exposed as an interface library which parent projects can "link" into static libs.. --- src/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bed1b533..291e0cbb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -54,6 +54,11 @@ add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL # from being exported. target_sources(secp256k1 PRIVATE secp256k1.c $) +# Create a helper lib that parent projects can use to link secp256k1 into a +# static lib. +add_library(secp256k1_objs INTERFACE) +target_sources(secp256k1_objs INTERFACE $ $) + add_library(secp256k1_asm INTERFACE) if(SECP256K1_ASM STREQUAL "arm32") add_library(secp256k1_asm_arm OBJECT EXCLUDE_FROM_ALL) @@ -61,6 +66,7 @@ if(SECP256K1_ASM STREQUAL "arm32") asm/field_10x26_arm.s ) target_sources(secp256k1 PRIVATE $) + target_sources(secp256k1_objs INTERFACE $) target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm) endif() @@ -75,10 +81,13 @@ endif() get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE) set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic}) +# Add the include path for parent projects so that they don't have to manually add it. target_include_directories(secp256k1 INTERFACE - # Add the include path for parent projects so that they don't have to manually add it. $>:${PROJECT_SOURCE_DIR}/include>> ) +set_target_properties(secp256k1_objs PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "$" +) # This emulates Libtool to make sure Libtool and CMake agree on the ABI version, # see below "Calculate the version variables" in build-aux/ltmain.sh. From b77aae9226b95d65da53dad3d418229adc25311a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 19 Jun 2025 18:57:48 +0100 Subject: [PATCH 159/383] ci: Rename Docker image tag to reflect architecture --- .github/workflows/ci.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3108d6b..007e8ff9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: uses: docker/build-push-action@v5 with: file: ./ci/linux-debian.Dockerfile - tags: linux-debian-image + tags: x64-debian-image cache-from: type=gha cache-to: type=gha,mode=min @@ -106,7 +106,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -142,7 +142,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -174,7 +174,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -215,7 +215,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -258,7 +258,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -290,7 +290,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -333,7 +333,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -377,7 +377,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -428,7 +428,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -471,7 +471,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -678,7 +678,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -697,7 +697,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: linux-debian-image + tag: x64-debian-image command: | g++ -Werror include/*.h clang -Werror -x c++-header include/*.h From bcf77346b9d5b5084ff158c4d84f719da690d33c Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 19 Jun 2025 19:09:18 +0100 Subject: [PATCH 160/383] ci: Add `arm64` architecture to `docker_cache` job --- .github/workflows/ci.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 007e8ff9..459875d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,8 +46,18 @@ env: jobs: docker_cache: - name: "Build Docker image" - runs-on: ubuntu-latest + name: "Build ${{ matrix.arch }} Docker image" + runs-on: ${{ matrix.runner }} + + strategy: + fail-fast: false + matrix: + include: + - arch: x64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + steps: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -60,7 +70,7 @@ jobs: uses: docker/build-push-action@v5 with: file: ./ci/linux-debian.Dockerfile - tags: x64-debian-image + tags: ${{ matrix.arch }}-debian-image cache-from: type=gha cache-to: type=gha,mode=min From e814b79a8b7587b39432048a170e005c9efaa1cc Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:08:32 +0100 Subject: [PATCH 161/383] ci: Switch `arm64_debian` from QEMU to native `arm64` Docker image --- .github/workflows/ci.yml | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 459875d2..448475e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,7 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=min - linux_debian: + x86_64-debian: name: "x86_64: Linux (Debian stable)" runs-on: ubuntu-latest needs: docker_cache @@ -231,15 +231,13 @@ jobs: uses: ./.github/actions/print-logs if: ${{ !cancelled() }} - arm64_debian: - name: "ARM64: Linux (Debian stable, QEMU)" - runs-on: ubuntu-latest + arm64-debian: + name: "arm64: Linux (Debian stable)" + runs-on: ubuntu-24.04-arm needs: docker_cache env: - WRAPPER_CMD: 'qemu-aarch64' SECP256K1_TEST_ITERS: 16 - HOST: 'aarch64-linux-gnu' WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' @@ -248,27 +246,25 @@ jobs: MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' + CC: ${{ matrix.cc }} strategy: fail-fast: false matrix: - configuration: - - env_vars: { } # gcc - - env_vars: # clang - CC: 'clang --target=aarch64-linux-gnu' - - env_vars: # clang-snapshot - CC: 'clang-snapshot --target=aarch64-linux-gnu' + cc: + - 'gcc' + - 'clang' + - 'clang-snapshot' steps: - name: Checkout uses: actions/checkout@v4 - name: CI script - env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image + tag: arm64-debian-image - name: Print logs uses: ./.github/actions/print-logs From 5fafdfc30f3ed113d8037aa2e9ee12134e77df33 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:09:01 +0100 Subject: [PATCH 162/383] ci: Move `gcc-snapshot` build for `arm64` from Cirrus to GHA --- .cirrus.yml | 18 ------------------ .github/workflows/ci.yml | 1 + 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 023cd191..b3a5cecb 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -63,24 +63,6 @@ linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER test_script: - docker run --rm --mount "type=bind,src=./,dst=/ci_secp256k1" --env-file /tmp/env --replace --name "ci_secp256k1_arm" "ci_secp256k1_arm" bash -c "cd /ci_secp256k1/ && ./ci/ci.sh" -task: - name: "ARM64: Linux (Debian stable)" - persistent_worker: - labels: - type: arm64 - env: - ECDH: yes - RECOVERY: yes - EXTRAKEYS: yes - SCHNORRSIG: yes - MUSIG: yes - ELLSWIFT: yes - matrix: - # Currently only gcc-snapshot, the other compilers are tested on GHA with QEMU - - env: { CC: 'gcc-snapshot' } - << : *LINUX_ARM64_CONTAINER - << : *CAT_LOGS - task: name: "ARM64: Linux (Debian stable), Valgrind" persistent_worker: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 448475e7..d1e3096e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -254,6 +254,7 @@ jobs: cc: - 'gcc' - 'clang' + - 'gcc-snapshot' - 'clang-snapshot' steps: From 004f57fcd86de3ea8cb0e6a16f5bb665db9d1ed4 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 19 Jun 2025 20:09:36 +0100 Subject: [PATCH 163/383] ci: Move Valgrind build for `arm64` from Cirrus to GHA --- .cirrus.yml | 86 ---------------------------------------- .github/workflows/ci.yml | 38 +++++++++++++----- 2 files changed, 29 insertions(+), 95 deletions(-) delete mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index b3a5cecb..00000000 --- a/.cirrus.yml +++ /dev/null @@ -1,86 +0,0 @@ -env: - ### cirrus config - CIRRUS_CLONE_DEPTH: 1 - ### compiler options - HOST: - WRAPPER_CMD: - # Specific warnings can be disabled with -Wno-error=foo. - # -pedantic-errors is not equivalent to -Werror=pedantic and thus not implied by -Werror according to the GCC manual. - WERROR_CFLAGS: -Werror -pedantic-errors - MAKEFLAGS: -j4 - BUILD: check - ### secp256k1 config - ECMULTWINDOW: 15 - ECMULTGENKB: 22 - ASM: no - WIDEMUL: auto - WITH_VALGRIND: yes - EXTRAFLAGS: - ### secp256k1 modules - EXPERIMENTAL: no - ECDH: no - RECOVERY: no - EXTRAKEYS: no - SCHNORRSIG: no - MUSIG: no - ELLSWIFT: no - ### test options - SECP256K1_TEST_ITERS: 64 - BENCH: yes - SECP256K1_BENCH_ITERS: 2 - CTIMETESTS: yes - SYMBOL_CHECK: yes - VIRTUAL_ENV: /root/venv - # Compile and run the tests - EXAMPLES: yes - -cat_logs_snippet: &CAT_LOGS - always: - cat_tests_log_script: - - cat tests.log || true - cat_noverify_tests_log_script: - - cat noverify_tests.log || true - cat_exhaustive_tests_log_script: - - cat exhaustive_tests.log || true - cat_ctime_tests_log_script: - - cat ctime_tests.log || true - cat_bench_log_script: - - cat bench.log || true - cat_config_log_script: - - cat config.log || true - cat_test_env_script: - - cat test_env.log || true - cat_ci_env_script: - - env - -linux_arm64_container_snippet: &LINUX_ARM64_CONTAINER - env_script: - - export PATH="$VIRTUAL_ENV/bin:$PATH" - - env | tee /tmp/env - build_script: - - DOCKER_BUILDKIT=1 docker build --file "ci/linux-debian.Dockerfile" --tag="ci_secp256k1_arm" - - docker image prune --force # Cleanup stale layers - test_script: - - docker run --rm --mount "type=bind,src=./,dst=/ci_secp256k1" --env-file /tmp/env --replace --name "ci_secp256k1_arm" "ci_secp256k1_arm" bash -c "cd /ci_secp256k1/ && ./ci/ci.sh" - -task: - name: "ARM64: Linux (Debian stable), Valgrind" - persistent_worker: - labels: - type: arm64 - env: - ECDH: yes - RECOVERY: yes - EXTRAKEYS: yes - SCHNORRSIG: yes - MUSIG: yes - ELLSWIFT: yes - WRAPPER_CMD: 'valgrind --error-exitcode=42' - SECP256K1_TEST_ITERS: 2 - matrix: - - env: { CC: 'gcc' } - - env: { CC: 'clang' } - - env: { CC: 'gcc-snapshot' } - - env: { CC: 'clang-snapshot' } - << : *LINUX_ARM64_CONTAINER - << : *CAT_LOGS diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1e3096e..69c7fdf6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -305,18 +305,38 @@ jobs: valgrind_debian: - name: "Valgrind (memcheck)" - runs-on: ubuntu-latest + name: "Valgrind ${{ matrix.binary_arch }} (memcheck)" + runs-on: ${{ matrix.runner }} needs: docker_cache strategy: fail-fast: false matrix: - configuration: - - env_vars: { CC: 'clang', ASM: 'auto' } - - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } - - env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } - - env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } + include: + - docker_arch: x64 + runner: ubuntu-latest + binary_arch: x64 + env_vars: { CC: 'clang', ASM: 'auto' } + - docker_arch: x64 + runner: ubuntu-latest + binary_arch: i686 + env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } + - docker_arch: arm64 + runner: ubuntu-24.04-arm + binary_arch: arm64 + env_vars: { CC: 'clang', ASM: 'auto' } + - docker_arch: x64 + runner: ubuntu-latest + binary_arch: x64 + env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } + - docker_arch: x64 + runner: ubuntu-latest + binary_arch: i686 + env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } + - docker_arch: arm64 + runner: ubuntu-24.04-arm + binary_arch: arm64 + env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } env: # The `--error-exitcode` is required to make the test fail if valgrind found errors, @@ -336,11 +356,11 @@ jobs: uses: actions/checkout@v4 - name: CI script - env: ${{ matrix.configuration.env_vars }} + env: ${{ matrix.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image + tag: ${{ matrix.docker_arch }}-debian-image - name: Print logs uses: ./.github/actions/print-logs From add146e1014a6d5c585bbf3e10a765c87194b795 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 19 Jun 2025 21:12:05 +0100 Subject: [PATCH 164/383] ci: Bump GCC snapshot major version to 16 --- ci/linux-debian.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 547b4022..92ec80d2 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -40,7 +40,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ apt-get clean && rm -rf /var/lib/apt/lists/* # Build and install gcc snapshot -ARG GCC_SNAPSHOT_MAJOR=15 +ARG GCC_SNAPSHOT_MAJOR=16 RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ mkdir gcc && cd gcc && \ wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \ From 7106dce6fd410043fc297139c6307cb6016d2a7b Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Fri, 27 Jun 2025 18:59:02 +0200 Subject: [PATCH 165/383] cmake: configure libsecp256k1.pc during install When installing to a given prefix, make sure that the .pc file contains that prefix rather than the value of CMAKE_INSTALL_PREFIX that the project was configured with. --- cmake/GeneratePkgConfigFile.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/GeneratePkgConfigFile.cmake b/cmake/GeneratePkgConfigFile.cmake index 9c1d7f1d..ff335957 100644 --- a/cmake/GeneratePkgConfigFile.cmake +++ b/cmake/GeneratePkgConfigFile.cmake @@ -1,8 +1,12 @@ function(generate_pkg_config_file in_file) - set(prefix ${CMAKE_INSTALL_PREFIX}) + set(prefix "@CMAKE_INSTALL_PREFIX@") set(exec_prefix \${prefix}) set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) set(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR}) set(PACKAGE_VERSION ${PROJECT_VERSION}) - configure_file(${in_file} ${PROJECT_NAME}.pc @ONLY) + configure_file(${in_file} ${PROJECT_NAME}.pc.in @ONLY) + install(CODE "configure_file( + \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc.in\" + \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc\" + @ONLY)" ALL_COMPONENTS) endfunction() From 0dfe387dbe345d92d12b3de5c41a685fb6654211 Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Thu, 19 Jun 2025 10:02:23 +0200 Subject: [PATCH 166/383] cmake: support the use of launchers in ctest -S scripts --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 02abaa97..26cc49b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ project(libsecp256k1 LANGUAGES C ) enable_testing() +include(CTestUseLaunchers) # Allow users to set CTEST_USE_LAUNCHERS in custom `ctest -S` scripts. list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # The library version is based on libtool versioning of the ABI. The set of From 44b205e9eeac216a1cd15a910709606aca633947 Mon Sep 17 00:00:00 2001 From: Daniel Pfeifer Date: Mon, 30 Jun 2025 16:49:14 +0200 Subject: [PATCH 167/383] Revert "cmake: configure libsecp256k1.pc during install" This reverts commit 7106dce6fd410043fc297139c6307cb6016d2a7b. This causes a regression for packaging, as the generated `.pc` file will contain the location that was used to build the package archive. --- cmake/GeneratePkgConfigFile.cmake | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cmake/GeneratePkgConfigFile.cmake b/cmake/GeneratePkgConfigFile.cmake index ff335957..9c1d7f1d 100644 --- a/cmake/GeneratePkgConfigFile.cmake +++ b/cmake/GeneratePkgConfigFile.cmake @@ -1,12 +1,8 @@ function(generate_pkg_config_file in_file) - set(prefix "@CMAKE_INSTALL_PREFIX@") + set(prefix ${CMAKE_INSTALL_PREFIX}) set(exec_prefix \${prefix}) set(libdir \${exec_prefix}/${CMAKE_INSTALL_LIBDIR}) set(includedir \${prefix}/${CMAKE_INSTALL_INCLUDEDIR}) set(PACKAGE_VERSION ${PROJECT_VERSION}) - configure_file(${in_file} ${PROJECT_NAME}.pc.in @ONLY) - install(CODE "configure_file( - \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc.in\" - \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc\" - @ONLY)" ALL_COMPONENTS) + configure_file(${in_file} ${PROJECT_NAME}.pc @ONLY) endfunction() From 3352f9d667afd92e553d79604c7e884121e18aa5 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 10 Jul 2025 17:46:51 +0200 Subject: [PATCH 168/383] ci: enable musig module for native macOS arm64 job --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69c7fdf6..805281c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -573,13 +573,13 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } - BUILD: 'distcheck' steps: From e5297f6d79b4fb91c8dae27e26958155811c33a9 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 2 Jul 2025 11:43:32 +0200 Subject: [PATCH 169/383] build: Refactor visibility logic --- include/secp256k1.h | 71 ++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 1d25a02a..d67d9642 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -121,45 +121,38 @@ typedef int (*secp256k1_nonce_function)( #endif /* Symbol visibility. */ -#if defined(_WIN32) - /* GCC for Windows (e.g., MinGW) accepts the __declspec syntax - * for MSVC compatibility. A __declspec declaration implies (but is not - * exactly equivalent to) __attribute__ ((visibility("default"))), and so we - * actually want __declspec even on GCC, see "Microsoft Windows Function - * Attributes" in the GCC manual and the recommendations in - * https://gcc.gnu.org/wiki/Visibility. */ -# if defined(SECP256K1_BUILD) -# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT) - /* Building libsecp256k1 as a DLL. - * 1. If using Libtool, it defines DLL_EXPORT automatically. - * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */ -# define SECP256K1_API extern __declspec (dllexport) -# else - /* Building libsecp256k1 as a static library on Windows. - * No declspec is needed, and so we would want the non-Windows-specific - * logic below take care of this case. However, this may result in setting - * __attribute__ ((visibility("default"))), which is supposed to be a noop - * on Windows but may trigger warnings when compiling with -flto due to a - * bug in GCC, see - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */ -# define SECP256K1_API extern -# endif - /* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static - * library on Windows. */ -# elif !defined(SECP256K1_STATIC) - /* Consuming libsecp256k1 as a DLL. */ -# define SECP256K1_API extern __declspec (dllimport) -# endif -#endif -#ifndef SECP256K1_API -/* All cases not captured by the Windows-specific logic. */ -# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD) - /* Building libsecp256k1 using GCC or compatible. */ -# define SECP256K1_API extern __attribute__ ((visibility ("default"))) -# else - /* Fall back to standard C's extern. */ -# define SECP256K1_API extern -# endif +#if !defined(SECP256K1_API) +# if defined(SECP256K1_BUILD) + /* On Windows, assume a shared library only if explicitly requested. + * 1. If using Libtool, it defines DLL_EXPORT automatically. + * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */ +# if defined(_WIN32) && (defined(SECP256K1_DLL_EXPORT) || defined(DLL_EXPORT)) + /* GCC for Windows (e.g., MinGW) accepts the __declspec syntax for + * MSVC compatibility. A __declspec declaration implies (but is not + * exactly equivalent to) __attribute__ ((visibility("default"))), + * and so we actually want __declspec even on GCC, see "Microsoft + * Windows Function Attributes" in the GCC manual and the + * recommendations in https://gcc.gnu.org/wiki/Visibility . */ +# define SECP256K1_API extern __declspec(dllexport) + /* Avoid __attribute__ ((visibility("default"))) on Windows to get rid + * of warnings when compiling with -flto due to a bug in GCC, see + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */ +# elif !defined(_WIN32) && defined (__GNUC__) && (__GNUC__ >= 4) +# define SECP256K1_API extern __attribute__ ((visibility("default"))) +# else +# define SECP256K1_API extern +# endif +# else + /* On Windows, SECP256K1_STATIC must be defined when consuming + * libsecp256k1 as a static library. Note that SECP256K1_STATIC is a + * "consumer-only" macro, and it has no meaning when building + * libsecp256k1. */ +# if defined(_WIN32) && !defined(SECP256K1_STATIC) +# define SECP256K1_API extern __declspec(dllimport) +# else +# define SECP256K1_API extern +# endif +# endif #endif /* Warning attributes From ce7923874f3f51dd87f396e0be655e2b25ad4629 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 2 Jul 2025 11:56:40 +0200 Subject: [PATCH 170/383] build: Add SECP256K1_NO_API_VISIBILITY_ATTRIBUTES --- include/secp256k1.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/secp256k1.h b/include/secp256k1.h index d67d9642..f55a6ab9 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -121,6 +121,25 @@ typedef int (*secp256k1_nonce_function)( #endif /* Symbol visibility. */ +#if !defined(SECP256K1_API) && defined(SECP256K1_NO_API_VISIBILITY_ATTRIBUTES) + /* The user has requested that we don't specify visibility attributes in + * the public API. + * + * Since all our non-API declarations use the static qualifier, this means + * that the user can use -fvisibility= to set the visibility of the + * API symbols. For instance, -fvisibility=hidden can be useful *even for + * the API symbols*, e.g., when building a static library which is linked + * into a shared library, and the latter should not re-export the + * libsecp256k1 API. + * + * While visibility is a concept that applies only to shared libraries, + * setting visibility will still make a difference when building a static + * library: the visibility settings will be stored in the static library, + * solely for the potential case that the static library will be linked into + * a shared library. In that case, the stored visibility settings will + * resurface and be honored for the shared library. */ +# define SECP256K1_API extern +#endif #if !defined(SECP256K1_API) # if defined(SECP256K1_BUILD) /* On Windows, assume a shared library only if explicitly requested. From c82d84bb86f9769a4f9d958f40e86cd99e071bc7 Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 2 Jul 2025 15:18:06 +0000 Subject: [PATCH 171/383] build: add CMake option for disabling symbol visibility attributes Co-authored-by: Tim Ruffing --- CMakeLists.txt | 3 +++ src/CMakeLists.txt | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 26cc49b1..98c51ac1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,8 @@ endif() option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL}) +option(SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES "Enable visibility attributes in the API." ON) + ## Modules # We declare all options before processing them, to make sure we can express @@ -312,6 +314,7 @@ else() set(cross_status "FALSE") endif() message("Cross compiling ....................... ${cross_status}") +message("API visibility attributes ............. ${SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES}") message("Valgrind .............................. ${SECP256K1_VALGRIND}") get_directory_property(definitions COMPILE_DEFINITIONS) string(REPLACE ";" " " definitions "${definitions}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f1d2ee3..f9ede8b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -54,6 +54,10 @@ add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL # from being exported. target_sources(secp256k1 PRIVATE secp256k1.c $) +if(NOT SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES) + target_compile_definitions(secp256k1 PRIVATE SECP256K1_NO_API_VISIBILITY_ATTRIBUTES) +endif() + # Create a helper lib that parent projects can use to link secp256k1 into a # static lib. add_library(secp256k1_objs INTERFACE) From bf082221ff55be706e162f1a15e9df3247ef7e7b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:37:09 +0100 Subject: [PATCH 172/383] cmake: Make `secp256k1_objs` inherit interface defines from `secp256k1` This change effectively adds `-DSECP256K1_STATIC` to usage requirements of `secp256k1_objs` on Windows, preventing LNK4217 linker warnings. --- src/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f1d2ee3..7ec6045c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,7 +86,8 @@ target_include_directories(secp256k1 INTERFACE $>:${PROJECT_SOURCE_DIR}/include>> ) set_target_properties(secp256k1_objs PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "$" + INTERFACE_COMPILE_DEFINITIONS "$" + INTERFACE_INCLUDE_DIRECTORIES "$" ) # This emulates Libtool to make sure Libtool and CMake agree on the ABI version, From 983711cd6dcb21144d416321d679b25d2d641f7d Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Jul 2025 14:44:57 +0200 Subject: [PATCH 173/383] musig/tests: Refactor vectors_signverify for improved readability --- src/modules/musig/tests_impl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index ce6ae178..e4c13cee 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -910,12 +910,14 @@ static void musig_test_vectors_signverify(void) { * the signing key does not belong to any pubkey. */ continue; } + expected = c->error != MUSIG_PUBKEY; CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); CHECK(expected || c->error == error); if (!expected) { continue; } + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); expected = c->error != MUSIG_AGGNONCE; CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); @@ -924,9 +926,8 @@ static void musig_test_vectors_signverify(void) { } CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); expected = c->error != MUSIG_SECNONCE; + musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); if (expected) { CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); } else { From 8d967a602b14c86d0f9e43a31fdfe76f39f32091 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Jul 2025 14:47:57 +0200 Subject: [PATCH 174/383] musig/test: Remove dead code This avoids a compiler warning on clang-snapshot about &keypair being uninitialized. --- src/modules/musig/tests_impl.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index e4c13cee..361a989f 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -927,12 +927,9 @@ static void musig_test_vectors_signverify(void) { CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); expected = c->error != MUSIG_SECNONCE; + CHECK(!expected); musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); - if (expected) { - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } else { - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); } for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) { const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i]; From 40b4a0652078c797df3ceb66387b8cfe60e6dab8 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Wed, 16 Jul 2025 08:58:10 +0000 Subject: [PATCH 175/383] changelog: update Co-authored-by: Tim Ruffing --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12abd357..99925457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Added + - CMake: Added `secp256k1_objs` interface library to allow parent projects to embed libsecp256k1 object files into their own static libraries. + - build: Added `SECP256K1_NO_API_VISIBILITY_ATTRIBUTES` preprocessor flag (CMake option: `SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES`) that disables explicit "visibility" attributes for API symbols. Defining this macro enables the user to control the visibility of the API symbols via `-fvisibility=` when building libsecp256k1. (All non-API declarations will always have hidden visibility, even with `SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES` defined.) For instance, `-fvisibility=hidden` can be useful even for the API symbols, e.g., when building a static libsecp256k1 which is linked into a shared library, and the latter should not re-export the libsecp256k1 API. + +#### Changed + - The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` to the constant context object are now const. + - Removed `SECP256K1_WARN_UNUSED_RESULT` attribute (defined as `__attribute__ ((__warn_unused_result__))`) from several API functions that always return 1. Compilers will no longer warn if the return value is unused. + - CMake: Building with CMake is no longer considered experimental. + - CMake: The minimum required CMake version was increased to 3.22. + - CMake: Shared libraries built with CMake on FreeBSD now create the full versioned filename and symlink chain, matching the behavior of autotools builds. + #### Removed - Removed previously deprecated function aliases `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add` and `secp256k1_ec_privkey_tweak_mul`. Use `secp256k1_ec_seckey_negate`, `secp256k1_ec_seckey_tweak_add` and `secp256k1_ec_seckey_tweak_mul` instead. +#### ABI Compatibility +The symbols `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add`, and `secp256k1_ec_privkey_tweak_mul` were removed. +The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` have been made const. +Otherwise, the library maintains backward compatibility with version 0.6.0. + ## [0.6.0] - 2024-11-04 #### Added From cde4130898e9b661695b74e8a8344a7201e224ed Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 21 Jul 2025 14:08:23 +0000 Subject: [PATCH 176/383] musig/tests: initialize keypair The keypair is unused in musig_partial_sign, but clang-snapshot gives a compiler warning anyway. --- src/modules/musig/tests_impl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index 361a989f..4694c31a 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -918,6 +918,7 @@ static void musig_test_vectors_signverify(void) { continue; } CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); expected = c->error != MUSIG_AGGNONCE; CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); From f67b0ac1a0ac1b8fa5d574cd0662231f071435fc Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Jul 2025 16:35:16 +0200 Subject: [PATCH 177/383] ci: Don't hardcode ABI version --- .github/workflows/ci.yml | 3 ++- ci/ci.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 805281c3..d5196c53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -652,10 +652,11 @@ jobs: - name: Symbol check if: ${{ matrix.configuration.symbol_check }} + shell: bash run: | py -3 --version py -3 -m pip install lief - py -3 .\tools\symbol-check.py build\bin\RelWithDebInfo\libsecp256k1-5.dll + py -3 ./tools/symbol-check.py build/bin/RelWithDebInfo/libsecp256k1-*.dll - name: Check run: | diff --git a/ci/ci.sh b/ci/ci.sh index 3285ecc9..08e84efd 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -113,7 +113,7 @@ then case "$HOST" in *mingw*) ls -l .libs - python3 ./tools/symbol-check.py .libs/libsecp256k1-5.dll + python3 ./tools/symbol-check.py .libs/libsecp256k1-*.dll ;; *) python3 ./tools/symbol-check.py .libs/libsecp256k1.so From a3e742d9478c202cbe93e721567e0f1dea1c8bde Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Jul 2025 16:21:31 +0200 Subject: [PATCH 178/383] release: Prepare for 0.7.0 --- CHANGELOG.md | 8 ++++---- CMakeLists.txt | 6 +++--- configure.ac | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99925457..3e9e720c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,14 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.7.0] - 2025-07-21 #### Added - CMake: Added `secp256k1_objs` interface library to allow parent projects to embed libsecp256k1 object files into their own static libraries. - build: Added `SECP256K1_NO_API_VISIBILITY_ATTRIBUTES` preprocessor flag (CMake option: `SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES`) that disables explicit "visibility" attributes for API symbols. Defining this macro enables the user to control the visibility of the API symbols via `-fvisibility=` when building libsecp256k1. (All non-API declarations will always have hidden visibility, even with `SECP256K1_ENABLE_API_VISIBILITY_ATTRIBUTES` defined.) For instance, `-fvisibility=hidden` can be useful even for the API symbols, e.g., when building a static libsecp256k1 which is linked into a shared library, and the latter should not re-export the libsecp256k1 API. #### Changed - - The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` to the constant context object are now const. + - The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` to the constant context objects are now `const`. - Removed `SECP256K1_WARN_UNUSED_RESULT` attribute (defined as `__attribute__ ((__warn_unused_result__))`) from several API functions that always return 1. Compilers will no longer warn if the return value is unused. - CMake: Building with CMake is no longer considered experimental. - CMake: The minimum required CMake version was increased to 3.22. @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### ABI Compatibility The symbols `secp256k1_ec_privkey_negate`, `secp256k1_ec_privkey_tweak_add`, and `secp256k1_ec_privkey_tweak_mul` were removed. -The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` have been made const. +The pointers `secp256k1_context_static` and `secp256k1_context_no_precomp` have been made `const`. Otherwise, the library maintains backward compatibility with version 0.6.0. ## [0.6.0] - 2024-11-04 @@ -185,7 +185,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. -[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...HEAD +[0.7.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.4.1...v0.5.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 98c51ac1..a34f42d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.6.1 + VERSION 0.7.0 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -21,8 +21,8 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) +set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) set(${PROJECT_NAME}_LIB_VERSION_AGE 0) #============================= diff --git a/configure.ac b/configure.ac index 406227fc..808aa79e 100644 --- a/configure.ac +++ b/configure.ac @@ -4,17 +4,17 @@ AC_PREREQ([2.60]) # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) -define(_PKG_VERSION_MINOR, 6) -define(_PKG_VERSION_PATCH, 1) -define(_PKG_VERSION_IS_RELEASE, false) +define(_PKG_VERSION_MINOR, 7) +define(_PKG_VERSION_PATCH, 0) +define(_PKG_VERSION_IS_RELEASE, true) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. -define(_LIB_VERSION_CURRENT, 5) -define(_LIB_VERSION_REVISION, 1) +define(_LIB_VERSION_CURRENT, 6) +define(_LIB_VERSION_REVISION, 0) define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From 7ab8b0cc01dd30711a221969b194d3b7d870bc46 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 21 Jul 2025 17:55:16 +0000 Subject: [PATCH 179/383] release cleanup: bump version after 0.7.0 --- CHANGELOG.md | 3 +++ CMakeLists.txt | 4 ++-- configure.ac | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e9e720c..53c787b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + ## [0.7.0] - 2025-07-21 #### Added @@ -185,6 +187,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. +[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...HEAD [0.7.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index a34f42d2..25919fd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.7.0 + VERSION 0.7.1 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -22,7 +22,7 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) set(${PROJECT_NAME}_LIB_VERSION_AGE 0) #============================= diff --git a/configure.ac b/configure.ac index 808aa79e..ce24248f 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,8 @@ AC_PREREQ([2.60]) # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 7) -define(_PKG_VERSION_PATCH, 0) -define(_PKG_VERSION_IS_RELEASE, true) +define(_PKG_VERSION_PATCH, 1) +define(_PKG_VERSION_IS_RELEASE, false) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. define(_LIB_VERSION_CURRENT, 6) -define(_LIB_VERSION_REVISION, 0) +define(_LIB_VERSION_REVISION, 1) define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From 9ea54c69b7d99d6fedccc8a4b8f18c0a68742ff6 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 23 Jul 2025 14:11:58 +0100 Subject: [PATCH 180/383] tests: update Wycheproof files Pulls in relevant changes from https://github.com/C2SP/wycheproof/pull/150. --- src/wycheproof/WYCHEPROOF_COPYING | 4 ++-- .../ecdsa_secp256k1_sha256_bitcoin_test.json | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wycheproof/WYCHEPROOF_COPYING b/src/wycheproof/WYCHEPROOF_COPYING index 26957043..c6d0e6ee 100644 --- a/src/wycheproof/WYCHEPROOF_COPYING +++ b/src/wycheproof/WYCHEPROOF_COPYING @@ -1,7 +1,7 @@ * The file `ecdsa_secp256k1_sha256_bitcoin_test.json` in this directory comes from project Wycheproof with git commit - `df4e933efef449fc88af0c06e028d425d84a9495`, see - https://github.com/C2SP/wycheproof/blob/df4e933efef449fc88af0c06e028d425d84a9495/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json + `1f32ea7bb6cc5bd111cbd5507456b255dc8337c3`, see + https://github.com/C2SP/wycheproof/blob/1f32ea7bb6cc5bd111cbd5507456b255dc8337c3/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json * The file `ecdh_secp256k1_test.json` in this directory comes from project Wycheproof with git commit diff --git a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json index aa0cc8a4..350b0da0 100644 --- a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json +++ b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json @@ -5,7 +5,7 @@ "numberOfTests" : 463, "header" : [ "Test vectors of type EcdsaBitcoinVerify are meant for the verification", - "of a ECDSA variant used for bitcoin, that add signature non-malleability." + "of a ECDSA variant used for Bitcoin, that add signature non-malleability." ], "notes" : { "ArithmeticError" : { @@ -47,7 +47,7 @@ "InvalidSignature" : { "bugType" : "AUTH_BYPASS", "description" : "The signature contains special case values such as r=0 and s=0. Buggy implementations may accept such values, if the implementation does not check boundaries and computes s^(-1) == 0.", - "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowning the message to sign.", + "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowing the message to sign.", "cves" : [ "CVE-2022-21449", "CVE-2021-43572", @@ -57,7 +57,7 @@ "InvalidTypesInSignature" : { "bugType" : "AUTH_BYPASS", "description" : "The signature contains invalid types. Dynamic typed languages sometime coerce such values of different types into integers. If an implementation is careless and has additional bugs, such as not checking integer boundaries then it may be possible that such signatures are accepted.", - "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowning the message to sign.", + "effect" : "Accepting such signatures can have the effect that an adversary can forge signatures without even knowing the message to sign.", "cves" : [ "CVE-2022-21449" ] @@ -95,8 +95,8 @@ }, "SignatureMalleabilityBitcoin" : { "bugType" : "SIGNATURE_MALLEABILITY", - "description" : "\"BitCoins\"-curves are curves where signature malleability can be a serious issue. An implementation should only accept a signature s where s < n/2. If an implementation is not meant for uses cases that require signature malleability then this implementation should be tested with another set of test vectors.", - "effect" : "In bitcoin exchanges, it may be used to make a double deposits or double withdrawals", + "description" : "Signature malleability can be a serious issue in Bitcoin. An implementation should only accept a signature s where s < n/2. If an implementation is not meant for use cases that require signature malleability then this implementation should be tested with another set of test vectors.", + "effect" : "In Bitcoin exchanges, it may be used to make a double deposits or double withdrawals", "links" : [ "https://en.bitcoin.it/wiki/Transaction_malleability", "https://en.bitcoinwiki.org/wiki/Transaction_Malleability" From 5433648ca0d2e8fb6679acbdee74d2f40c7ef25a Mon Sep 17 00:00:00 2001 From: Adrien Ufferte Date: Sun, 15 Jun 2025 16:41:26 +0200 Subject: [PATCH 181/383] Fix typos and spellings --- src/ecmult_gen_impl.h | 2 +- src/tests.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 070a1213..16de638c 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -213,7 +213,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 * but this would simply discard the bits that fall off at the bottom, * and thus, for example, bitdata could still have only two values if we * happen to shift by exactly 31 positions. We use a rotation instead, - * which ensures that bitdata doesn't loose entropy. This relies on the + * which ensures that bitdata doesn't lose entropy. This relies on the * rotation being atomic, i.e., the compiler emitting an actual rot * instruction. */ uint32_t bitdata = secp256k1_rotr32(recoded[bit_pos >> 5], bit_pos & 0x1f); diff --git a/src/tests.c b/src/tests.c index 52614401..0f7b0d4c 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3904,7 +3904,7 @@ static void test_ge(void) { free(gej); } -static void test_intialized_inf(void) { +static void test_initialized_inf(void) { secp256k1_ge p; secp256k1_gej pj, npj, infj1, infj2, infj3; secp256k1_fe zinv; @@ -4030,7 +4030,7 @@ static void run_ge(void) { test_ge(); } test_add_neg_y_diff_x(); - test_intialized_inf(); + test_initialized_inf(); test_ge_bytes(); } From 7b07b229571d80c228f7719c4ffdaf48e397f1a0 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 27 Jul 2025 15:35:58 +0100 Subject: [PATCH 182/383] cmake: Avoid contaminating parent project's cache with BUILD_SHARED_LIBS The CMake cache is global in scope. Therefore, setting the standard cache variable `BUILD_SHARED_LIBS` can inadvertently affect the behavior of a parent project. This change: 1. Sets the `BUILD_SHARED_LIBS` cache variable only when libsecp256k1 is the top-level project. 2. Removes the `SECP256K1_DISABLE_SHARED` cache variable. This enables parent projects that include libsecp256k1 as a subproject to rely solely on standard CMake variables for configuring the library type. --- CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25919fd5..11dc3f6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,10 +34,8 @@ set(CMAKE_C_EXTENSIONS OFF) #============================= # Configurable options #============================= -option(BUILD_SHARED_LIBS "Build shared libraries." ON) -option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF) -if(SECP256K1_DISABLE_SHARED) - set(BUILD_SHARED_LIBS OFF) +if(libsecp256k1_IS_TOP_LEVEL) + option(BUILD_SHARED_LIBS "Build shared libraries." ON) endif() option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL}) From c25c3c8a885f2adac754c163e115bdd883c8772d Mon Sep 17 00:00:00 2001 From: josibake Date: Thu, 31 Jul 2025 14:25:31 +0100 Subject: [PATCH 183/383] test: update wycheproof test vectors Pull in updated test vectors. This update is done as a follow-up to #1711. --- src/wycheproof/WYCHEPROOF_COPYING | 4 ++-- src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wycheproof/WYCHEPROOF_COPYING b/src/wycheproof/WYCHEPROOF_COPYING index c6d0e6ee..c9a4ef81 100644 --- a/src/wycheproof/WYCHEPROOF_COPYING +++ b/src/wycheproof/WYCHEPROOF_COPYING @@ -1,7 +1,7 @@ * The file `ecdsa_secp256k1_sha256_bitcoin_test.json` in this directory comes from project Wycheproof with git commit - `1f32ea7bb6cc5bd111cbd5507456b255dc8337c3`, see - https://github.com/C2SP/wycheproof/blob/1f32ea7bb6cc5bd111cbd5507456b255dc8337c3/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json + `7ae4532f417575ced2b1cbbabed81a7fecfaef5d`, see + https://github.com/C2SP/wycheproof/blob/7ae4532f417575ced2b1cbbabed81a7fecfaef5d/testvectors_v1/ecdsa_secp256k1_sha256_bitcoin_test.json * The file `ecdh_secp256k1_test.json` in this directory comes from project Wycheproof with git commit diff --git a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json index 350b0da0..add468f5 100644 --- a/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json +++ b/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json @@ -95,7 +95,7 @@ }, "SignatureMalleabilityBitcoin" : { "bugType" : "SIGNATURE_MALLEABILITY", - "description" : "Signature malleability can be a serious issue in Bitcoin. An implementation should only accept a signature s where s < n/2. If an implementation is not meant for use cases that require signature malleability then this implementation should be tested with another set of test vectors.", + "description" : "Signature malleability can be a serious issue in Bitcoin. An implementation should only accept a signature s where s < n/2. If an implementation is meant for use cases that tolerate signature malleability then this implementation should not be tested with this set of test vectors.", "effect" : "In Bitcoin exchanges, it may be used to make a double deposits or double withdrawals", "links" : [ "https://en.bitcoin.it/wiki/Transaction_malleability", From 24ba8ff168c30c7ad003e7e6bb4a4d2f947c9063 Mon Sep 17 00:00:00 2001 From: Maximilian Hubert <64627729+gap-editor@users.noreply.github.com> Date: Sat, 9 Aug 2025 23:51:04 +0200 Subject: [PATCH 184/383] chore(ci): Fix typo in Dockerfile comment --- ci/linux-debian.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 92ec80d2..8ced83f2 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -19,7 +19,7 @@ RUN dpkg --add-architecture i386 && \ dpkg --add-architecture arm64 && \ dpkg --add-architecture ppc64el -# dkpg-dev: to make pkg-config work in cross-builds +# dpkg-dev: to make pkg-config work in cross-builds # llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces RUN apt-get update && apt-get install --no-install-recommends -y \ git ca-certificates \ From a9e955d3ea25a83c413e54dc0f5c24c47fc8bc88 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sat, 29 Apr 2023 23:09:36 +0100 Subject: [PATCH 185/383] autotools, docs: Adjust help string for `--enable-coverage` option --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ce24248f..2f156ddc 100644 --- a/configure.ac +++ b/configure.ac @@ -144,7 +144,7 @@ AC_ARG_ENABLE(benchmark, [SECP_SET_DEFAULT([enable_benchmark], [yes], [yes])]) AC_ARG_ENABLE(coverage, - AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis [default=no]]), [], + AS_HELP_STRING([--enable-coverage],[enable coverage analysis support [default=no]]), [], [SECP_SET_DEFAULT([enable_coverage], [no], [no])]) AC_ARG_ENABLE(tests, From 106a7cbf41bef1d4a529a9c214d7380ac88bee9b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:29:23 +0100 Subject: [PATCH 186/383] doc: Exclude modules' `bench_impl.h` headers from coverage report --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 80890fb7..ccc1af63 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,12 +92,12 @@ Run the tests: To create a report, `gcovr` is recommended, as it includes branch coverage reporting: - $ gcovr --exclude 'src/bench*' --print-summary + $ gcovr --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --print-summary To create a HTML report with coloured and annotated source code: $ mkdir -p coverage - $ gcovr --exclude 'src/bench*' --html --html-details -o coverage/coverage.html + $ gcovr --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --html --html-details -o coverage/coverage.html #### Exhaustive tests From 1aecce5936db9424cf526c565ef2501f21109b95 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:35:53 +0100 Subject: [PATCH 187/383] doc: Add `--merge-mode-functions=separate` option to `gcovr` invocations Otherwise, commands fail with the error: ``` Stderr of gcov was >><< End of stderr Exception was >>Got function secp256k1_scalar_split_lambda on multiple lines: 67, 142. You can run gcovr with --merge-mode-functions=MERGE_MODE. The available values for MERGE_MODE are described in the documentation.<< End of stderr ``` --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ccc1af63..9462b30d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,12 +92,12 @@ Run the tests: To create a report, `gcovr` is recommended, as it includes branch coverage reporting: - $ gcovr --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --print-summary + $ gcovr --merge-mode-functions=separate --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --print-summary To create a HTML report with coloured and annotated source code: $ mkdir -p coverage - $ gcovr --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --html --html-details -o coverage/coverage.html + $ gcovr --merge-mode-functions=separate --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --html --html-details -o coverage/coverage.html #### Exhaustive tests From 0458def51e18b7500dac8aec019b637dfade0667 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:32:07 +0100 Subject: [PATCH 188/383] doc: Add `--gcov-ignore-parse-errors=all` option to `gcovr` invocations Otherwise, commands might fail due to bugs in the `gcov` tool. --- CONTRIBUTING.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9462b30d..f0011086 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,12 +92,14 @@ Run the tests: To create a report, `gcovr` is recommended, as it includes branch coverage reporting: - $ gcovr --merge-mode-functions=separate --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --print-summary + $ gcovr --gcov-ignore-parse-errors=all --merge-mode-functions=separate --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --print-summary To create a HTML report with coloured and annotated source code: $ mkdir -p coverage - $ gcovr --merge-mode-functions=separate --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --html --html-details -o coverage/coverage.html + $ gcovr --gcov-ignore-parse-errors=all --merge-mode-functions=separate --exclude 'src/bench*' --exclude 'src/modules/.*/bench_impl.h' --html --html-details -o coverage/coverage.html + +On `gcovr` >=8.3, `--gcov-ignore-parse-errors=all` can be replaced with `--gcov-suspicious-hits-threshold=140737488355330`. #### Exhaustive tests From 489a43d1bf7d886274dc24c0a544f08b7b064aec Mon Sep 17 00:00:00 2001 From: VolodymyrBg Date: Mon, 18 Aug 2025 12:19:08 +0000 Subject: [PATCH 189/383] docs: fix broken link to eprint cache.pdf paper --- src/ecmult_gen_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 16de638c..b943fe2a 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -242,7 +242,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, * by Dag Arne Osvik, Adi Shamir, and Eran Tromer - * (https://www.tau.ac.il/~tromer/papers/cache.pdf) + * (https://eprint.iacr.org/2005/271.pdf) */ for (index = 0; index < COMB_POINTS; ++index) { secp256k1_ge_storage_cmov(&adds, &secp256k1_ecmult_gen_prec_table[block][index], index == abs); From 5153cf1c91b6967b3cb0adcd0b990a0cffb2a0b2 Mon Sep 17 00:00:00 2001 From: josibake Date: Fri, 15 Aug 2025 09:37:29 +0100 Subject: [PATCH 190/383] tests: refactor tagged hash tests Move the sha256_tag_test_internal function out of the musig module into tests.c. This makes it available to other modules wishing to verify tagged hashes without needing to duplicate the function. Change the function signature to expect a const unsigned char and update the tagged hash tests to use static const unsigned char character arrays (where necessary). Add a comment for each tag. This is done as a convenience for checking the strings against the protocol specifications, where the tags are normally specified as strings. Update tests in the ellswift and schnorrsig modules to use the sha256_tag_test_internal helper function. --- src/modules/ellswift/tests_impl.h | 14 ++++++------- src/modules/musig/tests_impl.h | 31 ++++++++++++++--------------- src/modules/schnorrsig/tests_impl.h | 14 ++++++------- src/tests.c | 7 +++++++ 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 3c314c9b..b90fd0ab 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -405,31 +405,31 @@ void run_ellswift_tests(void) { /* Test hash initializers. */ { - secp256k1_sha256 sha, sha_optimized; + secp256k1_sha256 sha_optimized; + /* "secp256k1_ellswift_encode" */ static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; + /* "secp256k1_ellswift_create" */ static const unsigned char create_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'c', 'r', 'e', 'a', 't', 'e'}; + /* "bip324_ellswift_xonly_ecdh" */ static const unsigned char bip324_tag[] = {'b', 'i', 'p', '3', '2', '4', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'x', 'o', 'n', 'l', 'y', '_', 'e', 'c', 'd', 'h'}; /* Check that hash initialized by * secp256k1_ellswift_sha256_init_encode has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, encode_tag, sizeof(encode_tag)); secp256k1_ellswift_sha256_init_encode(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, encode_tag, sizeof(encode_tag)); /* Check that hash initialized by * secp256k1_ellswift_sha256_init_create has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, create_tag, sizeof(create_tag)); secp256k1_ellswift_sha256_init_create(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, create_tag, sizeof(create_tag)); /* Check that hash initialized by * secp256k1_ellswift_sha256_init_bip324 has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, bip324_tag, sizeof(bip324_tag)); secp256k1_ellswift_sha256_init_bip324(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); } } diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index 4694c31a..b57b2626 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -548,40 +548,39 @@ static void musig_nonce_test(void) { } } -static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { - secp256k1_sha256 sha; - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); - test_sha256_eq(&sha, sha_tagged); -} - /* Checks that the initialized tagged hashes have the expected * state. */ static void sha256_tag_test(void) { secp256k1_sha256 sha; { - char tag[] = "KeyAgg list"; + /* "KeyAgg list" */ + static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'l', 'i', 's', 't'}; secp256k1_musig_keyagglist_sha256(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + test_sha256_tag_midstate(&sha, tag, sizeof(tag)); } { - char tag[] = "KeyAgg coefficient"; + /* "KeyAgg coefficient" */ + static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'c', 'o', 'e', 'f', 'f', 'i', 'c', 'i', 'e', 'n', 't'}; secp256k1_musig_keyaggcoef_sha256(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + test_sha256_tag_midstate(&sha, tag, sizeof(tag)); } { - unsigned char tag[] = "MuSig/aux"; + /* "MuSig/aux" */ + static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'a', 'u', 'x' }; secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + test_sha256_tag_midstate(&sha, tag, sizeof(tag)); } { - unsigned char tag[] = "MuSig/nonce"; + /* "MuSig/nonce" */ + static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'n', 'o', 'n', 'c', 'e' }; secp256k1_nonce_function_musig_sha256_tagged(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + test_sha256_tag_midstate(&sha, tag, sizeof(tag)); } { - unsigned char tag[] = "MuSig/noncecoef"; + /* "MuSig/noncecoef" */ + static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'n', 'o', 'n', 'c', 'e', 'c', 'o', 'e', 'f' }; secp256k1_musig_compute_noncehash_sha256_tagged(&sha); - sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + test_sha256_tag_midstate(&sha, tag, sizeof(tag)); } } diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 2d716a01..5abbeefe 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -21,11 +21,12 @@ static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, s } static void run_nonce_function_bip340_tests(void) { - unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; - unsigned char aux_tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; + /* "BIP0340/nonce" */ + static const unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; + /* "BIP0340/aux" */ + static const unsigned char aux_tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; unsigned char algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; size_t algolen = sizeof(algo); - secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; unsigned char nonce[32], nonce_z[32]; unsigned char msg[32]; @@ -39,16 +40,15 @@ static void run_nonce_function_bip340_tests(void) { /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, tag, sizeof(tag)); secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); + /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, aux_tag, sizeof(aux_tag)); testrand256(msg); testrand256(key); diff --git a/src/tests.c b/src/tests.c index 0f7b0d4c..28bec590 100644 --- a/src/tests.c +++ b/src/tests.c @@ -609,6 +609,13 @@ static void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 CHECK(sha1->bytes == sha2->bytes); CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); } +/* Convenience function for using test_sha256_eq to verify the correctness of a + * tagged hash midstate. This function is used by some module tests. */ +static void test_sha256_tag_midstate(secp256k1_sha256 *sha_tagged, const unsigned char *tag, size_t taglen) { + secp256k1_sha256 sha; + secp256k1_sha256_initialize_tagged(&sha, tag, taglen); + test_sha256_eq(&sha, sha_tagged); +} static void run_hmac_sha256_tests(void) { static const char *keys[6] = { From 7379a5bed317d7a17a5f0a5b16bc01a903c573d2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 24 Aug 2025 11:11:07 +0100 Subject: [PATCH 191/383] doc: Recommend clang-cl when building on Windows --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f7a59b2b..ee184dbe 100644 --- a/README.md +++ b/README.md @@ -135,13 +135,11 @@ To cross compile for Android with [NDK](https://developer.android.com/ndk/guides ### Building on Windows -To build on Windows with Visual Studio, a proper [generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) must be specified for a new build tree. - -The following example assumes using of Visual Studio 2022 and CMake v3.21+. +The following example assumes Visual Studio 2022. Using clang-cl is recommended. In "Developer Command Prompt for VS 2022": - >cmake -G "Visual Studio 17 2022" -A x64 -B build + >cmake -B build -T ClangCL >cmake --build build --config RelWithDebInfo Usage examples From 737912430df3a1743810ebdf3c28ce31479f4d84 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 24 Aug 2025 11:08:02 +0100 Subject: [PATCH 192/383] ci: Add more tests for clang-cl --- .github/workflows/ci.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3108d6b..f6d3176b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -604,8 +604,16 @@ jobs: cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' - job_name: 'x86 (MSVC): Windows (VS 2022)' cmake_options: '-A Win32' - - job_name: 'x64 (MSVC): Windows (clang-cl)' - cmake_options: '-T ClangCL' + - job_name: 'x64 (clang-cl): Windows (VS 2022, shared)' + cmake_options: '-T ClangCL -DBUILD_SHARED_LIBS=ON' + symbol_check: 'true' + - job_name: 'x64 (clang-cl): Windows (VS 2022, static)' + cmake_options: '-T ClangCL -DBUILD_SHARED_LIBS=OFF' + - job_name: 'x64 (clang-cl): Windows (VS 2022, int128_struct)' + cmake_options: '-T ClangCL -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct' + - job_name: 'x64 (clang-cl): Windows (VS 2022, int128_struct with __(u)mulh)' + cmake_options: '-T ClangCL -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int128_struct' + cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' steps: - name: Checkout From 960ba5f9c60c3fd454ad4160ce9131eb77d61d7e Mon Sep 17 00:00:00 2001 From: John Moffett Date: Mon, 1 Sep 2025 09:18:48 -0400 Subject: [PATCH 193/383] Use size_t instead of int for RFC6979 outlen copy If outlen is > INT_MAX, could trigger segfault or hang after copy int now = outlen. --- src/hash_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hash_impl.h b/src/hash_impl.h index 956e0ea4..1065acd6 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -265,7 +265,7 @@ static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 while (outlen > 0) { secp256k1_hmac_sha256 hmac; - int now = outlen; + size_t now = outlen; secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); secp256k1_hmac_sha256_finalize(&hmac, rng->v); From 325d65a8cfae6d4c34098709d0a9e942e4963d03 Mon Sep 17 00:00:00 2001 From: John Moffett Date: Tue, 2 Sep 2025 09:26:09 -0400 Subject: [PATCH 194/383] Rename and clear var containing k or -k buf currently holds k or -k and isn't cleared, so clear it and rename to nonce32 to clarify its sensitivity and match how it is named in the corresponding ECDSA sign_inner. --- src/modules/schnorrsig/main_impl.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 2ed7be67..13d92449 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -139,7 +139,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_gej rj; secp256k1_ge pk; secp256k1_ge r; - unsigned char buf[32] = { 0 }; + unsigned char nonce32[32] = { 0 }; unsigned char pk_buf[32]; unsigned char seckey[32]; int ret = 1; @@ -164,8 +164,8 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar_get_b32(seckey, &sk); secp256k1_fe_get_b32(pk_buf, &pk.x); - ret &= !!noncefp(buf, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); - secp256k1_scalar_set_b32(&k, buf, NULL); + ret &= !!noncefp(nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); + secp256k1_scalar_set_b32(&k, nonce32, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); @@ -191,6 +191,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); secp256k1_memclear(seckey, sizeof(seckey)); + secp256k1_memclear(nonce32, sizeof(nonce32)); secp256k1_gej_clear(&rj); return ret; From 806de38bfc24b481c5858f1df011eb909208a674 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 5 Sep 2025 19:11:29 +0200 Subject: [PATCH 195/383] doc: mention ctx requirement for `_ellswift_create` (not secp256k1_context_static) --- include/secp256k1_ellswift.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/secp256k1_ellswift.h b/include/secp256k1_ellswift.h index 0d1293e9..4cda5d5c 100644 --- a/include/secp256k1_ellswift.h +++ b/include/secp256k1_ellswift.h @@ -130,7 +130,7 @@ SECP256K1_API int secp256k1_ellswift_decode( * * Returns: 1: secret was valid, public key was stored. * 0: secret was invalid, try again. - * Args: ctx: pointer to a context object + * Args: ctx: pointer to a context object (not secp256k1_context_static) * Out: ell64: pointer to a 64-byte array to receive the ElligatorSwift * public key * In: seckey32: pointer to a 32-byte secret key From 7ebaa134a758946f703eaba02fe19cf5a0598490 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 7 Sep 2025 23:39:13 +0200 Subject: [PATCH 196/383] check-abi: remove support for obsolete CMake library output location (src/libsecp256k1.so) The CMake library output location was changed from "src/" to "lib/" in PR #1553, supporting the old location shouldn't be necessary anymore. --- tools/check-abi.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tools/check-abi.sh b/tools/check-abi.sh index 601a64ba..a3ca67a6 100755 --- a/tools/check-abi.sh +++ b/tools/check-abi.sh @@ -49,14 +49,7 @@ checkout_and_build() { -DSECP256K1_BUILD_CTIME_TESTS=OFF \ -DSECP256K1_BUILD_EXAMPLES=OFF cmake --build . -j "$(nproc)" - # FIXME: Just set LIBPATH to lib/libsecp256k1.so once version 0.6.0 is - # released. - if [ -f "src/libsecp256k1.so" ]; then - LIBPATH="src/libsecp256k1.so" - else - LIBPATH="lib/libsecp256k1.so" - fi - abi-dumper $LIBPATH -o ABI.dump -lver "$2" -public-headers ../include/ + abi-dumper lib/libsecp256k1.so -o ABI.dump -lver "$2" -public-headers ../include/ cd "$_orig_dir" } From 399b582a5f7422bac3b1707d34ffad80e072f796 Mon Sep 17 00:00:00 2001 From: John Moffett Date: Mon, 8 Sep 2025 12:21:48 -0400 Subject: [PATCH 197/383] Split memclear into two versions secp256k1_memclear has the side effect of undefining bytes for valgrind checks. In some cases, we may want to zero bytes but allow subsequent reads. So we split memclear into memclear_explicit, which makes no guarantees about the content of the buffer on return, and memzero_explicit, which guarantees zero value on return. Change the memset in partial_sign to use memzero_explicit. --- src/ecmult_gen_impl.h | 8 ++++---- src/field_impl.h | 2 +- src/group_impl.h | 4 ++-- src/hash_impl.h | 10 +++++----- src/modules/ecdh/main_impl.h | 4 ++-- src/modules/ellswift/main_impl.h | 2 +- src/modules/musig/session_impl.h | 8 ++++---- src/modules/schnorrsig/main_impl.h | 6 +++--- src/scalar_impl.h | 2 +- src/secp256k1.c | 4 ++-- src/util.h | 19 ++++++++++++++++--- 11 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index b943fe2a..2159eed5 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -277,8 +277,8 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 /* Cleanup. */ secp256k1_fe_clear(&neg); secp256k1_ge_clear(&add); - secp256k1_memclear(&adds, sizeof(adds)); - secp256k1_memclear(&recoded, sizeof(recoded)); + secp256k1_memclear_explicit(&adds, sizeof(adds)); + secp256k1_memclear_explicit(&recoded, sizeof(recoded)); } /* Setup blinding values for secp256k1_ecmult_gen. */ @@ -310,7 +310,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const VERIFY_CHECK(seed32 != NULL); memcpy(keydata + 32, seed32, 32); secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); - secp256k1_memclear(keydata, sizeof(keydata)); + secp256k1_memclear_explicit(keydata, sizeof(keydata)); /* Compute projective blinding factor (cannot be 0). */ secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); @@ -331,7 +331,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_ge_set_gej(&ctx->ge_offset, &gb); /* Clean up. */ - secp256k1_memclear(nonce32, sizeof(nonce32)); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&b); secp256k1_gej_clear(&gb); secp256k1_fe_clear(&f); diff --git a/src/field_impl.h b/src/field_impl.h index 896507a3..7aa7de43 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -19,7 +19,7 @@ #endif SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { - secp256k1_memclear(a, sizeof(secp256k1_fe)); + secp256k1_memclear_explicit(a, sizeof(secp256k1_fe)); } SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { diff --git a/src/group_impl.h b/src/group_impl.h index b8f2395d..81a24b9d 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -337,11 +337,11 @@ static void secp256k1_ge_set_infinity(secp256k1_ge *r) { } static void secp256k1_gej_clear(secp256k1_gej *r) { - secp256k1_memclear(r, sizeof(secp256k1_gej)); + secp256k1_memclear_explicit(r, sizeof(secp256k1_gej)); } static void secp256k1_ge_clear(secp256k1_ge *r) { - secp256k1_memclear(r, sizeof(secp256k1_ge)); + secp256k1_memclear_explicit(r, sizeof(secp256k1_ge)); } static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { diff --git a/src/hash_impl.h b/src/hash_impl.h index 1065acd6..43419177 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -172,7 +172,7 @@ static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const uns } static void secp256k1_sha256_clear(secp256k1_sha256 *hash) { - secp256k1_memclear(hash, sizeof(*hash)); + secp256k1_memclear_explicit(hash, sizeof(*hash)); } static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { @@ -200,7 +200,7 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const rkey[n] ^= 0x5c ^ 0x36; } secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); - secp256k1_memclear(rkey, sizeof(rkey)); + secp256k1_memclear_explicit(rkey, sizeof(rkey)); } static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { @@ -211,12 +211,12 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned unsigned char temp[32]; secp256k1_sha256_finalize(&hash->inner, temp); secp256k1_sha256_write(&hash->outer, temp, 32); - secp256k1_memclear(temp, sizeof(temp)); + secp256k1_memclear_explicit(temp, sizeof(temp)); secp256k1_sha256_finalize(&hash->outer, out32); } static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) { - secp256k1_memclear(hash, sizeof(*hash)); + secp256k1_memclear_explicit(hash, sizeof(*hash)); } static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { @@ -285,7 +285,7 @@ static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 } static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng) { - secp256k1_memclear(rng, sizeof(*rng)); + secp256k1_memclear_explicit(rng, sizeof(*rng)); } #undef Round diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 842b5359..9f2dfdd5 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -62,8 +62,8 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se ret = hashfp(output, x, y, data); - secp256k1_memclear(x, sizeof(x)); - secp256k1_memclear(y, sizeof(y)); + secp256k1_memclear_explicit(x, sizeof(x)); + secp256k1_memclear_explicit(y, sizeof(y)); secp256k1_scalar_clear(&s); secp256k1_ge_clear(&pt); secp256k1_gej_clear(&res); diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 745a9691..0d13f734 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -582,7 +582,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, /* Invoke hasher */ ret = hashfp(output, sx, ell_a64, ell_b64, data); - secp256k1_memclear(sx, sizeof(sx)); + secp256k1_memclear_explicit(sx, sizeof(sx)); secp256k1_fe_clear(&px); secp256k1_scalar_clear(&s); diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index d8dcd00c..2c8778b3 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -385,10 +385,10 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c secp256k1_scalar_set_b32(&k[i], buf, NULL); /* Attempt to erase secret data */ - secp256k1_memclear(buf, sizeof(buf)); + secp256k1_memclear_explicit(buf, sizeof(buf)); secp256k1_sha256_clear(&sha_tmp); } - secp256k1_memclear(rand, sizeof(rand)); + secp256k1_memclear_explicit(rand, sizeof(rand)); secp256k1_sha256_clear(&sha); } @@ -518,7 +518,7 @@ int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_mu if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) { return 0; } - secp256k1_memclear(seckey, sizeof(seckey)); + secp256k1_memclear_explicit(seckey, sizeof(seckey)); return 1; } @@ -679,7 +679,7 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p ret = secp256k1_musig_secnonce_load(ctx, k, &pk, secnonce); /* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls * of this function to fail */ - memset(secnonce, 0, sizeof(*secnonce)); + secp256k1_memzero_explicit(secnonce, sizeof(*secnonce)); if (!ret) { secp256k1_musig_partial_sign_clear(&sk, k); return 0; diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 13d92449..b410b19e 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -94,7 +94,7 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, nonce32); secp256k1_sha256_clear(&sha); - secp256k1_memclear(masked_key, sizeof(masked_key)); + secp256k1_memclear_explicit(masked_key, sizeof(masked_key)); return 1; } @@ -190,8 +190,8 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_memczero(sig64, 64, !ret); secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); - secp256k1_memclear(seckey, sizeof(seckey)); - secp256k1_memclear(nonce32, sizeof(nonce32)); + secp256k1_memclear_explicit(seckey, sizeof(seckey)); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_gej_clear(&rj); return ret; diff --git a/src/scalar_impl.h b/src/scalar_impl.h index 0232a8c2..9965c2ba 100644 --- a/src/scalar_impl.h +++ b/src/scalar_impl.h @@ -28,7 +28,7 @@ static const secp256k1_scalar secp256k1_scalar_one = SECP256K1_SCALAR_CONST(0, 0 static const secp256k1_scalar secp256k1_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { - secp256k1_memclear(r, sizeof(secp256k1_scalar)); + secp256k1_memclear_explicit(r, sizeof(secp256k1_scalar)); } static int secp256k1_scalar_set_b32_seckey(secp256k1_scalar *r, const unsigned char *bin) { diff --git a/src/secp256k1.c b/src/secp256k1.c index 0915af77..26336a45 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -499,7 +499,7 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m } secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_memclear(keydata, sizeof(keydata)); + secp256k1_memclear_explicit(keydata, sizeof(keydata)); secp256k1_rfc6979_hmac_sha256_clear(&rng); return 1; } @@ -550,7 +550,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc * seckey. As a result is_sec_valid is included in ret only after ret was * used as a branching variable. */ ret &= is_sec_valid; - secp256k1_memclear(nonce32, sizeof(nonce32)); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); secp256k1_scalar_clear(&sec); diff --git a/src/util.h b/src/util.h index 5f29f407..94e0837d 100644 --- a/src/util.h +++ b/src/util.h @@ -219,8 +219,8 @@ static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) { } } -/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ -static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { +/* Zeroes memory to prevent leaking sensitive info. Won't be optimized out. */ +static SECP256K1_INLINE void secp256k1_memzero_explicit(void *ptr, size_t len) { #if defined(_MSC_VER) /* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */ SecureZeroMemory(ptr, len); @@ -242,6 +242,19 @@ static SECP256K1_INLINE void secp256k1_memclear(void *ptr, size_t len) { void *(*volatile const volatile_memset)(void *, int, size_t) = memset; volatile_memset(ptr, 0, len); #endif +} + +/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. + * The state of the memory after this call is unspecified so callers must not + * make any assumptions about its contents. + * + * In VERIFY builds, it has the side effect of marking the memory as undefined. + * This helps to detect use-after-clear bugs where code incorrectly reads from + * cleansed memory during testing. + */ +static SECP256K1_INLINE void secp256k1_memclear_explicit(void *ptr, size_t len) { + /* The current implementation zeroes, but callers must not rely on this */ + secp256k1_memzero_explicit(ptr, len); #ifdef VERIFY SECP256K1_CHECKMEM_UNDEFINE(ptr, len); #endif @@ -277,7 +290,7 @@ static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size } ret = (acc == 0); /* acc may contain secret values. Try to explicitly clear it. */ - secp256k1_memclear(&acc, sizeof(acc)); + secp256k1_memclear_explicit(&acc, sizeof(acc)); return ret; } From 83d0fa25a826d716f809e00ef0a67385b776aec9 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 8 Sep 2025 19:18:39 +0000 Subject: [PATCH 198/383] extrakeys: fix pubkey_sort_cmp test Instead of providing CTX directly, pass a cmp_data object containing CTX. Otherwise, memory sanitizer fails with "use-of-uninitialized-value". --- src/modules/extrakeys/tests_impl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h index 60299ce0..1f10ceed 100644 --- a/src/modules/extrakeys/tests_impl.h +++ b/src/modules/extrakeys/tests_impl.h @@ -605,7 +605,9 @@ static void test_sort(void) { } secp256k1_pubkey_sort(CTX, pk_ptr, 5); for (j = 1; j < 5; j++) { - CHECK(secp256k1_pubkey_sort_cmp(&pk_ptr[j - 1], &pk_ptr[j], CTX) <= 0); + secp256k1_pubkey_sort_cmp_data cmp_data; + cmp_data.ctx = CTX; + CHECK(secp256k1_pubkey_sort_cmp(&pk_ptr[j - 1], &pk_ptr[j], &cmp_data) <= 0); } } } From 654a8c327c6a22989007a3e864a8c917336fc783 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 15 Aug 2024 17:43:29 +0200 Subject: [PATCH 199/383] refactor: Use array initialization for unterminated strings The previous code is correct and harmless to initialize an array with a non-terminated character sequence using a string literal. However, it requires exactly specifying the array size, which can be cumbersome. Also, GCC-15 may issue the -Wunterminated-string-initialization warning. [1] Fix both issues by using array initialization. This refactoring commit does not change behavior. [1] Example warning: src/modules/schnorrsig/main_impl.h:48:46: error: initializer-string for array of 'unsigned char' is too long [-Werror=unterminated-string-initialization] 48 | static const unsigned char bip340_algo[13] = "BIP0340/nonce"; | ^~~~~~~~~~~~~~~ (cherry picked from commit fa67b6752d8ba3e4c41f6c36b1c6b94a21770419) Conflicts: src/testrand_impl.h (kept local name `secp256k1_testrand_seed`) --- examples/schnorr.c | 4 ++-- src/modules/ellswift/tests_impl.h | 6 +++--- src/modules/schnorrsig/main_impl.h | 2 +- src/modules/schnorrsig/tests_impl.h | 10 +++++----- src/testrand_impl.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/schnorr.c b/examples/schnorr.c index 4c0dd1c1..f9bab637 100644 --- a/examples/schnorr.c +++ b/examples/schnorr.c @@ -18,9 +18,9 @@ #include "examples_util.h" int main(void) { - unsigned char msg[12] = "Hello World!"; + unsigned char msg[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'}; unsigned char msg_hash[32]; - unsigned char tag[17] = "my_fancy_protocol"; + unsigned char tag[] = {'m', 'y', '_', 'f', 'a', 'n', 'c', 'y', '_', 'p', 'r', 'o', 't', 'o', 'c', 'o', 'l'}; unsigned char seckey[32]; unsigned char randomize[32]; unsigned char auxiliary_rand[32]; diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 7d1efbc4..fc163f39 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -406,9 +406,9 @@ void run_ellswift_tests(void) { /* Test hash initializers. */ { secp256k1_sha256 sha, sha_optimized; - static const unsigned char encode_tag[25] = "secp256k1_ellswift_encode"; - static const unsigned char create_tag[25] = "secp256k1_ellswift_create"; - static const unsigned char bip324_tag[26] = "bip324_ellswift_xonly_ecdh"; + static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; + static const unsigned char create_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'c', 'r', 'e', 'a', 't', 'e'}; + static const unsigned char bip324_tag[] = {'b', 'i', 'p', '3', '2', '4', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'x', 'o', 'n', 'l', 'y', '_', 'e', 'c', 'd', 'h'}; /* Check that hash initialized by * secp256k1_ellswift_sha256_init_encode has the expected diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 26727e46..57f7eadd 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -45,7 +45,7 @@ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 * /* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 * by using the correct tagged hash function. */ -static const unsigned char bip340_algo[13] = "BIP0340/nonce"; +static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC; diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 8ada90a8..f1f4b608 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -21,9 +21,9 @@ static void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, s } static void run_nonce_function_bip340_tests(void) { - unsigned char tag[13] = "BIP0340/nonce"; - unsigned char aux_tag[11] = "BIP0340/aux"; - unsigned char algo[13] = "BIP0340/nonce"; + unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; + unsigned char aux_tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'a', 'u', 'x'}; + unsigned char algo[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'n', 'o', 'n', 'c', 'e'}; size_t algolen = sizeof(algo); secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; @@ -158,7 +158,7 @@ static void test_schnorrsig_api(void) { /* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the * expected state. */ static void test_schnorrsig_sha256_tagged(void) { - unsigned char tag[17] = "BIP0340/challenge"; + unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; @@ -806,7 +806,7 @@ static void test_schnorrsig_sign(void) { unsigned char sk[32]; secp256k1_xonly_pubkey pk; secp256k1_keypair keypair; - const unsigned char msg[32] = "this is a msg for a schnorrsig.."; + const unsigned char msg[] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'm', 's', 'g', ' ', 'f', 'o', 'r', ' ', 'a', ' ', 's', 'c', 'h', 'n', 'o', 'r', 'r', 's', 'i', 'g', '.', '.'}; unsigned char sig[64]; unsigned char sig2[64]; unsigned char zeros64[64] = { 0 }; diff --git a/src/testrand_impl.h b/src/testrand_impl.h index cff82a45..48645206 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -19,7 +19,7 @@ static uint64_t secp256k1_test_state[4]; SECP256K1_INLINE static void secp256k1_testrand_seed(const unsigned char *seed16) { - static const unsigned char PREFIX[19] = "secp256k1 test init"; + static const unsigned char PREFIX[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', ' ', 't', 'e', 's', 't', ' ', 'i', 'n', 'i', 't'}; unsigned char out32[32]; secp256k1_sha256 hash; int i; From c4570307ecb814d326c52cd79b58d1b027af8355 Mon Sep 17 00:00:00 2001 From: BEULAHEVANJALIN Date: Sat, 6 Sep 2025 19:25:24 +0530 Subject: [PATCH 200/383] test/fix: refactor unterminated string initializers to brace arrays - Mirror upstream fix (bitcoin-core/secp256k1 fa67b675) - Convert tags, test vectors, and constants in -zkp-only modules (ecdsa_adaptor, ecdsa_s2c, musig, bppp, rangeproof, schnorrsig_halfagg) - Avoid -Wunterminated-string-initialization without changing behavior --- src/modules/bppp/tests_impl.h | 2 +- src/modules/ecdsa_adaptor/dleq_impl.h | 2 +- src/modules/ecdsa_adaptor/main_impl.h | 2 +- src/modules/ecdsa_adaptor/tests_impl.h | 8 +++---- src/modules/ecdsa_s2c/tests_impl.h | 26 ++++++++++----------- src/modules/musig/tests_impl.h | 8 +++---- src/modules/rangeproof/tests_impl.h | 2 +- src/modules/schnorrsig_halfagg/tests_impl.h | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index 2ee2ac98..a2e29b84 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -103,7 +103,7 @@ static void test_bppp_generators_fixed(void) { } static void test_bppp_tagged_hash(void) { - unsigned char tag_data[29] = "Bulletproofs_pp/v0/commitment"; + unsigned char tag_data[] = {'B', 'u', 'l', 'l', 'e', 't', 'p', 'r', 'o', 'o', 'f', 's', '_', 'p', 'p', '/', 'v', '0', '/', 'c', 'o', 'm', 'm', 'i', 't', 'm', 'e', 'n', 't'}; secp256k1_sha256 sha; secp256k1_sha256 sha_cached; unsigned char output[32]; diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index 2660328c..ff946c2c 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -18,7 +18,7 @@ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) { } /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ -static const unsigned char dleq_algo[4] = "DLEQ"; +static const unsigned char dleq_algo[] = {'D','L','E','Q'}; static int secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) { unsigned char buf[33]; diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index 77f1627b..d75764f4 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -98,7 +98,7 @@ static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(secp256k1_s } /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ -static const unsigned char ecdsa_adaptor_algo[16] = "ECDSAadaptor/non"; +static const unsigned char ecdsa_adaptor_algo[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; /* Modified BIP-340 nonce function */ static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo, size_t algolen, void *data) { diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index c3b3d43d..46aec3d7 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -730,11 +730,11 @@ static void ecdsa_adaptor_test_sha256_eq(const secp256k1_sha256 *sha1, const sec } static void run_nonce_function_ecdsa_adaptor_tests(void) { - unsigned char tag[16] = "ECDSAadaptor/non"; - unsigned char aux_tag[16] = "ECDSAadaptor/aux"; - unsigned char algo[16] = "ECDSAadaptor/non"; + unsigned char tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; + unsigned char aux_tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'a', 'u', 'x'}; + unsigned char algo[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; size_t algolen = sizeof(algo); - unsigned char dleq_tag[4] = "DLEQ"; + unsigned char dleq_tag[] = {'D', 'L', 'E', 'Q'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; unsigned char nonce[32]; diff --git a/src/modules/ecdsa_s2c/tests_impl.h b/src/modules/ecdsa_s2c/tests_impl.h index 7bbd8770..48f3a3a2 100644 --- a/src/modules/ecdsa_s2c/tests_impl.h +++ b/src/modules/ecdsa_s2c/tests_impl.h @@ -10,8 +10,8 @@ #include "../../../include/secp256k1_ecdsa_s2c.h" static void test_ecdsa_s2c_tagged_hash(void) { - unsigned char tag_data[14] = "s2c/ecdsa/data"; - unsigned char tag_point[15] = "s2c/ecdsa/point"; + unsigned char tag_data[] = {'s', '2', 'c', '/', 'e', 'c', 'd', 's', 'a', '/', 'd', 'a', 't', 'a'}; + unsigned char tag_point[] = {'s', '2', 'c', '/', 'e', 'c', 'd', 's', 'a', '/', 'p', 'o', 'i', 'n', 't'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; unsigned char output[32]; @@ -78,10 +78,10 @@ static void run_s2c_opening_test(void) { static void test_ecdsa_s2c_api(void) { secp256k1_ecdsa_s2c_opening s2c_opening; secp256k1_ecdsa_signature sig; - const unsigned char msg[32] = "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"; - const unsigned char sec[32] = "ssssssssssssssssssssssssssssssss"; - const unsigned char s2c_data[32] = "dddddddddddddddddddddddddddddddd"; - const unsigned char hostrand[32] = "hrhrhrhrhrhrhrhrhrhrhrhrhrhrhrhr"; + const unsigned char msg[] = {'m', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm', 'm'}; + const unsigned char sec[] = {'s', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's', 's'}; + const unsigned char s2c_data[] = {'d', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd', 'd'}; + const unsigned char hostrand[] = {'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r', 'h', 'r'}; unsigned char hostrand_commitment[32]; secp256k1_pubkey pk; @@ -148,14 +148,14 @@ typedef struct { static ecdsa_s2c_test ecdsa_s2c_tests[] = { { - "\x1b\xf6\xfb\x42\xf4\x1e\xb8\x76\xc4\xd7\xaa\x0d\x67\x24\x2b\x00\xba\xab\x99\xdc\x20\x84\x49\x3e\x4e\x63\x27\x7f\xa1\xf7\x7f\x22", - "\x03\xf0\x30\xde\xf3\x18\x8c\x0f\x56\xfc\xea\x87\x43\x5b\x30\x76\x43\xf4\x5d\xaf\xe2\x2c\xbc\x82\xfd\x56\x03\x4f\xae\x97\x41\x7d\x3a", - "\x02\xdf\x63\x75\x5d\x1f\x32\x92\xbf\xfe\xd8\x29\x86\xb1\x06\x49\x7c\x93\xb1\xf8\xbd\xc0\x45\x4b\x6b\x0b\x0a\x47\x79\xc0\xef\x71\x88", + {0x1b, 0xf6, 0xfb, 0x42, 0xf4, 0x1e, 0xb8, 0x76, 0xc4, 0xd7, 0xaa, 0x0d, 0x67, 0x24, 0x2b, 0x00, 0xba, 0xab, 0x99, 0xdc, 0x20, 0x84, 0x49, 0x3e, 0x4e, 0x63, 0x27, 0x7f, 0xa1, 0xf7, 0x7f, 0x22}, + {0x03, 0xf0, 0x30, 0xde, 0xf3, 0x18, 0x8c, 0x0f, 0x56, 0xfc, 0xea, 0x87, 0x43, 0x5b, 0x30, 0x76, 0x43, 0xf4, 0x5d, 0xaf, 0xe2, 0x2c, 0xbc, 0x82, 0xfd, 0x56, 0x03, 0x4f, 0xae, 0x97, 0x41, 0x7d, 0x3a}, + {0x02, 0xdf, 0x63, 0x75, 0x5d, 0x1f, 0x32, 0x92, 0xbf, 0xfe, 0xd8, 0x29, 0x86, 0xb1, 0x06, 0x49, 0x7c, 0x93, 0xb1, 0xf8, 0xbd, 0xc0, 0x45, 0x4b, 0x6b, 0x0b, 0x0a, 0x47, 0x79, 0xc0, 0xef, 0x71, 0x88}, }, { - "\x35\x19\x9a\x8f\xbf\x84\xad\x6e\xf6\x9a\x18\x4c\x1b\x19\x28\x5b\xef\xbe\x06\xe6\x0b\x62\x64\xe6\xd3\x73\x89\x3f\x68\x55\xe2\x4a", - "\x03\x90\x17\x17\xce\x7c\x74\x84\xa2\xce\x1b\x7d\xc7\x40\x3b\x14\xe0\x35\x49\x71\x39\x3e\xc0\x92\xa7\xf3\xe0\xc8\xe4\xe2\xd2\x63\x9d", - "\x02\xc0\x4a\xc7\xf7\x71\xe8\xeb\xdb\xf3\x15\xff\x5e\x58\xb7\xfe\x95\x16\x10\x21\x03\x50\x00\x66\x17\x2c\x4f\xac\x5b\x20\xf9\xe0\xea", + {0x35, 0x19, 0x9a, 0x8f, 0xbf, 0x84, 0xad, 0x6e, 0xf6, 0x9a, 0x18, 0x4c, 0x1b, 0x19, 0x28, 0x5b, 0xef, 0xbe, 0x06, 0xe6, 0x0b, 0x62, 0x64, 0xe6, 0xd3, 0x73, 0x89, 0x3f, 0x68, 0x55, 0xe2, 0x4a}, + {0x03, 0x90, 0x17, 0x17, 0xce, 0x7c, 0x74, 0x84, 0xa2, 0xce, 0x1b, 0x7d, 0xc7, 0x40, 0x3b, 0x14, 0xe0, 0x35, 0x49, 0x71, 0x39, 0x3e, 0xc0, 0x92, 0xa7, 0xf3, 0xe0, 0xc8, 0xe4, 0xe2, 0xd2, 0x63, 0x9d}, + {0x02, 0xc0, 0x4a, 0xc7, 0xf7, 0x71, 0xe8, 0xeb, 0xdb, 0xf3, 0x15, 0xff, 0x5e, 0x58, 0xb7, 0xfe, 0x95, 0x16, 0x10, 0x21, 0x03, 0x50, 0x00, 0x66, 0x17, 0x2c, 0x4f, 0xac, 0x5b, 0x20, 0xf9, 0xe0, 0xea}, }, }; @@ -207,7 +207,7 @@ static void test_ecdsa_s2c_sign_verify(void) { { /* invalid privkeys */ unsigned char zero_privkey[32] = {0}; - unsigned char overflow_privkey[32] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + unsigned char overflow_privkey[32] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; CHECK(secp256k1_ecdsa_s2c_sign(CTX, &signature, NULL, message, zero_privkey, s2c_data) == 0); CHECK(secp256k1_ecdsa_s2c_sign(CTX, &signature, NULL, message, overflow_privkey, s2c_data) == 0); } diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index 753b8ac5..d77aed66 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -579,8 +579,8 @@ static void scriptless_atomic_swap(secp256k1_scratch_space *scratch) { int nonce_parity_b; unsigned char seed_a[2][32] = { "a0", "a1" }; unsigned char seed_b[2][32] = { "b0", "b1" }; - const unsigned char msg32_a[32] = "this is the message blockchain a"; - const unsigned char msg32_b[32] = "this is the message blockchain b"; + const unsigned char msg32_a[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'a'}; + const unsigned char msg32_b[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'b'}; int i; /* Step 1: key setup */ @@ -676,12 +676,12 @@ static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char static void sha256_tag_test(void) { secp256k1_sha256 sha_tagged; { - char tag[11] = "KeyAgg list"; + char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'l', 'i', 's', 't'}; secp256k1_musig_keyagglist_sha256(&sha_tagged); sha256_tag_test_internal(&sha_tagged, (unsigned char*)tag, sizeof(tag)); } { - char tag[18] = "KeyAgg coefficient"; + char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'c', 'o', 'e', 'f', 'f', 'i', 'c', 'i', 'e', 'n', 't'}; secp256k1_musig_keyaggcoef_sha256(&sha_tagged); sha256_tag_test_internal(&sha_tagged, (unsigned char*)tag, sizeof(tag)); } diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index 49cc16cf..f2ca3214 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -414,7 +414,7 @@ static void test_single_value_proof(uint64_t val) { unsigned char blind[32]; unsigned char blind_out[32]; unsigned char nonce[32]; - const unsigned char message[1] = " "; /* no message will fit into a single-value proof */ + const unsigned char message[] = { ' ' }; /* no message will fit into a single-value proof */ unsigned char message_out[sizeof(proof)] = { 0 }; size_t plen = sizeof(proof); uint64_t min_val_out = 0; diff --git a/src/modules/schnorrsig_halfagg/tests_impl.h b/src/modules/schnorrsig_halfagg/tests_impl.h index 16ac3ab3..37099849 100644 --- a/src/modules/schnorrsig_halfagg/tests_impl.h +++ b/src/modules/schnorrsig_halfagg/tests_impl.h @@ -8,7 +8,7 @@ /* We test that the hash initialized by secp256k1_schnorrsig_sha256_tagged_aggregate * has the expected state. */ void test_schnorrsig_sha256_tagged_aggregate(void) { - unsigned char tag[18] = "HalfAgg/randomizer"; + unsigned char tag[] = {'H', 'a', 'l', 'f', 'A', 'g', 'g', '/', 'r', 'a', 'n', 'd', 'o', 'm', 'i', 'z', 'e', 'r'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; From 40bd8549dd0a7dfcb885537cdbd2b1bc4a10b8a6 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Jul 2025 14:47:57 +0200 Subject: [PATCH 201/383] musig/test: Remove dead code This avoids a compiler warning on clang-snapshot about &keypair being uninitialized. (cherry picked from commit 8d967a602b14c86d0f9e43a31fdfe76f39f32091) --- src/modules/musig/tests_impl.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index d77aed66..ed744e5b 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -1022,13 +1022,10 @@ static void musig_test_vectors_signverify(void) { CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); expected = c->error != MUSIG_SECNONCE; - if (expected) { - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } else { - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } + CHECK(!expected); + musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); } for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) { const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i]; From 53fd89b6354842786aadf103a69ba5236ba7ac49 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 21 Jul 2025 14:08:23 +0000 Subject: [PATCH 202/383] musig/tests: initialize keypair The keypair is unused in musig_partial_sign, but clang-snapshot gives a compiler warning anyway. --- src/modules/musig/tests_impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index ed744e5b..ce99b367 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -1013,6 +1013,8 @@ static void musig_test_vectors_signverify(void) { if (!expected) { continue; } + CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); expected = c->error != MUSIG_AGGNONCE; CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); From 7d779c6d9d3a4f31b0ad69d6bb6b1b2ed6610218 Mon Sep 17 00:00:00 2001 From: BEULAHEVANJALIN Date: Mon, 8 Sep 2025 13:33:36 +0530 Subject: [PATCH 203/383] examples/musig: use brace-enclosed initializer for 32-byte msg Switch msg initialization from a string literal to a brace-enclosed array to avoid -Wunterminated-string-initialization. Upstream removed the trailing '!' from the message; this change retains it. --- examples/musig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/musig.c b/examples/musig.c index 16dd12f3..d4a02195 100644 --- a/examples/musig.c +++ b/examples/musig.c @@ -169,7 +169,7 @@ static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secr const secp256k1_pubkey *pubkeys_ptr[N_SIGNERS]; secp256k1_xonly_pubkey agg_pk; secp256k1_musig_keyagg_cache cache; - unsigned char msg[32] = "this_could_be_the_hash_of_a_msg!"; + unsigned char msg[] = {'t', 'h', 'i', 's', '_', 'c', 'o', 'u', 'l', 'd', ' ', 'b', 'e', ' ', 't', 'h', 'e', '_', 'h', 'a', 's', 'h', '_', 'o', 'f', '_', 'a', '_', 'm', 's', 'g', '!'}; unsigned char sig[64]; /* Create a secp256k1 context */ From 0c91c5604130a56bb1628fd12c56edf60de966b0 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 12 Sep 2025 03:53:06 +0200 Subject: [PATCH 204/383] test: introduce group order byte-array constant for deduplication --- src/modules/ecdh/tests_impl.h | 8 ++------ src/tests.c | 22 +++------------------- src/testutil.h | 8 ++++++++ 3 files changed, 13 insertions(+), 25 deletions(-) diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index 6888f18c..82651311 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -90,12 +90,7 @@ static void test_ecdh_generator_basepoint(void) { static void test_bad_scalar(void) { unsigned char s_zero[32] = { 0 }; - unsigned char s_overflow[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; + unsigned char s_overflow[32] = { 0 }; unsigned char s_rand[32] = { 0 }; unsigned char output[32]; secp256k1_scalar rand; @@ -107,6 +102,7 @@ static void test_bad_scalar(void) { CHECK(secp256k1_ec_pubkey_create(CTX, &point, s_rand) == 1); /* Try to multiply it by bad values */ + memcpy(s_overflow, secp256k1_group_order_bytes, 32); CHECK(secp256k1_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0); CHECK(secp256k1_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0); /* ...and a good one */ diff --git a/src/tests.c b/src/tests.c index 28bec590..cb3b3c42 100644 --- a/src/tests.c +++ b/src/tests.c @@ -6036,12 +6036,7 @@ static void run_ec_pubkey_parse_test(void) { } static void run_eckey_edge_case_test(void) { - const unsigned char orderc[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 - }; + const unsigned char *orderc = secp256k1_group_order_bytes; const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; unsigned char ctmp[33]; unsigned char ctmp2[33]; @@ -6355,13 +6350,7 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char return 1; } if (counter < 5) { - static const unsigned char order[] = { - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, - 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, - 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 - }; - memcpy(nonce32, order, 32); + memcpy(nonce32, secp256k1_group_order_bytes, 32); if (counter == 4) { nonce32[31]++; } @@ -7379,12 +7368,7 @@ static void test_ecdsa_edge_cases(void) { /* Privkey export where pubkey is the point at infinity. */ { unsigned char privkey[300]; - unsigned char seckey[32] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, - }; + const unsigned char *seckey = secp256k1_group_order_bytes; size_t outlen = 300; CHECK(!ec_privkey_export_der(CTX, privkey, &outlen, seckey, 0)); outlen = 300; diff --git a/src/testutil.h b/src/testutil.h index 64b3bb41..480f6a1a 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -11,6 +11,14 @@ #include "testrand.h" #include "util.h" +/* group order of the secp256k1 curve in 32-byte big endian representation */ +static const unsigned char secp256k1_group_order_bytes[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 +}; + static void testutil_random_fe(secp256k1_fe *x) { unsigned char bin[32]; do { From 9cce7038635afa7e94c434f1571a8e435350cb51 Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 9 Sep 2025 15:35:47 -0400 Subject: [PATCH 205/383] refactor: move 'gettime_i64()' to tests_common.h Relocate the clock time getter to tests_common.h to make it easily reusable across test programs. This will be useful for the upcoming unit test framework. Context - why not placing it inside testutil.h?: The bench program links against the production-compiled library, not its own compiled version. Therefore, `gettime_i64()` cannot be moved to testutil.h, because testutil.h calls `secp256k1_pubkey_save()`, which exists only in the internal secp256k1.c and not in the public API. --- Makefile.am | 1 + src/bench.h | 22 +--------------------- src/tests_common.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 src/tests_common.h diff --git a/Makefile.am b/Makefile.am index d511853b..4cc97bab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,6 +45,7 @@ noinst_HEADERS += src/precomputed_ecmult.h noinst_HEADERS += src/precomputed_ecmult_gen.h noinst_HEADERS += src/assumptions.h noinst_HEADERS += src/checkmem.h +noinst_HEADERS += src/tests_common.h noinst_HEADERS += src/testutil.h noinst_HEADERS += src/util.h noinst_HEADERS += src/util_local_visibility.h diff --git a/src/bench.h b/src/bench.h index 232fb35f..4e8e961b 100644 --- a/src/bench.h +++ b/src/bench.h @@ -12,27 +12,7 @@ #include #include -#if (defined(_MSC_VER) && _MSC_VER >= 1900) -# include -#else -# include -#endif - -static int64_t gettime_i64(void) { -#if (defined(_MSC_VER) && _MSC_VER >= 1900) - /* C11 way to get wallclock time */ - struct timespec tv; - if (!timespec_get(&tv, TIME_UTC)) { - fputs("timespec_get failed!", stderr); - exit(EXIT_FAILURE); - } - return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL; -#endif -} +#include "tests_common.h" #define FP_EXP (6) #define FP_MULT (1000000LL) diff --git a/src/tests_common.h b/src/tests_common.h new file mode 100644 index 00000000..a341633b --- /dev/null +++ b/src/tests_common.h @@ -0,0 +1,42 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_TESTS_COMMON_H +#define SECP256K1_TESTS_COMMON_H + +/*********************************************************************** + * Test Support Utilities + * + * This file provides general-purpose functions for tests and benchmark + * programs. Unlike testutil.h, this file is not linked to the library, + * allowing each program to choose whether to run against the production + * API or access library internals directly. + ***********************************************************************/ + +#include + +#if (defined(_MSC_VER) && _MSC_VER >= 1900) +# include +#else +# include +#endif + +static int64_t gettime_i64(void) { +#if (defined(_MSC_VER) && _MSC_VER >= 1900) + /* C11 way to get wallclock time */ + struct timespec tv; + if (!timespec_get(&tv, TIME_UTC)) { + fputs("timespec_get failed!", stderr); + exit(EXIT_FAILURE); + } + return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL; +#endif +} + +#endif /* SECP256K1_TESTS_COMMON_H */ From e639e6caa981f1b2461ff1c794ab13c39e51827e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 15 Apr 2024 17:07:41 +0200 Subject: [PATCH 206/383] autotools: Disable eager MSan in ctime_tests Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> --- build-aux/m4/bitcoin_secp.m4 | 12 ++++++++++++ configure.ac | 33 +++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4 index 11adef4f..fee2d7b4 100644 --- a/build-aux/m4/bitcoin_secp.m4 +++ b/build-aux/m4/bitcoin_secp.m4 @@ -45,6 +45,18 @@ fi AC_MSG_RESULT($has_valgrind) ]) +AC_DEFUN([SECP_MSAN_CHECK], [ +AC_MSG_CHECKING(whether MemorySanitizer is enabled) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + #if defined(__has_feature) + # if __has_feature(memory_sanitizer) + # error "MemorySanitizer is enabled." + # endif + #endif + ]])], [msan_enabled=no], [msan_enabled=yes]) +AC_MSG_RESULT([$msan_enabled]) +]) + dnl SECP_TRY_APPEND_CFLAGS(flags, VAR) dnl Append flags to VAR if CC accepts them. AC_DEFUN([SECP_TRY_APPEND_CFLAGS], [ diff --git a/configure.ac b/configure.ac index 4d2a6e67..a9c33550 100644 --- a/configure.ac +++ b/configure.ac @@ -296,6 +296,20 @@ if test x"$enable_ctime_tests" = x"auto"; then enable_ctime_tests=$enable_valgrind fi +print_msan_notice=no +if test x"$enable_ctime_tests" = x"yes" && test x"$GCC" = x"yes"; then + SECP_MSAN_CHECK + # MSan on Clang >=16 reports unitialized memory in function parameters and return values, even if + # the uninitalized variable is never actually "used". This is called "eager" checking, and it's + # sounds like good idea for normal use of MSan. However, it yields many false positives in the + # ctime_tests because many return values depend on secret (i.e., "uninitialized") values, and + # we're only interested in detecting branches (which count as "uses") on secret data. + if test x"$msan_enabled" = x"yes"; then + SECP_TRY_APPEND_CFLAGS([-fno-sanitize-memory-param-retval], SECP_CFLAGS) + print_msan_notice=yes + fi +fi + if test x"$enable_coverage" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DCOVERAGE=1" SECP_CFLAGS="-O0 --coverage $SECP_CFLAGS" @@ -660,9 +674,16 @@ if test x"$set_widemul" != xauto; then echo " wide multiplication = $set_widemul" fi echo -echo " valgrind = $enable_valgrind" -echo " CC = $CC" -echo " CPPFLAGS = $CPPFLAGS" -echo " SECP_CFLAGS = $SECP_CFLAGS" -echo " CFLAGS = $CFLAGS" -echo " LDFLAGS = $LDFLAGS" +echo " valgrind = $enable_valgrind" +echo " CC = $CC" +echo " CPPFLAGS = $CPPFLAGS" +echo " SECP_CFLAGS = $SECP_CFLAGS" +echo " CFLAGS = $CFLAGS" +echo " LDFLAGS = $LDFLAGS" + +if test x"$print_msan_notice" = x"yes"; then + echo + echo "Note:" + echo " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to SECP_CFLAGS" + echo " to avoid false positives in ctime_tests. Pass --disable-ctime-tests to avoid this." +fi From 76b3396516eef38251a1389f7fa982d46b922aab Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 22 May 2024 15:10:33 +0200 Subject: [PATCH 207/383] configure: Move "experimental" warning to bottom to make it more promiment --- configure.ac | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index a9c33550..673d6fbc 100644 --- a/configure.ac +++ b/configure.ac @@ -556,12 +556,7 @@ fi ### Check for --enable-experimental if necessary ### -if test x"$enable_experimental" = x"yes"; then - AC_MSG_NOTICE([******]) - AC_MSG_NOTICE([WARNING: experimental build]) - AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) - AC_MSG_NOTICE([******]) -else +if test x"$enable_experimental" = x"no"; then # The order of the following tests matters. If the user enables a dependent # module (which automatically enables the module dependencies) we want to # print an error for the dependent module, not the module dependency. Hence, @@ -687,3 +682,10 @@ if test x"$print_msan_notice" = x"yes"; then echo " MemorySanitizer detected, tried to add -fno-sanitize-memory-param-retval to SECP_CFLAGS" echo " to avoid false positives in ctime_tests. Pass --disable-ctime-tests to avoid this." fi + +if test x"$enable_experimental" = x"yes"; then + echo + echo "WARNING: Experimental build" + echo " Experimental features do not have stable APIs or properties, and may not be safe for" + echo " production use." +fi From fd259fe9ad320af4ea10ccf60f545f7f75ac18d4 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 22 May 2024 16:51:51 +0200 Subject: [PATCH 208/383] ci: Add job with -fsanitize-memory-param-retval --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36293f13..5dc8859e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -556,11 +556,18 @@ jobs: matrix: configuration: - env_vars: + CTIMETESTS: 'yes' CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g' - env_vars: ECMULTGENPRECISION: 2 ECMULTWINDOW: 2 + CTIMETESTS: 'yes' CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g -O3' + - env_vars: + # -fsanitize-memory-param-retval is clang's default, but our build system disables it + # when ctime_tests when enabled. + CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g' + CTIMETESTS: 'no' env: ECDH: 'yes' @@ -576,7 +583,6 @@ jobs: ECDSAADAPTOR: 'yes' BPPP: 'yes' SCHNORRSIG_HALFAGG: 'yes' - CTIMETESTS: 'yes' CC: 'clang' SECP256K1_TEST_ITERS: 32 ASM: 'no' From 7321bdf27bdc6a68875c61510c1a0d9ec4b0b7e3 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 15 Sep 2025 01:51:33 +0200 Subject: [PATCH 209/383] doc: clarify API doc of `secp256k1_ecdsa_recover` return value Co-authored-by: Tim Ruffing --- include/secp256k1_recovery.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/secp256k1_recovery.h b/include/secp256k1_recovery.h index 93a2e4cc..2430f993 100644 --- a/include/secp256k1_recovery.h +++ b/include/secp256k1_recovery.h @@ -92,7 +92,17 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable( /** Recover an ECDSA public key from a signature. * - * Returns: 1: public key successfully recovered (which guarantees a correct signature). + * Successful public key recovery guarantees that the signature, after normalization, + * passes `secp256k1_ecdsa_verify`. Thus, explicit verification is not necessary. + * + * However, a recoverable signature that successfully passes `secp256k1_ecdsa_recover`, + * when converted to a non-recoverable signature (using + * `secp256k1_ecdsa_recoverable_signature_convert`), is not guaranteed to be + * normalized and thus not guaranteed to pass `secp256k1_ecdsa_verify`. If a + * normalized signature is required, call `secp256k1_ecdsa_signature_normalize` + * after `secp256k1_ecdsa_recoverable_signature_convert`. + * + * Returns: 1: public key successfully recovered * 0: otherwise. * Args: ctx: pointer to a context object. * Out: pubkey: pointer to the recovered public key. From dfe284ed2d24ab44705ca5ecd8f3f7e1b8e4c278 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 16 Sep 2025 23:01:06 +0200 Subject: [PATCH 210/383] bench: improve context creation in ECDH benchmark Calling `secp256k1_context_create` with `SECP256K1_FLAGS_TYPE_CONTEXT` seems to be not strictly API-compliant, as the only allowed (non-deprecated) value is `SECP256K1_CONTEXT_NONE`, even if the former happens to map to the latter currently. Fix this by not dynamically creating a context in the first place and switch to using the static context, as it is sufficient for this benchmark and presumably matches what the "no capabilities" comment intended back then. --- src/modules/ecdh/bench_impl.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/modules/ecdh/bench_impl.h b/src/modules/ecdh/bench_impl.h index c23aaa94..8924e1fa 100644 --- a/src/modules/ecdh/bench_impl.h +++ b/src/modules/ecdh/bench_impl.h @@ -10,7 +10,7 @@ #include "../../../include/secp256k1_ecdh.h" typedef struct { - secp256k1_context *ctx; + const secp256k1_context *ctx; secp256k1_pubkey point; unsigned char scalar[32]; } bench_ecdh_data; @@ -46,12 +46,9 @@ static void run_ecdh_bench(int iters, int argc, char** argv) { bench_ecdh_data data; int d = argc == 1; - /* create a context with no capabilities */ - data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); + data.ctx = secp256k1_context_static; if (d || have_flag(argc, argv, "ecdh")) run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); - - secp256k1_context_destroy(data.ctx); } #endif /* SECP256K1_MODULE_ECDH_BENCH_H */ From a1be8ed1b1e9f9ce2935a095bfa2b140a3971e1b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:03:44 +0100 Subject: [PATCH 211/383] ci: Silent Homebrew's noisy reinstall warnings --- .github/workflows/ci.yml | 58 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5dc8859e..e6cde1a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -711,7 +711,7 @@ jobs: - name: Install Homebrew packages run: | - brew install automake libtool gcc + brew install --quiet automake libtool gcc ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc - name: Install and cache Valgrind @@ -739,6 +739,62 @@ jobs: run: env if: ${{ always() }} + arm64-macos-native: + name: "ARM64: macOS Sonoma" + # See: https://github.com/actions/runner-images#available-images. + runs-on: macos-14 + + env: + CC: 'clang' + HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 + WITH_VALGRIND: 'no' + CTIMETESTS: 'no' + + strategy: + fail-fast: false + matrix: + env_vars: + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } + - BUILD: 'distcheck' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Homebrew packages + run: | + brew install --quiet automake libtool gcc + ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc + + - name: CI script + env: ${{ matrix.env_vars }} + run: ./ci/ci.sh + + - run: cat tests.log || true + if: ${{ always() }} + - run: cat noverify_tests.log || true + if: ${{ always() }} + - run: cat exhaustive_tests.log || true + if: ${{ always() }} + - run: cat ctime_tests.log || true + if: ${{ always() }} + - run: cat bench.log || true + if: ${{ always() }} + - run: cat config.log || true + if: ${{ always() }} + - run: cat test_env.log || true + if: ${{ always() }} + - name: CI env + run: env + if: ${{ always() }} + win64-native: name: ${{ matrix.configuration.job_name }} # See: https://github.com/actions/runner-images#available-images. From b9a82b481fc35c5db3a127185ffada77fe107d46 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 25 Oct 2024 08:18:02 +0100 Subject: [PATCH 212/383] ci: Update macOS image The macOS 12 GHA image has been deprecated since 2024-10-07. See: https://github.com/actions/runner-images/issues/10721 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6cde1a3..9a4f44b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -680,10 +680,10 @@ jobs: run: env if: ${{ always() }} - macos-native: - name: "x86_64: macOS Monterey" + x86_64-macos-native: + name: "x86_64: macOS Ventura, Valgrind" # See: https://github.com/actions/runner-images#available-images. - runs-on: macos-12 # Use M1 once available https://github.com/github/roadmap/issues/528 + runs-on: macos-13 env: CC: 'clang' From ab560078aa9c7e977fade4ceae4a20ef8e5be025 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 17 Sep 2025 23:19:12 +0100 Subject: [PATCH 213/383] build: Fix warnings in x86_64 assembly check This change fixes: - `-Wuninitialized` in both Autotools and CMake; - `-Wreturn-type` in CMake only. --- build-aux/m4/bitcoin_secp.m4 | 2 +- cmake/CheckX86_64Assembly.cmake | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build-aux/m4/bitcoin_secp.m4 b/build-aux/m4/bitcoin_secp.m4 index 048267fa..1428d4d9 100644 --- a/build-aux/m4/bitcoin_secp.m4 +++ b/build-aux/m4/bitcoin_secp.m4 @@ -3,7 +3,7 @@ AC_DEFUN([SECP_X86_64_ASM_CHECK],[ AC_MSG_CHECKING(for x86_64 assembly availability) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]],[[ - uint64_t a = 11, tmp; + uint64_t a = 11, tmp = 0; __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); ]])], [has_x86_64_asm=yes], [has_x86_64_asm=no]) AC_MSG_RESULT([$has_x86_64_asm]) diff --git a/cmake/CheckX86_64Assembly.cmake b/cmake/CheckX86_64Assembly.cmake index ae82cd47..ca18919e 100644 --- a/cmake/CheckX86_64Assembly.cmake +++ b/cmake/CheckX86_64Assembly.cmake @@ -4,10 +4,11 @@ function(check_x86_64_assembly) check_c_source_compiles(" #include - int main() + int main(void) { - uint64_t a = 11, tmp; + uint64_t a = 11, tmp = 0; __asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\"); + return 0; } " HAVE_X86_64_ASM) set(HAVE_X86_64_ASM ${HAVE_X86_64_ASM} PARENT_SCOPE) From 895f53d1cf9719f34b5248afe6aab33deeb8e26c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 20 Aug 2025 09:57:10 +0200 Subject: [PATCH 214/383] docs: Clarify that callback can be called more than once --- include/secp256k1.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index f55a6ab9..ae31ff70 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -340,9 +340,9 @@ SECP256K1_API void secp256k1_context_destroy( * * On the other hand, during debug stage, one would want to be informed about * such mistakes, and the default (crashing) may be inadvisable. - * When this callback is triggered, the API function called is guaranteed not - * to cause a crash, though its return value and output arguments are - * undefined. + * Should this callback return instead of crashing, the return value and output + * arguments of the API function call are undefined. Moreover, the same API + * call may trigger the callback again in this case. * * When this function has not been called (or called with fn==NULL), then the * default handler will be used. The library provides a default handler which From 4d90585feaa52711133deb0c5a3cb32fca73d042 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 20 Aug 2025 09:59:54 +0200 Subject: [PATCH 215/383] docs: Improve API docs of _context_set_illegal_callback --- include/secp256k1.h | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index ae31ff70..b0a13b14 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -261,7 +261,7 @@ SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); * secp256k1_context_create (or secp256k1_context_preallocated_create), which will * take care of performing the self tests. * - * If the tests fail, this function will call the default error handler to abort the + * If the tests fail, this function will call the default error callback to abort the * program (see secp256k1_context_set_error_callback). */ SECP256K1_API void secp256k1_selftest(void); @@ -334,36 +334,37 @@ SECP256K1_API void secp256k1_context_destroy( * an API call. It will only trigger for violations that are mentioned * explicitly in the header. * - * The philosophy is that these shouldn't be dealt with through a - * specific return value, as calling code should not have branches to deal with - * the case that this code itself is broken. + * The philosophy is that these shouldn't be dealt with through a specific + * return value, as calling code should not have branches to deal with the case + * that this code itself is broken. * * On the other hand, during debug stage, one would want to be informed about - * such mistakes, and the default (crashing) may be inadvisable. - * Should this callback return instead of crashing, the return value and output - * arguments of the API function call are undefined. Moreover, the same API - * call may trigger the callback again in this case. + * such mistakes, and the default (crashing) may be inadvisable. Should this + * callback return instead of crashing, the return value and output arguments + * of the API function call are undefined. Moreover, the same API call may + * trigger the callback again in this case. * - * When this function has not been called (or called with fn==NULL), then the - * default handler will be used. The library provides a default handler which - * writes the message to stderr and calls abort. This default handler can be + * When this function has not been called (or called with fun==NULL), then the + * default callback will be used. The library provides a default callback which + * writes the message to stderr and calls abort. This default callback can be * replaced at link time if the preprocessor macro * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build * has been configured with --enable-external-default-callbacks. Then the * following two symbols must be provided to link against: * - void secp256k1_default_illegal_callback_fn(const char *message, void *data); * - void secp256k1_default_error_callback_fn(const char *message, void *data); - * The library can call these default handlers even before a proper callback data + * The library may call a default callback even before a proper callback data * pointer could have been set using secp256k1_context_set_illegal_callback or * secp256k1_context_set_error_callback, e.g., when the creation of a context - * fails. In this case, the corresponding default handler will be called with + * fails. In this case, the corresponding default callback will be called with * the data pointer argument set to NULL. * * Args: ctx: pointer to a context object. * In: fun: pointer to a function to call when an illegal argument is * passed to the API, taking a message and an opaque pointer. - * (NULL restores the default handler.) - * data: the opaque pointer to pass to fun above, must be NULL for the default handler. + * (NULL restores the default callback.) + * data: the opaque pointer to pass to fun above, must be NULL for the + * default callback. * * See also secp256k1_context_set_error_callback. */ @@ -380,8 +381,8 @@ SECP256K1_API void secp256k1_context_set_illegal_callback( * to abort the program. * * This can only trigger in case of a hardware failure, miscompilation, - * memory corruption, serious bug in the library, or other error would can - * otherwise result in undefined behaviour. It will not trigger due to mere + * memory corruption, serious bug in the library, or other error that would + * result in undefined behaviour. It will not trigger due to mere * incorrect usage of the API (see secp256k1_context_set_illegal_callback * for that). After this callback returns, anything may happen, including * crashing. @@ -389,9 +390,10 @@ SECP256K1_API void secp256k1_context_set_illegal_callback( * Args: ctx: pointer to a context object. * In: fun: pointer to a function to call when an internal error occurs, * taking a message and an opaque pointer (NULL restores the - * default handler, see secp256k1_context_set_illegal_callback + * default callback, see secp256k1_context_set_illegal_callback * for details). - * data: the opaque pointer to pass to fun above, must be NULL for the default handler. + * data: the opaque pointer to pass to fun above, must be NULL for the + * default callback. * * See also secp256k1_context_set_illegal_callback. */ From 48789dafc2a866bbc639184f0387637c0decb8c5 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 3 Sep 2025 10:59:37 -0400 Subject: [PATCH 216/383] test: introduce (mini) unit test framework Lightweight unit testing framework, providing a structured way to define, execute, and report tests. It includes a central test registry, a flexible command-line argument parser of the form "--key=value" / "-k=value" / "-key=value" (facilitating future framework extensions), ability to run tests in parallel and accumulated test time logging reports. So far the supported command-line args are: - "--jobs=" or "-j=" to specify the number of parallel workers. - "--seed=" to specify the RNG seed (random if not set). - "--iterations=" or "-i=" to specify the number of iterations. Compatibility Note: To stay compatible with previous versions, the framework also supports the two original positional arguments: the iterations count and the RNG seed (in that order). --- Makefile.am | 4 +- configure.ac | 8 ++ src/CMakeLists.txt | 14 +- src/tests.c | 347 +++++++++++++++++++++++++-------------------- src/unit_test.c | 342 ++++++++++++++++++++++++++++++++++++++++++++ src/unit_test.h | 120 ++++++++++++++++ 6 files changed, 683 insertions(+), 152 deletions(-) create mode 100644 src/unit_test.c create mode 100644 src/unit_test.h diff --git a/Makefile.am b/Makefile.am index 4cc97bab..dc798575 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,8 @@ noinst_HEADERS += src/assumptions.h noinst_HEADERS += src/checkmem.h noinst_HEADERS += src/tests_common.h noinst_HEADERS += src/testutil.h +noinst_HEADERS += src/unit_test.h +noinst_HEADERS += src/unit_test.c noinst_HEADERS += src/util.h noinst_HEADERS += src/util_local_visibility.h noinst_HEADERS += src/int128.h @@ -121,7 +123,7 @@ if USE_TESTS TESTS += noverify_tests noinst_PROGRAMS += noverify_tests noverify_tests_SOURCES = src/tests.c -noverify_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES) +noverify_tests_CPPFLAGS = $(SECP_CONFIG_DEFINES) $(TEST_DEFINES) noverify_tests_LDADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) noverify_tests_LDFLAGS = -static if !ENABLE_COVERAGE diff --git a/configure.ac b/configure.ac index 2f156ddc..6028ee28 100644 --- a/configure.ac +++ b/configure.ac @@ -443,6 +443,14 @@ if test x"$enable_experimental" = x"no"; then fi fi +# Check for concurrency support (tests only) +if test "x$enable_tests" != x"no"; then + AC_CHECK_HEADERS([sys/types.h sys/wait.h unistd.h]) + AS_IF([test "x$ac_cv_header_sys_types_h" = xyes && test "x$ac_cv_header_sys_wait_h" = xyes && + test "x$ac_cv_header_unistd_h" = xyes], [TEST_DEFINES="-DSUPPORTS_CONCURRENCY=1"], TEST_DEFINES="") + AC_SUBST(TEST_DEFINES) +fi + ### ### Generate output ### diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fa3b2903..ecbbbbe8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -134,15 +134,27 @@ if(SECP256K1_BUILD_BENCHMARK) endif() if(SECP256K1_BUILD_TESTS) + include(CheckIncludeFile) + check_include_file(sys/types.h HAVE_SYS_TYPES_H) + check_include_file(sys/wait.h HAVE_SYS_WAIT_H) + check_include_file(unistd.h HAVE_UNISTD_H) + + set(TEST_DEFINITIONS "") + if(HAVE_SYS_TYPES_H AND HAVE_SYS_WAIT_H AND HAVE_UNISTD_H) + list(APPEND TEST_DEFINITIONS SUPPORTS_CONCURRENCY=1) + endif() + add_executable(noverify_tests tests.c) target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm) + target_compile_definitions(noverify_tests PRIVATE ${TEST_DEFINITIONS}) add_test(NAME secp256k1_noverify_tests COMMAND noverify_tests) if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage") add_executable(tests tests.c) - target_compile_definitions(tests PRIVATE VERIFY) + target_compile_definitions(tests PRIVATE VERIFY ${TEST_DEFINITIONS}) target_link_libraries(tests secp256k1_precomputed secp256k1_asm) add_test(NAME secp256k1_tests COMMAND tests) endif() + unset(TEST_DEFINITIONS) endif() if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) diff --git a/src/tests.c b/src/tests.c index 28bec590..efcdbdc8 100644 --- a/src/tests.c +++ b/src/tests.c @@ -25,6 +25,8 @@ #include "checkmem.h" #include "testutil.h" #include "util.h" +#include "unit_test.h" +#include "unit_test.c" #include "../contrib/lax_der_parsing.c" #include "../contrib/lax_der_privatekey_parsing.c" @@ -37,7 +39,6 @@ #define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else -static int COUNT = 16; static secp256k1_context *CTX = NULL; static secp256k1_context *STATIC_CTX = NULL; @@ -227,6 +228,12 @@ static void run_static_context_tests(int use_prealloc) { } } +static void run_all_static_context_tests(void) +{ + run_static_context_tests(0); + run_static_context_tests(1); +} + static void run_proper_context_tests(int use_prealloc) { int32_t dummy = 0; secp256k1_context *my_ctx, *my_ctx_fresh; @@ -349,6 +356,12 @@ static void run_proper_context_tests(int use_prealloc) { secp256k1_context_preallocated_destroy(NULL); } +static void run_all_proper_context_tests(void) +{ + run_proper_context_tests(0); + run_proper_context_tests(1); +} + static void run_scratch_tests(void) { const size_t adj_alloc = ((500 + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT; @@ -7666,38 +7679,173 @@ static void run_cmov_tests(void) { ge_storage_cmov_test(); } -int main(int argc, char **argv) { - /* Disable buffering for stdout to improve reliability of getting - * diagnostic information. Happens right at the start of main because - * setbuf must be used before any other operation on the stream. */ - setbuf(stdout, NULL); - /* Also disable buffering for stderr because it's not guaranteed that it's - * unbuffered on all systems. */ - setbuf(stderr, NULL); +/* --------------------------------------------------------- */ +/* Test Registry */ +/* --------------------------------------------------------- */ - /* find iteration count */ - if (argc > 1) { - COUNT = strtol(argv[1], NULL, 0); - } else { - const char* env = getenv("SECP256K1_TEST_ITERS"); - if (env && strlen(env) > 0) { - COUNT = strtol(env, NULL, 0); - } - } - if (COUNT <= 0) { - fputs("An iteration count of 0 or less is not allowed.\n", stderr); - return EXIT_FAILURE; - } - printf("test count = %i\n", COUNT); +/* --- Special test cases that must run before RNG initialization --- */ +static const struct tf_test_entry tests_no_rng[] = { + CASE(xoshiro256pp_tests), +}; +static const struct tf_test_module registry_modules_no_rng = MAKE_TEST_MODULE(no_rng); - /* run test RNG tests (must run before we really initialize the test RNG) */ - run_xoshiro256pp_tests(); +/* --- Standard test cases start here --- */ +static const struct tf_test_entry tests_general[] = { + CASE(selftest_tests), + CASE(all_proper_context_tests), + CASE(all_static_context_tests), + CASE(deprecated_context_flags_test), + CASE(scratch_tests), +}; - /* find random seed */ - testrand_init(argc > 2 ? argv[2] : NULL); +static const struct tf_test_entry tests_integer[] = { +#ifdef SECP256K1_WIDEMUL_INT128 + CASE(int128_tests), +#endif + CASE(ctz_tests), + CASE(modinv_tests), + CASE(inverse_tests), +}; - /*** Setup test environment ***/ +static const struct tf_test_entry tests_hash[] = { + CASE(sha256_known_output_tests), + CASE(sha256_counter_tests), + CASE(hmac_sha256_tests), + CASE(rfc6979_hmac_sha256_tests), + CASE(tagged_sha256_tests), +}; +static const struct tf_test_entry tests_scalar[] = { + CASE(scalar_tests), +}; + +static const struct tf_test_entry tests_field[] = { + CASE(field_half), + CASE(field_misc), + CASE(field_convert), + CASE(field_be32_overflow), + CASE(fe_mul), + CASE(sqr), + CASE(sqrt), +}; + +static const struct tf_test_entry tests_group[] = { + CASE(ge), + CASE(gej), + CASE(group_decompress), +}; + +static const struct tf_test_entry tests_ecmult[] = { + CASE(ecmult_pre_g), + CASE(wnaf), + CASE(point_times_order), + CASE(ecmult_near_split_bound), + CASE(ecmult_chain), + CASE(ecmult_constants), + CASE(ecmult_gen_blind), + CASE(ecmult_const_tests), + CASE(ecmult_multi_tests), + CASE(ec_combine), +}; + +static const struct tf_test_entry tests_ec[] = { + CASE(endomorphism_tests), + CASE(ec_pubkey_parse_test), + CASE(eckey_edge_case_test), + CASE(eckey_negate_test), +}; + +#ifdef ENABLE_MODULE_ECDH +static const struct tf_test_entry tests_ecdh[] = { + CASE(ecdh_tests), +}; +#endif + +static const struct tf_test_entry tests_ecdsa[] = { + CASE(ec_illegal_argument_tests), + CASE(pubkey_comparison), + CASE(pubkey_sort), + CASE(random_pubkeys), + CASE(ecdsa_der_parse), + CASE(ecdsa_sign_verify), + CASE(ecdsa_end_to_end), + CASE(ecdsa_edge_cases), + CASE(ecdsa_wycheproof), +}; + +#ifdef ENABLE_MODULE_RECOVERY +static const struct tf_test_entry tests_recovery[] = { + /* ECDSA pubkey recovery tests */ + CASE(recovery_tests), +}; +#endif + +#ifdef ENABLE_MODULE_EXTRAKEYS +static const struct tf_test_entry tests_extrakeys[] = { + CASE(extrakeys_tests), +}; +#endif + +#ifdef ENABLE_MODULE_SCHNORRSIG +static const struct tf_test_entry tests_schnorrsig[] = { + CASE(schnorrsig_tests), +}; +#endif + +#ifdef ENABLE_MODULE_MUSIG +static const struct tf_test_entry tests_musig[] = { + CASE(musig_tests), +}; +#endif + +#ifdef ENABLE_MODULE_ELLSWIFT +static const struct tf_test_entry tests_ellswift[] = { + CASE(ellswift_tests), +}; +#endif + +static const struct tf_test_entry tests_utils[] = { + CASE(hsort_tests), + CASE(secp256k1_memczero_test), + CASE(secp256k1_is_zero_array_test), + CASE(secp256k1_byteorder_tests), + CASE(cmov_tests), +}; + +/* Register test modules */ +static const struct tf_test_module registry_modules[] = { + MAKE_TEST_MODULE(general), + MAKE_TEST_MODULE(integer), + MAKE_TEST_MODULE(hash), + MAKE_TEST_MODULE(scalar), + MAKE_TEST_MODULE(field), + MAKE_TEST_MODULE(group), + MAKE_TEST_MODULE(ecmult), + MAKE_TEST_MODULE(ec), +#ifdef ENABLE_MODULE_ECDH + MAKE_TEST_MODULE(ecdh), +#endif + MAKE_TEST_MODULE(ecdsa), +#ifdef ENABLE_MODULE_RECOVERY + MAKE_TEST_MODULE(recovery), +#endif +#ifdef ENABLE_MODULE_EXTRAKEYS + MAKE_TEST_MODULE(extrakeys), +#endif +#ifdef ENABLE_MODULE_SCHNORRSIG + MAKE_TEST_MODULE(schnorrsig), +#endif +#ifdef ENABLE_MODULE_MUSIG + MAKE_TEST_MODULE(musig), +#endif +#ifdef ENABLE_MODULE_ELLSWIFT + MAKE_TEST_MODULE(ellswift), +#endif + MAKE_TEST_MODULE(utils), +}; + +/* Setup test environment */ +static int setup(void) { /* Create a global context available to all tests */ CTX = secp256k1_context_create(SECP256K1_CONTEXT_NONE); /* Randomize the context only with probability 15/16 @@ -7716,129 +7864,28 @@ int main(int argc, char **argv) { CHECK(STATIC_CTX != NULL); memcpy(STATIC_CTX, secp256k1_context_static, sizeof(secp256k1_context)); CHECK(!secp256k1_context_is_proper(STATIC_CTX)); + return 0; +} - /*** Run actual tests ***/ - - /* selftest tests */ - run_selftest_tests(); - - /* context tests */ - run_proper_context_tests(0); run_proper_context_tests(1); - run_static_context_tests(0); run_static_context_tests(1); - run_deprecated_context_flags_test(); - - /* scratch tests */ - run_scratch_tests(); - - /* integer arithmetic tests */ -#ifdef SECP256K1_WIDEMUL_INT128 - run_int128_tests(); -#endif - run_ctz_tests(); - run_modinv_tests(); - run_inverse_tests(); - - /* sorting tests */ - run_hsort_tests(); - - /* hash tests */ - run_sha256_known_output_tests(); - run_sha256_counter_tests(); - run_hmac_sha256_tests(); - run_rfc6979_hmac_sha256_tests(); - run_tagged_sha256_tests(); - - /* scalar tests */ - run_scalar_tests(); - - /* field tests */ - run_field_half(); - run_field_misc(); - run_field_convert(); - run_field_be32_overflow(); - run_fe_mul(); - run_sqr(); - run_sqrt(); - - /* group tests */ - run_ge(); - run_gej(); - run_group_decompress(); - - /* ecmult tests */ - run_ecmult_pre_g(); - run_wnaf(); - run_point_times_order(); - run_ecmult_near_split_bound(); - run_ecmult_chain(); - run_ecmult_constants(); - run_ecmult_gen_blind(); - run_ecmult_const_tests(); - run_ecmult_multi_tests(); - run_ec_combine(); - - /* endomorphism tests */ - run_endomorphism_tests(); - - /* EC point parser test */ - run_ec_pubkey_parse_test(); - - /* EC key edge cases */ - run_eckey_edge_case_test(); - - /* EC key arithmetic test */ - run_eckey_negate_test(); - -#ifdef ENABLE_MODULE_ECDH - /* ecdh tests */ - run_ecdh_tests(); -#endif - - /* ecdsa tests */ - run_ec_illegal_argument_tests(); - run_pubkey_comparison(); - run_pubkey_sort(); - run_random_pubkeys(); - run_ecdsa_der_parse(); - run_ecdsa_sign_verify(); - run_ecdsa_end_to_end(); - run_ecdsa_edge_cases(); - run_ecdsa_wycheproof(); - -#ifdef ENABLE_MODULE_RECOVERY - /* ECDSA pubkey recovery tests */ - run_recovery_tests(); -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS - run_extrakeys_tests(); -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG - run_schnorrsig_tests(); -#endif - -#ifdef ENABLE_MODULE_MUSIG - run_musig_tests(); -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT - run_ellswift_tests(); -#endif - - /* util tests */ - run_secp256k1_memczero_test(); - run_secp256k1_is_zero_array_test(); - run_secp256k1_byteorder_tests(); - - run_cmov_tests(); - - /*** Tear down test environment ***/ +/* Shutdown test environment */ +static int teardown(void) { free(STATIC_CTX); secp256k1_context_destroy(CTX); - - testrand_finish(); - - printf("no problems found\n"); - return EXIT_SUCCESS; + return 0; } + +int main(int argc, char **argv) { + struct tf_framework tf = {0}; + tf.registry_modules = registry_modules; + tf.num_modules = sizeof(registry_modules) / sizeof(registry_modules[0]); + tf.registry_no_rng = ®istry_modules_no_rng; + + /* Add context creation/destruction functions */ + tf.fn_setup = setup; + tf.fn_teardown = teardown; + + /* Init and run framework */ + if (tf_init(&tf, argc, argv) != 0) return EXIT_FAILURE; + return tf_run(&tf); +} + diff --git a/src/unit_test.c b/src/unit_test.c new file mode 100644 index 00000000..914594bc --- /dev/null +++ b/src/unit_test.c @@ -0,0 +1,342 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#include +#include +#include + +#if defined(SUPPORTS_CONCURRENCY) +#include +#include +#include +#endif + +#include "unit_test.h" +#include "testrand.h" +#include "tests_common.h" + +#define UNUSED(x) (void)(x) + +/* Number of times certain tests will run */ +int COUNT = 16; + +static int parse_jobs_count(const char* key, const char* value, struct tf_framework* tf); +static int parse_iterations(const char* key, const char* value, struct tf_framework* tf); +static int parse_seed(const char* key, const char* value, struct tf_framework* tf); + +/* Mapping table: key -> handler */ +typedef int (*ArgHandler)(const char* key, const char* value, struct tf_framework* tf); +struct ArgMap { + const char* key; + ArgHandler handler; +}; + +/* + * Main entry point for handling command-line arguments. + * + * Developers should extend this map whenever new command-line + * options are introduced. Each new argument should be validated, + * converted to the appropriate type, and stored in 'tf->args' struct. + */ +static struct ArgMap arg_map[] = { + { "j", parse_jobs_count }, { "jobs", parse_jobs_count }, + { "i", parse_iterations }, { "iterations", parse_iterations }, + { "seed", parse_seed }, + { NULL, NULL } /* sentinel */ +}; + +/* Display options that are not printed elsewhere */ +static void print_args(const struct tf_args* args) { + printf("iterations = %d\n", COUNT); + printf("jobs = %d. %s execution.\n", args->num_processes, args->num_processes > 1 ? "Parallel" : "Sequential"); +} + +/* Main entry point for reading environment variables */ +static int read_env(struct tf_framework* tf) { + const char* env_iter = getenv("SECP256K1_TEST_ITERS"); + if (env_iter && strlen(env_iter) > 0) { + return parse_iterations("i", env_iter, tf); + } + return 0; +} + +static int parse_arg(const char* key, const char* value, struct tf_framework* tf) { + int i; + for (i = 0; arg_map[i].key != NULL; i++) { + if (strcmp(key, arg_map[i].key) == 0) { + return arg_map[i].handler(key, value, tf); + } + } + /* Unknown key: report just so typos don't silently pass. */ + fprintf(stderr, "Unknown argument '-%s=%s'\n", key, value); + return -1; +} + +static int parse_jobs_count(const char* key, const char* value, struct tf_framework* tf) { + char* ptr_val; + long val = strtol(value, &ptr_val, 10); /* base 10 */ + if (*ptr_val != '\0') { + fprintf(stderr, "Invalid number for -%s=%s\n", key, value); + return -1; + } + if (val < 0 || val > MAX_SUBPROCESSES) { + fprintf(stderr, "Arg '-%s' out of range: '%ld'. Range: 0..%d\n", key, val, MAX_SUBPROCESSES); + return -1; + } + tf->args.num_processes = (int) val; + return 0; +} + +static int parse_iterations(const char* key, const char* value, struct tf_framework* tf) { + UNUSED(key); UNUSED(tf); + if (!value) return 0; + COUNT = (int) strtol(value, NULL, 0); + if (COUNT <= 0) { + fputs("An iteration count of 0 or less is not allowed.\n", stderr); + return -1; + } + return 0; +} + +static int parse_seed(const char* key, const char* value, struct tf_framework* tf) { + UNUSED(key); + tf->args.custom_seed = (!value || strcmp(value, "NULL") == 0) ? NULL : value; + return 0; +} + +/* Strip up to two leading dashes */ +static const char* normalize_key(const char* arg, const char** err_msg) { + const char* key; + if (!arg || arg[0] != '-') { + *err_msg = "missing initial dash"; + return NULL; + } + /* single-dash short option */ + if (arg[1] != '-') return arg + 1; + + /* double-dash checks now */ + if (arg[2] == '\0') { + *err_msg = "missing option name after double dash"; + return NULL; + } + + if (arg[2] == '-') { + *err_msg = "too many leading dashes"; + return NULL; + } + + key = arg + 2; + if (key[1] == '\0') { + *err_msg = "short option cannot use double dash"; + return NULL; + } + return key; +} + +/* Read args: all must be in the form -key=value, --key=value or -key=value */ +static int read_args(int argc, char** argv, int start, struct tf_framework* tf) { + int i; + const char* key; + const char* value; + char* eq; + const char* err_msg = "unknown error"; + for (i = start; i < argc; i++) { + char* raw_arg = argv[i]; + if (!raw_arg || raw_arg[0] != '-') { + fprintf(stderr, "Invalid arg '%s': must start with '-'\n", raw_arg ? raw_arg : "(null)"); + return -1; + } + + key = normalize_key(raw_arg, &err_msg); + if (!key || *key == '\0') { + fprintf(stderr, "Invalid arg '%s': %s. Must be -k=value or --key=value\n", raw_arg, err_msg); + return -1; + } + + eq = strchr(raw_arg, '='); + if (!eq || eq == raw_arg + 1) { + fprintf(stderr, "Invalid arg '%s': must be -k=value or --key=value\n", raw_arg); + return -1; + } + + *eq = '\0'; /* split key and value */ + value = eq + 1; + if (!value || *value == '\0') { /* value is empty */ + fprintf(stderr, "Invalid arg '%s': value cannot be empty\n", raw_arg); + return -1; + } + + if (parse_arg(key, value, tf) != 0) return -1; + } + return 0; +} + +static void run_test(const struct tf_test_entry* t) { + printf("Running %s..\n", t->name); + t->func(); + printf("%s PASSED\n", t->name); +} + +/* Process tests in sequential order */ +static int run_sequential(struct tf_framework* tf) { + tf_test_ref ref; + const struct tf_test_module* mdl; + for (ref.group = 0; ref.group < tf->num_modules; ref.group++) { + mdl = &tf->registry_modules[ref.group]; + for (ref.idx = 0; ref.idx < mdl->size; ref.idx++) { + run_test(&mdl->data[ref.idx]); + } + } + return EXIT_SUCCESS; +} + +#if defined(SUPPORTS_CONCURRENCY) +/* Process tests in parallel */ +static int run_concurrent(struct tf_framework* tf) { + /* Sub-processes info */ + pid_t workers[MAX_SUBPROCESSES]; + int pipefd[2]; + int status = EXIT_SUCCESS; + int it; /* loop iterator */ + tf_test_ref ref; /* test index */ + + if (pipe(pipefd) != 0) { + perror("Error during pipe setup"); + return EXIT_FAILURE; + } + + /* Launch worker processes */ + for (it = 0; it < tf->args.num_processes; it++) { + pid_t pid = fork(); + if (pid < 0) { + perror("Error during process fork"); + return EXIT_FAILURE; + } + if (pid == 0) { + /* Child worker: read jobs from the shared pipe */ + close(pipefd[1]); /* children never write */ + while (read(pipefd[0], &ref, sizeof(ref)) == sizeof(ref)) { + run_test(&tf->registry_modules[ref.group].data[ref.idx]); + } + _exit(EXIT_SUCCESS); /* finish child process */ + } else { + /* Parent: save worker pid */ + workers[it] = pid; + } + } + + /* Parent: write all tasks into the pipe */ + close(pipefd[0]); /* close read end */ + for (ref.group = 0; ref.group < tf->num_modules; ref.group++) { + const struct tf_test_module* mdl = &tf->registry_modules[ref.group]; + for (ref.idx = 0; ref.idx < mdl->size; ref.idx++) { + if (write(pipefd[1], &ref, sizeof(ref)) == -1) { + perror("Error during workload distribution"); + close(pipefd[1]); + return EXIT_FAILURE; + } + } + } + /* Close write end to signal EOF */ + close(pipefd[1]); + /* Wait for all workers */ + for (it = 0; it < tf->args.num_processes; it++) { + int ret = 0; + if (waitpid(workers[it], &ret, 0) == -1 || ret != 0) { + status = EXIT_FAILURE; + } + } + + return status; +} +#endif + +static int tf_init(struct tf_framework* tf, int argc, char** argv) +{ + /* Caller must set the registry and its size before calling tf_init */ + if (tf->registry_modules == NULL || tf->num_modules <= 0) { + fprintf(stderr, "Error: tests registry not provided or empty\n"); + return EXIT_FAILURE; + } + + /* Initialize command-line options */ + tf->args.num_processes = 0; + tf->args.custom_seed = NULL; + + /* Disable buffering for stdout to improve reliability of getting + * diagnostic information. Happens right at the start of main because + * setbuf must be used before any other operation on the stream. */ + setbuf(stdout, NULL); + /* Also disable buffering for stderr because it's not guaranteed that it's + * unbuffered on all systems. */ + setbuf(stderr, NULL); + + /* Parse env args */ + if (read_env(tf) != 0) return EXIT_FAILURE; + + /* Parse command-line args */ + if (argc > 1) { + int named_arg_start = 1; /* index to begin processing named arguments */ + if (argc - 1 > MAX_ARGS) { /* first arg is always the binary path */ + fprintf(stderr, "Too many command-line arguments (max: %d)\n", MAX_ARGS); + return EXIT_FAILURE; + } + + /* Compatibility Note: The first two args were the number of iterations and the seed. */ + /* If provided, parse them and adjust the starting index for named arguments accordingly. */ + if (argv[1][0] != '-') { + int has_seed = argc > 2 && argv[2][0] != '-'; + if (parse_iterations("i", argv[1], tf) != 0) return EXIT_FAILURE; + if (has_seed) parse_seed("seed", argv[2], tf); + named_arg_start = has_seed ? 3 : 2; + } + if (read_args(argc, argv, named_arg_start, tf) != 0) { + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} + +static int tf_run(struct tf_framework* tf) { + /* Process exit status */ + int status; + /* Loop iterator */ + int it; + /* Initial test time */ + int64_t start_time = gettime_i64(); + + /* Log configuration */ + print_args(&tf->args); + + /* Run test RNG tests (must run before we really initialize the test RNG) */ + /* Note: currently, these tests are executed sequentially because there */ + /* is really only one test. */ + for (it = 0; tf->registry_no_rng && it < tf->registry_no_rng->size; it++) { + run_test(&tf->registry_no_rng->data[it]); + } + + /* Initialize test RNG and library contexts */ + testrand_init(tf->args.custom_seed); + if (tf->fn_setup && tf->fn_setup() != 0) return EXIT_FAILURE; + + /* Check whether to process tests sequentially or concurrently */ + if (tf->args.num_processes <= 1) { + status = run_sequential(tf); + } else { +#if defined(SUPPORTS_CONCURRENCY) + status = run_concurrent(tf); +#else + fputs("Parallel execution not supported on your system. Running sequentially...\n", stderr); + status = run_sequential(tf); +#endif + } + + /* Print accumulated time */ + printf("Total execution time: %.3f seconds\n", (double)(gettime_i64() - start_time) / 1000000); + if (tf->fn_teardown && tf->fn_teardown() != 0) return EXIT_FAILURE; + + return status; +} diff --git a/src/unit_test.h b/src/unit_test.h new file mode 100644 index 00000000..f1374a0d --- /dev/null +++ b/src/unit_test.h @@ -0,0 +1,120 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_UNIT_TEST_H +#define SECP256K1_UNIT_TEST_H + +/* --------------------------------------------------------- */ +/* Configurable constants */ +/* --------------------------------------------------------- */ + +/* Maximum number of command-line arguments. + * Must be at least as large as the total number of tests + * to allow specifying all tests individually. */ +#define MAX_ARGS 150 +/* Maximum number of parallel jobs */ +#define MAX_SUBPROCESSES 16 + +/* --------------------------------------------------------- */ +/* Test Framework Registry Macros */ +/* --------------------------------------------------------- */ + +#define CASE(name) { #name, run_##name } + +#define MAKE_TEST_MODULE(name) { \ + #name, \ + tests_##name, \ + sizeof(tests_##name) / sizeof(tests_##name[0]) \ +} + +/* --------------------------------------------------------- */ +/* Test Framework API */ +/* --------------------------------------------------------- */ + +typedef void (*test_fn)(void); + +struct tf_test_entry { + const char* name; + test_fn func; +}; + +struct tf_test_module { + const char* name; + const struct tf_test_entry* data; + int size; +}; + +typedef int (*setup_ctx_fn)(void); +typedef int (*teardown_fn)(void); + +/* Reference to a test in the registry. Group index and test index */ +typedef struct { + int group; + int idx; +} tf_test_ref; + +/* --- Command-line args --- */ +struct tf_args { + /* 0 => sequential; 1..MAX_SUBPROCESSES => parallel workers */ + int num_processes; + /* Specific RNG seed */ + const char* custom_seed; +}; + +/* --------------------------------------------------------- */ +/* Public API */ +/* --------------------------------------------------------- */ + +struct tf_framework { + /* Command-line args */ + struct tf_args args; + /* Test modules registry */ + const struct tf_test_module* registry_modules; + /* Num of modules */ + int num_modules; + /* Registry for tests that require no RNG init */ + const struct tf_test_module* registry_no_rng; + /* Specific context setup and teardown functions */ + setup_ctx_fn fn_setup; + teardown_fn fn_teardown; +}; + +/* + * Initialize the test framework. + * + * Must be called before tf_run() and before any output is performed to + * stdout or stderr, because this function disables buffering on both + * streams to ensure reliable diagnostic output. + * + * Parses command-line arguments and configures the framework context. + * The caller must initialize the following members of 'tf' before calling: + * - tf->registry_modules + * - tf->num_modules + * + * Side effects: + * - stdout and stderr are set to unbuffered mode via setbuf(). + * This allows immediate flushing of diagnostic messages but may + * affect performance for other output operations. + * + * Returns: + * EXIT_SUCCESS (0) on success, + * EXIT_FAILURE (non-zero) on error. + */ +static int tf_init(struct tf_framework* tf, int argc, char** argv); + +/* + * Run tests based on the provided test framework context. + * + * This function uses the configuration stored in the tf_framework + * (targets, number of processes, iteration count, etc.) to determine + * which tests to execute and how to execute them. + * + * Returns: + * EXIT_SUCCESS (0) if all tests passed, + * EXIT_FAILURE (non-zero) otherwise. + */ +static int tf_run(struct tf_framework* tf); + +#endif /* SECP256K1_UNIT_TEST_H */ From 9ec3bfe22dc662875e6fca2419713eae105dabee Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 9 Sep 2025 11:45:17 -0400 Subject: [PATCH 217/383] test: adapt modules to the new test infrastructure This not only provides a structural improvement but also allows us to (1) specify individual tests to run and (2) execute each of them concurrently. --- src/modules/ecdh/tests_impl.h | 17 ++++++----- src/modules/ellswift/tests_impl.h | 7 +++++ src/modules/extrakeys/tests_impl.h | 21 +++++++------- src/modules/musig/tests_impl.h | 45 ++++++++++++++--------------- src/modules/recovery/tests_impl.h | 25 ++++++++-------- src/modules/schnorrsig/tests_impl.h | 29 ++++++++++--------- src/tests.c | 38 +----------------------- src/unit_test.h | 13 +++++++++ 8 files changed, 91 insertions(+), 104 deletions(-) diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index 6888f18c..c1a5e73c 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -7,6 +7,8 @@ #ifndef SECP256K1_MODULE_ECDH_TESTS_H #define SECP256K1_MODULE_ECDH_TESTS_H +#include "../../unit_test.h" + static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { (void)y; (void)data; @@ -182,12 +184,13 @@ static void test_ecdh_wycheproof(void) { } } -static void run_ecdh_tests(void) { - test_ecdh_api(); - test_ecdh_generator_basepoint(); - test_bad_scalar(); - test_result_basepoint(); - test_ecdh_wycheproof(); -} +/* --- Test registry --- */ +static const struct tf_test_entry tests_ecdh[] = { + CASE1(test_ecdh_api), + CASE1(test_ecdh_generator_basepoint), + CASE1(test_bad_scalar), + CASE1(test_result_basepoint), + CASE1(test_ecdh_wycheproof), +}; #endif /* SECP256K1_MODULE_ECDH_TESTS_H */ diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index b90fd0ab..63c36e7f 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -7,6 +7,7 @@ #define SECP256K1_MODULE_ELLSWIFT_TESTS_H #include "../../../include/secp256k1_ellswift.h" +#include "../../unit_test.h" struct ellswift_xswiftec_inv_test { int enc_bitmap; @@ -433,4 +434,10 @@ void run_ellswift_tests(void) { } } +/* --- Test registry --- */ +/* TODO: subdivide test in cases */ +static const struct tf_test_entry tests_ellswift[] = { + CASE(ellswift_tests), +}; + #endif diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h index ab4ef4a7..abebd110 100644 --- a/src/modules/extrakeys/tests_impl.h +++ b/src/modules/extrakeys/tests_impl.h @@ -8,6 +8,7 @@ #define SECP256K1_MODULE_EXTRAKEYS_TESTS_H #include "../../../include/secp256k1_extrakeys.h" +#include "../../unit_test.h" static void test_xonly_pubkey(void) { secp256k1_pubkey pk; @@ -467,17 +468,17 @@ static void test_keypair_add(void) { } } -static void run_extrakeys_tests(void) { +/* --- Test registry --- */ +static const struct tf_test_entry tests_extrakeys[] = { /* xonly key test cases */ - test_xonly_pubkey(); - test_xonly_pubkey_tweak(); - test_xonly_pubkey_tweak_check(); - test_xonly_pubkey_tweak_recursive(); - test_xonly_pubkey_comparison(); - + CASE1(test_xonly_pubkey), + CASE1(test_xonly_pubkey_tweak), + CASE1(test_xonly_pubkey_tweak_check), + CASE1(test_xonly_pubkey_tweak_recursive), + CASE1(test_xonly_pubkey_comparison), /* keypair tests */ - test_keypair(); - test_keypair_add(); -} + CASE1(test_keypair), + CASE1(test_keypair_add), +}; #endif diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index b57b2626..b4ba1854 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -20,6 +20,7 @@ #include "../../group.h" #include "../../hash.h" #include "../../util.h" +#include "../../unit_test.h" #include "vectors.h" @@ -36,7 +37,7 @@ static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *p /* Just a simple (non-tweaked) 2-of-2 MuSig aggregate, sign, verify * test. */ -static void musig_simple_test(void) { +static void musig_simple_test_internal(void) { unsigned char sk[2][32]; secp256k1_keypair keypair[2]; secp256k1_musig_pubnonce pubnonce[2]; @@ -629,7 +630,7 @@ static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const /* Create aggregate public key P[0], tweak multiple times (using xonly and * plain tweaking) and test signing. */ -static void musig_tweak_test(void) { +static void musig_tweak_test_internal(void) { unsigned char sk[2][32]; secp256k1_pubkey pk[2]; const secp256k1_pubkey *pk_ptr[2]; @@ -1114,28 +1115,24 @@ static void musig_test_static_nonce_gen_counter(void) { CHECK(secp256k1_memcmp_var(pubnonce66, expected_pubnonce, sizeof(pubnonce66)) == 0); } -static void run_musig_tests(void) { - int i; +/* --- Test registry --- */ +REPEAT_TEST(musig_simple_test) +/* Run multiple times to ensure that pk and nonce have different y parities */ +REPEAT_TEST(musig_tweak_test) - for (i = 0; i < COUNT; i++) { - musig_simple_test(); - } - musig_api_tests(); - musig_nonce_test(); - for (i = 0; i < COUNT; i++) { - /* Run multiple times to ensure that pk and nonce have different y - * parities */ - musig_tweak_test(); - } - sha256_tag_test(); - musig_test_vectors_keyagg(); - musig_test_vectors_noncegen(); - musig_test_vectors_nonceagg(); - musig_test_vectors_signverify(); - musig_test_vectors_tweak(); - musig_test_vectors_sigagg(); - - musig_test_static_nonce_gen_counter(); -} +static const struct tf_test_entry tests_musig[] = { + CASE1(musig_simple_test), + CASE1(musig_api_tests), + CASE1(musig_nonce_test), + CASE1(musig_tweak_test), + CASE1(sha256_tag_test), + CASE1(musig_test_vectors_keyagg), + CASE1(musig_test_vectors_noncegen), + CASE1(musig_test_vectors_nonceagg), + CASE1(musig_test_vectors_signverify), + CASE1(musig_test_vectors_tweak), + CASE1(musig_test_vectors_sigagg), + CASE1(musig_test_static_nonce_gen_counter), +}; #endif diff --git a/src/modules/recovery/tests_impl.h b/src/modules/recovery/tests_impl.h index 7a28a3ce..09554a24 100644 --- a/src/modules/recovery/tests_impl.h +++ b/src/modules/recovery/tests_impl.h @@ -7,6 +7,8 @@ #ifndef SECP256K1_MODULE_RECOVERY_TESTS_H #define SECP256K1_MODULE_RECOVERY_TESTS_H +#include "../../unit_test.h" + static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { (void) msg32; (void) key32; @@ -28,7 +30,7 @@ static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned c return testrand_bits(1); } -static void test_ecdsa_recovery_api(void) { +static void test_ecdsa_recovery_api_internal(void) { /* Setup contexts that just count errors */ secp256k1_pubkey pubkey; secp256k1_pubkey recpubkey; @@ -92,7 +94,7 @@ static void test_ecdsa_recovery_api(void) { CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, recid) == 0); } -static void test_ecdsa_recovery_end_to_end(void) { +static void test_ecdsa_recovery_end_to_end_internal(void) { unsigned char extra[32] = {0x00}; unsigned char privkey[32]; unsigned char message[32]; @@ -324,15 +326,14 @@ static void test_ecdsa_recovery_edge_cases(void) { } } -static void run_recovery_tests(void) { - int i; - for (i = 0; i < COUNT; i++) { - test_ecdsa_recovery_api(); - } - for (i = 0; i < 64*COUNT; i++) { - test_ecdsa_recovery_end_to_end(); - } - test_ecdsa_recovery_edge_cases(); -} +/* --- Test registry --- */ +REPEAT_TEST(test_ecdsa_recovery_api) +REPEAT_TEST_MULT(test_ecdsa_recovery_end_to_end, 64) + +static const struct tf_test_entry tests_recovery[] = { + CASE1(test_ecdsa_recovery_api), + CASE1(test_ecdsa_recovery_end_to_end), + CASE1(test_ecdsa_recovery_edge_cases) +}; #endif /* SECP256K1_MODULE_RECOVERY_TESTS_H */ diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 5abbeefe..9a1b15f0 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -8,6 +8,7 @@ #define SECP256K1_MODULE_SCHNORRSIG_TESTS_H #include "../../../include/secp256k1_schnorrsig.h" +#include "../../unit_test.h" /* Checks that a bit flip in the n_flip-th argument (that has n_bytes many * bytes) changes the hash function @@ -802,7 +803,7 @@ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned cha return 1; } -static void test_schnorrsig_sign(void) { +static void test_schnorrsig_sign_internal(void) { unsigned char sk[32]; secp256k1_xonly_pubkey pk; secp256k1_keypair keypair; @@ -852,7 +853,7 @@ static void test_schnorrsig_sign(void) { /* Creates N_SIGS valid signatures and verifies them with verify and * verify_batch (TODO). Then flips some bits and checks that verification now * fails. */ -static void test_schnorrsig_sign_verify(void) { +static void test_schnorrsig_sign_verify_internal(void) { unsigned char sk[32]; unsigned char msg[N_SIGS][32]; unsigned char sig[N_SIGS][64]; @@ -965,18 +966,18 @@ static void test_schnorrsig_taproot(void) { CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); } -static void run_schnorrsig_tests(void) { - int i; - run_nonce_function_bip340_tests(); +/* --- Test registry --- */ +REPEAT_TEST(test_schnorrsig_sign) +REPEAT_TEST(test_schnorrsig_sign_verify) - test_schnorrsig_api(); - test_schnorrsig_sha256_tagged(); - test_schnorrsig_bip_vectors(); - for (i = 0; i < COUNT; i++) { - test_schnorrsig_sign(); - test_schnorrsig_sign_verify(); - } - test_schnorrsig_taproot(); -} +static const struct tf_test_entry tests_schnorrsig[] = { + CASE(nonce_function_bip340_tests), + CASE1(test_schnorrsig_api), + CASE1(test_schnorrsig_sha256_tagged), + CASE1(test_schnorrsig_bip_vectors), + CASE1(test_schnorrsig_sign), + CASE1(test_schnorrsig_sign_verify), + CASE1(test_schnorrsig_taproot), +}; #endif diff --git a/src/tests.c b/src/tests.c index efcdbdc8..5f4f6b0f 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7755,12 +7755,6 @@ static const struct tf_test_entry tests_ec[] = { CASE(eckey_negate_test), }; -#ifdef ENABLE_MODULE_ECDH -static const struct tf_test_entry tests_ecdh[] = { - CASE(ecdh_tests), -}; -#endif - static const struct tf_test_entry tests_ecdsa[] = { CASE(ec_illegal_argument_tests), CASE(pubkey_comparison), @@ -7773,37 +7767,6 @@ static const struct tf_test_entry tests_ecdsa[] = { CASE(ecdsa_wycheproof), }; -#ifdef ENABLE_MODULE_RECOVERY -static const struct tf_test_entry tests_recovery[] = { - /* ECDSA pubkey recovery tests */ - CASE(recovery_tests), -}; -#endif - -#ifdef ENABLE_MODULE_EXTRAKEYS -static const struct tf_test_entry tests_extrakeys[] = { - CASE(extrakeys_tests), -}; -#endif - -#ifdef ENABLE_MODULE_SCHNORRSIG -static const struct tf_test_entry tests_schnorrsig[] = { - CASE(schnorrsig_tests), -}; -#endif - -#ifdef ENABLE_MODULE_MUSIG -static const struct tf_test_entry tests_musig[] = { - CASE(musig_tests), -}; -#endif - -#ifdef ENABLE_MODULE_ELLSWIFT -static const struct tf_test_entry tests_ellswift[] = { - CASE(ellswift_tests), -}; -#endif - static const struct tf_test_entry tests_utils[] = { CASE(hsort_tests), CASE(secp256k1_memczero_test), @@ -7827,6 +7790,7 @@ static const struct tf_test_module registry_modules[] = { #endif MAKE_TEST_MODULE(ecdsa), #ifdef ENABLE_MODULE_RECOVERY + /* ECDSA pubkey recovery tests */ MAKE_TEST_MODULE(recovery), #endif #ifdef ENABLE_MODULE_EXTRAKEYS diff --git a/src/unit_test.h b/src/unit_test.h index f1374a0d..7052fdc7 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -22,6 +22,7 @@ /* --------------------------------------------------------- */ #define CASE(name) { #name, run_##name } +#define CASE1(name) { #name, name } #define MAKE_TEST_MODULE(name) { \ #name, \ @@ -29,6 +30,18 @@ sizeof(tests_##name) / sizeof(tests_##name[0]) \ } +/* Macro to wrap a test internal function with a COUNT loop (iterations number) */ +#define REPEAT_TEST(fn) REPEAT_TEST_MULT(fn, 1) +#define REPEAT_TEST_MULT(fn, multiplier) \ + static void fn(void) { \ + int i; \ + int repeat = COUNT * (multiplier); \ + for (i = 0; i < repeat; i++) \ + fn##_internal(); \ + } + + + /* --------------------------------------------------------- */ /* Test Framework API */ /* --------------------------------------------------------- */ From 0302c1a3d73137fcf75a7ca0f0f3cbcec0368ec8 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 3 Sep 2025 15:27:23 -0400 Subject: [PATCH 218/383] test: add --help for command-line options Add a help message for the test suite, documenting available options, defaults, and backward-compatible positional arguments. --- src/unit_test.c | 28 ++++++++++++++++++++++++++++ src/unit_test.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/src/unit_test.c b/src/unit_test.c index 914594bc..04878eec 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -74,6 +74,23 @@ static int parse_arg(const char* key, const char* value, struct tf_framework* tf return -1; } +static void help(void) { + printf("Usage: ./tests [options]\n\n"); + printf("Run the test suite for the project with optional configuration.\n\n"); + printf("Options:\n"); + printf(" --help, -h Show this help message\n"); + printf(" --jobs=, -j= Number of parallel worker processes (default: 0 = sequential)\n"); + printf(" --iterations=, -i= Number of iterations for each test (default: 16)\n"); + printf(" --seed= Set a specific RNG seed (default: random)\n"); + printf("\n"); + printf("Notes:\n"); + printf(" - All arguments must be provided in the form '--key=value', '-key=value' or '-k=value'.\n"); + printf(" - Single or double dashes are allowed for multi character options.\n"); + printf(" - Unknown arguments are reported but ignored.\n"); + printf(" - Sequential execution occurs if -jobs=0 or unspecified.\n"); + printf(" - Iterations and seed can also be passed as positional arguments before any other argument for backward compatibility.\n"); +} + static int parse_jobs_count(const char* key, const char* value, struct tf_framework* tf) { char* ptr_val; long val = strtol(value, &ptr_val, 10); /* base 10 */ @@ -157,6 +174,11 @@ static int read_args(int argc, char** argv, int start, struct tf_framework* tf) eq = strchr(raw_arg, '='); if (!eq || eq == raw_arg + 1) { + /* Allowed options without value */ + if (strcmp(key, "h") == 0 || strcmp(key, "help") == 0) { + tf->args.help = 1; + return 0; + } fprintf(stderr, "Invalid arg '%s': must be -k=value or --key=value\n", raw_arg); return -1; } @@ -264,6 +286,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) /* Initialize command-line options */ tf->args.num_processes = 0; tf->args.custom_seed = NULL; + tf->args.help = 0; /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because @@ -295,6 +318,11 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) if (read_args(argc, argv, named_arg_start, tf) != 0) { return EXIT_FAILURE; } + + if (tf->args.help) { + help(); + exit(EXIT_SUCCESS); + } } return EXIT_SUCCESS; diff --git a/src/unit_test.h b/src/unit_test.h index 7052fdc7..1eefb016 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -74,6 +74,8 @@ struct tf_args { int num_processes; /* Specific RNG seed */ const char* custom_seed; + /* Whether to print the help msg */ + int help; }; /* --------------------------------------------------------- */ From 953f7b008865ed503f36b040c4af4db96c4d54d9 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 3 Sep 2025 17:18:23 -0400 Subject: [PATCH 219/383] test: support running specific tests/modules targets Add support for specifying single tests or modules to run via the "--target" or "-t" command-line option. Multiple targets can be provided; only the specified tests or all tests in the specified module/s will run instead of the full suite. Examples: -t= runs an specific test. -t= runs all tests within the specified module. Both options can be provided multiple times. --- src/unit_test.c | 96 +++++++++++++++++++++++++++++++++++++++---------- src/unit_test.h | 13 ++++--- 2 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/unit_test.c b/src/unit_test.c index 04878eec..513bc2cc 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -25,6 +25,7 @@ int COUNT = 16; static int parse_jobs_count(const char* key, const char* value, struct tf_framework* tf); static int parse_iterations(const char* key, const char* value, struct tf_framework* tf); static int parse_seed(const char* key, const char* value, struct tf_framework* tf); +static int parse_target(const char* key, const char* value, struct tf_framework* tf); /* Mapping table: key -> handler */ typedef int (*ArgHandler)(const char* key, const char* value, struct tf_framework* tf); @@ -41,6 +42,7 @@ struct ArgMap { * converted to the appropriate type, and stored in 'tf->args' struct. */ static struct ArgMap arg_map[] = { + { "t", parse_target }, { "target", parse_target }, { "j", parse_jobs_count }, { "jobs", parse_jobs_count }, { "i", parse_iterations }, { "iterations", parse_iterations }, { "seed", parse_seed }, @@ -82,6 +84,8 @@ static void help(void) { printf(" --jobs=, -j= Number of parallel worker processes (default: 0 = sequential)\n"); printf(" --iterations=, -i= Number of iterations for each test (default: 16)\n"); printf(" --seed= Set a specific RNG seed (default: random)\n"); + printf(" --target=, -t= Run a specific test (can be provided multiple times)\n"); + printf(" --target=, -t= Run all tests within a specific module (can be provided multiple times)\n"); printf("\n"); printf("Notes:\n"); printf(" - All arguments must be provided in the form '--key=value', '-key=value' or '-k=value'.\n"); @@ -152,6 +156,34 @@ static const char* normalize_key(const char* arg, const char** err_msg) { return key; } +static int parse_target(const char* key, const char* value, struct tf_framework* tf) { + int group, idx; + const struct tf_test_entry* entry; + UNUSED(key); + /* Find test index in the registry */ + for (group = 0; group < tf->num_modules; group++) { + const struct tf_test_module* module = &tf->registry_modules[group]; + int add_all = strcmp(value, module->name) == 0; /* select all from module */ + for (idx = 0; idx < module->size; idx++) { + entry = &module->data[idx]; + if (add_all || strcmp(value, entry->name) == 0) { + if (tf->args.targets.size >= MAX_ARGS) { + fprintf(stderr, "Too many -target args (max: %d)\n", MAX_ARGS); + return -1; + } + tf->args.targets.slots[tf->args.targets.size++] = entry; + /* Matched a single test, we're done */ + if (!add_all) return 0; + } + } + /* If add_all was true, we added all tests in the module, so return */ + if (add_all) return 0; + } + fprintf(stderr, "Error: target '%s' not found (missing or module disabled).\n" + "Run program with -print_tests option to display available tests and modules.\n", value); + return -1; +} + /* Read args: all must be in the form -key=value, --key=value or -key=value */ static int read_args(int argc, char** argv, int start, struct tf_framework* tf) { int i; @@ -203,18 +235,16 @@ static void run_test(const struct tf_test_entry* t) { /* Process tests in sequential order */ static int run_sequential(struct tf_framework* tf) { - tf_test_ref ref; - const struct tf_test_module* mdl; - for (ref.group = 0; ref.group < tf->num_modules; ref.group++) { - mdl = &tf->registry_modules[ref.group]; - for (ref.idx = 0; ref.idx < mdl->size; ref.idx++) { - run_test(&mdl->data[ref.idx]); - } + int it; + for (it = 0; it < tf->args.targets.size; it++) { + run_test(tf->args.targets.slots[it]); } return EXIT_SUCCESS; } #if defined(SUPPORTS_CONCURRENCY) +static const int MAX_TARGETS = 255; + /* Process tests in parallel */ static int run_concurrent(struct tf_framework* tf) { /* Sub-processes info */ @@ -222,7 +252,15 @@ static int run_concurrent(struct tf_framework* tf) { int pipefd[2]; int status = EXIT_SUCCESS; int it; /* loop iterator */ - tf_test_ref ref; /* test index */ + unsigned char idx; /* test index */ + + if (tf->args.targets.size > MAX_TARGETS) { + fprintf(stderr, "Internal Error: the number of targets (%d) exceeds the maximum supported (%d). " + "If you need more, extend 'run_concurrent()' to handle additional targets.\n", + tf->args.targets.size, MAX_TARGETS); + exit(EXIT_FAILURE); + } + if (pipe(pipefd) != 0) { perror("Error during pipe setup"); @@ -239,8 +277,8 @@ static int run_concurrent(struct tf_framework* tf) { if (pid == 0) { /* Child worker: read jobs from the shared pipe */ close(pipefd[1]); /* children never write */ - while (read(pipefd[0], &ref, sizeof(ref)) == sizeof(ref)) { - run_test(&tf->registry_modules[ref.group].data[ref.idx]); + while (read(pipefd[0], &idx, sizeof(idx)) == sizeof(idx)) { + run_test(tf->args.targets.slots[(int)idx]); } _exit(EXIT_SUCCESS); /* finish child process */ } else { @@ -251,14 +289,12 @@ static int run_concurrent(struct tf_framework* tf) { /* Parent: write all tasks into the pipe */ close(pipefd[0]); /* close read end */ - for (ref.group = 0; ref.group < tf->num_modules; ref.group++) { - const struct tf_test_module* mdl = &tf->registry_modules[ref.group]; - for (ref.idx = 0; ref.idx < mdl->size; ref.idx++) { - if (write(pipefd[1], &ref, sizeof(ref)) == -1) { - perror("Error during workload distribution"); - close(pipefd[1]); - return EXIT_FAILURE; - } + for (it = 0; it < tf->args.targets.size; it++) { + idx = (unsigned char)it; + if (write(pipefd[1], &idx, sizeof(idx)) == -1) { + perror("Error during workload distribution"); + close(pipefd[1]); + return EXIT_FAILURE; } } /* Close write end to signal EOF */ @@ -287,6 +323,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) tf->args.num_processes = 0; tf->args.custom_seed = NULL; tf->args.help = 0; + tf->args.targets.size = 0; /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because @@ -331,11 +368,30 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) static int tf_run(struct tf_framework* tf) { /* Process exit status */ int status; + /* Whether to run all tests */ + int run_all; /* Loop iterator */ int it; /* Initial test time */ int64_t start_time = gettime_i64(); + /* Populate targets with all tests if none were explicitly specified */ + run_all = tf->args.targets.size == 0; + if (run_all) { + int group, idx; + for (group = 0; group < tf->num_modules; group++) { + const struct tf_test_module* module = &tf->registry_modules[group]; + for (idx = 0; idx < module->size; idx++) { + if (tf->args.targets.size >= MAX_ARGS) { + fprintf(stderr, "Internal Error: Number of tests (%d) exceeds MAX_ARGS (%d). " + "Increase MAX_ARGS to accommodate all tests.\n", tf->args.targets.size, MAX_ARGS); + return EXIT_FAILURE; + } + tf->args.targets.slots[tf->args.targets.size++] = &module->data[idx]; + } + } + } + /* Log configuration */ print_args(&tf->args); @@ -343,7 +399,9 @@ static int tf_run(struct tf_framework* tf) { /* Note: currently, these tests are executed sequentially because there */ /* is really only one test. */ for (it = 0; tf->registry_no_rng && it < tf->registry_no_rng->size; it++) { - run_test(&tf->registry_no_rng->data[it]); + if (run_all) { /* future: support filtering */ + run_test(&tf->registry_no_rng->data[it]); + } } /* Initialize test RNG and library contexts */ diff --git a/src/unit_test.h b/src/unit_test.h index 1eefb016..e76b8c01 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -62,11 +62,12 @@ struct tf_test_module { typedef int (*setup_ctx_fn)(void); typedef int (*teardown_fn)(void); -/* Reference to a test in the registry. Group index and test index */ -typedef struct { - int group; - int idx; -} tf_test_ref; +struct tf_targets { + /* Target tests indexes */ + const struct tf_test_entry* slots[MAX_ARGS]; + /* Next available slot */ + int size; +}; /* --- Command-line args --- */ struct tf_args { @@ -76,6 +77,8 @@ struct tf_args { const char* custom_seed; /* Whether to print the help msg */ int help; + /* Target tests indexes */ + struct tf_targets targets; }; /* --------------------------------------------------------- */ From 95b9953ea44ad6273dd8ddd2040844a54936ed71 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 8 Sep 2025 14:17:12 -0400 Subject: [PATCH 220/383] test: Add option to display all available tests Useful option to avoid opening the large tests.c file just to find the test case you want to run. --- src/unit_test.c | 31 ++++++++++++++++++++++++++++++- src/unit_test.h | 2 ++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/unit_test.c b/src/unit_test.c index 513bc2cc..4eace526 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -81,6 +81,7 @@ static void help(void) { printf("Run the test suite for the project with optional configuration.\n\n"); printf("Options:\n"); printf(" --help, -h Show this help message\n"); + printf(" --list_tests, -l Display list of all available tests and modules\n"); printf(" --jobs=, -j= Number of parallel worker processes (default: 0 = sequential)\n"); printf(" --iterations=, -i= Number of iterations for each test (default: 16)\n"); printf(" --seed= Set a specific RNG seed (default: random)\n"); @@ -95,6 +96,24 @@ static void help(void) { printf(" - Iterations and seed can also be passed as positional arguments before any other argument for backward compatibility.\n"); } +/* Print all tests in registry */ +static void print_test_list(struct tf_framework* tf) { + int m, t, total = 0; + printf("\nAvailable tests (%d modules):\n", tf->num_modules); + printf("========================================\n"); + for (m = 0; m < tf->num_modules; m++) { + const struct tf_test_module* mod = &tf->registry_modules[m]; + printf("Module: %s (%d tests)\n", mod->name, mod->size); + for (t = 0; t < mod->size; t++) { + printf("\t[%3d] %s\n", total + 1, mod->data[t].name); + total++; + } + printf("----------------------------------------\n"); + } + printf("\nRun specific module: ./tests -t=\n"); + printf("Run specific test: ./tests -t=\n\n"); +} + static int parse_jobs_count(const char* key, const char* value, struct tf_framework* tf) { char* ptr_val; long val = strtol(value, &ptr_val, 10); /* base 10 */ @@ -180,7 +199,7 @@ static int parse_target(const char* key, const char* value, struct tf_framework* if (add_all) return 0; } fprintf(stderr, "Error: target '%s' not found (missing or module disabled).\n" - "Run program with -print_tests option to display available tests and modules.\n", value); + "Run program with -list_tests option to display available tests and modules.\n", value); return -1; } @@ -211,6 +230,10 @@ static int read_args(int argc, char** argv, int start, struct tf_framework* tf) tf->args.help = 1; return 0; } + if (strcmp(key, "l") == 0 || strcmp(key, "list_tests") == 0) { + tf->args.list_tests = 1; + return 0; + } fprintf(stderr, "Invalid arg '%s': must be -k=value or --key=value\n", raw_arg); return -1; } @@ -324,6 +347,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) tf->args.custom_seed = NULL; tf->args.help = 0; tf->args.targets.size = 0; + tf->args.list_tests = 0; /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because @@ -360,6 +384,11 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) help(); exit(EXIT_SUCCESS); } + + if (tf->args.list_tests) { + print_test_list(tf); + exit(EXIT_SUCCESS); + } } return EXIT_SUCCESS; diff --git a/src/unit_test.h b/src/unit_test.h index e76b8c01..b41e9f75 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -77,6 +77,8 @@ struct tf_args { const char* custom_seed; /* Whether to print the help msg */ int help; + /* Whether to print the tests list msg */ + int list_tests; /* Target tests indexes */ struct tf_targets targets; }; From 2f4546ce5610f4f7841fc2dc2eef68dbfcdcc761 Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 9 Sep 2025 11:02:05 -0400 Subject: [PATCH 221/383] test: add --log option to display tests execution When enabled (--log=1), shows test start, completion, and execution time. --- src/unit_test.c | 32 +++++++++++++++++++++++++++----- src/unit_test.h | 5 +++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/unit_test.c b/src/unit_test.c index 4eace526..a1858a11 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -26,6 +26,7 @@ static int parse_jobs_count(const char* key, const char* value, struct tf_framew static int parse_iterations(const char* key, const char* value, struct tf_framework* tf); static int parse_seed(const char* key, const char* value, struct tf_framework* tf); static int parse_target(const char* key, const char* value, struct tf_framework* tf); +static int parse_logging(const char* key, const char* value, struct tf_framework* tf); /* Mapping table: key -> handler */ typedef int (*ArgHandler)(const char* key, const char* value, struct tf_framework* tf); @@ -46,6 +47,7 @@ static struct ArgMap arg_map[] = { { "j", parse_jobs_count }, { "jobs", parse_jobs_count }, { "i", parse_iterations }, { "iterations", parse_iterations }, { "seed", parse_seed }, + { "log", parse_logging }, { NULL, NULL } /* sentinel */ }; @@ -87,6 +89,7 @@ static void help(void) { printf(" --seed= Set a specific RNG seed (default: random)\n"); printf(" --target=, -t= Run a specific test (can be provided multiple times)\n"); printf(" --target=, -t= Run all tests within a specific module (can be provided multiple times)\n"); + printf(" --log=<0|1> Enable or disable test execution logging (default: 0 = disabled)\n"); printf("\n"); printf("Notes:\n"); printf(" - All arguments must be provided in the form '--key=value', '-key=value' or '-k=value'.\n"); @@ -146,6 +149,12 @@ static int parse_seed(const char* key, const char* value, struct tf_framework* t return 0; } +static int parse_logging(const char* key, const char* value, struct tf_framework* tf) { + UNUSED(key); + tf->args.logging = value && strcmp(value, "1") == 0; + return 0; +} + /* Strip up to two leading dashes */ static const char* normalize_key(const char* arg, const char** err_msg) { const char* key; @@ -250,17 +259,20 @@ static int read_args(int argc, char** argv, int start, struct tf_framework* tf) return 0; } -static void run_test(const struct tf_test_entry* t) { +static void run_test_log(const struct tf_test_entry* t) { + int64_t start_time = gettime_i64(); printf("Running %s..\n", t->name); t->func(); - printf("%s PASSED\n", t->name); + printf("Test %s PASSED (%.3f sec)\n", t->name, (double)(gettime_i64() - start_time) / 1000000); } +static void run_test(const struct tf_test_entry* t) { t->func(); } + /* Process tests in sequential order */ static int run_sequential(struct tf_framework* tf) { int it; for (it = 0; it < tf->args.targets.size; it++) { - run_test(tf->args.targets.slots[it]); + tf->fn_run_test(tf->args.targets.slots[it]); } return EXIT_SUCCESS; } @@ -301,7 +313,7 @@ static int run_concurrent(struct tf_framework* tf) { /* Child worker: read jobs from the shared pipe */ close(pipefd[1]); /* children never write */ while (read(pipefd[0], &idx, sizeof(idx)) == sizeof(idx)) { - run_test(tf->args.targets.slots[(int)idx]); + tf->fn_run_test(tf->args.targets.slots[(int)idx]); } _exit(EXIT_SUCCESS); /* finish child process */ } else { @@ -348,6 +360,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) tf->args.help = 0; tf->args.targets.size = 0; tf->args.list_tests = 0; + tf->args.logging = 0; /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because @@ -391,6 +404,7 @@ static int tf_init(struct tf_framework* tf, int argc, char** argv) } } + tf->fn_run_test = tf->args.logging ? run_test_log : run_test; return EXIT_SUCCESS; } @@ -403,6 +417,12 @@ static int tf_run(struct tf_framework* tf) { int it; /* Initial test time */ int64_t start_time = gettime_i64(); + /* Verify 'tf_init' has been called */ + if (!tf->fn_run_test) { + fprintf(stderr, "Error: No test runner set. You must call 'tf_init' first to initialize the framework " + "or manually assign 'fn_run_test' before calling 'tf_run'.\n"); + return EXIT_FAILURE; + } /* Populate targets with all tests if none were explicitly specified */ run_all = tf->args.targets.size == 0; @@ -421,6 +441,8 @@ static int tf_run(struct tf_framework* tf) { } } + if (!tf->args.logging) printf("Tests running silently. Use '-log=1' to enable detailed logging\n"); + /* Log configuration */ print_args(&tf->args); @@ -429,7 +451,7 @@ static int tf_run(struct tf_framework* tf) { /* is really only one test. */ for (it = 0; tf->registry_no_rng && it < tf->registry_no_rng->size; it++) { if (run_all) { /* future: support filtering */ - run_test(&tf->registry_no_rng->data[it]); + tf->fn_run_test(&tf->registry_no_rng->data[it]); } } diff --git a/src/unit_test.h b/src/unit_test.h index b41e9f75..bf301e53 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -61,6 +61,7 @@ struct tf_test_module { typedef int (*setup_ctx_fn)(void); typedef int (*teardown_fn)(void); +typedef void (*run_test_fn)(const struct tf_test_entry*); struct tf_targets { /* Target tests indexes */ @@ -81,6 +82,8 @@ struct tf_args { int list_tests; /* Target tests indexes */ struct tf_targets targets; + /* Enable test execution logging */ + int logging; }; /* --------------------------------------------------------- */ @@ -99,6 +102,8 @@ struct tf_framework { /* Specific context setup and teardown functions */ setup_ctx_fn fn_setup; teardown_fn fn_teardown; + /* Test runner function (can be customized) */ + run_test_fn fn_run_test; }; /* From 122014edb38762acbf8c98edae0ce54d630b072b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:08:09 +0100 Subject: [PATCH 222/383] ci: Add `scope` parameter to `cache-{to,from}` options This change fixes an issue where only the latest image cache was available. --- .github/actions/run-in-docker-action/action.yml | 8 ++++++-- .github/workflows/ci.yml | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index 74933686..f9bd4746 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -7,6 +7,10 @@ inputs: tag: description: 'A tag of an image' required: true + scope: + description: 'A cached image scope' + required: false + default: ${{ runner.arch }} command: description: 'A command to run in a container' required: false @@ -24,7 +28,7 @@ runs: file: ${{ inputs.dockerfile }} tags: ${{ inputs.tag }} load: true - cache-from: type=gha + cache-from: type=gha,scope=${{ inputs.scope }} - uses: docker/build-push-action@v5 id: retry_builder @@ -34,7 +38,7 @@ runs: file: ${{ inputs.dockerfile }} tags: ${{ inputs.tag }} load: true - cache-from: type=gha + cache-from: type=gha,scope=${{ inputs.scope }} - # Workaround for https://github.com/google/sanitizers/issues/1614 . # The underlying issue has been fixed in clang 18.1.3. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9783251d..83b38240 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,8 +71,8 @@ jobs: with: file: ./ci/linux-debian.Dockerfile tags: ${{ matrix.arch }}-debian-image - cache-from: type=gha - cache-to: type=gha,mode=min + cache-from: type=gha,scope=${{ runner.arch }} + cache-to: type=gha,scope=${{ runner.arch }},mode=min x86_64-debian: name: "x86_64: Linux (Debian stable)" From b2a95a420ff67ae0e162aaea022e1142e3701df8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:54:24 +0100 Subject: [PATCH 223/383] ci: Drop `tags` input for `docker/build-push-action` The `tags` input is unused for caching. --- .../actions/run-in-docker-action/action.yml | 8 ++--- .github/workflows/ci.yml | 31 ++++--------------- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index f9bd4746..2af23643 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -4,9 +4,6 @@ inputs: dockerfile: description: 'A Dockerfile that defines an image' required: true - tag: - description: 'A tag of an image' - required: true scope: description: 'A cached image scope' required: false @@ -26,7 +23,6 @@ runs: with: context: . file: ${{ inputs.dockerfile }} - tags: ${{ inputs.tag }} load: true cache-from: type=gha,scope=${{ inputs.scope }} @@ -36,7 +32,6 @@ runs: with: context: . file: ${{ inputs.dockerfile }} - tags: ${{ inputs.tag }} load: true cache-from: type=gha,scope=${{ inputs.scope }} @@ -51,7 +46,8 @@ runs: $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \ --volume ${{ github.workspace }}:${{ github.workspace }} \ --workdir ${{ github.workspace }} \ - ${{ inputs.tag }} bash -c " + $(docker images -q | head -n1) \ + bash -c " git config --global --add safe.directory ${{ github.workspace }} ${{ inputs.command }} " diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83b38240..49f16b87 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,7 +70,6 @@ jobs: uses: docker/build-push-action@v5 with: file: ./ci/linux-debian.Dockerfile - tags: ${{ matrix.arch }}-debian-image cache-from: type=gha,scope=${{ runner.arch }} cache-to: type=gha,scope=${{ runner.arch }},mode=min @@ -116,7 +115,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -152,7 +150,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -184,7 +181,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -225,7 +221,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -265,7 +260,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: arm64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -297,7 +291,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -313,28 +306,22 @@ jobs: fail-fast: false matrix: include: - - docker_arch: x64 - runner: ubuntu-latest + - runner: ubuntu-latest binary_arch: x64 env_vars: { CC: 'clang', ASM: 'auto' } - - docker_arch: x64 - runner: ubuntu-latest + - runner: ubuntu-latest binary_arch: i686 env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'auto' } - - docker_arch: arm64 - runner: ubuntu-24.04-arm + - runner: ubuntu-24.04-arm binary_arch: arm64 env_vars: { CC: 'clang', ASM: 'auto' } - - docker_arch: x64 - runner: ubuntu-latest + - runner: ubuntu-latest binary_arch: x64 env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } - - docker_arch: x64 - runner: ubuntu-latest + - runner: ubuntu-latest binary_arch: i686 env_vars: { CC: 'i686-linux-gnu-gcc', HOST: 'i686-linux-gnu', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } - - docker_arch: arm64 - runner: ubuntu-24.04-arm + - runner: ubuntu-24.04-arm binary_arch: arm64 env_vars: { CC: 'clang', ASM: 'no', ECMULTGENKB: 2, ECMULTWINDOW: 2 } @@ -360,7 +347,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: ${{ matrix.docker_arch }}-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -404,7 +390,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -455,7 +440,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -498,7 +482,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -714,7 +697,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image - name: Print logs uses: ./.github/actions/print-logs @@ -733,7 +715,6 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile - tag: x64-debian-image command: | g++ -Werror include/*.h clang -Werror -x c++-header include/*.h From 70ae177ca06b4d24c73c411d8524507d68aff45a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:54:37 +0100 Subject: [PATCH 224/383] ci: Bump `docker/build-push-action` version See https://github.com/docker/build-push-action/releases. --- .github/actions/run-in-docker-action/action.yml | 4 ++-- .github/workflows/ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index 2af23643..d3ab44b1 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -17,7 +17,7 @@ runs: steps: - uses: docker/setup-buildx-action@v3 - - uses: docker/build-push-action@v5 + - uses: docker/build-push-action@v6 id: main_builder continue-on-error: true with: @@ -26,7 +26,7 @@ runs: load: true cache-from: type=gha,scope=${{ inputs.scope }} - - uses: docker/build-push-action@v5 + - uses: docker/build-push-action@v6 id: retry_builder if: steps.main_builder.outcome == 'failure' with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49f16b87..f22ef2a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: network=host - name: Build container - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: file: ./ci/linux-debian.Dockerfile cache-from: type=gha,scope=${{ runner.arch }} From f163c35897db9a4adc2a5b37926942817a4fdeb7 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:54:47 +0100 Subject: [PATCH 225/383] ci: Set `DEBIAN_FRONTEND=noninteractive` This suppresses `debconf: unable to initialize frontend: ...` warnings. --- ci/linux-debian.Dockerfile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 8ced83f2..22b6d35c 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -21,7 +21,7 @@ RUN dpkg --add-architecture i386 && \ # dpkg-dev: to make pkg-config work in cross-builds # llvm: for llvm-symbolizer, which is used by clang's UBSan for symbolized stack traces -RUN apt-get update && apt-get install --no-install-recommends -y \ +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ git ca-certificates \ make automake libtool pkg-config dpkg-dev valgrind qemu-user \ gcc clang llvm libclang-rt-dev libc6-dbg \ @@ -34,14 +34,15 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ gcc-mingw-w64-i686-win32 wine32 \ python3-full && \ if ! ( dpkg --print-architecture | grep --quiet "arm64" ) ; then \ - apt-get install --no-install-recommends -y \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ gcc-aarch64-linux-gnu libc6-dev-arm64-cross libc6-dbg:arm64 ;\ fi && \ apt-get clean && rm -rf /var/lib/apt/lists/* # Build and install gcc snapshot ARG GCC_SNAPSHOT_MAJOR=16 -RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev libmpfr-dev libmpc-dev flex && \ +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ + wget libgmp-dev libmpfr-dev libmpc-dev flex && \ mkdir gcc && cd gcc && \ wget --progress=dot:giga --https-only --recursive --accept '*.tar.xz' --level 1 --no-directories "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}" && \ wget "https://gcc.gnu.org/pub/gcc/snapshots/LATEST-${GCC_SNAPSHOT_MAJOR}/sha512.sum" && \ @@ -62,7 +63,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y wget libgmp-dev # Install clang snapshot, see https://apt.llvm.org/ RUN \ # Setup GPG keys of LLVM repository - apt-get update && apt-get install --no-install-recommends -y wget && \ + apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y wget && \ wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ # Add repository for this Debian release . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ @@ -70,7 +71,7 @@ RUN \ # Determine the version number of the LLVM development branch LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ # Install - apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ # Create symlink ln -s "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang-snapshot && \ # Clean up From 6894c964f3504ab2bc09b46e17ba30c725d232f3 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:19:16 +0100 Subject: [PATCH 226/383] Fix Clang 21+ `-Wuninitialized-const-pointer` warning when using MSan Co-authored-by: Tim Ruffing --- src/checkmem.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/checkmem.h b/src/checkmem.h index 7e333ce5..08eae47d 100644 --- a/src/checkmem.h +++ b/src/checkmem.h @@ -48,7 +48,17 @@ # if __has_feature(memory_sanitizer) # include # define SECP256K1_CHECKMEM_ENABLED 1 -# define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) +# if defined(__clang__) && ((__clang_major__ == 21 && __clang_minor__ >= 1) || __clang_major__ >= 22) +# define SECP256K1_CHECKMEM_UNDEFINE(p, len) do { \ + /* Work around https://github.com/llvm/llvm-project/issues/160094 */ \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wuninitialized-const-pointer\"") \ + __msan_allocated_memory((p), (len)); \ + _Pragma("clang diagnostic pop") \ + } while(0) +# else +# define SECP256K1_CHECKMEM_UNDEFINE(p, len) __msan_allocated_memory((p), (len)) +# endif # define SECP256K1_CHECKMEM_DEFINE(p, len) __msan_unpoison((p), (len)) # define SECP256K1_CHECKMEM_MSAN_DEFINE(p, len) __msan_unpoison((p), (len)) # define SECP256K1_CHECKMEM_CHECK(p, len) __msan_check_mem_is_initialized((p), (len)) From 53585f93b7e6fe3933c77216f45e7d4f785436b5 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:19:45 +0100 Subject: [PATCH 227/383] ci: Use clang-snapshot in "MSan" job --- .github/workflows/ci.yml | 5 ++++- ci/linux-debian.Dockerfile | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f22ef2a3..ad3568d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -417,6 +417,9 @@ jobs: # when ctime_tests when enabled. CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -fsanitize-memory-param-retval -g' CTIMETESTS: 'no' + cc: + - 'clang' + - 'clang-snapshot' env: ECDH: 'yes' @@ -425,7 +428,7 @@ jobs: SCHNORRSIG: 'yes' MUSIG: 'yes' ELLSWIFT: 'yes' - CC: 'clang' + CC: ${{ matrix.cc }} SECP256K1_TEST_ITERS: 32 ASM: 'no' WITH_VALGRIND: 'no' diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 22b6d35c..a575d9b1 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -71,7 +71,7 @@ RUN \ # Determine the version number of the LLVM development branch LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ # Install - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y "clang-${LLVM_VERSION}" "libclang-rt-${LLVM_VERSION}-dev" && \ # Create symlink ln -s "/usr/bin/clang-${LLVM_VERSION}" /usr/bin/clang-snapshot && \ # Clean up From 574c2f3080eeb65995a1c1a430ed7f84803afd26 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:47:23 +0100 Subject: [PATCH 228/383] ci: Use YAML anchor and aliases for repeated "Checkout" steps --- .github/workflows/ci.yml | 54 ++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f22ef2a3..4e0a028c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,8 @@ jobs: CC: ${{ matrix.cc }} steps: - - name: Checkout + - &CHECKOUT + name: Checkout uses: actions/checkout@v4 - name: CI script @@ -143,8 +144,7 @@ jobs: CC: ${{ matrix.cc }} steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script uses: ./.github/actions/run-in-docker-action @@ -174,8 +174,7 @@ jobs: CTIMETESTS: 'no' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script uses: ./.github/actions/run-in-docker-action @@ -213,8 +212,7 @@ jobs: CTIMETESTS: 'no' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script env: ${{ matrix.configuration.env_vars }} @@ -253,8 +251,7 @@ jobs: - 'clang-snapshot' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script uses: ./.github/actions/run-in-docker-action @@ -284,8 +281,7 @@ jobs: CTIMETESTS: 'no' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script uses: ./.github/actions/run-in-docker-action @@ -339,8 +335,7 @@ jobs: SECP256K1_TEST_ITERS: 2 steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script env: ${{ matrix.env_vars }} @@ -382,8 +377,7 @@ jobs: SYMBOL_CHECK: 'no' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script env: ${{ matrix.configuration.env_vars }} @@ -432,8 +426,7 @@ jobs: SYMBOL_CHECK: 'no' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script env: ${{ matrix.configuration.env_vars }} @@ -474,8 +467,7 @@ jobs: HOST: 'i686-w64-mingw32' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script env: ${{ matrix.configuration.env_vars }} @@ -514,8 +506,7 @@ jobs: - BUILD: 'distcheck' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: Install Homebrew packages run: | @@ -566,8 +557,7 @@ jobs: - BUILD: 'distcheck' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: Install Homebrew packages run: | @@ -626,8 +616,7 @@ jobs: cpp_flags: '/DSECP256K1_MSVC_MULH_TEST_OVERRIDE' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: Generate buildsystem run: cmake -E env CFLAGS="/WX ${{ matrix.configuration.cpp_flags }}" cmake -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON ${{ matrix.configuration.cmake_options }} @@ -662,8 +651,7 @@ jobs: runs-on: windows-2022 steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: Add cl.exe to PATH uses: ilammy/msvc-dev-cmd@v1 @@ -690,8 +678,7 @@ jobs: ELLSWIFT: 'yes' steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script uses: ./.github/actions/run-in-docker-action @@ -708,8 +695,7 @@ jobs: needs: docker_cache steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script uses: ./.github/actions/run-in-docker-action @@ -727,8 +713,7 @@ jobs: options: --user root steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: CI script run: | @@ -739,8 +724,7 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - run: ./autogen.sh && ./configure --enable-dev-mode && make distcheck From a889cd93dfe5558aaa0320e241555bb96483c92b Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:49:05 +0100 Subject: [PATCH 229/383] ci: Bump `actions/checkout` version See https://github.com/actions/checkout/releases. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e0a028c..6f7b51dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: steps: - &CHECKOUT name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: CI script env: ${{ matrix.configuration.env_vars }} From 4b644da199587cdf9554fb48c0da7643c3ce7f30 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:51:22 +0100 Subject: [PATCH 230/383] ci: Use YAML anchor and aliases for repeated "Print logs" steps --- .github/workflows/ci.yml | 55 ++++++++++------------------------------ 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f7b51dd..7195b7da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,7 +117,8 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs + - &PRINT_LOGS + name: Print logs uses: ./.github/actions/print-logs if: ${{ !cancelled() }} @@ -151,9 +152,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS s390x_debian: name: "s390x (big-endian): Linux (Debian stable, QEMU)" @@ -181,10 +180,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} - + - *PRINT_LOGS arm32_debian: name: "ARM32: Linux (Debian stable, QEMU)" @@ -220,9 +216,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS arm64-debian: name: "arm64: Linux (Debian stable)" @@ -258,9 +252,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS ppc64le_debian: name: "ppc64le: Linux (Debian stable, QEMU)" @@ -288,10 +280,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} - + - *PRINT_LOGS valgrind_debian: name: "Valgrind ${{ matrix.binary_arch }} (memcheck)" @@ -343,9 +332,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS sanitizers_debian: name: "UBSan, ASan, LSan" @@ -385,9 +372,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS msan_debian: name: "MSan" @@ -434,10 +419,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} - + - *PRINT_LOGS mingw_debian: name: ${{ matrix.configuration.job_name }} @@ -475,9 +457,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS x86_64-macos-native: name: "x86_64: macOS Ventura, Valgrind" @@ -526,9 +506,7 @@ jobs: python3 -m pip install lief python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS arm64-macos-native: name: "ARM64: macOS Sonoma" @@ -578,10 +556,7 @@ jobs: python3 -m pip install lief python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} - + - *PRINT_LOGS win64-native: name: ${{ matrix.configuration.job_name }} @@ -685,9 +660,7 @@ jobs: with: dockerfile: ./ci/linux-debian.Dockerfile - - name: Print logs - uses: ./.github/actions/print-logs - if: ${{ !cancelled() }} + - *PRINT_LOGS cxx_headers_debian: name: "C++ (public headers)" From dff1bc107d593b12e824cbc04b0d220f2ffeb967 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 12:23:54 +0100 Subject: [PATCH 231/383] ci, refactor: Generalize use of `matrix.configuration.env_vars` --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7195b7da..07a574d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,6 +130,8 @@ jobs: strategy: fail-fast: false matrix: + configuration: + - env_vars: {} cc: - 'i686-linux-gnu-gcc' - 'clang --target=i686-pc-linux-gnu -isystem /usr/i686-linux-gnu/include' @@ -148,6 +150,7 @@ jobs: - *CHECKOUT - name: CI script + env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile @@ -159,6 +162,11 @@ jobs: runs-on: ubuntu-latest needs: docker_cache + strategy: + matrix: + configuration: + - env_vars: {} + env: WRAPPER_CMD: 'qemu-s390x' SECP256K1_TEST_ITERS: 16 @@ -176,6 +184,7 @@ jobs: - *CHECKOUT - name: CI script + env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile @@ -238,6 +247,8 @@ jobs: strategy: fail-fast: false matrix: + configuration: + - env_vars: {} cc: - 'gcc' - 'clang' @@ -248,6 +259,7 @@ jobs: - *CHECKOUT - name: CI script + env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile @@ -259,6 +271,11 @@ jobs: runs-on: ubuntu-latest needs: docker_cache + strategy: + matrix: + configuration: + - env_vars: {} + env: WRAPPER_CMD: 'qemu-ppc64le' SECP256K1_TEST_ITERS: 16 @@ -276,6 +293,7 @@ jobs: - *CHECKOUT - name: CI script + env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile @@ -283,14 +301,14 @@ jobs: - *PRINT_LOGS valgrind_debian: - name: "Valgrind ${{ matrix.binary_arch }} (memcheck)" - runs-on: ${{ matrix.runner }} + name: "Valgrind ${{ matrix.configuration.binary_arch }} (memcheck)" + runs-on: ${{ matrix.configuration.runner }} needs: docker_cache strategy: fail-fast: false matrix: - include: + configuration: - runner: ubuntu-latest binary_arch: x64 env_vars: { CC: 'clang', ASM: 'auto' } @@ -327,7 +345,7 @@ jobs: - *CHECKOUT - name: CI script - env: ${{ matrix.env_vars }} + env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile @@ -640,6 +658,11 @@ jobs: runs-on: ubuntu-latest needs: docker_cache + strategy: + matrix: + configuration: + - env_vars: {} + env: CC: 'g++' CFLAGS: '-fpermissive -g' @@ -656,6 +679,7 @@ jobs: - *CHECKOUT - name: CI script + env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile From 1decc49a1f08564064420468fc48b9aebd3989d3 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 12:24:25 +0100 Subject: [PATCH 232/383] ci: Use YAML anchor and aliases for repeated "CI script" steps --- .github/workflows/ci.yml | 90 +++++++--------------------------------- 1 file changed, 15 insertions(+), 75 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07a574d0..83272941 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,8 @@ jobs: name: Checkout uses: actions/checkout@v5 - - name: CI script + - &CI_SCRIPT_IN_DOCKER + name: CI script env: ${{ matrix.configuration.env_vars }} uses: ./.github/actions/run-in-docker-action with: @@ -148,13 +149,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS s390x_debian: @@ -182,13 +177,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS arm32_debian: @@ -218,13 +207,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS arm64-debian: @@ -257,13 +240,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS ppc64le_debian: @@ -291,13 +268,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS valgrind_debian: @@ -343,13 +314,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS sanitizers_debian: @@ -383,13 +348,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS msan_debian: @@ -430,13 +389,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS mingw_debian: @@ -468,13 +421,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS x86_64-macos-native: @@ -514,7 +461,8 @@ jobs: - name: Install and cache Valgrind uses: ./.github/actions/install-homebrew-valgrind - - name: CI script + - &CI_SCRIPT_ON_HOST + name: CI script env: ${{ matrix.env_vars }} run: ./ci/ci.sh @@ -560,9 +508,7 @@ jobs: brew install --quiet automake libtool gcc ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc - - name: CI script - env: ${{ matrix.env_vars }} - run: ./ci/ci.sh + - *CI_SCRIPT_ON_HOST - name: Symbol check env: @@ -677,13 +623,7 @@ jobs: steps: - *CHECKOUT - - - name: CI script - env: ${{ matrix.configuration.env_vars }} - uses: ./.github/actions/run-in-docker-action - with: - dockerfile: ./ci/linux-debian.Dockerfile - + - *CI_SCRIPT_IN_DOCKER - *PRINT_LOGS cxx_headers_debian: From 15d014804e5927b0f9dd8ed4fdc0be2a45f74e24 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 14 Oct 2025 12:24:36 +0100 Subject: [PATCH 233/383] ci: Drop default for `inputs.command` in `run-in-docker-action` This change decreases coupling. --- .github/actions/run-in-docker-action/action.yml | 3 +-- .github/workflows/ci.yml | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index d3ab44b1..5d46ca1b 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -10,8 +10,7 @@ inputs: default: ${{ runner.arch }} command: description: 'A command to run in a container' - required: false - default: ./ci/ci.sh + required: true runs: using: "composite" steps: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83272941..8508224e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,6 +117,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile + command: ./ci/ci.sh - &PRINT_LOGS name: Print logs From c09519f0e383da3c36e33522ca8708c17103d96a Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 15 Oct 2025 15:20:38 +0100 Subject: [PATCH 234/383] ci: Drop workaround for Valgrind older than 3.20.0 --- ci/ci.sh | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/ci/ci.sh b/ci/ci.sh index 08e84efd..515c14cd 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -52,22 +52,6 @@ if [ -n "$WRAPPER_CMD" ]; then $WRAPPER_CMD --version fi -# Workaround for https://bugs.kde.org/show_bug.cgi?id=452758 (fixed in valgrind 3.20.0). -case "${CC:-undefined}" in - clang*) - if [ "$CTIMETESTS" = "yes" ] && [ "$WITH_VALGRIND" = "yes" ] - then - export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4" - else - case "$WRAPPER_CMD" in - valgrind*) - export CFLAGS="${CFLAGS:+$CFLAGS }-gdwarf-4" - ;; - esac - fi - ;; -esac - ./autogen.sh ./configure \ From 8bc50b72ff600f1b3cc05003c2de35a355512aab Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 15 Oct 2025 15:31:21 +0100 Subject: [PATCH 235/383] ci: Switch to macOS 15 Sequoia Intel-based image The `macos-13` image has been deprecated and will be unavailable soon. See: https://github.com/actions/runner-images/issues/13045. --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dceab4f8..61767515 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -429,9 +429,8 @@ jobs: - *PRINT_LOGS x86_64-macos-native: - name: "x86_64: macOS Ventura, Valgrind" - # See: https://github.com/actions/runner-images#available-images. - runs-on: macos-13 + name: "x86_64: macOS Sequoia, Valgrind" + runs-on: macos-15-intel env: CC: 'clang' From 26166c4f5fd5688c31e488449ee2325eb8f2fb36 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 17 Oct 2025 14:18:42 +0000 Subject: [PATCH 236/383] ecmult_multi: reduce strauss memory usage by 30% --- src/ecmult_impl.h | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 0b53b3fc..29f02f54 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -220,9 +220,24 @@ static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, return last_set_bit + 1; } +/* Same as secp256k1_ecmult_wnaf, but stores to int8_t array. Requires w <= 8. */ +static int secp256k1_ecmult_wnaf_small(int8_t *wnaf, int len, const secp256k1_scalar *a, int w) { + int wnaf_tmp[256]; + int ret, i; + + VERIFY_CHECK(2 <= w && w <= 8); + ret = secp256k1_ecmult_wnaf(wnaf_tmp, len, a, w); + + for (i = 0; i < len; i++) { + wnaf[i] = (int8_t)wnaf_tmp[i]; + } + + return ret; +} + struct secp256k1_strauss_point_state { - int wnaf_na_1[129]; - int wnaf_na_lam[129]; + int8_t wnaf_na_1[129]; + int8_t wnaf_na_lam[129]; int bits_na_1; int bits_na_lam; }; @@ -259,8 +274,8 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state * secp256k1_scalar_split_lambda(&na_1, &na_lam, &na[np]); /* build wnaf representation for na_1 and na_lam. */ - state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A); - state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &na_lam, WINDOW_A); + state->ps[no].bits_na_1 = secp256k1_ecmult_wnaf_small(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A); + state->ps[no].bits_na_lam = secp256k1_ecmult_wnaf_small(state->ps[no].wnaf_na_lam, 129, &na_lam, WINDOW_A); VERIFY_CHECK(state->ps[no].bits_na_1 <= 129); VERIFY_CHECK(state->ps[no].bits_na_lam <= 129); if (state->ps[no].bits_na_1 > bits) { From 153eea20c2527252c4a1785869def7bc052435d0 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:04:51 +0000 Subject: [PATCH 237/383] bench: Use `ALIGNMENT` macro instead of hardcoded value --- src/bench_ecmult.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index b2bab65d..c9a1d900 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -334,7 +334,7 @@ int main(int argc, char **argv) { } data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; + scratch_size = secp256k1_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT; if (!have_flag(argc, argv, "simple")) { data.scratch = secp256k1_scratch_space_create(data.ctx, scratch_size); } else { From 2f73e5281de44e2c2bcf60ebc7b113440e13b07f Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 28 Oct 2025 15:00:58 +0100 Subject: [PATCH 238/383] group: Avoid using infinity field directly in other modules --- src/ecmult_const_impl.h | 19 ++++++++++--------- src/ecmult_impl.h | 4 ++-- src/tests.c | 4 ++-- src/tests_exhaustive.c | 14 +++++++------- src/testutil.h | 12 ++++-------- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/ecmult_const_impl.h b/src/ecmult_const_impl.h index 4f662091..1d24aeaf 100644 --- a/src/ecmult_const_impl.h +++ b/src/ecmult_const_impl.h @@ -87,17 +87,15 @@ static void secp256k1_ecmult_const_odd_multiples_table_globalz(secp256k1_ge *pre secp256k1_fe neg_y; \ VERIFY_CHECK((n) < (1U << ECMULT_CONST_GROUP_SIZE)); \ VERIFY_CHECK(index < (1U << (ECMULT_CONST_GROUP_SIZE - 1))); \ - /* Unconditionally set r->x = (pre)[m].x. r->y = (pre)[m].y. because it's either the correct one + /* Unconditionally set r->x = (pre)[m].x and r->y = (pre)[m].y because it's either the correct one * or will get replaced in the later iterations, this is needed to make sure `r` is initialized. */ \ - (r)->x = (pre)[m].x; \ - (r)->y = (pre)[m].y; \ + secp256k1_ge_set_xy((r), &(pre)[m].x, &(pre)[m].y); \ for (m = 1; m < ECMULT_CONST_TABLE_SIZE; m++) { \ /* This loop is used to avoid secret data in array indices. See * the comment in ecmult_gen_impl.h for rationale. */ \ secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == index); \ secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == index); \ } \ - (r)->infinity = 0; \ secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ secp256k1_fe_cmov(&(r)->y, &neg_y, negative); \ } while(0) @@ -375,11 +373,14 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, SECP256K1_FE_VERIFY_MAGNITUDE(&g, 2); - /* Compute base point P = (n*g, g^2), the effective affine version of (n*g, g^2, v), which has - * corresponding affine X coordinate n/d. */ - secp256k1_fe_mul(&p.x, &g, n); - secp256k1_fe_sqr(&p.y, &g); - p.infinity = 0; + /* Compute base point P = (n*g, g^2), the effective affine version of + * (n*g, g^2, v), which has corresponding affine X coordinate n/d. */ + { + secp256k1_fe x, y; + secp256k1_fe_mul(&x, &g, n); + secp256k1_fe_sqr(&y, &g); + secp256k1_ge_set_xy(&p, &x, &y); + } /* Perform x-only EC multiplication of P with q. */ VERIFY_CHECK(!secp256k1_scalar_is_zero(q)); diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 0b53b3fc..20cf750f 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -75,7 +75,7 @@ static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_ge *pre_a, sec secp256k1_ge d_ge; int i; - VERIFY_CHECK(!a->infinity); + VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); secp256k1_gej_double_var(&d, a, NULL); @@ -341,7 +341,7 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state * } } - if (!r->infinity) { + if (!secp256k1_gej_is_infinity(r)) { secp256k1_fe_mul(&r->z, &r->z, &Z); } } diff --git a/src/tests.c b/src/tests.c index 0ccdbeec..dc5f2790 100644 --- a/src/tests.c +++ b/src/tests.c @@ -4152,8 +4152,8 @@ static void test_group_decompress(const secp256k1_fe* x) { secp256k1_fe_normalize_var(&ge_even.y); /* No infinity allowed. */ - CHECK(!ge_even.infinity); - CHECK(!ge_odd.infinity); + CHECK(!secp256k1_ge_is_infinity(&ge_even)); + CHECK(!secp256k1_ge_is_infinity(&ge_odd)); /* Check that the x coordinates check out. */ CHECK(secp256k1_fe_equal(&ge_even.x, x)); diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index f8bbcaaf..13bda611 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -103,9 +103,11 @@ static void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_ secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); /* add_zinv_var */ - zless_gej.infinity = groupj[j].infinity; - zless_gej.x = groupj[j].x; - zless_gej.y = groupj[j].y; + if (secp256k1_gej_is_infinity(&groupj[j])) { + secp256k1_ge_set_infinity(&zless_gej); + } else { + secp256k1_ge_set_xy(&zless_gej, &groupj[j].x, &groupj[j].y); + } secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); CHECK(secp256k1_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); } @@ -422,10 +424,8 @@ int main(int argc, char** argv) { secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); secp256k1_ge_set_gej(&generated, &generatedj); - CHECK(group[i].infinity == 0); - CHECK(generated.infinity == 0); - CHECK(secp256k1_fe_equal(&generated.x, &group[i].x)); - CHECK(secp256k1_fe_equal(&generated.y, &group[i].y)); + CHECK(!secp256k1_ge_is_infinity(&group[i])); + CHECK(secp256k1_ge_eq_var(&group[i], &generated)); } } diff --git a/src/testutil.h b/src/testutil.h index 480f6a1a..93ee3d58 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -96,17 +96,13 @@ static void testutil_random_ge_test(secp256k1_ge *ge) { break; } } while(1); - ge->infinity = 0; } static void testutil_random_ge_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { - secp256k1_fe z2, z3; - testutil_random_fe_non_zero_test(&gej->z); - secp256k1_fe_sqr(&z2, &gej->z); - secp256k1_fe_mul(&z3, &z2, &gej->z); - secp256k1_fe_mul(&gej->x, &ge->x, &z2); - secp256k1_fe_mul(&gej->y, &ge->y, &z3); - gej->infinity = ge->infinity; + secp256k1_fe z; + testutil_random_fe_non_zero_test(&z); + secp256k1_gej_set_ge(gej, ge); + secp256k1_gej_rescale(gej, &z); } static void testutil_random_gej_test(secp256k1_gej *gej) { From f252da7e6e1bbd0082fd43c4ffabfa90abafb248 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:12:39 +0000 Subject: [PATCH 239/383] ci: Use Python virtual environment in "x86_64-macos-native" job --- .github/workflows/ci.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61767515..59d22514 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -469,9 +469,14 @@ jobs: env: ${{ matrix.env_vars }} run: ./ci/ci.sh - - name: Symbol check + - &SYMBOL_CHECK_MACOS + name: Symbol check + env: + VIRTUAL_ENV: '${{ github.workspace }}/venv' run: | python3 --version + python3 -m venv $VIRTUAL_ENV + export PATH="$VIRTUAL_ENV/bin:$PATH" python3 -m pip install lief python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib @@ -512,17 +517,7 @@ jobs: ln -s $(brew --prefix gcc)/bin/gcc-?? /usr/local/bin/gcc - *CI_SCRIPT_ON_HOST - - - name: Symbol check - env: - VIRTUAL_ENV: '${{ github.workspace }}/venv' - run: | - python3 --version - python3 -m venv $VIRTUAL_ENV - export PATH="$VIRTUAL_ENV/bin:$PATH" - python3 -m pip install lief - python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib - + - *SYMBOL_CHECK_MACOS - *PRINT_LOGS win64-native: From fc7458ca3e28d9eb34427a766122accaa0f36f26 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 17 Nov 2025 16:43:49 +0100 Subject: [PATCH 240/383] introduce `secp256k1_eckey_pubkey_serialize{33,65}` functions --- src/eckey.h | 4 ++++ src/eckey_impl.h | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/eckey.h b/src/eckey.h index d54d44c9..3ebe8969 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -16,6 +16,10 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); +/** Serialize a group element (that is not allowed to be infinity) to a compressed public key (33 bytes). */ +static void secp256k1_eckey_pubkey_serialize33(secp256k1_ge *elem, unsigned char *pub33); +/** Serialize a group element (that is not allowed to be infinity) to an uncompressed public key (65 bytes). */ +static void secp256k1_eckey_pubkey_serialize65(secp256k1_ge *elem, unsigned char *pub65); static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge *key, const secp256k1_scalar *tweak); diff --git a/src/eckey_impl.h b/src/eckey_impl.h index a88a5964..4f647607 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -55,6 +55,25 @@ static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *p return 1; } +static void secp256k1_eckey_pubkey_serialize33(secp256k1_ge *elem, unsigned char *pub33) { + VERIFY_CHECK(!secp256k1_ge_is_infinity(elem)); + + secp256k1_fe_normalize_var(&elem->x); + secp256k1_fe_normalize_var(&elem->y); + pub33[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; + secp256k1_fe_get_b32(&pub33[1], &elem->x); +} + +static void secp256k1_eckey_pubkey_serialize65(secp256k1_ge *elem, unsigned char *pub65) { + VERIFY_CHECK(!secp256k1_ge_is_infinity(elem)); + + secp256k1_fe_normalize_var(&elem->x); + secp256k1_fe_normalize_var(&elem->y); + pub65[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; + secp256k1_fe_get_b32(&pub65[1], &elem->x); + secp256k1_fe_get_b32(&pub65[33], &elem->y); +} + static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { secp256k1_scalar_add(key, key, tweak); return !secp256k1_scalar_is_zero(key); From adb76f82eadadf4f9df4cd958f7c266b551b50c6 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 17 Nov 2025 16:58:01 +0100 Subject: [PATCH 241/383] use new `_eckey_pubkey_serialize{33,65}` functions in public API --- src/secp256k1.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/secp256k1.c b/src/secp256k1.c index 26336a45..c2d3fcbd 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -280,10 +280,14 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o ARG_CHECK(pubkey != NULL); ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { - ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, !!(flags & SECP256K1_FLAGS_BIT_COMPRESSION)); - if (ret) { - *outputlen = len; + if (flags & SECP256K1_FLAGS_BIT_COMPRESSION) { + secp256k1_eckey_pubkey_serialize33(&Q, output); + *outputlen = 33; + } else { + secp256k1_eckey_pubkey_serialize65(&Q, output); + *outputlen = 65; } + ret = 1; } return ret; } From 0d3659c547bdd5a477346e1ef14be3f98cc08f2e Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 17 Nov 2025 18:13:56 +0100 Subject: [PATCH 242/383] use new `_eckey_pubkey_serialize{33,65}` functions in modules (ellswift,musig) --- src/modules/ellswift/main_impl.h | 9 +-------- src/modules/musig/keyagg_impl.h | 9 +-------- src/modules/musig/session_impl.h | 29 +++-------------------------- 3 files changed, 5 insertions(+), 42 deletions(-) diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 0d13f734..096f4a3c 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -406,19 +406,12 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64 if (secp256k1_pubkey_load(ctx, &p, pubkey)) { secp256k1_fe t; unsigned char p64[64] = {0}; - size_t ser_size; - int ser_ret; secp256k1_sha256 hash; /* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using * BIP340 tagged hash with tag "secp256k1_ellswift_encode". */ secp256k1_ellswift_sha256_init_encode(&hash); - ser_ret = secp256k1_eckey_pubkey_serialize(&p, p64, &ser_size, 1); -#ifdef VERIFY - VERIFY_CHECK(ser_ret && ser_size == 33); -#else - (void)ser_ret; -#endif + secp256k1_eckey_pubkey_serialize33(&p, p64); secp256k1_sha256_write(&hash, p64, sizeof(p64)); secp256k1_sha256_write(&hash, rnd32, 32); diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h index 0db4fce8..87869a41 100644 --- a/src/modules/musig/keyagg_impl.h +++ b/src/modules/musig/keyagg_impl.h @@ -124,18 +124,11 @@ static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsig } else { secp256k1_sha256 sha; unsigned char buf[33]; - size_t buflen = sizeof(buf); - int ret; secp256k1_musig_keyaggcoef_sha256(&sha); secp256k1_sha256_write(&sha, pks_hash, 32); - ret = secp256k1_eckey_pubkey_serialize(pk, buf, &buflen, 1); -#ifdef VERIFY /* Serialization does not fail since the pk is not the point at infinity * (according to this function's precondition). */ - VERIFY_CHECK(ret && buflen == sizeof(buf)); -#else - (void) ret; -#endif + secp256k1_eckey_pubkey_serialize33(pk, buf); secp256k1_sha256_write(&sha, buf, sizeof(buf)); secp256k1_sha256_finalize(&sha, buf); secp256k1_scalar_set_b32(r, buf, NULL); diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 2c8778b3..6a80a27b 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -25,15 +25,8 @@ static void secp256k1_musig_ge_serialize_ext(unsigned char *out33, secp256k1_ge* if (secp256k1_ge_is_infinity(ge)) { memset(out33, 0, 33); } else { - int ret; - size_t size = 33; - ret = secp256k1_eckey_pubkey_serialize(ge, out33, &size, 1); -#ifdef VERIFY /* Serialize must succeed because the point is not at infinity */ - VERIFY_CHECK(ret && size == 33); -#else - (void) ret; -#endif + secp256k1_eckey_pubkey_serialize33(ge, out33); } } @@ -224,15 +217,8 @@ int secp256k1_musig_pubnonce_serialize(const secp256k1_context* ctx, unsigned ch return 0; } for (i = 0; i < 2; i++) { - int ret; - size_t size = 33; - ret = secp256k1_eckey_pubkey_serialize(&ges[i], &out66[33*i], &size, 1); -#ifdef VERIFY /* serialize must succeed because the point was just loaded */ - VERIFY_CHECK(ret && size == 33); -#else - (void) ret; -#endif + secp256k1_eckey_pubkey_serialize33(&ges[i], &out66[33*i]); } return 1; } @@ -398,11 +384,9 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp secp256k1_gej nonce_ptj[2]; int i; unsigned char pk_ser[33]; - size_t pk_ser_len = sizeof(pk_ser); unsigned char aggpk_ser[32]; unsigned char *aggpk_ser_ptr = NULL; secp256k1_ge pk; - int pk_serialize_success; int ret = 1; ARG_CHECK(pubnonce != NULL); @@ -429,15 +413,8 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { return 0; } - pk_serialize_success = secp256k1_eckey_pubkey_serialize(&pk, pk_ser, &pk_ser_len, 1); - -#ifdef VERIFY /* A pubkey cannot be the point at infinity */ - VERIFY_CHECK(pk_serialize_success); - VERIFY_CHECK(pk_ser_len == sizeof(pk_ser)); -#else - (void) pk_serialize_success; -#endif + secp256k1_eckey_pubkey_serialize33(&pk, pk_ser); secp256k1_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); From f5e815f4306ea1763d27d83646b4f06e3d2f0b94 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 17 Nov 2025 18:35:32 +0100 Subject: [PATCH 243/383] remove secp256k1_eckey_pubkey_serialize function --- src/eckey.h | 1 - src/eckey_impl.h | 20 -------------------- src/tests.c | 23 +++++++++-------------- 3 files changed, 9 insertions(+), 35 deletions(-) diff --git a/src/eckey.h b/src/eckey.h index 3ebe8969..c2bbc470 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -15,7 +15,6 @@ #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); /** Serialize a group element (that is not allowed to be infinity) to a compressed public key (33 bytes). */ static void secp256k1_eckey_pubkey_serialize33(secp256k1_ge *elem, unsigned char *pub33); /** Serialize a group element (that is not allowed to be infinity) to an uncompressed public key (65 bytes). */ diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 4f647607..48745e8f 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -35,26 +35,6 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char } } -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { - VERIFY_CHECK(compressed == 0 || compressed == 1); - - if (secp256k1_ge_is_infinity(elem)) { - return 0; - } - secp256k1_fe_normalize_var(&elem->x); - secp256k1_fe_normalize_var(&elem->y); - secp256k1_fe_get_b32(&pub[1], &elem->x); - if (compressed) { - *size = 33; - pub[0] = secp256k1_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; - } else { - *size = 65; - pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; - secp256k1_fe_get_b32(&pub[33], &elem->y); - } - return 1; -} - static void secp256k1_eckey_pubkey_serialize33(secp256k1_ge *elem, unsigned char *pub33) { VERIFY_CHECK(!secp256k1_ge_is_infinity(elem)); diff --git a/src/tests.c b/src/tests.c index 0ccdbeec..4029de56 100644 --- a/src/tests.c +++ b/src/tests.c @@ -4315,8 +4315,6 @@ static void test_point_times_order(const secp256k1_gej *point) { secp256k1_scalar nx; secp256k1_gej res1, res2; secp256k1_ge res3; - unsigned char pub[65]; - size_t psize = 65; testutil_random_scalar_order_test(&x); secp256k1_scalar_negate(&nx, &x); secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ @@ -4326,9 +4324,6 @@ static void test_point_times_order(const secp256k1_gej *point) { secp256k1_ge_set_gej(&res3, &res1); CHECK(secp256k1_ge_is_infinity(&res3)); CHECK(secp256k1_ge_is_valid_var(&res3) == 0); - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); - psize = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); /* check zero/one edge cases */ secp256k1_ecmult(&res1, point, &secp256k1_scalar_zero, &secp256k1_scalar_zero); secp256k1_ge_set_gej(&res3, &res1); @@ -5435,7 +5430,6 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar secp256k1_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj; secp256k1_ge r; unsigned char bytes[65]; - size_t size = 65; secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); secp256k1_gej_set_infinity(&infj); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); @@ -5456,9 +5450,8 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar secp256k1_sha256_write(acc, zerobyte, 1); } else { /* Store other points using their uncompressed serialization. */ - secp256k1_eckey_pubkey_serialize(&r, bytes, &size, 0); - CHECK(size == 65); - secp256k1_sha256_write(acc, bytes, size); + secp256k1_eckey_pubkey_serialize65(&r, bytes); + secp256k1_sha256_write(acc, bytes, sizeof(bytes)); } } @@ -6543,16 +6536,18 @@ static void test_random_pubkeys(void) { size_t size = len; firstb = in[0]; /* If the pubkey can be parsed, it should round-trip... */ - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); - CHECK(size == len); + if (len == 33) { + secp256k1_eckey_pubkey_serialize33(&elem, out); + } else { + secp256k1_eckey_pubkey_serialize65(&elem, out); + } CHECK(secp256k1_memcmp_var(&in[1], &out[1], len-1) == 0); /* ... except for the type of hybrid inputs. */ if ((in[0] != 6) && (in[0] != 7)) { CHECK(in[0] == out[0]); } size = 65; - CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); - CHECK(size == 65); + secp256k1_eckey_pubkey_serialize65(&elem, in); CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); CHECK(secp256k1_ge_eq_var(&elem2, &elem)); /* Check that the X9.62 hybrid type is checked. */ @@ -6567,7 +6562,7 @@ static void test_random_pubkeys(void) { } if (res) { CHECK(secp256k1_ge_eq_var(&elem, &elem2)); - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); + secp256k1_eckey_pubkey_serialize65(&elem, out); CHECK(secp256k1_memcmp_var(&in[1], &out[1], 64) == 0); } } From 7eb86bdb0154a24a627c342c7bfcc95320155779 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:40:50 +0000 Subject: [PATCH 244/383] autotools: Rename `build-aux` to `autotools-aux` This change improves separation from CMake build directories, which typically use the "build" prefix. Additionally, corresponding `.gitignore` entries have been refactored. --- .gitignore | 17 +++-------------- Makefile.am | 2 +- {build-aux => autotools-aux}/m4/bitcoin_secp.m4 | 0 configure.ac | 4 ++-- src/CMakeLists.txt | 2 +- 5 files changed, 7 insertions(+), 18 deletions(-) rename {build-aux => autotools-aux}/m4/bitcoin_secp.m4 (100%) diff --git a/.gitignore b/.gitignore index ce33a84a..cae28210 100644 --- a/.gitignore +++ b/.gitignore @@ -45,20 +45,9 @@ coverage.*.html *.gcno *.gcov -build-aux/ar-lib -build-aux/config.guess -build-aux/config.sub -build-aux/depcomp -build-aux/install-sh -build-aux/ltmain.sh -build-aux/m4/libtool.m4 -build-aux/m4/lt~obsolete.m4 -build-aux/m4/ltoptions.m4 -build-aux/m4/ltsugar.m4 -build-aux/m4/ltversion.m4 -build-aux/missing -build-aux/compile -build-aux/test-driver +/autotools-aux/ +!/autotools-aux/m4/bitcoin_secp.m4 + libsecp256k1.pc ### CMake diff --git a/Makefile.am b/Makefile.am index dc798575..07d7a2ba 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 +ACLOCAL_AMFLAGS = -I autotools-aux/m4 # AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo # which does not have an explicit foo_CFLAGS variable set. diff --git a/build-aux/m4/bitcoin_secp.m4 b/autotools-aux/m4/bitcoin_secp.m4 similarity index 100% rename from build-aux/m4/bitcoin_secp.m4 rename to autotools-aux/m4/bitcoin_secp.m4 diff --git a/configure.ac b/configure.ac index 6028ee28..36699c17 100644 --- a/configure.ac +++ b/configure.ac @@ -19,8 +19,8 @@ define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CONFIG_AUX_DIR([autotools-aux]) +AC_CONFIG_MACRO_DIR([autotools-aux/m4]) AC_CANONICAL_HOST # Require Automake 1.11.2 for AM_PROG_AR diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ecbbbbe8..46db7780 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,7 +95,7 @@ set_target_properties(secp256k1_objs PROPERTIES ) # This emulates Libtool to make sure Libtool and CMake agree on the ABI version, -# see below "Calculate the version variables" in build-aux/ltmain.sh. +# see below "Calculate the version variables" in autotools-aux/ltmain.sh. math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}") set_target_properties(secp256k1 PROPERTIES SOVERSION ${${PROJECT_NAME}_soversion} From 748c0fdd67c646c83bd62e74a8e205e04d314e07 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:42:08 +0000 Subject: [PATCH 245/383] Add CMake build directory patterns to `.gitignore` --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index cae28210..fbc311d7 100644 --- a/.gitignore +++ b/.gitignore @@ -52,8 +52,8 @@ libsecp256k1.pc ### CMake /CMakeUserPresets.json -# Default CMake build directory. -/build +# CMake build directories. +/*build* ### Python __pycache__/ From 3b5b03f30169903baae7f365cff3137a371a9a8d Mon Sep 17 00:00:00 2001 From: kevkevinpal Date: Thu, 4 Dec 2025 16:53:15 -0500 Subject: [PATCH 246/383] doc/bench: Added cmake build options to bench error messages --- src/bench.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bench.c b/src/bench.c index 8ba7623a..04685d93 100644 --- a/src/bench.c +++ b/src/bench.c @@ -205,7 +205,7 @@ int main(int argc, char** argv) { #ifndef ENABLE_MODULE_ECDH if (have_flag(argc, argv, "ecdh")) { fprintf(stderr, "./bench: ECDH module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-ecdh.\n\n"); + fprintf(stderr, "See README.md for configuration instructions.\n\n"); return EXIT_FAILURE; } #endif @@ -213,7 +213,7 @@ int main(int argc, char** argv) { #ifndef ENABLE_MODULE_RECOVERY if (have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) { fprintf(stderr, "./bench: Public key recovery module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-recovery.\n\n"); + fprintf(stderr, "See README.md for configuration instructions.\n\n"); return EXIT_FAILURE; } #endif @@ -221,7 +221,7 @@ int main(int argc, char** argv) { #ifndef ENABLE_MODULE_SCHNORRSIG if (have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "schnorrsig_sign") || have_flag(argc, argv, "schnorrsig_verify")) { fprintf(stderr, "./bench: Schnorr signatures module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-schnorrsig.\n\n"); + fprintf(stderr, "See README.md for configuration instructions.\n\n"); return EXIT_FAILURE; } #endif @@ -231,7 +231,7 @@ int main(int argc, char** argv) { have_flag(argc, argv, "encode") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_keygen") || have_flag(argc, argv, "ellswift_ecdh")) { fprintf(stderr, "./bench: ElligatorSwift module not enabled.\n"); - fprintf(stderr, "Use ./configure --enable-module-ellswift.\n\n"); + fprintf(stderr, "See README.md for configuration instructions.\n\n"); return EXIT_FAILURE; } #endif From 5a08c1bcdc958f264450e771d7923922526f74f1 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sat, 6 Dec 2025 01:04:18 +0100 Subject: [PATCH 247/383] Add ARG_CHECKs to ensure "array of pointers" elements are non-NULL --- src/modules/musig/keyagg_impl.h | 3 +++ src/modules/musig/session_impl.h | 8 ++++++++ src/secp256k1.c | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h index 87869a41..e412a27e 100644 --- a/src/modules/musig/keyagg_impl.h +++ b/src/modules/musig/keyagg_impl.h @@ -177,6 +177,9 @@ int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_xonly_pub } ARG_CHECK(pubkeys != NULL); ARG_CHECK(n_pubkeys > 0); + for (i = 0; i < n_pubkeys; i++) { + ARG_CHECK(pubkeys[i] != NULL); + } ecmult_data.ctx = ctx; ecmult_data.pks = pubkeys; diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 6a80a27b..4a245ada 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -521,10 +521,15 @@ static int secp256k1_musig_sum_pubnonces(const secp256k1_context* ctx, secp256k1 int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggnonce *aggnonce, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { secp256k1_gej aggnonce_ptsj[2]; secp256k1_ge aggnonce_pts[2]; + size_t i; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(aggnonce != NULL); ARG_CHECK(pubnonces != NULL); ARG_CHECK(n_pubnonces > 0); + for (i = 0; i < n_pubnonces; i++) { + ARG_CHECK(pubnonces[i] != NULL); + } if (!secp256k1_musig_sum_pubnonces(ctx, aggnonce_ptsj, pubnonces, n_pubnonces)) { return 0; @@ -782,6 +787,9 @@ int secp256k1_musig_partial_sig_agg(const secp256k1_context* ctx, unsigned char ARG_CHECK(session != NULL); ARG_CHECK(partial_sigs != NULL); ARG_CHECK(n_sigs > 0); + for (i = 0; i < n_sigs; i++) { + ARG_CHECK(partial_sigs[i] != NULL); + } if (!secp256k1_musig_session_load(ctx, &session_i, session)) { return 0; diff --git a/src/secp256k1.c b/src/secp256k1.c index c2d3fcbd..bce06d37 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -325,8 +325,13 @@ static int secp256k1_ec_pubkey_sort_cmp(const void* pk1, const void* pk2, void * } int secp256k1_ec_pubkey_sort(const secp256k1_context* ctx, const secp256k1_pubkey **pubkeys, size_t n_pubkeys) { + size_t i; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkeys != NULL); + for (i = 0; i < n_pubkeys; i++) { + ARG_CHECK(pubkeys[i] != NULL); + } /* Suppress wrong warning (fixed in MSVC 19.33) */ #if defined(_MSC_VER) && (_MSC_VER < 1933) From 8bcda186d20e11ba9a04e6917928f062513b534f Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 9 Dec 2025 01:30:56 +0100 Subject: [PATCH 248/383] test: Add non-NULL checks for "pointer of array" API functions --- src/modules/musig/tests_impl.h | 21 +++++++++++++++++++++ src/tests.c | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index b4ba1854..de09c5e2 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -201,6 +201,13 @@ static void musig_api_tests(void) { CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_agg(CTX, NULL, &keyagg_cache, pk_ptr, 2) == 1); CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, NULL, pk_ptr, 2) == 1); + /* check that NULL in array of public key pointers is not allowed */ + for (i = 0; i < 2; i++) { + const secp256k1_pubkey *original_ptr = pk_ptr[i]; + pk_ptr[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, NULL, pk_ptr, 2)); + pk_ptr[i] = original_ptr; + } CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, NULL, 2)); CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, invalid_pk_ptr2, 2)); @@ -350,6 +357,13 @@ static void musig_api_tests(void) { /** Receive nonces and aggregate **/ CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + /* check that NULL in array of public nonce pointers is not allowed */ + for (i = 0; i < 2; i++) { + const secp256k1_musig_pubnonce *original_ptr = pubnonce_ptr[i]; + pubnonce_ptr[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2)); + pubnonce_ptr[i] = original_ptr; + } CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, NULL, pubnonce_ptr, 2)); CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, NULL, 2)); CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 0)); @@ -474,6 +488,13 @@ static void musig_api_tests(void) { /** Signature aggregation and verification */ CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); + /* check that NULL in array of partial signature pointers is not allowed */ + for (i = 0; i < 2; i++) { + const secp256k1_musig_partial_sig *original_ptr = partial_sig_ptr[i]; + partial_sig_ptr[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2)); + partial_sig_ptr[i] = original_ptr; + } CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, NULL, &session, partial_sig_ptr, 2)); CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, NULL, partial_sig_ptr, 2)); CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &invalid_session, partial_sig_ptr, 2)); diff --git a/src/tests.c b/src/tests.c index 4029de56..14aa7858 100644 --- a/src/tests.c +++ b/src/tests.c @@ -6052,6 +6052,7 @@ static void run_eckey_edge_case_test(void) { secp256k1_pubkey pubkey_negone; const secp256k1_pubkey *pubkeys[3]; size_t len; + int i; /* Group order is too large, reject. */ CHECK(secp256k1_ec_seckey_verify(CTX, orderc) == 0); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); @@ -6245,6 +6246,14 @@ static void run_eckey_edge_case_test(void) { CHECK(secp256k1_ec_pubkey_combine(CTX, &pubkey, pubkeys, 3) == 1); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(secp256k1_pubkey)); CHECK(secp256k1_memcmp_var(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + /* check that NULL in array of pubkey pointers is not allowed */ + for (i = 0; i < 3; i++) { + const secp256k1_pubkey *original_ptr = pubkeys[i]; + secp256k1_pubkey result; + pubkeys[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_combine(CTX, &result, pubkeys, 3)); + pubkeys[i] = original_ptr; + } len = 33; CHECK(secp256k1_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); CHECK(secp256k1_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); @@ -6640,6 +6649,7 @@ static void permute(size_t *arr, size_t n) { static void test_sort_api(void) { secp256k1_pubkey pks[2]; const secp256k1_pubkey *pks_ptr[2]; + int i; pks_ptr[0] = &pks[0]; pks_ptr[1] = &pks[1]; @@ -6648,6 +6658,13 @@ static void test_sort_api(void) { testutil_random_pubkey_test(&pks[1]); CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); + /* check that NULL in array of public key pointers is not allowed */ + for (i = 0; i < 2; i++) { + const secp256k1_pubkey *original_ptr = pks_ptr[i]; + pks_ptr[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_sort(CTX, pks_ptr, 2)); + pks_ptr[i] = original_ptr; + } CHECK_ILLEGAL(CTX, secp256k1_ec_pubkey_sort(CTX, NULL, 2)); CHECK(secp256k1_ec_pubkey_sort(CTX, pks_ptr, 0) == 1); /* Test illegal public keys */ From 3daab83a6050805763da5ac9ebe8217d1965eb0c Mon Sep 17 00:00:00 2001 From: kevkevinpal Date: Tue, 9 Dec 2025 16:08:35 -0500 Subject: [PATCH 249/383] refactor: remove ret from secp256k1_ec_pubkey_serialize --- src/secp256k1.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/secp256k1.c b/src/secp256k1.c index c2d3fcbd..7d6b9bd3 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -268,7 +268,6 @@ int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pu int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { secp256k1_ge Q; size_t len; - int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(outputlen != NULL); @@ -287,9 +286,9 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *o secp256k1_eckey_pubkey_serialize65(&Q, output); *outputlen = 65; } - ret = 1; + return 1; } - return ret; + return 0; } int secp256k1_ec_pubkey_cmp(const secp256k1_context* ctx, const secp256k1_pubkey* pubkey0, const secp256k1_pubkey* pubkey1) { From ae00c552df55f4d170175903855901d640b92761 Mon Sep 17 00:00:00 2001 From: John Moffett Date: Tue, 9 Dec 2025 12:43:49 -0500 Subject: [PATCH 250/383] Add VERIFY_CHECKs that flags are 0 or 1 Flags for constant-time masking rely on the values being exactly 0 or 1 rather than 0 or true. Add VERIFY_CHECKs to enforce in VERIFY builds as a preventative measure and add documentation where relevant. --- src/field.h | 3 ++- src/field_10x26_impl.h | 2 ++ src/field_5x52_impl.h | 2 ++ src/group.h | 6 ++++-- src/group_impl.h | 2 ++ src/modules/musig/session_impl.h | 3 ++- src/scalar.h | 6 +++--- src/scalar_4x64_impl.h | 3 +++ src/scalar_8x32_impl.h | 3 +++ src/scalar_low_impl.h | 3 +++ src/util.h | 5 ++++- 11 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/field.h b/src/field.h index 1f6ba746..e3f0234f 100644 --- a/src/field.h +++ b/src/field.h @@ -307,7 +307,8 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe */ static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ +/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time. + * Both *r and *a must be initialized. Flag must be 0 or 1. */ static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); /** Conditionally move a field element in constant time. diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index ea14c273..aa45434d 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -1014,6 +1014,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp25 SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = vflag + ~((uint32_t)0); mask1 = ~mask0; @@ -1097,6 +1098,7 @@ static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) { static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = vflag + ~((uint32_t)0); mask1 = ~mask0; diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 46dca6b9..3a976135 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -349,6 +349,7 @@ SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp25 SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = vflag + ~((uint64_t)0); mask1 = ~mask0; @@ -416,6 +417,7 @@ static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) { static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); mask0 = vflag + ~((uint64_t)0); mask1 = ~mask0; diff --git a/src/group.h b/src/group.h index 05ae0d20..ee3ebbbe 100644 --- a/src/group.h +++ b/src/group.h @@ -169,10 +169,12 @@ static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge /** Convert a group element back from the storage type. */ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ +/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time. + * Both *r and *a must be initialized. Flag must be 0 or 1. */ static void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag); -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ +/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time. + * Both *r and *a must be initialized. Flag must be 0 or 1. */ static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); /** Rescale a jacobian point by b which must be non-zero. Constant-time. */ diff --git a/src/group_impl.h b/src/group_impl.h index 81a24b9d..f5169650 100644 --- a/src/group_impl.h +++ b/src/group_impl.h @@ -898,6 +898,7 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) { SECP256K1_GEJ_VERIFY(r); SECP256K1_GEJ_VERIFY(a); + VERIFY_CHECK(flag == 0 || flag == 1); secp256k1_fe_cmov(&r->x, &a->x, flag); secp256k1_fe_cmov(&r->y, &a->y, flag); @@ -908,6 +909,7 @@ static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k } static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { + VERIFY_CHECK(flag == 0 || flag == 1); secp256k1_fe_storage_cmov(&r->x, &a->x, flag); secp256k1_fe_storage_cmov(&r->y, &a->y, flag); } diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 6a80a27b..6fb32884 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -69,7 +69,8 @@ static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1 return 1; } -/* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */ +/* If flag is 1, invalidate the secnonce; if flag is 0, leave it. + * Constant-time. Flag must be 0 or 1. */ static void secp256k1_musig_secnonce_invalidate(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, int flag) { secp256k1_memczero(secnonce->data, sizeof(secnonce->data), flag); /* The flag argument is usually classified. So, the line above makes the diff --git a/src/scalar.h b/src/scalar.h index 70f49b1c..40d67191 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -48,7 +48,7 @@ static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* /** Add two scalars together (modulo the group order). Returns whether it overflowed. */ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); -/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ +/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. Flag must be 0 or 1. */ static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); /** Multiply two scalars (modulo the group order). */ @@ -78,7 +78,7 @@ static int secp256k1_scalar_is_even(const secp256k1_scalar *a); /** Check whether a scalar is higher than the group order divided by 2. */ static int secp256k1_scalar_is_high(const secp256k1_scalar *a); -/** Conditionally negate a number, in constant time. +/** Conditionally negate a number, in constant time. Flag must be 0 or 1. * Returns -1 if the number was negated, 1 otherwise */ static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); @@ -95,7 +95,7 @@ static void secp256k1_scalar_split_lambda(secp256k1_scalar * SECP256K1_RESTRICT /** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ +/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time. Both *r and *a must be initialized. Flag must be 0 or 1. */ static void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag); /** Check invariants on a scalar (no-op unless VERIFY is enabled). */ diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 807b9b70..a5bf18fe 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -120,6 +120,7 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { secp256k1_uint128 t; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(r); VERIFY_CHECK(bit < 256); @@ -259,6 +260,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { uint64_t mask = -vflag; uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; secp256k1_uint128 t; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(r); secp256k1_u128_from_u64(&t, r->d[0] ^ mask); @@ -911,6 +913,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(a); SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d)); diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index 26104960..aa87b1d3 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -147,6 +147,7 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { uint64_t t; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(r); VERIFY_CHECK(bit < 256); @@ -314,6 +315,7 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { uint32_t mask = -vflag; uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(r); r->d[0] = t & nonzero; t >>= 32; @@ -709,6 +711,7 @@ SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(a); SECP256K1_CHECKMEM_CHECK_VERIFY(r->d, sizeof(r->d)); diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 84e1a380..628bfd33 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -56,6 +56,7 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { SECP256K1_SCALAR_VERIFY(r); + VERIFY_CHECK(flag == 0 || flag == 1); if (flag && bit < 32) *r += ((uint32_t)1 << bit); @@ -121,6 +122,7 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { SECP256K1_SCALAR_VERIFY(r); + VERIFY_CHECK(flag == 0 || flag == 1); if (flag) secp256k1_scalar_negate(r, r); @@ -157,6 +159,7 @@ SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const static SECP256K1_INLINE void secp256k1_scalar_cmov(secp256k1_scalar *r, const secp256k1_scalar *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_SCALAR_VERIFY(a); SECP256K1_CHECKMEM_CHECK_VERIFY(r, sizeof(*r)); diff --git a/src/util.h b/src/util.h index 94e0837d..46ab3810 100644 --- a/src/util.h +++ b/src/util.h @@ -212,6 +212,7 @@ static SECP256K1_INLINE void secp256k1_memczero(void *s, size_t len, int flag) { take only be 0 or 1, which leads to variable time code. */ volatile int vflag = flag; unsigned char mask = -(unsigned char) vflag; + VERIFY_CHECK(flag == 0 || flag == 1); while (len) { *p &= ~mask; p++; @@ -294,7 +295,8 @@ static SECP256K1_INLINE int secp256k1_is_zero_array(const unsigned char *s, size return ret; } -/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized and non-negative.*/ +/** If flag is 1, set *r equal to *a; if flag is 0, leave it. Constant-time. + * Both *r and *a must be initialized and non-negative. Flag must be 0 or 1. */ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) { unsigned int mask0, mask1, r_masked, a_masked; /* Access flag with a volatile-qualified lvalue. @@ -302,6 +304,7 @@ static SECP256K1_INLINE void secp256k1_int_cmov(int *r, const int *a, int flag) take only be 0 or 1, which leads to variable time code. */ volatile int vflag = flag; + VERIFY_CHECK(flag == 0 || flag == 1); /* Casting a negative int to unsigned and back to int is implementation defined behavior */ VERIFY_CHECK(*r >= 0 && *a >= 0); From d822b2902106829bae1455cabec6bfca9a265a77 Mon Sep 17 00:00:00 2001 From: furszy Date: Sun, 14 Dec 2025 10:31:41 -0500 Subject: [PATCH 251/383] test: split monolithic ellswift test into independent cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No behavior changes. Refactors the previously monolithic ElligatorSwift test into isolated, independent test cases. Doing so allows the test suite to execute these cases in parallel rather than sequentially. Overall, seen 35-40% tests time reduction locally. This is quite useful for the Debug build with no optimizations, which is noticeably slow. #### Local Debug-build Results (7 jobs): - master: 138.0 seconds. - this PR: 89.3 seconds. (~1.55× speedup, ~35% reduction) #### Local Release-build Results (7 jobs): - master: 9.5 seconds. - this PR: 5.9 seconds. (~1.61× speedup, ~38% reduction) --- src/modules/ellswift/tests_impl.h | 98 ++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 63c36e7f..4cc7f4b5 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -177,9 +177,9 @@ static int ellswift_xdh_hash_x32(unsigned char *output, const unsigned char *x32 return 1; } -void run_ellswift_tests(void) { - int i = 0; - /* Test vectors. */ +/* Run the test vectors for ellswift encoding */ +void ellswift_encoding_test_vectors_tests(void) { + int i; for (i = 0; (unsigned)i < sizeof(ellswift_xswiftec_inv_tests) / sizeof(ellswift_xswiftec_inv_tests[0]); ++i) { const struct ellswift_xswiftec_inv_test *testcase = &ellswift_xswiftec_inv_tests[i]; int c; @@ -195,6 +195,11 @@ void run_ellswift_tests(void) { } } } +} + +/* Run the test vectors for ellswift decoding */ +void ellswift_decoding_test_vectors_tests(void) { + int i; for (i = 0; (unsigned)i < sizeof(ellswift_decode_tests) / sizeof(ellswift_decode_tests[0]); ++i) { const struct ellswift_decode_test *testcase = &ellswift_decode_tests[i]; secp256k1_pubkey pubkey; @@ -207,6 +212,11 @@ void run_ellswift_tests(void) { CHECK(fe_equal(&testcase->x, &ge.x)); CHECK(secp256k1_fe_is_odd(&ge.y) == testcase->odd_y); } +} + +/* Run the test vectors for ellswift expected xdh BIP324 shared secrets */ +void ellswift_xdh_test_vectors_tests(void) { + int i; for (i = 0; (unsigned)i < sizeof(ellswift_xdh_tests_bip324) / sizeof(ellswift_xdh_tests_bip324[0]); ++i) { const struct ellswift_xdh_test *test = &ellswift_xdh_tests_bip324[i]; unsigned char shared_secret[32]; @@ -223,7 +233,11 @@ void run_ellswift_tests(void) { CHECK(ret); CHECK(secp256k1_memcmp_var(shared_secret, test->shared_secret, 32) == 0); } - /* Verify that secp256k1_ellswift_encode + decode roundtrips. */ +} + +/* Verify that secp256k1_ellswift_encode + decode roundtrips */ +void ellswift_encode_decode_roundtrip_tests(void) { + int i; for (i = 0; i < 1000 * COUNT; i++) { unsigned char rnd32[32]; unsigned char ell64[64]; @@ -240,7 +254,11 @@ void run_ellswift_tests(void) { /* Compare with original. */ CHECK(secp256k1_ge_eq_var(&g, &g2)); } - /* Verify the behavior of secp256k1_ellswift_create */ +} + +/* Verify the behavior of secp256k1_ellswift_create */ +void ellswift_create_tests(void) { + int i; for (i = 0; i < 400 * COUNT; i++) { unsigned char auxrnd32[32], sec32[32]; secp256k1_scalar sec; @@ -262,7 +280,11 @@ void run_ellswift_tests(void) { secp256k1_ecmult(&res, NULL, &secp256k1_scalar_zero, &sec); CHECK(secp256k1_gej_eq_ge_var(&res, &dec)); } - /* Verify that secp256k1_ellswift_xdh computes the right shared X coordinate. */ +} + +/* Verify that secp256k1_ellswift_xdh computes the right shared X coordinate */ +void ellswift_compute_shared_secret_tests(void) { + int i; for (i = 0; i < 800 * COUNT; i++) { unsigned char ell64[64], sec32[32], share32[32]; secp256k1_scalar sec; @@ -293,6 +315,10 @@ void run_ellswift_tests(void) { /* Compare. */ CHECK(fe_equal(&res.x, &share_x)); } +} + +void ellswift_xdh_correctness_tests(void) { + int i; /* Verify the joint behavior of secp256k1_ellswift_xdh */ for (i = 0; i < 200 * COUNT; i++) { unsigned char auxrnd32a[32], auxrnd32b[32], auxrnd32a_bad[32], auxrnd32b_bad[32]; @@ -403,41 +429,47 @@ void run_ellswift_tests(void) { CHECK(secp256k1_memcmp_var(share32_bad, share32b, 32) != 0); } } +} - /* Test hash initializers. */ - { - secp256k1_sha256 sha_optimized; - /* "secp256k1_ellswift_encode" */ - static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; - /* "secp256k1_ellswift_create" */ - static const unsigned char create_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'c', 'r', 'e', 'a', 't', 'e'}; - /* "bip324_ellswift_xonly_ecdh" */ - static const unsigned char bip324_tag[] = {'b', 'i', 'p', '3', '2', '4', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'x', 'o', 'n', 'l', 'y', '_', 'e', 'c', 'd', 'h'}; +/* Test hash initializers */ +void ellswift_hash_init_tests(void) { + secp256k1_sha256 sha_optimized; + /* "secp256k1_ellswift_encode" */ + static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; + /* "secp256k1_ellswift_create" */ + static const unsigned char create_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'c', 'r', 'e', 'a', 't', 'e'}; + /* "bip324_ellswift_xonly_ecdh" */ + static const unsigned char bip324_tag[] = {'b', 'i', 'p', '3', '2', '4', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'x', 'o', 'n', 'l', 'y', '_', 'e', 'c', 'd', 'h'}; - /* Check that hash initialized by - * secp256k1_ellswift_sha256_init_encode has the expected - * state. */ - secp256k1_ellswift_sha256_init_encode(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, encode_tag, sizeof(encode_tag)); + /* Check that hash initialized by + * secp256k1_ellswift_sha256_init_encode has the expected + * state. */ + secp256k1_ellswift_sha256_init_encode(&sha_optimized); + test_sha256_tag_midstate(&sha_optimized, encode_tag, sizeof(encode_tag)); - /* Check that hash initialized by - * secp256k1_ellswift_sha256_init_create has the expected - * state. */ - secp256k1_ellswift_sha256_init_create(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, create_tag, sizeof(create_tag)); + /* Check that hash initialized by + * secp256k1_ellswift_sha256_init_create has the expected + * state. */ + secp256k1_ellswift_sha256_init_create(&sha_optimized); + test_sha256_tag_midstate(&sha_optimized, create_tag, sizeof(create_tag)); - /* Check that hash initialized by - * secp256k1_ellswift_sha256_init_bip324 has the expected - * state. */ - secp256k1_ellswift_sha256_init_bip324(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); - } + /* Check that hash initialized by + * secp256k1_ellswift_sha256_init_bip324 has the expected + * state. */ + secp256k1_ellswift_sha256_init_bip324(&sha_optimized); + test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); } /* --- Test registry --- */ -/* TODO: subdivide test in cases */ static const struct tf_test_entry tests_ellswift[] = { - CASE(ellswift_tests), + CASE1(ellswift_encoding_test_vectors_tests), + CASE1(ellswift_decoding_test_vectors_tests), + CASE1(ellswift_xdh_test_vectors_tests), + CASE1(ellswift_encode_decode_roundtrip_tests), + CASE1(ellswift_create_tests), + CASE1(ellswift_compute_shared_secret_tests), + CASE1(ellswift_xdh_correctness_tests), + CASE1(ellswift_hash_init_tests), }; #endif From 0406cfc4d1d414bbc806757bb42e540bf0d8a0c1 Mon Sep 17 00:00:00 2001 From: kevkevinpal Date: Thu, 18 Dec 2025 22:15:38 -0500 Subject: [PATCH 252/383] doc: include arg -DUSE_EXTERNAL_DEFAULT_CALLBACKS=1 for cmake --- include/secp256k1.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index b0a13b14..2799d4a1 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -349,7 +349,8 @@ SECP256K1_API void secp256k1_context_destroy( * writes the message to stderr and calls abort. This default callback can be * replaced at link time if the preprocessor macro * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build - * has been configured with --enable-external-default-callbacks. Then the + * has been configured with --enable-external-default-callbacks (GNU Autotools) or + * -DSECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS=ON (CMake). Then the * following two symbols must be provided to link against: * - void secp256k1_default_illegal_callback_fn(const char *message, void *data); * - void secp256k1_default_error_callback_fn(const char *message, void *data); From bb1d199de572ed3358a21a68f2fccd1037eee601 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 7 Jan 2026 11:30:16 +0100 Subject: [PATCH 253/383] ecmult: Use size_t for array indices into tables --- src/ecmult.h | 2 +- src/ecmult_compute_table_impl.h | 2 +- src/ecmult_impl.h | 27 ++++++++++++++------------- src/precompute_ecmult.c | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/ecmult.h b/src/ecmult.h index 326a5eeb..8d0a9f49 100644 --- a/src/ecmult.h +++ b/src/ecmult.h @@ -38,7 +38,7 @@ #endif /** The number of entries a table with precomputed multiples needs to have. */ -#define ECMULT_TABLE_SIZE(w) (1L << ((w)-2)) +#define ECMULT_TABLE_SIZE(w) ((size_t)1 << ((w)-2)) /** Double multiply: R = na*A + ng*G */ static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); diff --git a/src/ecmult_compute_table_impl.h b/src/ecmult_compute_table_impl.h index 69d59ce5..09b899b4 100644 --- a/src/ecmult_compute_table_impl.h +++ b/src/ecmult_compute_table_impl.h @@ -16,7 +16,7 @@ static void secp256k1_ecmult_compute_table(secp256k1_ge_storage* table, int window_g, const secp256k1_gej* gen) { secp256k1_gej gj; secp256k1_ge ge, dgen; - int j; + size_t j; gj = *gen; secp256k1_ge_set_gej_var(&ge, &gj); diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index c421750d..4046cd4c 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -311,8 +311,9 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state * } for (np = 0; np < no; ++np) { - for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - secp256k1_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i].x, &secp256k1_const_beta); + size_t j; + for (j = 0; j < ECMULT_TABLE_SIZE(WINDOW_A); j++) { + secp256k1_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + j], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + j].x, &secp256k1_const_beta); } } @@ -517,7 +518,6 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi size_t np; size_t no = 0; int i; - int j; for (np = 0; np < num; ++np) { if (secp256k1_scalar_is_zero(&sc[np]) || secp256k1_ge_is_infinity(&pt[np])) { @@ -535,16 +535,17 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi for (i = n_wnaf - 1; i >= 0; i--) { secp256k1_gej running_sum; + int j; + size_t buc; - for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { - secp256k1_gej_set_infinity(&buckets[j]); + for (buc = 0; buc < ECMULT_TABLE_SIZE(bucket_window+2); buc++) { + secp256k1_gej_set_infinity(&buckets[buc]); } for (np = 0; np < no; ++np) { int n = state->wnaf_na[np*n_wnaf + i]; struct secp256k1_pippenger_point_state point_state = state->ps[np]; secp256k1_ge tmp; - int idx; if (i == 0) { /* correct for wnaf skew */ @@ -555,16 +556,16 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi } } if (n > 0) { - idx = (n - 1)/2; - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); + buc = (n - 1)/2; + secp256k1_gej_add_ge_var(&buckets[buc], &buckets[buc], &pt[point_state.input_pos], NULL); } else if (n < 0) { - idx = -(n + 1)/2; + buc = -(n + 1)/2; secp256k1_ge_neg(&tmp, &pt[point_state.input_pos]); - secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); + secp256k1_gej_add_ge_var(&buckets[buc], &buckets[buc], &tmp, NULL); } } - for(j = 0; j < bucket_window; j++) { + for (j = 0; j < bucket_window; j++) { secp256k1_gej_double_var(r, r, NULL); } @@ -577,8 +578,8 @@ static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_wi * * The doubling is done implicitly by deferring the final window doubling (of 'r'). */ - for(j = ECMULT_TABLE_SIZE(bucket_window+2) - 1; j > 0; j--) { - secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); + for (buc = ECMULT_TABLE_SIZE(bucket_window+2) - 1; buc > 0; buc--) { + secp256k1_gej_add_var(&running_sum, &running_sum, &buckets[buc], NULL); secp256k1_gej_add_var(r, r, &running_sum, NULL); } diff --git a/src/precompute_ecmult.c b/src/precompute_ecmult.c index 021fe394..8579c85f 100644 --- a/src/precompute_ecmult.c +++ b/src/precompute_ecmult.c @@ -20,7 +20,7 @@ #include "ecmult_compute_table_impl.h" static void print_table(FILE *fp, const char *name, int window_g, const secp256k1_ge_storage* table) { - int j; + size_t j; int i; fprintf(fp, "const secp256k1_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); From 47eb70959a91bbfa10dc209e8ccbe7350f5b9b04 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 7 Jan 2026 11:32:20 +0100 Subject: [PATCH 254/383] ecmult: Use size_t for array indices in _odd_multiplies_table --- src/ecmult_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ecmult_impl.h b/src/ecmult_impl.h index 4046cd4c..1a05244c 100644 --- a/src/ecmult_impl.h +++ b/src/ecmult_impl.h @@ -70,10 +70,10 @@ * Lastly the zr[0] value, which isn't used above, is set so that: * - a.z = z(pre_a[0]) / zr[0] */ -static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) { +static void secp256k1_ecmult_odd_multiples_table(size_t n, secp256k1_ge *pre_a, secp256k1_fe *zr, secp256k1_fe *z, const secp256k1_gej *a) { secp256k1_gej d, ai; secp256k1_ge d_ge; - int i; + size_t i; VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); From bd5ced1fe174e4568261e66025b93c922d8e4be3 Mon Sep 17 00:00:00 2001 From: kevkevinpal Date: Mon, 29 Dec 2025 22:01:35 -0500 Subject: [PATCH 255/383] doc/bench: added help text for SECP256K1_BENCH_ITERS env var for bench_ecmult In addition a print message saying some tests were skipped was added --- src/bench_ecmult.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index c9a1d900..e8fab149 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -19,9 +19,12 @@ #define POINTS 32768 -static void help(char **argv) { +static void help(char **argv, int default_iters) { printf("Benchmark EC multiplication algorithms\n"); printf("\n"); + printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); + printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); + printf("\n"); printf("Usage: %s \n", argv[0]); printf("The output shows the number of multiplied and summed points right after the\n"); printf("function name. The letter 'g' indicates that one of the points is the generator.\n"); @@ -308,7 +311,8 @@ int main(int argc, char **argv) { int i, p; size_t scratch_size; - int iters = get_iters(10000); + int default_iters = 10000; + int iters = get_iters(default_iters); data.ecmult_multi = secp256k1_ecmult_multi_var; @@ -316,7 +320,7 @@ int main(int argc, char **argv) { if(have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(argv); + help(argv, default_iters); return EXIT_SUCCESS; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); @@ -328,7 +332,7 @@ int main(int argc, char **argv) { printf("Using simple algorithm:\n"); } else { fprintf(stderr, "%s: unrecognized argument '%s'.\n\n", argv[0], argv[1]); - help(argv); + help(argv, default_iters); return EXIT_FAILURE; } } @@ -381,6 +385,8 @@ int main(int argc, char **argv) { run_ecmult_multi_bench(&data, i << p, 1, iters); } } + } else { + printf("Skipping some benchmarks due to SECP256K1_BENCH_ITERS <= 2\n"); } if (data.scratch != NULL) { From 4ac651144b9a9b4f4cf144b2b067e5f73a53b68e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:18:48 +0000 Subject: [PATCH 256/383] cmake, refactor: Deduplicate test-related code Co-authored-by: furszy --- src/CMakeLists.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ecbbbbe8..10f96c30 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -144,15 +144,16 @@ if(SECP256K1_BUILD_TESTS) list(APPEND TEST_DEFINITIONS SUPPORTS_CONCURRENCY=1) endif() - add_executable(noverify_tests tests.c) - target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm) - target_compile_definitions(noverify_tests PRIVATE ${TEST_DEFINITIONS}) - add_test(NAME secp256k1_noverify_tests COMMAND noverify_tests) + function(add_executable_and_tests exe_name verify_definition) + add_executable(${exe_name} tests.c) + target_link_libraries(${exe_name} secp256k1_precomputed secp256k1_asm) + target_compile_definitions(${exe_name} PRIVATE ${verify_definition} ${TEST_DEFINITIONS}) + add_test(NAME secp256k1_${exe_name} COMMAND ${exe_name}) + endfunction() + + add_executable_and_tests(noverify_tests "") if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage") - add_executable(tests tests.c) - target_compile_definitions(tests PRIVATE VERIFY ${TEST_DEFINITIONS}) - target_link_libraries(tests secp256k1_precomputed secp256k1_asm) - add_test(NAME secp256k1_tests COMMAND tests) + add_executable_and_tests(tests VERIFY) endif() unset(TEST_DEFINITIONS) endif() From f95b263f2366a87c7aa9e7b98882f92d6bb5caec Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 13 Jan 2026 16:19:05 +0000 Subject: [PATCH 257/383] cmake: Add DiscoverTests module Co-authored-by: Daniel Pfeifer --- cmake/DiscoverTests.cmake | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 cmake/DiscoverTests.cmake diff --git a/cmake/DiscoverTests.cmake b/cmake/DiscoverTests.cmake new file mode 100644 index 00000000..683780a8 --- /dev/null +++ b/cmake/DiscoverTests.cmake @@ -0,0 +1,71 @@ +# TODO: rework/remove once test discovery is implemented upstream: +# https://gitlab.kitware.com/cmake/cmake/-/issues/26920 +function(discover_tests target) + set(options "") + set(oneValueArgs DISCOVERY_MATCH TEST_NAME_REPLACEMENT TEST_ARGS_REPLACEMENT) + set(multiValueArgs DISCOVERY_ARGS PROPERTIES) + cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${oneValueArgs}" "${multiValueArgs}") + + set(file_base ${CMAKE_CURRENT_BINARY_DIR}/${target}) + set(include_file ${file_base}_include.cmake) + + set(properties_content) + list(LENGTH arg_PROPERTIES properties_len) + if(properties_len GREATER "0") + set(properties_content " set_tests_properties(\"\${test_name}\" PROPERTIES\n") + math(EXPR num_properties "${properties_len} / 2") + foreach(i RANGE 0 ${num_properties} 2) + math(EXPR value_index "${i} + 1") + list(GET arg_PROPERTIES ${i} name) + list(GET arg_PROPERTIES ${value_index} value) + string(APPEND properties_content " \"${name}\" \"${value}\"\n") + endforeach() + string(APPEND properties_content " )\n") + endif() + + string(CONCAT include_content + "set(runner [[$]])\n" + "set(launcher [[$]])\n" + "set(emulator [[$<$:$>]])\n" + "\n" + "execute_process(\n" + " COMMAND \${launcher} \${emulator} \${runner} ${arg_DISCOVERY_ARGS}\n" + " OUTPUT_VARIABLE output OUTPUT_STRIP_TRAILING_WHITESPACE\n" + " ERROR_VARIABLE output ERROR_STRIP_TRAILING_WHITESPACE\n" + " RESULT_VARIABLE result\n" + ")\n" + "\n" + "if(NOT result EQUAL 0)\n" + " add_test([[${target}_DISCOVERY_FAILURE]] \${launcher} \${emulator} \${runner} ${arg_DISCOVERY_ARGS})\n" + "else()\n" + " string(REPLACE \"\\n\" \";\" lines \"\${output}\")\n" + " foreach(line IN LISTS lines)\n" + " if(line MATCHES \"${arg_DISCOVERY_MATCH}\")\n" + " string(REGEX REPLACE \"${arg_DISCOVERY_MATCH}\" \"${arg_TEST_NAME_REPLACEMENT}\" test_name \"\${line}\")\n" + " string(REGEX REPLACE \"${arg_DISCOVERY_MATCH}\" \"${arg_TEST_ARGS_REPLACEMENT}\" test_args \"\${line}\")\n" + " separate_arguments(test_args)\n" + " add_test(\"\${test_name}\" \${launcher} \${emulator} \${runner} \${test_args})\n" + ${properties_content} + " endif()\n" + " endforeach()\n" + "endif()\n" + ) + + get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + file(GENERATE + OUTPUT ${file_base}_include-$.cmake + CONTENT "${include_content}" + ) + file(WRITE ${include_file} + "include(\"${file_base}_include-\${CTEST_CONFIGURATION_TYPE}.cmake\")" + ) + else() + file(GENERATE + OUTPUT ${include_file} + CONTENT "${include_content}" + ) + endif() + + set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES ${include_file}) +endfunction() From 29ac4d8491b326ffaeb8e43d152a2d09049b9af3 Mon Sep 17 00:00:00 2001 From: Justsomebuddy Date: Wed, 14 Jan 2026 11:26:00 +0000 Subject: [PATCH 258/383] sage: verify Eisenstein integer connection for GLV constants Add assertions to verify that the GLV decomposition constants arise from the Eisenstein integer factorization of the group order N. The group order factors as N = pi * conj(pi) in Z[w], where pi = A - B*w is an Eisenstein prime. The GLV eigenvalue LAMBDA = B/A mod N, which is the image of w^2 under the isomorphism Z[w]/(pi) -> Z/NZ. --- sage/gen_split_lambda_constants.sage | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sage/gen_split_lambda_constants.sage b/sage/gen_split_lambda_constants.sage index 7d4359e0..7a5761ac 100644 --- a/sage/gen_split_lambda_constants.sage +++ b/sage/gen_split_lambda_constants.sage @@ -81,6 +81,15 @@ assert (A1 + A2)/2 < sqrt(N) assert B1 < sqrt(N) assert B2 < sqrt(N) +# Verify connection to Eisenstein integers Z[w] where w = (-1 + sqrt(-3))/2. +# The group order N factors as N = pi * conj(pi) in Z[w], where pi = A - B*w +# is an Eisenstein prime with norm A^2 + A*B + B^2. The GLV endomorphism +# eigenvalue LAMBDA equals B/A mod N, which is the image of w^2 under the +# isomorphism Z[w]/(pi) -> Z/NZ (since w -> A/B and (A/B)^2 = B/A in Z/NZ). +A_EIS, B_EIS = -B1, A1 +assert A_EIS**2 + A_EIS*B_EIS + B_EIS**2 == N +assert Z(B_EIS / A_EIS) == LAMBDA + G1 = round((2**384)*B2/N) G2 = round((2**384)*(-B1)/N) From 29f26ec3cfb5abf9a9ac3106c11aeb24e573fc24 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:53:17 +0000 Subject: [PATCH 259/383] cmake: Integrate DiscoverTests and normalize test names Updates the build system to use the new DiscoverTests module. This also standardizes test names to use dot-separated parts for consistency. --- examples/CMakeLists.txt | 3 +-- src/CMakeLists.txt | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c9da9de6..86172f88 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,8 +8,7 @@ function(add_example name) secp256k1 $<$:bcrypt> ) - set(test_name ${name}_example) - add_test(NAME secp256k1_${test_name} COMMAND ${target_name}) + add_test(NAME secp256k1.example.${name} COMMAND ${target_name}) endfunction() add_example(ecdsa) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 10f96c30..6186369d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -148,7 +148,13 @@ if(SECP256K1_BUILD_TESTS) add_executable(${exe_name} tests.c) target_link_libraries(${exe_name} secp256k1_precomputed secp256k1_asm) target_compile_definitions(${exe_name} PRIVATE ${verify_definition} ${TEST_DEFINITIONS}) - add_test(NAME secp256k1_${exe_name} COMMAND ${exe_name}) + include(DiscoverTests) + discover_tests(${exe_name} + DISCOVERY_ARGS "--list_tests" + DISCOVERY_MATCH "^\\t\\\\[ *[0-9]+\\\\] ([^ ].*)$" + TEST_NAME_REPLACEMENT "secp256k1.${exe_name}.\\\\1" + TEST_ARGS_REPLACEMENT "--target=\\\\1 --log=1" + ) endfunction() add_executable_and_tests(noverify_tests "") @@ -163,7 +169,7 @@ if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) add_executable(exhaustive_tests tests_exhaustive.c) target_link_libraries(exhaustive_tests secp256k1_asm) target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) - add_test(NAME secp256k1_exhaustive_tests COMMAND exhaustive_tests) + add_test(NAME secp256k1.exhaustive_tests COMMAND exhaustive_tests) endif() if(SECP256K1_BUILD_CTIME_TESTS) From 8354618e02bcccf3893bcf0ec99639b6e520509f Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 13 Jan 2026 17:26:47 +0000 Subject: [PATCH 260/383] cmake: Set `LABELS` property for tests --- examples/CMakeLists.txt | 3 +++ src/CMakeLists.txt | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 86172f88..808917c4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -9,6 +9,9 @@ function(add_example name) $<$:bcrypt> ) add_test(NAME secp256k1.example.${name} COMMAND ${target_name}) + set_tests_properties(secp256k1.example.${name} PROPERTIES + LABELS secp256k1_example + ) endfunction() add_example(ecdsa) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6186369d..f80573ca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,8 @@ if(SECP256K1_BUILD_TESTS) DISCOVERY_MATCH "^\\t\\\\[ *[0-9]+\\\\] ([^ ].*)$" TEST_NAME_REPLACEMENT "secp256k1.${exe_name}.\\\\1" TEST_ARGS_REPLACEMENT "--target=\\\\1 --log=1" + PROPERTIES + LABELS "secp256k1_${exe_name}" ) endfunction() @@ -170,6 +172,9 @@ if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) target_link_libraries(exhaustive_tests secp256k1_asm) target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) add_test(NAME secp256k1.exhaustive_tests COMMAND exhaustive_tests) + set_tests_properties(secp256k1.exhaustive_tests PROPERTIES + LABELS secp256k1_exhaustive + ) endif() if(SECP256K1_BUILD_CTIME_TESTS) From db8750de466aba8c141f5a960e6a91362a260c22 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Thu, 22 Jan 2026 09:09:27 +0000 Subject: [PATCH 261/383] sync-upstream: improve help text --- contrib/sync-upstream.sh | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index b910a599..26a842c0 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -3,18 +3,30 @@ set -eou pipefail help() { - echo "$0 [-b ] range [end]" - echo " merges every merge commit present in upstream and missing in (default: master)." - echo " If the optional [end] commit is provided, only merges up to [end]." - echo " If the optional [-b branch] provided, then ." + echo "Sync merge commits from bitcoin-core/secp256k1 into secp256k1-zkp." echo - echo "$0 [-b ] select ... " - echo " merges every selected merge commit into (default: master)" + echo "Usage:" + echo " $0 [-b ] range [end]" + echo " Merges every merge commit present in upstream/master and missing in " + echo " (default: master). If the optional [end] commit is provided, only merges" + echo " up to and including [end]." echo - echo "This tool creates a branch and a script that can be executed to create the" - echo "PR automatically. The script requires the github-cli tool (aka gh)." - echo "" - echo "Tip: \`git log --oneline upstream/master --merges\` shows merge commits." + echo " $0 [-b ] select ... " + echo " Merges every selected merge commit into (default: master)." + echo + echo "This tool creates a temporary branch and attempts to merge the upstream commits." + echo "If there are merge conflicts, resolve them and run tests, then use the generated" + echo "script contrib/gh-pr-create.sh to create the PR (requires the gh tool)." + echo + echo "Setup:" + echo " Requires a remote named 'upstream' pointing to bitcoin-core/secp256k1." + echo " The script will fetch it automatically, and offer to create it if missing." + echo " To add manually: git remote add upstream git@github.com:bitcoin-core/secp256k1.git" + echo + echo "Listing upstream merge commits:" + echo " To list merge commits in upstream/master that are missing from (oldest first):" + echo " git log --oneline --merges \$(git merge-base upstream/master )..upstream/master | tac" + echo " Use these for [end] in 'range' or as arguments to 'select'." exit 1 } From 1bc74a22f87dd7c3da706095a06765db1bbfc7c1 Mon Sep 17 00:00:00 2001 From: 8144225309 Date: Thu, 22 Jan 2026 10:28:30 -0500 Subject: [PATCH 262/383] test: show both Autotools and CMake usage for ctime_tests The existing message only shows the libtool command, which is specific to Autotools builds. Fixes #1697 --- src/ctime_tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ctime_tests.c b/src/ctime_tests.c index f81bdb92..f80042a8 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -49,7 +49,7 @@ int main(void) { if (!SECP256K1_CHECKMEM_RUNNING()) { fprintf(stderr, "This test can only usefully be run inside valgrind because it was not compiled under msan.\n"); - fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n"); + fprintf(stderr, "Usage: valgrind ./ctime_tests (or with Autotools: libtool --mode=execute valgrind ./ctime_tests)\n"); return EXIT_FAILURE; } ctx = secp256k1_context_create(SECP256K1_CONTEXT_DECLASSIFY); From c09215f7af9db3e34427ff9a5633e7978acabca1 Mon Sep 17 00:00:00 2001 From: kevkevinpal Date: Thu, 8 Jan 2026 12:15:33 -0500 Subject: [PATCH 263/383] bench: fail early if user inputs invalid value for SECP256K1_BENCH_ITERS In this change the get_iters function was updated to print an error message and then return 0. In the functions that use get_iters they print the help text and then EXIT_FAILURE --- src/bench.c | 9 +++++++-- src/bench.h | 8 +++++++- src/bench_ecmult.c | 4 ++++ src/bench_internal.c | 6 +++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/bench.c b/src/bench.c index 04685d93..a5231b71 100644 --- a/src/bench.c +++ b/src/bench.c @@ -177,8 +177,6 @@ int main(int argc, char** argv) { bench_data data; int d = argc == 1; - int default_iters = 20000; - int iters = get_iters(default_iters); /* Check for invalid user arguments */ char* valid_args[] = {"ecdsa", "verify", "ecdsa_verify", "sign", "ecdsa_sign", "ecdh", "recover", @@ -188,6 +186,13 @@ int main(int argc, char** argv) { size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]); int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size); + int default_iters = 20000; + int iters = get_iters(default_iters); + if (iters == 0) { + help(default_iters); + return EXIT_FAILURE; + } + if (argc > 1) { if (have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") diff --git a/src/bench.h b/src/bench.h index 4e8e961b..72a3f211 100644 --- a/src/bench.h +++ b/src/bench.h @@ -150,7 +150,13 @@ static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) static int get_iters(int default_iters) { char* env = getenv("SECP256K1_BENCH_ITERS"); if (env) { - return strtol(env, NULL, 0); + char* endptr; + long int iters = strtol(env, &endptr, 0); + if (*endptr != '\0' || iters <= 0) { + printf("Error: Value of SECP256K1_BENCH_ITERS is not a positive integer: %s\n\n", env); + return 0; + } + return iters; } else { return default_iters; } diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index e8fab149..bcf8b431 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -313,6 +313,10 @@ int main(int argc, char **argv) { int default_iters = 10000; int iters = get_iters(default_iters); + if (iters == 0) { + help(argv, default_iters); + return EXIT_FAILURE; + } data.ecmult_multi = secp256k1_ecmult_multi_var; diff --git a/src/bench_internal.c b/src/bench_internal.c index 8688a4dc..001bd25e 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -385,9 +385,13 @@ static void bench_context(void* arg, int iters) { int main(int argc, char **argv) { bench_inv data; + int d = argc == 1; /* default */ int default_iters = 20000; int iters = get_iters(default_iters); - int d = argc == 1; /* default */ + if (iters == 0) { + help(default_iters); + return EXIT_FAILURE; + } if (argc > 1) { if (have_flag(argc, argv, "-h") From c4b6a81a6062492eb23c428afc978d45b20d36e8 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Jan 2026 16:26:39 +0000 Subject: [PATCH 264/383] changelog: update in preparation for the v0.7.1 release --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53c787b3..92ad9236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +#### Changed + - Tests: Introduced a unit test framework with support for parallel test execution, selective test running, and named command-line arguments. Run `./tests -help` for usage information. + +#### Fixed + - Increased the number of cases where the library attempts to clear secrets from the stack. + - build: Fixed x86_64 assembly feature check that could fail when user-provided `CFLAGS` included `-Werror`. This would cause the build to fall back to the slower C implementation instead of using the optimized x86_64 assembly. + ## [0.7.0] - 2025-07-21 #### Added From 20a209f11c0b688dae97ad5d2a515d00022d7799 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Jan 2026 16:39:20 +0000 Subject: [PATCH 265/383] release: prepare for 0.7.1 --- CHANGELOG.md | 7 +++++-- configure.ac | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92ad9236..29d23a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.7.1] - 2026-01-26 #### Changed - Tests: Introduced a unit test framework with support for parallel test execution, selective test running, and named command-line arguments. Run `./tests -help` for usage information. @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Increased the number of cases where the library attempts to clear secrets from the stack. - build: Fixed x86_64 assembly feature check that could fail when user-provided `CFLAGS` included `-Werror`. This would cause the build to fall back to the slower C implementation instead of using the optimized x86_64 assembly. +#### ABI Compatibility +The ABI is backward compatible with version 0.7.0. + ## [0.7.0] - 2025-07-21 #### Added @@ -194,7 +197,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. -[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...HEAD +[0.7.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.0...v0.5.1 diff --git a/configure.ac b/configure.ac index 6028ee28..97ea2259 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ AC_PREREQ([2.60]) define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 7) define(_PKG_VERSION_PATCH, 1) -define(_PKG_VERSION_IS_RELEASE, false) +define(_PKG_VERSION_IS_RELEASE, true) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: From ae7eb729c0450fcb5c79117e04ee92694a5a5e77 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 26 Jan 2026 19:18:39 +0000 Subject: [PATCH 266/383] release cleanup: bump version after 0.7.1 --- CHANGELOG.md | 3 +++ CMakeLists.txt | 4 ++-- configure.ac | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29d23a96..d4beb9c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + ## [0.7.1] - 2026-01-26 #### Changed @@ -197,6 +199,7 @@ This version was in fact never released. The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6). Therefore, this version number does not uniquely identify a set of source files. +[Unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.1...HEAD [0.7.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.5.1...v0.6.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 11dc3f6e..01b14b53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(libsecp256k1 # The package (a.k.a. release) version is based on semantic versioning 2.0.0 of # the API. All changes in experimental modules are treated as # backwards-compatible and therefore at most increase the minor version. - VERSION 0.7.1 + VERSION 0.7.2 DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1." HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1" LANGUAGES C @@ -22,7 +22,7 @@ list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. set(${PROJECT_NAME}_LIB_VERSION_CURRENT 6) -set(${PROJECT_NAME}_LIB_VERSION_REVISION 1) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 2) set(${PROJECT_NAME}_LIB_VERSION_AGE 0) #============================= diff --git a/configure.ac b/configure.ac index 97ea2259..d7465612 100644 --- a/configure.ac +++ b/configure.ac @@ -5,8 +5,8 @@ AC_PREREQ([2.60]) # backwards-compatible and therefore at most increase the minor version. define(_PKG_VERSION_MAJOR, 0) define(_PKG_VERSION_MINOR, 7) -define(_PKG_VERSION_PATCH, 1) -define(_PKG_VERSION_IS_RELEASE, true) +define(_PKG_VERSION_PATCH, 2) +define(_PKG_VERSION_IS_RELEASE, false) # The library version is based on libtool versioning of the ABI. The set of # rules for updating the version can be found here: @@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true) # All changes in experimental modules are treated as if they don't affect the # interface and therefore only increase the revision. define(_LIB_VERSION_CURRENT, 6) -define(_LIB_VERSION_REVISION, 1) +define(_LIB_VERSION_REVISION, 2) define(_LIB_VERSION_AGE, 0) AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1]) From f9cf003d9b3c58e26de4ba6ed3d7f7d9b3e36328 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 26 Jan 2026 14:30:31 +0200 Subject: [PATCH 267/383] scalar: Port bitcoin-core/secp256k1#1512 to zkp-specific code --- src/scalar_4x64_impl.h | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index 7ef726f7..11622b0f 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -882,7 +882,7 @@ static void secp256k1_scalar_mul_512(uint64_t *l8, const secp256k1_scalar *a, co #endif } -static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { +static void secp256k1_scalar_sqr_512(uint64_t *l8, const secp256k1_scalar *a) { #ifdef USE_ASM_X86_64 __asm__ __volatile__( /* Preload */ @@ -893,7 +893,7 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { /* (rax,rdx) = a0 * a0 */ "movq %%r11, %%rax\n" "mulq %%r11\n" - /* Extract l0 */ + /* Extract l8[0] */ "movq %%rax, 0(%%rsi)\n" /* (r8,r9,r10) = (rdx,0) */ "movq %%rdx, %%r8\n" @@ -908,7 +908,7 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" - /* Extract l1 */ + /* Extract l8[1] */ "movq %%r8, 8(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += 2 * a0 * a2 */ @@ -926,7 +926,7 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" - /* Extract l2 */ + /* Extract l8[2] */ "movq %%r9, 16(%%rsi)\n" "xorq %%r9, %%r9\n" /* (r10,r8,r9) += 2 * a0 * a3 */ @@ -947,7 +947,7 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" "adcq $0, %%r9\n" - /* Extract l3 */ + /* Extract l8[3] */ "movq %%r10, 24(%%rsi)\n" "xorq %%r10, %%r10\n" /* (r8,r9,r10) += 2 * a1 * a3 */ @@ -965,7 +965,7 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { "addq %%rax, %%r8\n" "adcq %%rdx, %%r9\n" "adcq $0, %%r10\n" - /* Extract l4 */ + /* Extract l8[4] */ "movq %%r8, 32(%%rsi)\n" "xorq %%r8, %%r8\n" /* (r9,r10,r8) += 2 * a2 * a3 */ @@ -977,45 +977,48 @@ static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { "addq %%rax, %%r9\n" "adcq %%rdx, %%r10\n" "adcq $0, %%r8\n" - /* Extract l5 */ + /* Extract l8[5] */ "movq %%r9, 40(%%rsi)\n" /* (r10,r8) += a3 * a3 */ "movq %%r14, %%rax\n" "mulq %%r14\n" "addq %%rax, %%r10\n" "adcq %%rdx, %%r8\n" - /* Extract l6 */ + /* Extract l8[6] */ "movq %%r10, 48(%%rsi)\n" - /* Extract l7 */ + /* Extract l8[7] */ "movq %%r8, 56(%%rsi)\n" : - : "S"(l), "D"(a->d) + : "S"(l8), "D"(a->d) : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory"); + + SECP256K1_CHECKMEM_MSAN_DEFINE(l8, sizeof(*l8) * 8); + #else /* 160 bit accumulator. */ uint64_t c0 = 0, c1 = 0; uint32_t c2 = 0; - /* l[0..7] = a[0..3] * b[0..3]. */ + /* l8[0..7] = a[0..3] * b[0..3]. */ muladd_fast(a->d[0], a->d[0]); - extract_fast(l[0]); + extract_fast(l8[0]); muladd2(a->d[0], a->d[1]); - extract(l[1]); + extract(l8[1]); muladd2(a->d[0], a->d[2]); muladd(a->d[1], a->d[1]); - extract(l[2]); + extract(l8[2]); muladd2(a->d[0], a->d[3]); muladd2(a->d[1], a->d[2]); - extract(l[3]); + extract(l8[3]); muladd2(a->d[1], a->d[3]); muladd(a->d[2], a->d[2]); - extract(l[4]); + extract(l8[4]); muladd2(a->d[2], a->d[3]); - extract(l[5]); + extract(l8[5]); muladd_fast(a->d[3], a->d[3]); - extract_fast(l[6]); + extract_fast(l8[6]); VERIFY_CHECK(c1 == 0); - l[7] = c0; + l8[7] = c0; #endif } From 0267b6551268deafdf22d1bdcf171ece181df88e Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Fri, 30 Jan 2026 14:32:36 +0000 Subject: [PATCH 268/383] release process: mention the `[Unreleased]` link clearly Adding this link was forgotten in the first version of the 0.7.1 release PR but caught in PR review. --- doc/release-process.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release-process.md b/doc/release-process.md index a64bae0f..3cf183df 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -61,7 +61,7 @@ Perform these checks when reviewing the release PR (see below): 4. Open a PR to the master branch with a commit (using message `"release cleanup: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that * sets `_PKG_VERSION_IS_RELEASE` to `false` and increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac`, * increments the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt`, and - * adds an `[Unreleased]` section header to the [CHANGELOG.md](../CHANGELOG.md). + * adds an `[Unreleased]` section header and a corresponding `[Unreleased]` link at the bottom of [CHANGELOG.md](../CHANGELOG.md). If other maintainers are not present to approve the PR, it can be merged without ACKs. 5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). From 0ffb1749a5811bb63902f00c9fa73b49588d0557 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 1 Feb 2026 18:51:16 +0000 Subject: [PATCH 269/383] ci, docker: Fix LLVM repository signature failure The LLVM apt repository uses legacy SHA1 signatures which are now rejected by the stricter Sequoia PGP policy. This change extends the 'sha1.second_preimage_resistance' cutoff date to 9999-01-01 in the default Sequoia config. This effectively whitelists the legacy signature algorithm, preventing "OpenPGP signature verification failed" errors during `apt-get update`. See https://github.com/llvm/llvm-project/issues/153385. --- ci/linux-debian.Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index a575d9b1..a862f1b1 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -67,6 +67,9 @@ RUN \ wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ # Add repository for this Debian release . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ + # Temporarily work around Sequoia PGP policy deadline for legacy repositories. + # See https://github.com/llvm/llvm-project/issues/153385. + sed -i 's/\(sha1\.second_preimage_resistance =\).*/\1 9999-01-01/' /usr/share/apt/default-sequoia.config && \ apt-get update && \ # Determine the version number of the LLVM development branch LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ From 2f18567d2494a3dddbec62ab414bd5784d2be3f8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:17:18 +0000 Subject: [PATCH 270/383] ci: Rotate Docker cache keys every 4 weeks This forces a periodic clean build to ensure we do not rely on stale cache layers indefinitely. --- .github/actions/run-in-docker-action/action.yml | 3 +-- .github/workflows/ci.yml | 12 ++++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index 5d46ca1b..0884d3a4 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -6,8 +6,7 @@ inputs: required: true scope: description: 'A cached image scope' - required: false - default: ${{ runner.arch }} + required: true command: description: 'A command to run in a container' required: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59d22514..3e74f3d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,8 @@ jobs: docker_cache: name: "Build ${{ matrix.arch }} Docker image" runs-on: ${{ matrix.runner }} + outputs: + cache_scope: ${{ steps.cache_timestamp.outputs.period }} strategy: fail-fast: false @@ -59,6 +61,10 @@ jobs: runner: ubuntu-24.04-arm steps: + - name: Get cache validity period + id: cache_timestamp + run: echo "period=$(($(date +%V) / 4))" >> "$GITHUB_OUTPUT" + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: @@ -70,8 +76,8 @@ jobs: uses: docker/build-push-action@v6 with: file: ./ci/linux-debian.Dockerfile - cache-from: type=gha,scope=${{ runner.arch }} - cache-to: type=gha,scope=${{ runner.arch }},mode=min + cache-from: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }} + cache-to: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }},mode=min x86_64-debian: name: "x86_64: Linux (Debian stable)" @@ -117,6 +123,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile + scope: ${{ runner.arch }}-${{ needs.docker_cache.outputs.cache_scope }} command: ./ci/ci.sh - &PRINT_LOGS @@ -636,6 +643,7 @@ jobs: uses: ./.github/actions/run-in-docker-action with: dockerfile: ./ci/linux-debian.Dockerfile + scope: ${{ runner.arch }}-${{ needs.docker_cache.outputs.cache_scope }} command: | g++ -Werror include/*.h clang -Werror -x c++-header include/*.h From 2ccff6eb73665b72cd4b2019a68f90ffcadad18c Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:21:11 +0000 Subject: [PATCH 271/383] ci: Add weekly schedule --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e74f3d0..308035c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: - '**' tags-ignore: - '**' + schedule: + # Run on the default branch every Monday morning. + # This also warms the Docker caches after key rotation. + - cron: '22 2 * * 1' concurrency: group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }} From 13e3bee5048fe9115e607f1065af3c82a22192ac Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:10:47 +0000 Subject: [PATCH 272/383] refactor: Remove trailing whitespace --- include/secp256k1.h | 2 +- src/bench.h | 2 +- src/field.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 2799d4a1..9de45f1f 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -349,7 +349,7 @@ SECP256K1_API void secp256k1_context_destroy( * writes the message to stderr and calls abort. This default callback can be * replaced at link time if the preprocessor macro * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build - * has been configured with --enable-external-default-callbacks (GNU Autotools) or + * has been configured with --enable-external-default-callbacks (GNU Autotools) or * -DSECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS=ON (CMake). Then the * following two symbols must be provided to link against: * - void secp256k1_default_illegal_callback_fn(const char *message, void *data); diff --git a/src/bench.h b/src/bench.h index 72a3f211..f88277aa 100644 --- a/src/bench.h +++ b/src/bench.h @@ -59,7 +59,7 @@ static void print_number(const int64_t x) { y /= 10; } } else if (c == 0) { /* fractional part is 0 */ - buffer[--ptr] = '0'; + buffer[--ptr] = '0'; } buffer[--ptr] = '.'; do { diff --git a/src/field.h b/src/field.h index e3f0234f..945029ec 100644 --- a/src/field.h +++ b/src/field.h @@ -233,7 +233,7 @@ static void secp256k1_fe_add_int(secp256k1_fe *r, int a); #define secp256k1_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, secp256k1_fe_mul_int_unchecked(r, a)) /** Like secp256k1_fe_mul_int but a is not checked to be an integer constant expression. - * + * * Should not be called directly outside of tests. */ static void secp256k1_fe_mul_int_unchecked(secp256k1_fe *r, int a); From fb229e7602e47de1df23141838c0596a4b64aeca Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:40:41 +0000 Subject: [PATCH 273/383] build: Add `-Wtrailing-whitespace=any` compiler flag --- CMakeLists.txt | 1 + configure.ac | 1 + src/checkmem.h | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 01b14b53..4953a4b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,6 +224,7 @@ else() try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only. try_append_c_flags(-Wshadow) try_append_c_flags(-Wstrict-prototypes) + try_append_c_flags(-Wtrailing-whitespace=any) # GCC >= 15.0 try_append_c_flags(-Wundef) endif() diff --git a/configure.ac b/configure.ac index 6efb4aab..e68af3ca 100644 --- a/configure.ac +++ b/configure.ac @@ -111,6 +111,7 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [ SECP_TRY_APPEND_CFLAGS([-Wcast-align=strict], $1) # GCC >= 8.0 SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only SECP_TRY_APPEND_CFLAGS([-Wreserved-identifier], $1) # Clang >= 13.0 only + SECP_TRY_APPEND_CFLAGS([-Wtrailing-whitespace=any], $1) # GCC >= 15.0 CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS" fi diff --git a/src/checkmem.h b/src/checkmem.h index 08eae47d..88c65c8e 100644 --- a/src/checkmem.h +++ b/src/checkmem.h @@ -78,10 +78,15 @@ # if defined(__clang__) && defined(__APPLE__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wreserved-identifier" +# elif defined(__GNUC__) && (__GNUC__ >= 15) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wtrailing-whitespace" # endif # include # if defined(__clang__) && defined(__APPLE__) # pragma clang diagnostic pop +# elif defined(__GNUC__) && (__GNUC__ >= 15) +# pragma GCC diagnostic pop # endif # define SECP256K1_CHECKMEM_ENABLED 1 # define SECP256K1_CHECKMEM_UNDEFINE(p, len) VALGRIND_MAKE_MEM_UNDEFINED((p), (len)) From 86cae58d2f342f8a3b49dd70dca8989cb271c504 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Thu, 29 Jan 2026 12:43:40 +0000 Subject: [PATCH 274/383] build: Add `-Wleading-whitespace=spaces` compiler flag --- CMakeLists.txt | 1 + configure.ac | 1 + 2 files changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4953a4b4..4ef69c08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,6 +217,7 @@ else() try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0. try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only. try_append_c_flags(-Wextra) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions. + try_append_c_flags(-Wleading-whitespace=spaces) # GCC >= 15.0 try_append_c_flags(-Wnested-externs) try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic. try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic. diff --git a/configure.ac b/configure.ac index e68af3ca..a21447ce 100644 --- a/configure.ac +++ b/configure.ac @@ -112,6 +112,7 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [ SECP_TRY_APPEND_CFLAGS([-Wconditional-uninitialized], $1) # Clang >= 3.0 only SECP_TRY_APPEND_CFLAGS([-Wreserved-identifier], $1) # Clang >= 13.0 only SECP_TRY_APPEND_CFLAGS([-Wtrailing-whitespace=any], $1) # GCC >= 15.0 + SECP_TRY_APPEND_CFLAGS([-Wleading-whitespace=spaces], $1) # GCC >= 15.0 CFLAGS="$SECP_TRY_APPEND_DEFAULT_CFLAGS_saved_CFLAGS" fi From 97b3c47849a7d124506a6208e1583ab74270188b Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 30 Jan 2026 15:58:30 +0100 Subject: [PATCH 275/383] refactor: remove unnecessary `malloc` result casts It seems that there is no good reason to do this and it's even considered bad practice, see e.g. https://stackoverflow.com/a/605858 This commit touches mostly test code, the only two functions used in production are `secp256k1_context_{create,clone}`. Instances were found manually via `$ git grep "malloc("` --- src/modules/schnorrsig/bench_impl.h | 16 ++++++++-------- src/secp256k1.c | 4 ++-- src/tests.c | 14 +++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/modules/schnorrsig/bench_impl.h b/src/modules/schnorrsig/bench_impl.h index 93a878ed..069464d0 100644 --- a/src/modules/schnorrsig/bench_impl.h +++ b/src/modules/schnorrsig/bench_impl.h @@ -51,18 +51,18 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) { int d = argc == 1; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - data.keypairs = (const secp256k1_keypair **)malloc(iters * sizeof(secp256k1_keypair *)); - data.pk = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - data.msgs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); - data.sigs = (const unsigned char **)malloc(iters * sizeof(unsigned char *)); + data.keypairs = malloc(iters * sizeof(secp256k1_keypair *)); + data.pk = malloc(iters * sizeof(unsigned char *)); + data.msgs = malloc(iters * sizeof(unsigned char *)); + data.sigs = malloc(iters * sizeof(unsigned char *)); CHECK(MSGLEN >= 4); for (i = 0; i < iters; i++) { unsigned char sk[32]; - unsigned char *msg = (unsigned char *)malloc(MSGLEN); - unsigned char *sig = (unsigned char *)malloc(64); - secp256k1_keypair *keypair = (secp256k1_keypair *)malloc(sizeof(*keypair)); - unsigned char *pk_char = (unsigned char *)malloc(32); + unsigned char *msg = malloc(MSGLEN); + unsigned char *sig = malloc(64); + secp256k1_keypair *keypair = malloc(sizeof(*keypair)); + unsigned char *pk_char = malloc(32); secp256k1_xonly_pubkey pk; msg[0] = sk[0] = i; msg[1] = sk[1] = i >> 8; diff --git a/src/secp256k1.c b/src/secp256k1.c index ddd98495..218ceafb 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -140,7 +140,7 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne secp256k1_context* secp256k1_context_create(unsigned int flags) { size_t const prealloc_size = secp256k1_context_preallocated_size(flags); - secp256k1_context* ctx = (secp256k1_context*)checked_malloc(&default_error_callback, prealloc_size); + secp256k1_context* ctx = checked_malloc(&default_error_callback, prealloc_size); if (EXPECT(secp256k1_context_preallocated_create(ctx, flags) == NULL, 0)) { free(ctx); return NULL; @@ -168,7 +168,7 @@ secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { ARG_CHECK(secp256k1_context_is_proper(ctx)); prealloc_size = secp256k1_context_preallocated_clone_size(ctx); - ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, prealloc_size); + ret = checked_malloc(&ctx->error_callback, prealloc_size); ret = secp256k1_context_preallocated_clone(ctx, ret); return ret; } diff --git a/src/tests.c b/src/tests.c index e09f5c7d..23f1dc09 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3676,8 +3676,8 @@ static void test_ge(void) { * negation, and then those two again but with randomized Z coordinate. * - The same is then done for lambda*p1 and lambda^2*p1. */ - secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_ge *ge = checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = checked_malloc(&CTX->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); secp256k1_fe zf, r; secp256k1_fe zfi2, zfi3; @@ -3811,7 +3811,7 @@ static void test_ge(void) { /* Test adding all points together in random order equals infinity. */ { secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); + secp256k1_gej *gej_shuffled = checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } @@ -3832,8 +3832,8 @@ static void test_ge(void) { /* Test batch gej -> ge conversion without known z ratios. */ { - secp256k1_ge *ge_set_all_var = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all_var = checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); secp256k1_ge_set_all_gej_var(&ge_set_all_var[0], &gej[0], 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { secp256k1_fe s; @@ -5175,8 +5175,8 @@ static void test_ecmult_multi_batch_size_helper(void) { static void test_ecmult_multi_batching(void) { static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; secp256k1_scalar scG; - secp256k1_scalar *sc = (secp256k1_scalar *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_scalar) * n_points); - secp256k1_ge *pt = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * n_points); + secp256k1_scalar *sc = checked_malloc(&CTX->error_callback, sizeof(secp256k1_scalar) * n_points); + secp256k1_ge *pt = checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * n_points); secp256k1_gej r; secp256k1_gej r2; ecmult_multi_data data; From 3ae72e78677eae2acc75eb0dd2b98fc59a825b29 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 3 Feb 2026 08:51:11 +0000 Subject: [PATCH 276/383] ci: Disable Docker build summary generation These summaries provide little practical value to the development workflow and clutter the CI output. --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 308035c6..432bb89a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,9 @@ env: SYMBOL_CHECK: 'yes' # Compile and run the examples. EXAMPLES: 'yes' + # Disable Docker build summary generation. + # See https://github.com/docker/build-push-action/blob/master/README.md#environment-variables. + DOCKER_BUILD_SUMMARY: false jobs: docker_cache: From 4fb7ccf5d41c6ae3f69eeee9807457e2186ae0d2 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:24:14 +0000 Subject: [PATCH 277/383] ci: Enforce base-10 evaluation --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 308035c6..78c9b94e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: steps: - name: Get cache validity period id: cache_timestamp - run: echo "period=$(($(date +%V) / 4))" >> "$GITHUB_OUTPUT" + run: echo "period=$((10#$(date +%V) / 4))" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From f47bbc07f0a1979a9e363898c5191811f9d8def5 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 4 Feb 2026 17:35:09 +0530 Subject: [PATCH 278/383] test: add unit tests for secp256k1_scalar_check_overflow --- src/tests.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/tests.c b/src/tests.c index e09f5c7d..b2e43eda 100644 --- a/src/tests.c +++ b/src/tests.c @@ -2193,8 +2193,58 @@ static void run_scalar_set_b32_seckey_tests(void) { CHECK(secp256k1_scalar_set_b32_seckey(&s2, b32) == 0); } +static void test_scalar_check_overflow(void) { + secp256k1_scalar s; + const secp256k1_scalar n_minus_1 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364140UL + ); + const secp256k1_scalar n = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL + ); + const secp256k1_scalar n_plus_1 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364142UL + ); + const secp256k1_scalar max = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL + ); + + int i; + + secp256k1_scalar_set_int(&s, 0); + CHECK(secp256k1_scalar_check_overflow(&s) == 0); + CHECK(secp256k1_scalar_check_overflow(&n_minus_1) == 0); + CHECK(secp256k1_scalar_check_overflow(&n) == 1); + CHECK(secp256k1_scalar_check_overflow(&n_plus_1) == 1); + CHECK(secp256k1_scalar_check_overflow(&max) == 1); + + for (i = 0; i < 2 * COUNT; i++) { + int expected_overflow; + int overflow = 0; + unsigned char b32[32]; + + testrand256(b32); + + /* Force top bits to be 0xFF sometimes to ensure we hit overflows */ + if (i % 2 == 0) { + memset(b32, 0xFF, 16); + } + + expected_overflow = (secp256k1_memcmp_var(b32, secp256k1_group_order_bytes, 32) >= 0); + + secp256k1_scalar_set_b32(&s, b32, &overflow); + CHECK(overflow == expected_overflow); + } +} + static void run_scalar_tests(void) { int i; + + test_scalar_check_overflow(); + for (i = 0; i < 128 * COUNT; i++) { scalar_test(); } @@ -2258,15 +2308,6 @@ static void run_scalar_tests(void) { } } - { - /* Does check_overflow check catch all ones? */ - static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, - 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL - ); - CHECK(secp256k1_scalar_check_overflow(&overflowed)); - } - { /* Static test vectors. * These were reduced from ~10^12 random vectors based on comparison-decision From 41cead8a0bb2fdccc93a04973ef6859dad93c150 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Feb 2026 15:50:58 +0100 Subject: [PATCH 279/383] sync-upstream: Extend git usage tips --- contrib/sync-upstream.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index 26a842c0..c1ad8e0a 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -116,7 +116,17 @@ do done # Remove trailing "," TITLE=${TITLE%?} -BODY=$(printf "%s\n\n%s\n%s" "$BODY" "This PR can be recreated with \`$REPRODUCE_COMMAND\`." "Tip: Use \`git show --remerge-diff\` to show the changes manually added to the merge commit.") +BODY+=$(cat <\` to show the conflict resolution in the merge commit. + * Use \`git read-tree --reset -u \` to replay these resolutions during the conflict resolution stage when recreating the PR branch locally. + Be aware that this may discard your index as well as the uncommitted changes and untracked files in your worktree. +EOF +) echo "-----------------------------------" echo "$TITLE" From 96a415b1c0cdd7570c9d1cc80330c124daf557fd Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Thu, 5 Feb 2026 17:29:53 +0200 Subject: [PATCH 280/383] scalar: Port bitcoin-core/secp256k1#1393 to zkp-specific code --- src/scalar_4x64_impl.h | 2 ++ src/scalar_8x32_impl.h | 2 ++ src/scalar_low_impl.h | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index fb8d59e1..e797de0c 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -51,6 +51,8 @@ SECP256K1_INLINE static void secp256k1_scalar_set_u64(secp256k1_scalar *r, uint6 r->d[1] = 0; r->d[2] = 0; r->d[3] = 0; + + SECP256K1_SCALAR_VERIFY(r); } SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index e541f211..4ca85c99 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -73,6 +73,8 @@ SECP256K1_INLINE static void secp256k1_scalar_set_u64(secp256k1_scalar *r, uint6 r->d[5] = 0; r->d[6] = 0; r->d[7] = 0; + + SECP256K1_SCALAR_VERIFY(r); } SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 0e867815..04c4770d 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -30,7 +30,7 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static void secp256k1_scalar_set_u64(secp256k1_scalar *r, uint64_t v) { *r = v % EXHAUSTIVE_TEST_ORDER; - secp256k1_scalar_verify(r); + SECP256K1_SCALAR_VERIFY(r); } SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { From 2cb2e312e9e2e29725b449afd732b8b73074fffe Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Thu, 5 Feb 2026 19:02:49 +0200 Subject: [PATCH 281/383] extrakeys: Migrate to bitcoin-core/secp256k1#1518 secp256k1_ec_pubkey_sort --- include/secp256k1_extrakeys.h | 15 -- include/secp256k1_musig.h | 2 +- src/modules/extrakeys/Makefile.am.include | 4 +- src/modules/extrakeys/hsort.h | 22 --- src/modules/extrakeys/hsort_impl.h | 116 ------------- src/modules/extrakeys/main_impl.h | 35 ---- src/modules/extrakeys/tests_impl.h | 195 ---------------------- 7 files changed, 2 insertions(+), 387 deletions(-) delete mode 100644 src/modules/extrakeys/hsort.h delete mode 100644 src/modules/extrakeys/hsort_impl.h diff --git a/include/secp256k1_extrakeys.h b/include/secp256k1_extrakeys.h index 9f091163..ad70b92f 100644 --- a/include/secp256k1_extrakeys.h +++ b/include/secp256k1_extrakeys.h @@ -240,21 +240,6 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Sort public keys using lexicographic order of their compressed - * serialization. - * - * Returns: 0 if the arguments are invalid. 1 otherwise. - * - * Args: ctx: pointer to a context object - * In: pubkeys: array of pointers to pubkeys to sort - * n_pubkeys: number of elements in the pubkeys array - */ -SECP256K1_API int secp256k1_pubkey_sort( - const secp256k1_context *ctx, - const secp256k1_pubkey **pubkeys, - size_t n_pubkeys -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); - #ifdef __cplusplus } #endif diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index 28ecf1ef..0c539e8a 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -186,7 +186,7 @@ SECP256K1_API int secp256k1_musig_partial_sig_parse( * * Different orders of `pubkeys` result in different `agg_pk`s. * - * Before aggregating, the pubkeys can be sorted with `secp256k1_pubkey_sort` + * Before aggregating, the pubkeys can be sorted with `secp256k1_ec_pubkey_sort` * which ensures the same `agg_pk` result for the same multiset of pubkeys. * This is useful to do before `pubkey_agg`, such that the order of pubkeys * does not affect the aggregate public key. diff --git a/src/modules/extrakeys/Makefile.am.include b/src/modules/extrakeys/Makefile.am.include index fe496fd2..622d8bb4 100644 --- a/src/modules/extrakeys/Makefile.am.include +++ b/src/modules/extrakeys/Makefile.am.include @@ -1,6 +1,4 @@ include_HEADERS += include/secp256k1_extrakeys.h noinst_HEADERS += src/modules/extrakeys/tests_impl.h noinst_HEADERS += src/modules/extrakeys/tests_exhaustive_impl.h -noinst_HEADERS += src/modules/extrakeys/main_impl.h -noinst_HEADERS += src/modules/extrakeys/hsort.h -noinst_HEADERS += src/modules/extrakeys/hsort_impl.h +noinst_HEADERS += src/modules/extrakeys/main_impl.h \ No newline at end of file diff --git a/src/modules/extrakeys/hsort.h b/src/modules/extrakeys/hsort.h deleted file mode 100644 index 5352ef1e..00000000 --- a/src/modules/extrakeys/hsort.h +++ /dev/null @@ -1,22 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Russell O'Connor, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_HSORT_H -#define SECP256K1_HSORT_H - -#include -#include - -/* In-place, iterative heapsort with an interface matching glibc's qsort_r. This - * is preferred over standard library implementations because they generally - * make no guarantee about being fast for malicious inputs. - * - * See the qsort_r manpage for a description of the interface. - */ -static void secp256k1_hsort(void *ptr, size_t count, size_t size, - int (*cmp)(const void *, const void *, void *), - void *cmp_data); -#endif diff --git a/src/modules/extrakeys/hsort_impl.h b/src/modules/extrakeys/hsort_impl.h deleted file mode 100644 index e05aefdf..00000000 --- a/src/modules/extrakeys/hsort_impl.h +++ /dev/null @@ -1,116 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Russell O'Connor, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_HSORT_IMPL_H -#define SECP256K1_HSORT_IMPL_H - -#include "hsort.h" - -/* An array is a heap when, for all non-zero indexes i, the element at index i - * compares as less than or equal to the element at index parent(i) = (i-1)/2. - */ - -static SECP256K1_INLINE size_t child1(size_t i) { - VERIFY_CHECK(i <= (SIZE_MAX - 1)/2); - return 2*i + 1; -} - -static SECP256K1_INLINE size_t child2(size_t i) { - VERIFY_CHECK(i <= SIZE_MAX/2 - 1); - return child1(i)+1; -} - -static SECP256K1_INLINE void heap_swap64(unsigned char *a, size_t i, size_t j, size_t stride) { - unsigned char tmp[64]; - VERIFY_CHECK(stride <= 64); - memcpy(tmp, a + i*stride, stride); - memmove(a + i*stride, a + j*stride, stride); - memcpy(a + j*stride, tmp, stride); -} - -static SECP256K1_INLINE void heap_swap(unsigned char *a, size_t i, size_t j, size_t stride) { - while (64 < stride) { - heap_swap64(a + (stride - 64), i, j, 64); - stride -= 64; - } - heap_swap64(a, i, j, stride); -} - -static SECP256K1_INLINE void heap_down(unsigned char *a, size_t i, size_t heap_size, size_t stride, - int (*cmp)(const void *, const void *, void *), void *cmp_data) { - while (i < heap_size/2) { - VERIFY_CHECK(i <= SIZE_MAX/2 - 1); - /* Proof: - * i < heap_size/2 - * i + 1 <= heap_size/2 - * 2*i + 2 <= heap_size <= SIZE_MAX - * 2*i <= SIZE_MAX - 2 - */ - - VERIFY_CHECK(child1(i) < heap_size); - /* Proof: - * i < heap_size/2 - * i + 1 <= heap_size/2 - * 2*i + 2 <= heap_size - * 2*i + 1 < heap_size - * child1(i) < heap_size - */ - - /* Let [x] be notation for the contents at a[x*stride]. - * - * If [child1(i)] > [i] and [child2(i)] > [i], - * swap [i] with the larger child to ensure the new parent is larger - * than both children. When [child1(i)] == [child2(i)], swap [i] with - * [child2(i)]. - * Else if [child1(i)] > [i], swap [i] with [child1(i)]. - * Else if [child2(i)] > [i], swap [i] with [child2(i)]. - */ - if (child2(i) < heap_size - && 0 <= cmp(a + child2(i)*stride, a + child1(i)*stride, cmp_data)) { - if (0 < cmp(a + child2(i)*stride, a + i*stride, cmp_data)) { - heap_swap(a, i, child2(i), stride); - i = child2(i); - } else { - /* At this point we have [child2(i)] >= [child1(i)] and we have - * [child2(i)] <= [i], and thus [child1(i)] <= [i] which means - * that the next comparison can be skipped. */ - return; - } - } else if (0 < cmp(a + child1(i)*stride, a + i*stride, cmp_data)) { - heap_swap(a, i, child1(i), stride); - i = child1(i); - } else { - return; - } - } - /* heap_size/2 <= i - * heap_size/2 < i + 1 - * heap_size < 2*i + 2 - * heap_size <= 2*i + 1 - * heap_size <= child1(i) - * Thus child1(i) and child2(i) are now out of bounds and we are at a leaf. - */ -} - -/* In-place heap sort. */ -static void secp256k1_hsort(void *ptr, size_t count, size_t size, - int (*cmp)(const void *, const void *, void *), - void *cmp_data ) { - size_t i; - - for(i = count/2; 0 < i; --i) { - heap_down(ptr, i-1, count, size, cmp, cmp_data); - } - for(i = count; 1 < i; --i) { - /* Extract the largest value from the heap */ - heap_swap(ptr, 0, i-1, size); - - /* Repair the heap condition */ - heap_down(ptr, 0, i-1, size, cmp, cmp_data); - } -} - -#endif diff --git a/src/modules/extrakeys/main_impl.h b/src/modules/extrakeys/main_impl.h index 2ba41465..0c7e2667 100644 --- a/src/modules/extrakeys/main_impl.h +++ b/src/modules/extrakeys/main_impl.h @@ -9,7 +9,6 @@ #include "../../../include/secp256k1.h" #include "../../../include/secp256k1_extrakeys.h" -#include "hsort_impl.h" #include "../../util.h" static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) { @@ -283,38 +282,4 @@ int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_ke return ret; } -/* This struct wraps a const context pointer to satisfy the secp256k1_hsort api - * which expects a non-const cmp_data pointer. */ -typedef struct { - const secp256k1_context *ctx; -} secp256k1_pubkey_sort_cmp_data; - -static int secp256k1_pubkey_sort_cmp(const void* pk1, const void* pk2, void *cmp_data) { - return secp256k1_ec_pubkey_cmp(((secp256k1_pubkey_sort_cmp_data*)cmp_data)->ctx, - *(secp256k1_pubkey **)pk1, - *(secp256k1_pubkey **)pk2); -} - -int secp256k1_pubkey_sort(const secp256k1_context* ctx, const secp256k1_pubkey **pubkeys, size_t n_pubkeys) { - secp256k1_pubkey_sort_cmp_data cmp_data; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(pubkeys != NULL); - - cmp_data.ctx = ctx; - - /* Suppress wrong warning (fixed in MSVC 19.33) */ - #if defined(_MSC_VER) && (_MSC_VER < 1933) - #pragma warning(push) - #pragma warning(disable: 4090) - #endif - - secp256k1_hsort(pubkeys, n_pubkeys, sizeof(*pubkeys), secp256k1_pubkey_sort_cmp, &cmp_data); - - #if defined(_MSC_VER) && (_MSC_VER < 1933) - #pragma warning(pop) - #endif - - return 1; -} - #endif diff --git a/src/modules/extrakeys/tests_impl.h b/src/modules/extrakeys/tests_impl.h index 1f10ceed..45521d17 100644 --- a/src/modules/extrakeys/tests_impl.h +++ b/src/modules/extrakeys/tests_impl.h @@ -467,196 +467,6 @@ static void test_keypair_add(void) { } } -static void test_hsort_is_sorted(int *ints, size_t n) { - size_t i; - for (i = 1; i < n; i++) { - CHECK(ints[i-1] <= ints[i]); - } -} - -static int test_hsort_cmp(const void *i1, const void *i2, void *counter) { - *(size_t*)counter += 1; - return *(int*)i1 - *(int*)i2; -} - -#define NUM 64 -static void test_hsort(void) { - int ints[NUM] = { 0 }; - size_t counter = 0; - int i, j; - - secp256k1_hsort(ints, 0, sizeof(ints[0]), test_hsort_cmp, &counter); - CHECK(counter == 0); - secp256k1_hsort(ints, 1, sizeof(ints[0]), test_hsort_cmp, &counter); - CHECK(counter == 0); - secp256k1_hsort(ints, NUM, sizeof(ints[0]), test_hsort_cmp, &counter); - CHECK(counter > 0); - test_hsort_is_sorted(ints, NUM); - - /* Test hsort with length n array and random elements in - * [-interval/2, interval/2] */ - for (i = 0; i < COUNT; i++) { - int n = secp256k1_testrand_int(NUM); - int interval = secp256k1_testrand_int(63) + 1; - for (j = 0; j < n; j++) { - ints[j] = secp256k1_testrand_int(interval) - interval/2; - } - secp256k1_hsort(ints, n, sizeof(ints[0]), test_hsort_cmp, &counter); - test_hsort_is_sorted(ints, n); - } -} -#undef NUM - -static void test_sort_helper(secp256k1_pubkey *pk, size_t *pk_order, size_t n_pk) { - size_t i; - const secp256k1_pubkey *pk_test[5]; - - for (i = 0; i < n_pk; i++) { - pk_test[i] = &pk[pk_order[i]]; - } - secp256k1_pubkey_sort(CTX, pk_test, n_pk); - for (i = 0; i < n_pk; i++) { - CHECK(secp256k1_memcmp_var(pk_test[i], &pk[i], sizeof(*pk_test[i])) == 0); - } -} - -static void permute(size_t *arr, size_t n) { - size_t i; - for (i = n - 1; i >= 1; i--) { - size_t tmp, j; - j = secp256k1_testrand_int(i + 1); - tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } -} - -static void rand_pk(secp256k1_pubkey *pk) { - unsigned char seckey[32]; - secp256k1_keypair keypair; - secp256k1_testrand256(seckey); - CHECK(secp256k1_keypair_create(CTX, &keypair, seckey) == 1); - CHECK(secp256k1_keypair_pub(CTX, pk, &keypair) == 1); -} - -static void test_sort_api(void) { - secp256k1_pubkey pks[2]; - const secp256k1_pubkey *pks_ptr[2]; - - pks_ptr[0] = &pks[0]; - pks_ptr[1] = &pks[1]; - - rand_pk(&pks[0]); - rand_pk(&pks[1]); - - CHECK(secp256k1_pubkey_sort(CTX, pks_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_pubkey_sort(CTX, NULL, 2)); - CHECK(secp256k1_pubkey_sort(CTX, pks_ptr, 0) == 1); - /* Test illegal public keys */ - memset(&pks[0], 0, sizeof(pks[0])); - CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_pubkey_sort(CTX, pks_ptr, 2) == 1)); - memset(&pks[1], 0, sizeof(pks[1])); - { - int32_t ecount = 0; - secp256k1_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); - CHECK(secp256k1_pubkey_sort(CTX, pks_ptr, 2) == 1); - CHECK(ecount == 2); - secp256k1_context_set_illegal_callback(CTX, NULL, NULL); - } -} - -static void test_sort(void) { - secp256k1_pubkey pk[5]; - unsigned char pk_ser[5][33] = { - { 0x02, 0x08 }, - { 0x02, 0x0b }, - { 0x02, 0x0c }, - { 0x03, 0x05 }, - { 0x03, 0x0a }, - }; - int i; - size_t pk_order[5] = { 0, 1, 2, 3, 4 }; - - for (i = 0; i < 5; i++) { - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk[i], pk_ser[i], sizeof(pk_ser[i]))); - } - - permute(pk_order, 1); - test_sort_helper(pk, pk_order, 1); - permute(pk_order, 2); - test_sort_helper(pk, pk_order, 2); - permute(pk_order, 3); - test_sort_helper(pk, pk_order, 3); - for (i = 0; i < COUNT; i++) { - permute(pk_order, 4); - test_sort_helper(pk, pk_order, 4); - } - for (i = 0; i < COUNT; i++) { - permute(pk_order, 5); - test_sort_helper(pk, pk_order, 5); - } - /* Check that sorting also works for random pubkeys */ - for (i = 0; i < COUNT; i++) { - int j; - const secp256k1_pubkey *pk_ptr[5]; - for (j = 0; j < 5; j++) { - rand_pk(&pk[j]); - pk_ptr[j] = &pk[j]; - } - secp256k1_pubkey_sort(CTX, pk_ptr, 5); - for (j = 1; j < 5; j++) { - secp256k1_pubkey_sort_cmp_data cmp_data; - cmp_data.ctx = CTX; - CHECK(secp256k1_pubkey_sort_cmp(&pk_ptr[j - 1], &pk_ptr[j], &cmp_data) <= 0); - } - } -} - -/* Test vectors from BIP-MuSig2 */ -static void test_sort_vectors(void) { - enum { N_PUBKEYS = 6 }; - unsigned char pk_ser[N_PUBKEYS][33] = { - { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, - 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, - 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 }, - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, - 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, - 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, - 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, - 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }, - { 0x02, 0x35, 0x90, 0xA9, 0x4E, 0x76, 0x8F, 0x8E, 0x18, 0x15, 0xC2, - 0xF2, 0x4B, 0x4D, 0x80, 0xA8, 0xE3, 0x14, 0x93, 0x16, 0xC3, 0x51, - 0x8C, 0xE7, 0xB7, 0xAD, 0x33, 0x83, 0x68, 0xD0, 0x38, 0xCA, 0x66 }, - { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, - 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, - 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xFF }, - { 0x02, 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, - 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, - 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 } - }; - secp256k1_pubkey pubkeys[N_PUBKEYS]; - secp256k1_pubkey *sorted[N_PUBKEYS]; - const secp256k1_pubkey *pks_ptr[N_PUBKEYS]; - int i; - - sorted[0] = &pubkeys[3]; - sorted[1] = &pubkeys[0]; - sorted[2] = &pubkeys[0]; - sorted[3] = &pubkeys[4]; - sorted[4] = &pubkeys[1]; - sorted[5] = &pubkeys[2]; - - for (i = 0; i < N_PUBKEYS; i++) { - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkeys[i], pk_ser[i], sizeof(pk_ser[i]))); - pks_ptr[i] = &pubkeys[i]; - } - CHECK(secp256k1_pubkey_sort(CTX, pks_ptr, N_PUBKEYS) == 1); - for (i = 0; i < N_PUBKEYS; i++) { - CHECK(secp256k1_memcmp_var(pks_ptr[i], sorted[i], sizeof(secp256k1_pubkey)) == 0); - } -} - static void run_extrakeys_tests(void) { /* xonly key test cases */ test_xonly_pubkey(); @@ -668,11 +478,6 @@ static void run_extrakeys_tests(void) { /* keypair tests */ test_keypair(); test_keypair_add(); - - test_hsort(); - test_sort_api(); - test_sort(); - test_sort_vectors(); } #endif From 040673bd44de8b98be3abf682e6e19ba6db33e8e Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 1 Feb 2026 18:51:16 +0000 Subject: [PATCH 282/383] ci, docker: Fix LLVM repository signature failure The LLVM apt repository uses legacy SHA1 signatures which are now rejected by the stricter Sequoia PGP policy. This change extends the 'sha1.second_preimage_resistance' cutoff date to 9999-01-01 in the default Sequoia config. This effectively whitelists the legacy signature algorithm, preventing "OpenPGP signature verification failed" errors during `apt-get update`. See https://github.com/llvm/llvm-project/issues/153385. --- ci/linux-debian.Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index 5ce715b4..aa50951b 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -66,6 +66,9 @@ RUN \ wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ # Add repository for this Debian release . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ + # Temporarily work around Sequoia PGP policy deadline for legacy repositories. + # See https://github.com/llvm/llvm-project/issues/153385. + sed -i 's/\(sha1\.second_preimage_resistance =\).*/\1 9999-01-01/' /usr/share/apt/default-sequoia.config && \ apt-get update && \ # Determine the version number of the LLVM development branch LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ From 91b2deab7bd7365dc7901fd4d850bcb10fe90ca2 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 6 Feb 2026 14:37:11 +0200 Subject: [PATCH 283/383] ci: Add zkp modules to arm64-macos-native job --- .github/workflows/ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17e82601..f2b38101 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -755,13 +755,13 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', SCHNORRSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', MUSIG: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' } - BUILD: 'distcheck' steps: From c49c9be5045cfade519446d6fd707b2c36e18387 Mon Sep 17 00:00:00 2001 From: kevkevinpal Date: Fri, 23 Jan 2026 18:27:35 +0000 Subject: [PATCH 284/383] bench: Update help functions in bench and bench_internal In the bench and bench_internal help functions argv was not being passed, in this change we pass in argv[0] and use it in the help text. Additionally instead of passing all of argv in bench_ecmult we now just pass argv[0] and is used as the executable_path variable. --- src/bench.c | 10 +++++----- src/bench_ecmult.c | 10 +++++----- src/bench_internal.c | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/bench.c b/src/bench.c index a5231b71..de7fef94 100644 --- a/src/bench.c +++ b/src/bench.c @@ -12,7 +12,7 @@ #include "util.h" #include "bench.h" -static void help(int default_iters) { +static void help(const char *executable_path, int default_iters) { printf("Benchmarks the following algorithms:\n"); printf(" - ECDSA signing/verification\n"); @@ -36,7 +36,7 @@ static void help(int default_iters) { printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); printf("\n"); - printf("Usage: ./bench [args]\n"); + printf("Usage: %s [args]\n", executable_path); printf("By default, all benchmarks will be run.\n"); printf("args:\n"); printf(" help : display this help and exit\n"); @@ -189,7 +189,7 @@ int main(int argc, char** argv) { int default_iters = 20000; int iters = get_iters(default_iters); if (iters == 0) { - help(default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } @@ -197,11 +197,11 @@ int main(int argc, char** argv) { if (have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(default_iters); + help(argv[0], default_iters); return EXIT_SUCCESS; } else if (invalid_args) { fprintf(stderr, "./bench: unrecognized argument.\n\n"); - help(default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } } diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index bcf8b431..7393730d 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -19,13 +19,13 @@ #define POINTS 32768 -static void help(char **argv, int default_iters) { +static void help(const char *executable_path, int default_iters) { printf("Benchmark EC multiplication algorithms\n"); printf("\n"); printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); printf("\n"); - printf("Usage: %s \n", argv[0]); + printf("Usage: %s [args]\n", executable_path); printf("The output shows the number of multiplied and summed points right after the\n"); printf("function name. The letter 'g' indicates that one of the points is the generator.\n"); printf("The benchmarks are divided by the number of points.\n"); @@ -314,7 +314,7 @@ int main(int argc, char **argv) { int default_iters = 10000; int iters = get_iters(default_iters); if (iters == 0) { - help(argv, default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } @@ -324,7 +324,7 @@ int main(int argc, char **argv) { if(have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(argv, default_iters); + help(argv[0], default_iters); return EXIT_SUCCESS; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); @@ -336,7 +336,7 @@ int main(int argc, char **argv) { printf("Using simple algorithm:\n"); } else { fprintf(stderr, "%s: unrecognized argument '%s'.\n\n", argv[0], argv[1]); - help(argv, default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } } diff --git a/src/bench_internal.c b/src/bench_internal.c index 001bd25e..fe16e93a 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -18,13 +18,13 @@ #include "ecmult_impl.h" #include "bench.h" -static void help(int default_iters) { +static void help(const char *executable_path, int default_iters) { printf("Benchmarks various internal routines.\n"); printf("\n"); printf("The default number of iterations for each benchmark is %d. This can be\n", default_iters); printf("customized using the SECP256K1_BENCH_ITERS environment variable.\n"); printf("\n"); - printf("Usage: ./bench_internal [args]\n"); + printf("Usage: %s [args]\n", executable_path); printf("By default, all benchmarks will be run.\n"); printf("args:\n"); printf(" help : display this help and exit\n"); @@ -389,7 +389,7 @@ int main(int argc, char **argv) { int default_iters = 20000; int iters = get_iters(default_iters); if (iters == 0) { - help(default_iters); + help(argv[0], default_iters); return EXIT_FAILURE; } @@ -397,7 +397,7 @@ int main(int argc, char **argv) { if (have_flag(argc, argv, "-h") || have_flag(argc, argv, "--help") || have_flag(argc, argv, "help")) { - help(default_iters); + help(argv[0], default_iters); return EXIT_SUCCESS; } } From 21c24fdc7aef67af6f83ae92226aef5084c3c6f3 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 13 Feb 2026 11:36:52 +0200 Subject: [PATCH 285/383] musig: Remove module in preparation for upstream merge --- .gitignore | 3 - CMakeLists.txt | 10 - Makefile.am | 15 - README.md | 8 +- ci/ci.sh | 4 +- configure.ac | 18 - contrib/musig2-vectors.py | 656 -------------- doc/musig-spec.mediawiki | 1 - examples/musig.c | 214 ----- include/secp256k1_musig.h | 609 ------------- src/CMakeLists.txt | 3 - src/ctime_tests.c | 72 -- src/modules/musig/Makefile.am.include | 8 - src/modules/musig/adaptor_impl.h | 101 --- src/modules/musig/keyagg.h | 40 - src/modules/musig/keyagg_impl.h | 311 ------- src/modules/musig/main_impl.h | 14 - src/modules/musig/musig.md | 63 -- src/modules/musig/session.h | 25 - src/modules/musig/session_impl.h | 705 --------------- src/modules/musig/tests_impl.h | 1193 ------------------------- src/modules/musig/vectors.h | 346 ------- src/secp256k1.c | 4 - src/tests.c | 8 - 24 files changed, 5 insertions(+), 4426 deletions(-) delete mode 100755 contrib/musig2-vectors.py delete mode 100644 doc/musig-spec.mediawiki delete mode 100644 examples/musig.c delete mode 100644 include/secp256k1_musig.h delete mode 100644 src/modules/musig/Makefile.am.include delete mode 100644 src/modules/musig/adaptor_impl.h delete mode 100644 src/modules/musig/keyagg.h delete mode 100644 src/modules/musig/keyagg_impl.h delete mode 100644 src/modules/musig/main_impl.h delete mode 100644 src/modules/musig/musig.md delete mode 100644 src/modules/musig/session.h delete mode 100644 src/modules/musig/session_impl.h delete mode 100644 src/modules/musig/tests_impl.h delete mode 100644 src/modules/musig/vectors.h diff --git a/.gitignore b/.gitignore index 82bdcf81..e24dcda4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ bench_internal bench_whitelist noverify_tests tests -example_musig exhaustive_tests precompute_ecmult_gen precompute_ecmult @@ -66,8 +65,6 @@ build-aux/test-driver libsecp256k1.pc contrib/gh-pr-create.sh -musig_example - ### CMake /CMakeUserPresets.json # Default CMake build directory. diff --git a/CMakeLists.txt b/CMakeLists.txt index 44e8b0e8..76a9e09e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,6 @@ option(SECP256K1_ENABLE_MODULE_GENERATOR "Enable NUMS generator module." ON) option(SECP256K1_ENABLE_MODULE_RANGEPROOF "Enable Range proof module." ON) option(SECP256K1_ENABLE_MODULE_SURJECTIONPROOF "Enable Surjection proof module." ON) option(SECP256K1_ENABLE_MODULE_WHITELIST "Enable key whitelist module." ON) -option(SECP256K1_ENABLE_MODULE_MUSIG "Enable MuSig module." ON) option(SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR "Enable ecdsa adaptor signatures module." ON) option(SECP256K1_ENABLE_MODULE_ECDSA_S2C "Enable ECDSA sign-to-contract module." ON) option(SECP256K1_ENABLE_MODULE_BPPP "Enable Bulletproofs++ module." ON) @@ -89,14 +88,6 @@ if(SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR) add_compile_definitions(ENABLE_MODULE_ECDSA_ADAPTOR=1) endif() -if(SECP256K1_ENABLE_MODULE_MUSIG) - if(DEFINED SECP256K1_ENABLE_MODULE_SCHNORRSIG AND NOT SECP256K1_ENABLE_MODULE_SCHNORRSIG) - message(FATAL_ERROR "Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.") - endif() - set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) - add_compile_definitions(ENABLE_MODULE_MUSIG=1) -endif() - if(SECP256K1_ENABLE_MODULE_WHITELIST) if(DEFINED SECP256K1_ENABLE_MODULE_RANGEPROOF AND NOT SECP256K1_ENABLE_MODULE_RANGEPROOF) message(FATAL_ERROR "Module dependency error: You have disabled the rangeproof module explicitly, but it is required by the whitelist module.") @@ -374,7 +365,6 @@ message(" generator ........................... ${SECP256K1_ENABLE_MODULE_GENER message(" rangeproof .......................... ${SECP256K1_ENABLE_MODULE_RANGEPROOF}") message(" surjectionproof ..................... ${SECP256K1_ENABLE_MODULE_SURJECTIONPROOF}") message(" whitelist ........................... ${SECP256K1_ENABLE_MODULE_WHITELIST}") -message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}") message(" ecdsa-s2c ........................... ${SECP256K1_ENABLE_MODULE_ECDSA_S2C}") message(" ecdsa-adaptor ....................... ${SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR}") message(" bppp ................................ ${SECP256K1_ENABLE_MODULE_BPPP}") diff --git a/Makefile.am b/Makefile.am index 04bc4c51..e142c9a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -197,17 +197,6 @@ ellswift_example_LDFLAGS += -lbcrypt endif TESTS += ellswift_example endif -if ENABLE_MODULE_MUSIG -noinst_PROGRAMS += musig_example -musig_example_SOURCES = examples/musig.c -musig_example_CPPFLAGS = -I$(top_srcdir)/include -DSECP256K1_STATIC -musig_example_LDADD = libsecp256k1.la -musig_example_LDFLAGS = -static -if BUILD_WINDOWS -musig_example_LDFLAGS += -lbcrypt -endif -TESTS += musig_example -endif endif ### Precomputed tables @@ -290,10 +279,6 @@ if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include endif -if ENABLE_MODULE_MUSIG -include src/modules/musig/Makefile.am.include -endif - if ENABLE_MODULE_RECOVERY include src/modules/recovery/Makefile.am.include endif diff --git a/README.md b/README.md index eddd67a7..488044b4 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,11 @@ libsecp256k1-zkp ![Dependencies: None](https://img.shields.io/badge/dependencies-none-success) -A fork of [libsecp256k1](https://github.com/bitcoin-core/secp256k1) with support for advanced and experimental features such as Confidential Assets and MuSig2 +A fork of [libsecp256k1](https://github.com/bitcoin-core/secp256k1) with support for advanced and experimental features such as Confidential Assets and Bulletproofs++ range proofs Added features: * Experimental module for ECDSA adaptor signatures. * Experimental module for ECDSA sign-to-contract. -* Experimental module for [MuSig2](src/modules/musig/musig.md). * Experimental module for Confidential Assets (Pedersen commitments, range proofs, and [surjection proofs](src/modules/surjection/surjection.md)). * Experimental module for Bulletproofs++ range proofs. * Experimental module for [address whitelisting](src/modules/whitelist/whitelist.md). @@ -27,7 +26,7 @@ Building with Autotools $ make check # run the test suite $ sudo make install # optional -To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. For experimental modules, you will also need `--enable-experimental` as well as a flag for each individual module, e.g. `--enable-module-musig`. +To compile optional modules (such as Schnorr signatures), you need to run `./configure` with additional flags (such as `--enable-module-schnorrsig`). Run `./configure --help` to see the full list of available flags. For experimental modules, you will also need `--enable-experimental` as well as a flag for each individual module, e.g. `--enable-module-rangeproof`. Building with CMake (experimental) ---------------------------------- @@ -74,9 +73,8 @@ Usage examples can be found in the [examples](examples) directory. To compile th * [Schnorr signatures example](examples/schnorr.c) * [Deriving a shared secret (ECDH) example](examples/ecdh.c) * [ElligatorSwift key exchange example](examples/ellswift.c) - * [MuSig example](examples/musig.c) -To compile the Schnorr signature, ECDH and MuSig examples, you need to enable the corresponding module by providing a flag to the `configure` script, for example `--enable-module-schnorrsig`. +To compile the Schnorr signature and ECDH examples, you need to enable the corresponding module by providing a flag to the `configure` script, for example `--enable-module-schnorrsig`. Benchmark ------------ diff --git a/ci/ci.sh b/ci/ci.sh index 828ff4b6..7c786bfe 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -14,7 +14,7 @@ print_environment() { for var in WERROR_CFLAGS MAKEFLAGS BUILD \ ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ EXPERIMENTAL ECDH RECOVERY EXTRAKEYS SCHNORRSIG SCHNORRSIG_HALFAGG ELLSWIFT \ - ECDSA_S2C GENERATOR RANGEPROOF WHITELIST MUSIG ECDSAADAPTOR BPPP \ + ECDSA_S2C GENERATOR RANGEPROOF WHITELIST ECDSAADAPTOR BPPP \ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS\ EXAMPLES \ HOST WRAPPER_CMD \ @@ -82,7 +82,7 @@ esac --enable-module-ecdsa-s2c="$ECDSA_S2C" \ --enable-module-bppp="$BPPP" \ --enable-module-rangeproof="$RANGEPROOF" --enable-module-whitelist="$WHITELIST" --enable-module-generator="$GENERATOR" \ - --enable-module-schnorrsig="$SCHNORRSIG" --enable-module-musig="$MUSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \ + --enable-module-schnorrsig="$SCHNORRSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \ --enable-module-schnorrsig="$SCHNORRSIG" \ --enable-module-schnorrsig-halfagg="$SCHNORRSIG_HALFAGG" \ --enable-examples="$EXAMPLES" \ diff --git a/configure.ac b/configure.ac index e0007537..37e36760 100644 --- a/configure.ac +++ b/configure.ac @@ -216,11 +216,6 @@ AC_ARG_ENABLE(module_whitelist, [], [SECP_SET_DEFAULT([enable_module_whitelist], [no], [yes])]) -AC_ARG_ENABLE(module_musig, - AS_HELP_STRING([--enable-module-musig],[enable MuSig module (experimental)]), - [], - [SECP_SET_DEFAULT([enable_module_musig], [no], [yes])]) - AC_ARG_ENABLE(module_ecdsa_s2c, AS_HELP_STRING([--enable-module-ecdsa-s2c],[enable ECDSA sign-to-contract module [default=no]]), [], @@ -475,14 +470,6 @@ if test x"$enable_module_ecdsa_adaptor" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ECDSA_ADAPTOR=1" fi -if test x"$enable_module_musig" = x"yes"; then - if test x"$enable_module_schnorrsig" = x"no"; then - AC_MSG_ERROR([Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the musig module.]) - fi - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_MUSIG=1" - enable_module_schnorrsig=yes -fi - if test x"$enable_module_whitelist" = x"yes"; then if test x"$enable_module_rangeproof" = x"no"; then AC_MSG_ERROR([Module dependency error: You have disabled the rangeproof module explicitly, but it is required by the whitelist module.]) @@ -564,9 +551,6 @@ if test x"$enable_experimental" = x"no"; then if test x"$enable_module_ecdsa_s2c" = x"yes"; then AC_MSG_ERROR([ECDSA sign-to-contract module module is experimental. Use --enable-experimental to allow.]) fi - if test x"$enable_module_musig" = x"yes"; then - AC_MSG_ERROR([MuSig module is experimental. Use --enable-experimental to allow.]) - fi if test x"$enable_module_whitelist" = x"yes"; then AC_MSG_ERROR([Key whitelisting module is experimental. Use --enable-experimental to allow.]) fi @@ -606,7 +590,6 @@ AM_CONDITIONAL([ENABLE_MODULE_GENERATOR], [test x"$enable_module_generator" = x" AM_CONDITIONAL([ENABLE_MODULE_RANGEPROOF], [test x"$enable_module_rangeproof" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_SURJECTIONPROOF], [test x"$enable_module_surjectionproof" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_WHITELIST], [test x"$enable_module_whitelist" = x"yes"]) -AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ECDSA_S2C], [test x"$enable_module_ecdsa_s2c" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_ECDSA_ADAPTOR], [test x"$enable_module_ecdsa_adaptor" = x"yes"]) AM_CONDITIONAL([ENABLE_MODULE_BPPP], [test x"$enable_module_bppp" = x"yes"]) @@ -646,7 +629,6 @@ if test x"$enable_module_surjectionproof" = x"yes" && test x"$enable_reduced_sur echo " reduced proof size = $enable_reduced_surjection_proof_size" fi echo " module whitelist = $enable_module_whitelist" -echo " module musig = $enable_module_musig" echo " module ecdsa-s2c = $enable_module_ecdsa_s2c" echo " module ecdsa-adaptor = $enable_module_ecdsa_adaptor" echo " module bppp = $enable_module_bppp" diff --git a/contrib/musig2-vectors.py b/contrib/musig2-vectors.py deleted file mode 100755 index 97424419..00000000 --- a/contrib/musig2-vectors.py +++ /dev/null @@ -1,656 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import json -import textwrap - -max_pubkeys = 0 - -if len(sys.argv) < 2: - print( - "This script converts BIP MuSig2 test vectors in a given directory to a C file that can be used in the test framework." - ) - print("Usage: %s " % sys.argv[0]) - sys.exit(1) - - -def hexstr_to_intarray(str): - return ", ".join([f"0x{b:02X}" for b in bytes.fromhex(str)]) - - -def create_init(name): - return """ -static const struct musig_%s_vector musig_%s_vector = { -""" % ( - name, - name, - ) - - -def init_array(key): - return textwrap.indent("{ %s },\n" % hexstr_to_intarray(data[key]), 4 * " ") - - -def init_arrays(key): - s = textwrap.indent("{\n", 4 * " ") - s += textwrap.indent( - ",\n".join(["{ %s }" % hexstr_to_intarray(x) for x in data[key]]), 8 * " " - ) - s += textwrap.indent("\n},\n", 4 * " ") - return s - - -def init_indices(array): - return " %d, { %s }" % ( - len(array), - ", ".join(map(str, array) if len(array) > 0 else "0"), - ) - - -def init_is_xonly(case): - if len(case["tweak_indices"]) > 0: - return ", ".join(map(lambda x: "1" if x else "0", case["is_xonly"])) - return "0" - - -def init_optional_expected(case): - return hexstr_to_intarray(case["expected"]) if "expected" in case else 0 - - -def init_cases(cases, f): - s = textwrap.indent("{\n", 4 * " ") - for (i, case) in enumerate(cases): - s += textwrap.indent("%s\n" % f(case), 8 * " ") - s += textwrap.indent("},\n", 4 * " ") - return s - - -def finish_init(): - return "};\n" - - -s = ( - """/** - * Automatically generated by %s. - * - * The test vectors for the KeySort function are included in this file. They can - * be found in src/modules/extrakeys/tests_impl.h. */ -""" - % sys.argv[0] -) - - -s += """ -enum MUSIG_ERROR { - MUSIG_PUBKEY, - MUSIG_TWEAK, - MUSIG_PUBNONCE, - MUSIG_AGGNONCE, - MUSIG_SECNONCE, - MUSIG_SIG, - MUSIG_SIG_VERIFY, - MUSIG_OTHER -}; -""" - -# key agg vectors -with open(sys.argv[1] + "/key_agg_vectors.json", "r") as f: - data = json.load(f) - - max_key_indices = max( - len(test_case["key_indices"]) for test_case in data["valid_test_cases"] - ) - max_tweak_indices = max( - len(test_case["tweak_indices"]) for test_case in data["error_test_cases"] - ) - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_tweaks = len(data["tweaks"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - # Add structures for valid and error cases - s += ( - """ -struct musig_key_agg_valid_test_case { - size_t key_indices_len; - size_t key_indices[%d]; - unsigned char expected[32]; -}; -""" - % max_key_indices - ) - s += """ -struct musig_key_agg_error_test_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t tweak_indices_len; - size_t tweak_indices[%d]; - int is_xonly[%d]; - enum MUSIG_ERROR error; -}; -""" % ( - max_key_indices, - max_tweak_indices, - max_tweak_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_key_agg_vector { - unsigned char pubkeys[%d][33]; - unsigned char tweaks[%d][32]; - struct musig_key_agg_valid_test_case valid_case[%d]; - struct musig_key_agg_error_test_case error_case[%d]; -}; -""" % ( - num_pubkeys, - num_tweaks, - num_valid_cases, - num_error_cases, - ) - - s += create_init("key_agg") - # Add pubkeys and tweaks to the vector - s += init_arrays("pubkeys") - s += init_arrays("tweaks") - - # Add valid cases to the vector - s += init_cases( - data["valid_test_cases"], - lambda case: "{ %s, { %s }}," - % (init_indices(case["key_indices"]), hexstr_to_intarray(case["expected"])), - ) - - def comment_to_error(case): - comment = case["comment"] - if "public key" in comment.lower(): - return "MUSIG_PUBKEY" - elif "tweak" in comment.lower(): - return "MUSIG_TWEAK" - else: - sys.exit("Unknown error") - - # Add error cases to the vector - s += init_cases( - data["error_test_cases"], - lambda case: "{ %s, %s, { %s }, %s }," - % ( - init_indices(case["key_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - comment_to_error(case), - ), - ) - - s += finish_init() - -# nonce gen vectors -with open(sys.argv[1] + "/nonce_gen_vectors.json", "r") as f: - data = json.load(f) - - # The MuSig2 implementation only allows messages of length 32 - data["test_cases"] = list( - filter(lambda c: c["msg"] is None or len(c["msg"]) == 64, data["test_cases"]) - ) - - num_tests = len(data["test_cases"]) - - s += """ -struct musig_nonce_gen_test_case { - unsigned char rand_[32]; - int has_sk; - unsigned char sk[32]; - unsigned char pk[33]; - int has_aggpk; - unsigned char aggpk[32]; - int has_msg; - unsigned char msg[32]; - int has_extra_in; - unsigned char extra_in[32]; - unsigned char expected_secnonce[97]; - unsigned char expected_pubnonce[66]; -}; -""" - - s += ( - """ -struct musig_nonce_gen_vector { - struct musig_nonce_gen_test_case test_case[%d]; -}; -""" - % num_tests - ) - - s += create_init("nonce_gen") - - def init_array_maybe(array): - return "%d , { %s }" % ( - 0 if array is None else 1, - hexstr_to_intarray(array) if array is not None else 0, - ) - - s += init_cases( - data["test_cases"], - lambda case: "{ { %s }, %s, { %s }, %s, %s, %s, { %s }, { %s } }," - % ( - hexstr_to_intarray(case["rand_"]), - init_array_maybe(case["sk"]), - hexstr_to_intarray(case["pk"]), - init_array_maybe(case["aggpk"]), - init_array_maybe(case["msg"]), - init_array_maybe(case["extra_in"]), - hexstr_to_intarray(case["expected_secnonce"]), - hexstr_to_intarray(case["expected_pubnonce"]), - ), - ) - - s += finish_init() - -# nonce agg vectors -with open(sys.argv[1] + "/nonce_agg_vectors.json", "r") as f: - data = json.load(f) - - num_pnonces = len(data["pnonces"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - pnonce_indices_len = 2 - for case in data["valid_test_cases"] + data["error_test_cases"]: - assert len(case["pnonce_indices"]) == pnonce_indices_len - - # Add structures for valid and error cases - s += """ -struct musig_nonce_agg_test_case { - size_t pnonce_indices[2]; - /* if valid case */ - unsigned char expected[66]; - /* if error case */ - int invalid_nonce_idx; -}; -""" - # Add structure for entire vector - s += """ -struct musig_nonce_agg_vector { - unsigned char pnonces[%d][66]; - struct musig_nonce_agg_test_case valid_case[%d]; - struct musig_nonce_agg_test_case error_case[%d]; -}; -""" % ( - num_pnonces, - num_valid_cases, - num_error_cases, - ) - - s += create_init("nonce_agg") - s += init_arrays("pnonces") - - for cases in (data["valid_test_cases"], data["error_test_cases"]): - s += init_cases( - cases, - lambda case: "{ { %s }, { %s }, %d }," - % ( - ", ".join(map(str, case["pnonce_indices"])), - init_optional_expected(case), - case["error"]["signer"] if "error" in case else 0, - ), - ) - s += finish_init() - -# sign/verify vectors -with open(sys.argv[1] + "/sign_verify_vectors.json", "r") as f: - data = json.load(f) - - # The MuSig2 implementation only allows messages of length 32 - assert list(filter(lambda x: len(x) == 64, data["msgs"]))[0] == data["msgs"][0] - data["msgs"] = [data["msgs"][0]] - - def filter_msg32(k): - return list(filter(lambda x: x["msg_index"] == 0, data[k])) - - data["valid_test_cases"] = filter_msg32("valid_test_cases") - data["sign_error_test_cases"] = filter_msg32("sign_error_test_cases") - data["verify_error_test_cases"] = filter_msg32("verify_error_test_cases") - data["verify_fail_test_cases"] = filter_msg32("verify_fail_test_cases") - - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_secnonces = len(data["secnonces"]) - num_pubnonces = len(data["pnonces"]) - num_aggnonces = len(data["aggnonces"]) - num_msgs = len(data["msgs"]) - num_valid_cases = len(data["valid_test_cases"]) - num_sign_error_cases = len(data["sign_error_test_cases"]) - num_verify_fail_cases = len(data["verify_fail_test_cases"]) - num_verify_error_cases = len(data["verify_error_test_cases"]) - - all_cases = ( - data["valid_test_cases"] - + data["sign_error_test_cases"] - + data["verify_error_test_cases"] - + data["verify_fail_test_cases"] - ) - max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) - max_nonce_indices = max( - len(test_case["nonce_indices"]) if "nonce_indices" in test_case else 0 - for test_case in all_cases - ) - # Add structures for valid and error cases - s += ( - """ -/* Omit pubnonces in the test vectors because our partial signature verification - * implementation is able to accept the aggnonce directly. */ -struct musig_valid_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t aggnonce_index; - size_t msg_index; - size_t signer_index; - unsigned char expected[32]; -}; -""" - % max_key_indices - ) - - s += ( - """ -struct musig_sign_error_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t aggnonce_index; - size_t msg_index; - size_t secnonce_index; - enum MUSIG_ERROR error; -}; -""" - % max_key_indices - ) - - s += """ -struct musig_verify_fail_error_case { - unsigned char sig[32]; - size_t key_indices_len; - size_t key_indices[%d]; - size_t nonce_indices_len; - size_t nonce_indices[%d]; - size_t msg_index; - size_t signer_index; - enum MUSIG_ERROR error; -}; -""" % ( - max_key_indices, - max_nonce_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_sign_verify_vector { - unsigned char sk[32]; - unsigned char pubkeys[%d][33]; - unsigned char secnonces[%d][194]; - unsigned char pubnonces[%d][194]; - unsigned char aggnonces[%d][66]; - unsigned char msgs[%d][32]; - struct musig_valid_case valid_case[%d]; - struct musig_sign_error_case sign_error_case[%d]; - struct musig_verify_fail_error_case verify_fail_case[%d]; - struct musig_verify_fail_error_case verify_error_case[%d]; -}; -""" % ( - num_pubkeys, - num_secnonces, - num_pubnonces, - num_aggnonces, - num_msgs, - num_valid_cases, - num_sign_error_cases, - num_verify_fail_cases, - num_verify_error_cases, - ) - - s += create_init("sign_verify") - s += init_array("sk") - s += init_arrays("pubkeys") - s += init_arrays("secnonces") - s += init_arrays("pnonces") - s += init_arrays("aggnonces") - s += init_arrays("msgs") - - s += init_cases( - data["valid_test_cases"], - lambda case: "{ %s, %d, %d, %d, { %s }}," - % ( - init_indices(case["key_indices"]), - case["aggnonce_index"], - case["msg_index"], - case["signer_index"], - init_optional_expected(case), - ), - ) - - def sign_error(case): - comment = case["comment"] - if "pubkey" in comment or "public key" in comment: - return "MUSIG_PUBKEY" - elif "Aggregate nonce" in comment: - return "MUSIG_AGGNONCE" - elif "Secnonce" in comment: - return "MUSIG_SECNONCE" - else: - sys.exit("Unknown sign error") - - s += init_cases( - data["sign_error_test_cases"], - lambda case: "{ %s, %d, %d, %d, %s }," - % ( - init_indices(case["key_indices"]), - case["aggnonce_index"], - case["msg_index"], - case["secnonce_index"], - sign_error(case), - ), - ) - - def verify_error(case): - comment = case["comment"] - if "exceeds" in comment: - return "MUSIG_SIG" - elif "Wrong signer" in comment or "Wrong signature" in comment: - return "MUSIG_SIG_VERIFY" - elif "pubnonce" in comment: - return "MUSIG_PUBNONCE" - elif "pubkey" in comment: - return "MUSIG_PUBKEY" - else: - sys.exit("Unknown verify error") - - for cases in ("verify_fail_test_cases", "verify_error_test_cases"): - s += init_cases( - data[cases], - lambda case: "{ { %s }, %s, %s, %d, %d, %s }," - % ( - hexstr_to_intarray(case["sig"]), - init_indices(case["key_indices"]), - init_indices(case["nonce_indices"]), - case["msg_index"], - case["signer_index"], - verify_error(case), - ), - ) - - s += finish_init() - -# tweak vectors -with open(sys.argv[1] + "/tweak_vectors.json", "r") as f: - data = json.load(f) - - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_pubnonces = len(data["pnonces"]) - num_tweaks = len(data["tweaks"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - all_cases = data["valid_test_cases"] + data["error_test_cases"] - max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) - max_tweak_indices = max(len(test_case["tweak_indices"]) for test_case in all_cases) - max_nonce_indices = max(len(test_case["nonce_indices"]) for test_case in all_cases) - # Add structures for valid and error cases - s += """ -struct musig_tweak_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t nonce_indices_len; - size_t nonce_indices[%d]; - size_t tweak_indices_len; - size_t tweak_indices[%d]; - int is_xonly[%d]; - size_t signer_index; - unsigned char expected[32]; -}; -""" % ( - max_key_indices, - max_nonce_indices, - max_tweak_indices, - max_tweak_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_tweak_vector { - unsigned char sk[32]; - unsigned char secnonce[97]; - unsigned char aggnonce[66]; - unsigned char msg[32]; - unsigned char pubkeys[%d][33]; - unsigned char pubnonces[%d][194]; - unsigned char tweaks[%d][32]; - struct musig_tweak_case valid_case[%d]; - struct musig_tweak_case error_case[%d]; -}; -""" % ( - num_pubkeys, - num_pubnonces, - num_tweaks, - num_valid_cases, - num_error_cases, - ) - s += create_init("tweak") - s += init_array("sk") - s += init_array("secnonce") - s += init_array("aggnonce") - s += init_array("msg") - s += init_arrays("pubkeys") - s += init_arrays("pnonces") - s += init_arrays("tweaks") - - s += init_cases( - data["valid_test_cases"], - lambda case: "{ %s, %s, %s, { %s }, %d, { %s }}," - % ( - init_indices(case["key_indices"]), - init_indices(case["nonce_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - case["signer_index"], - init_optional_expected(case), - ), - ) - - s += init_cases( - data["error_test_cases"], - lambda case: "{ %s, %s, %s, { %s }, %d, { %s }}," - % ( - init_indices(case["key_indices"]), - init_indices(case["nonce_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - case["signer_index"], - init_optional_expected(case), - ), - ) - - s += finish_init() - -# sigagg vectors -with open(sys.argv[1] + "/sig_agg_vectors.json", "r") as f: - data = json.load(f) - - num_pubkeys = len(data["pubkeys"]) - max_pubkeys = max(num_pubkeys, max_pubkeys) - num_tweaks = len(data["tweaks"]) - num_psigs = len(data["psigs"]) - num_valid_cases = len(data["valid_test_cases"]) - num_error_cases = len(data["error_test_cases"]) - - all_cases = data["valid_test_cases"] + data["error_test_cases"] - max_key_indices = max(len(test_case["key_indices"]) for test_case in all_cases) - max_tweak_indices = max(len(test_case["tweak_indices"]) for test_case in all_cases) - max_psig_indices = max(len(test_case["psig_indices"]) for test_case in all_cases) - - # Add structures for valid and error cases - s += """ -/* Omit pubnonces in the test vectors because they're only needed for - * implementations that do not directly accept an aggnonce. */ -struct musig_sig_agg_case { - size_t key_indices_len; - size_t key_indices[%d]; - size_t tweak_indices_len; - size_t tweak_indices[%d]; - int is_xonly[%d]; - unsigned char aggnonce[66]; - size_t psig_indices_len; - size_t psig_indices[%d]; - /* if valid case */ - unsigned char expected[64]; - /* if error case */ - int invalid_sig_idx; -}; -""" % ( - max_key_indices, - max_tweak_indices, - max_tweak_indices, - max_psig_indices, - ) - - # Add structure for entire vector - s += """ -struct musig_sig_agg_vector { - unsigned char pubkeys[%d][33]; - unsigned char tweaks[%d][32]; - unsigned char psigs[%d][32]; - unsigned char msg[32]; - struct musig_sig_agg_case valid_case[%d]; - struct musig_sig_agg_case error_case[%d]; -}; -""" % ( - num_pubkeys, - num_tweaks, - num_psigs, - num_valid_cases, - num_error_cases, - ) - - s += create_init("sig_agg") - s += init_arrays("pubkeys") - s += init_arrays("tweaks") - s += init_arrays("psigs") - s += init_array("msg") - - for cases in (data["valid_test_cases"], data["error_test_cases"]): - s += init_cases( - cases, - lambda case: "{ %s, %s, { %s }, { %s }, %s, { %s }, %d }," - % ( - init_indices(case["key_indices"]), - init_indices(case["tweak_indices"]), - init_is_xonly(case), - hexstr_to_intarray(case["aggnonce"]), - init_indices(case["psig_indices"]), - init_optional_expected(case), - case["error"]["signer"] if "error" in case else 0, - ), - ) - s += finish_init() -s += "enum { MUSIG_VECTORS_MAX_PUBKEYS = %d };" % max_pubkeys -print(s) diff --git a/doc/musig-spec.mediawiki b/doc/musig-spec.mediawiki deleted file mode 100644 index 017a0c3e..00000000 --- a/doc/musig-spec.mediawiki +++ /dev/null @@ -1 +0,0 @@ -This document was moved to [https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki]. \ No newline at end of file diff --git a/examples/musig.c b/examples/musig.c deleted file mode 100644 index d4a02195..00000000 --- a/examples/musig.c +++ /dev/null @@ -1,214 +0,0 @@ -/************************************************************************* - * Written in 2018 by Jonas Nick * - * To the extent possible under law, the author(s) have dedicated all * - * copyright and related and neighboring rights to the software in this * - * file to the public domain worldwide. This software is distributed * - * without any warranty. For the CC0 Public Domain Dedication, see * - * EXAMPLES_COPYING or https://creativecommons.org/publicdomain/zero/1.0 * - *************************************************************************/ - -/** This file demonstrates how to use the MuSig module to create a - * 3-of-3 multisignature. Additionally, see the documentation in - * include/secp256k1_musig.h and src/modules/musig/musig.md. - */ - -#include -#include -#include - -#include -#include -#include - -#include "examples_util.h" - -struct signer_secrets { - secp256k1_keypair keypair; - secp256k1_musig_secnonce secnonce; -}; - -struct signer { - secp256k1_pubkey pubkey; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_partial_sig partial_sig; -}; - - /* Number of public keys involved in creating the aggregate signature */ -#define N_SIGNERS 3 -/* Create a key pair, store it in signer_secrets->keypair and signer->pubkey */ -static int create_keypair(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { - unsigned char seckey[32]; - while (1) { - if (!fill_random(seckey, sizeof(seckey))) { - printf("Failed to generate randomness\n"); - return 1; - } - if (secp256k1_keypair_create(ctx, &signer_secrets->keypair, seckey)) { - break; - } - } - if (!secp256k1_keypair_pub(ctx, &signer->pubkey, &signer_secrets->keypair)) { - return 0; - } - return 1; -} - -/* Tweak the pubkey corresponding to the provided keyagg cache, update the cache - * and return the tweaked aggregate pk. */ -static int tweak(const secp256k1_context* ctx, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *cache) { - secp256k1_pubkey output_pk; - unsigned char plain_tweak[32] = "this could be a BIP32 tweak...."; - unsigned char xonly_tweak[32] = "this could be a taproot tweak.."; - - - /* Plain tweaking which, for example, allows deriving multiple child - * public keys from a single aggregate key using BIP32 */ - if (!secp256k1_musig_pubkey_ec_tweak_add(ctx, NULL, cache, plain_tweak)) { - return 0; - } - /* Note that we did not provided an output_pk argument, because the - * resulting pk is also saved in the cache and so if one is just interested - * in signing the output_pk argument is unnecessary. On the other hand, if - * one is not interested in signing, the same output_pk can be obtained by - * calling `secp256k1_musig_pubkey_get` right after key aggregation to get - * the full pubkey and then call `secp256k1_ec_pubkey_tweak_add`. */ - - /* Xonly tweaking which, for example, allows creating taproot commitments */ - if (!secp256k1_musig_pubkey_xonly_tweak_add(ctx, &output_pk, cache, xonly_tweak)) { - return 0; - } - /* Note that if we wouldn't care about signing, we can arrive at the same - * output_pk by providing the untweaked public key to - * `secp256k1_xonly_pubkey_tweak_add` (after converting it to an xonly pubkey - * if necessary with `secp256k1_xonly_pubkey_from_pubkey`). */ - - /* Now we convert the output_pk to an xonly pubkey to allow to later verify - * the Schnorr signature against it. For this purpose we can ignore the - * `pk_parity` output argument; we would need it if we would have to open - * the taproot commitment. */ - if (!secp256k1_xonly_pubkey_from_pubkey(ctx, agg_pk, NULL, &output_pk)) { - return 0; - } - return 1; -} - -/* Sign a message hash with the given key pairs and store the result in sig */ -static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const secp256k1_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) { - int i; - const secp256k1_musig_pubnonce *pubnonces[N_SIGNERS]; - const secp256k1_musig_partial_sig *partial_sigs[N_SIGNERS]; - /* The same for all signers */ - secp256k1_musig_session session; - - for (i = 0; i < N_SIGNERS; i++) { - unsigned char seckey[32]; - unsigned char session_id[32]; - /* Create random session ID. It is absolutely necessary that the session ID - * is unique for every call of secp256k1_musig_nonce_gen. Otherwise - * it's trivial for an attacker to extract the secret key! */ - if (!fill_random(session_id, sizeof(session_id))) { - return 0; - } - if (!secp256k1_keypair_sec(ctx, seckey, &signer_secrets[i].keypair)) { - return 0; - } - /* Initialize session and create secret nonce for signing and public - * nonce to send to the other signers. */ - if (!secp256k1_musig_nonce_gen(ctx, &signer_secrets[i].secnonce, &signer[i].pubnonce, session_id, seckey, &signer[i].pubkey, msg32, NULL, NULL)) { - return 0; - } - pubnonces[i] = &signer[i].pubnonce; - } - /* Communication round 1: A production system would exchange public nonces - * here before moving on. */ - for (i = 0; i < N_SIGNERS; i++) { - secp256k1_musig_aggnonce agg_pubnonce; - - /* Create aggregate nonce and initialize the session */ - if (!secp256k1_musig_nonce_agg(ctx, &agg_pubnonce, pubnonces, N_SIGNERS)) { - return 0; - } - if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache, NULL)) { - return 0; - } - /* partial_sign will clear the secnonce by setting it to 0. That's because - * you must _never_ reuse the secnonce (or use the same session_id to - * create a secnonce). If you do, you effectively reuse the nonce and - * leak the secret key. */ - if (!secp256k1_musig_partial_sign(ctx, &signer[i].partial_sig, &signer_secrets[i].secnonce, &signer_secrets[i].keypair, cache, &session)) { - return 0; - } - partial_sigs[i] = &signer[i].partial_sig; - } - /* Communication round 2: A production system would exchange - * partial signatures here before moving on. */ - for (i = 0; i < N_SIGNERS; i++) { - /* To check whether signing was successful, it suffices to either verify - * the aggregate signature with the aggregate public key using - * secp256k1_schnorrsig_verify, or verify all partial signatures of all - * signers individually. Verifying the aggregate signature is cheaper but - * verifying the individual partial signatures has the advantage that it - * can be used to determine which of the partial signatures are invalid - * (if any), i.e., which of the partial signatures cause the aggregate - * signature to be invalid and thus the protocol run to fail. It's also - * fine to first verify the aggregate sig, and only verify the individual - * sigs if it does not work. - */ - if (!secp256k1_musig_partial_sig_verify(ctx, &signer[i].partial_sig, &signer[i].pubnonce, &signer[i].pubkey, cache, &session)) { - return 0; - } - } - return secp256k1_musig_partial_sig_agg(ctx, sig64, &session, partial_sigs, N_SIGNERS); -} - - int main(void) { - secp256k1_context* ctx; - int i; - struct signer_secrets signer_secrets[N_SIGNERS]; - struct signer signers[N_SIGNERS]; - const secp256k1_pubkey *pubkeys_ptr[N_SIGNERS]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_musig_keyagg_cache cache; - unsigned char msg[] = {'t', 'h', 'i', 's', '_', 'c', 'o', 'u', 'l', 'd', ' ', 'b', 'e', ' ', 't', 'h', 'e', '_', 'h', 'a', 's', 'h', '_', 'o', 'f', '_', 'a', '_', 'm', 's', 'g', '!'}; - unsigned char sig[64]; - - /* Create a secp256k1 context */ - ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); - printf("Creating key pairs......"); - for (i = 0; i < N_SIGNERS; i++) { - if (!create_keypair(ctx, &signer_secrets[i], &signers[i])) { - printf("FAILED\n"); - return 1; - } - pubkeys_ptr[i] = &signers[i].pubkey; - } - printf("ok\n"); - printf("Combining public keys..."); - /* If you just want to aggregate and not sign the cache can be NULL */ - if (!secp256k1_musig_pubkey_agg(ctx, NULL, &agg_pk, &cache, pubkeys_ptr, N_SIGNERS)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - printf("Tweaking................"); - /* Optionally tweak the aggregate key */ - if (!tweak(ctx, &agg_pk, &cache)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - printf("Signing message........."); - if (!sign(ctx, signer_secrets, signers, &cache, msg, sig)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - printf("Verifying signature....."); - if (!secp256k1_schnorrsig_verify(ctx, sig, msg, 32, &agg_pk)) { - printf("FAILED\n"); - return 1; - } - printf("ok\n"); - secp256k1_context_destroy(ctx); - return 0; -} diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h deleted file mode 100644 index 0c539e8a..00000000 --- a/include/secp256k1_musig.h +++ /dev/null @@ -1,609 +0,0 @@ -#ifndef SECP256K1_MUSIG_H -#define SECP256K1_MUSIG_H - -#include "secp256k1_extrakeys.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** This module implements BIP 327 "MuSig2 for BIP340-compatible - * Multi-Signatures" - * (https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki) - * v1.0.0. You can find an example demonstrating the musig module in - * examples/musig.c. - * - * The module also supports BIP-341 ("Taproot") public key tweaking and adaptor - * signatures as described in - * https://github.com/ElementsProject/scriptless-scripts/pull/24. - * - * It is recommended to read the documentation in this include file carefully. - * Further notes on API usage can be found in src/modules/musig/musig.md - * - * Since the first version of MuSig is essentially replaced by MuSig2, we use - * MuSig, musig and MuSig2 synonymously unless noted otherwise. - */ - -/** Opaque data structures - * - * The exact representation of data inside is implementation defined and not - * guaranteed to be portable between different platforms or versions. If you - * need to convert to a format suitable for storage, transmission, or - * comparison, use the corresponding serialization and parsing functions. - */ - -/** Opaque data structure that caches information about public key aggregation. - * - * Guaranteed to be 197 bytes in size. It can be safely copied/moved. No - * serialization and parsing functions (yet). - */ -typedef struct { - unsigned char data[197]; -} secp256k1_musig_keyagg_cache; - -/** Opaque data structure that holds a signer's _secret_ nonce. - * - * Guaranteed to be 132 bytes in size. - * - * WARNING: This structure MUST NOT be copied or read or written to directly. A - * signer who is online throughout the whole process and can keep this - * structure in memory can use the provided API functions for a safe standard - * workflow. See - * https://blockstream.com/2019/02/18/musig-a-new-multisignature-standard/ for - * more details about the risks associated with serializing or deserializing - * this structure. - * - * We repeat, copying this data structure can result in nonce reuse which will - * leak the secret signing key. - */ -typedef struct { - unsigned char data[132]; -} secp256k1_musig_secnonce; - -/** Opaque data structure that holds a signer's public nonce. -* -* Guaranteed to be 132 bytes in size. It can be safely copied/moved. Serialized -* and parsed with `musig_pubnonce_serialize` and `musig_pubnonce_parse`. -*/ -typedef struct { - unsigned char data[132]; -} secp256k1_musig_pubnonce; - -/** Opaque data structure that holds an aggregate public nonce. - * - * Guaranteed to be 132 bytes in size. It can be safely copied/moved. - * Serialized and parsed with `musig_aggnonce_serialize` and - * `musig_aggnonce_parse`. - */ -typedef struct { - unsigned char data[132]; -} secp256k1_musig_aggnonce; - -/** Opaque data structure that holds a MuSig session. - * - * This structure is not required to be kept secret for the signing protocol to - * be secure. Guaranteed to be 133 bytes in size. It can be safely - * copied/moved. No serialization and parsing functions (yet). - */ -typedef struct { - unsigned char data[133]; -} secp256k1_musig_session; - -/** Opaque data structure that holds a partial MuSig signature. - * - * Guaranteed to be 36 bytes in size. Serialized and parsed with - * `musig_partial_sig_serialize` and `musig_partial_sig_parse`. - */ -typedef struct { - unsigned char data[36]; -} secp256k1_musig_partial_sig; - -/** Parse a signer's public nonce. - * - * Returns: 1 when the nonce could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: nonce: pointer to a nonce object - * In: in66: pointer to the 66-byte nonce to be parsed - */ -SECP256K1_API int secp256k1_musig_pubnonce_parse( - const secp256k1_context *ctx, - secp256k1_musig_pubnonce *nonce, - const unsigned char *in66 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a signer's public nonce - * - * Returns: 1 when the nonce could be serialized, 0 otherwise - * Args: ctx: pointer to a context object - * Out: out66: pointer to a 66-byte array to store the serialized nonce - * In: nonce: pointer to the nonce - */ -SECP256K1_API int secp256k1_musig_pubnonce_serialize( - const secp256k1_context *ctx, - unsigned char *out66, - const secp256k1_musig_pubnonce *nonce -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse an aggregate public nonce. - * - * Returns: 1 when the nonce could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: nonce: pointer to a nonce object - * In: in66: pointer to the 66-byte nonce to be parsed - */ -SECP256K1_API int secp256k1_musig_aggnonce_parse( - const secp256k1_context *ctx, - secp256k1_musig_aggnonce *nonce, - const unsigned char *in66 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize an aggregate public nonce - * - * Returns: 1 when the nonce could be serialized, 0 otherwise - * Args: ctx: pointer to a context object - * Out: out66: pointer to a 66-byte array to store the serialized nonce - * In: nonce: pointer to the nonce - */ -SECP256K1_API int secp256k1_musig_aggnonce_serialize( - const secp256k1_context *ctx, - unsigned char *out66, - const secp256k1_musig_aggnonce *nonce -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Serialize a MuSig partial signature - * - * Returns: 1 when the signature could be serialized, 0 otherwise - * Args: ctx: pointer to a context object - * Out: out32: pointer to a 32-byte array to store the serialized signature - * In: sig: pointer to the signature - */ -SECP256K1_API int secp256k1_musig_partial_sig_serialize( - const secp256k1_context *ctx, - unsigned char *out32, - const secp256k1_musig_partial_sig *sig -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Parse a MuSig partial signature. - * - * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: pointer to a context object - * Out: sig: pointer to a signature object - * In: in32: pointer to the 32-byte signature to be parsed - * - * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature verification with it is - * guaranteed to fail for every message and public key. - */ -SECP256K1_API int secp256k1_musig_partial_sig_parse( - const secp256k1_context *ctx, - secp256k1_musig_partial_sig *sig, - const unsigned char *in32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Computes an aggregate public key and uses it to initialize a keyagg_cache - * - * Different orders of `pubkeys` result in different `agg_pk`s. - * - * Before aggregating, the pubkeys can be sorted with `secp256k1_ec_pubkey_sort` - * which ensures the same `agg_pk` result for the same multiset of pubkeys. - * This is useful to do before `pubkey_agg`, such that the order of pubkeys - * does not affect the aggregate public key. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * scratch: should be NULL because it is not yet implemented. If it - * was implemented then the scratch space would be used to - * compute the aggregate pubkey by multiexponentiation. - * Generally, the larger the scratch space, the faster this - * function. However, the returns of providing a larger - * scratch space are diminishing. If NULL, an inefficient - * algorithm is used. - * Out: agg_pk: the MuSig-aggregated x-only public key. If you do not need it, - * this arg can be NULL. - * keyagg_cache: if non-NULL, pointer to a musig_keyagg_cache struct that - * is required for signing (or observing the signing session - * and verifying partial signatures). - * In: pubkeys: input array of pointers to public keys to aggregate. The order - * is important; a different order will result in a different - * aggregate public key. - * n_pubkeys: length of pubkeys array. Must be greater than 0. - */ -SECP256K1_API int secp256k1_musig_pubkey_agg( - const secp256k1_context *ctx, - secp256k1_scratch_space *scratch, - secp256k1_xonly_pubkey *agg_pk, - secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_pubkey * const *pubkeys, - size_t n_pubkeys -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(5); - -/** Obtain the aggregate public key from a keyagg_cache. - * - * This is only useful if you need the non-xonly public key, in particular for - * plain (non-xonly) tweaking or batch-verifying multiple key aggregations - * (not implemented). - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: agg_pk: the MuSig-aggregated public key. - * In: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by - * `musig_pubkey_agg` - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get( - const secp256k1_context *ctx, - secp256k1_pubkey *agg_pk, - const secp256k1_musig_keyagg_cache *keyagg_cache -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Apply plain "EC" tweaking to a public key in a given keyagg_cache by - * adding the generator multiplied with `tweak32` to it. This is useful for - * deriving child keys from an aggregate public key via BIP32. - * - * The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after - * the following pseudocode buf and buf2 have identical contents (absent - * earlier failures). - * - * secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...) - * secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache) - * secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache) - * secp256k1_ec_pubkey_serialize(..., buf, output_pk) - * secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32) - * secp256k1_ec_pubkey_serialize(..., buf2, agg_pk) - * - * This function is required if you want to _sign_ for a tweaked aggregate key. - * On the other hand, if you are only computing a public key, but not intending - * to create a signature for it, you can just use - * `secp256k1_ec_pubkey_tweak_add`. - * - * Returns: 0 if the arguments are invalid or the resulting public key would be - * invalid (only when the tweak is the negation of the corresponding - * secret key). 1 otherwise. - * Args: ctx: pointer to a context object - * Out: output_pubkey: pointer to a public key to store the result. Will be set - * to an invalid value if this function returns 0. If you - * do not need it, this arg can be NULL. - * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by - * `musig_pubkey_agg` - * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid - * according to `secp256k1_ec_seckey_verify`, this function - * returns 0. For uniformly random 32-byte arrays the - * chance of being invalid is negligible (around 1 in - * 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_ec_tweak_add( - const secp256k1_context *ctx, - secp256k1_pubkey *output_pubkey, - secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the - * generator multiplied with `tweak32` to it. This is useful for creating - * Taproot outputs. - * - * The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in - * the following pseudocode xonly_pubkey_tweak_add_check (absent earlier - * failures) returns 1. - * - * secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...) - * secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, tweak32, keyagg_cache) - * secp256k1_xonly_pubkey_serialize(..., buf, output_pk) - * secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32) - * - * This function is required if you want to _sign_ for a tweaked aggregate key. - * On the other hand, if you are only computing a public key, but not intending - * to create a signature for it, you can just use - * `secp256k1_xonly_pubkey_tweak_add`. - * - * Returns: 0 if the arguments are invalid or the resulting public key would be - * invalid (only when the tweak is the negation of the corresponding - * secret key). 1 otherwise. - * Args: ctx: pointer to a context object - * Out: output_pubkey: pointer to a public key to store the result. Will be set - * to an invalid value if this function returns 0. If you - * do not need it, this arg can be NULL. - * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by - * `musig_pubkey_agg` - * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid - * according to secp256k1_ec_seckey_verify, this function - * returns 0. For uniformly random 32-byte arrays the - * chance of being invalid is negligible (around 1 in - * 2^128). - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add( - const secp256k1_context *ctx, - secp256k1_pubkey *output_pubkey, - secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *tweak32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Starts a signing session by generating a nonce - * - * This function outputs a secret nonce that will be required for signing and a - * corresponding public nonce that is intended to be sent to other signers. - * - * MuSig differs from regular Schnorr signing in that implementers _must_ take - * special care to not reuse a nonce. This can be ensured by following these rules: - * - * 1. Each call to this function must have a UNIQUE session_id32 that must NOT BE - * REUSED in subsequent calls to this function. - * If you do not provide a seckey, session_id32 _must_ be UNIFORMLY RANDOM - * AND KEPT SECRET (even from other signers). If you do provide a seckey, - * session_id32 can instead be a counter (that must never repeat!). However, - * it is recommended to always choose session_id32 uniformly at random. - * 2. If you already know the seckey, message or aggregate public key - * cache, they can be optionally provided to derive the nonce and increase - * misuse-resistance. The extra_input32 argument can be used to provide - * additional data that does not repeat in normal scenarios, such as the - * current time. - * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility - * that it is used more than once for signing. - * - * Remember that nonce reuse will leak the secret key! - * Note that using the same seckey for multiple MuSig sessions is fine. - * - * Returns: 0 if the arguments are invalid and 1 otherwise - * Args: ctx: pointer to a context object (not secp256k1_context_static) - * Out: secnonce: pointer to a structure to store the secret nonce - * pubnonce: pointer to a structure to store the public nonce - * In: session_id32: a 32-byte session_id32 as explained above. Must be unique to this - * call to secp256k1_musig_nonce_gen and must be uniformly random - * unless you really know what you are doing. - * seckey: the 32-byte secret key that will later be used for signing, if - * already known (can be NULL) - * pubkey: public key of the signer creating the nonce. The secnonce - * output of this function cannot be used to sign for any - * other public key. - * msg32: the 32-byte message that will later be signed, if already known - * (can be NULL) - * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate - * (and potentially tweaked) public key if already known - * (can be NULL) - * extra_input32: an optional 32-byte array that is input to the nonce - * derivation function (can be NULL) - */ -SECP256K1_API int secp256k1_musig_nonce_gen( - const secp256k1_context *ctx, - secp256k1_musig_secnonce *secnonce, - secp256k1_musig_pubnonce *pubnonce, - const unsigned char *session_id32, - const unsigned char *seckey, - const secp256k1_pubkey *pubkey, - const unsigned char *msg32, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const unsigned char *extra_input32 -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6); - -/** Aggregates the nonces of all signers into a single nonce - * - * This can be done by an untrusted party to reduce the communication - * between signers. Instead of everyone sending nonces to everyone else, there - * can be one party receiving all nonces, aggregating the nonces with this - * function and then sending only the aggregate nonce back to the signers. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: aggnonce: pointer to an aggregate public nonce object for - * musig_nonce_process - * In: pubnonces: array of pointers to public nonces sent by the - * signers - * n_pubnonces: number of elements in the pubnonces array. Must be - * greater than 0. - */ -SECP256K1_API int secp256k1_musig_nonce_agg( - const secp256k1_context *ctx, - secp256k1_musig_aggnonce *aggnonce, - const secp256k1_musig_pubnonce * const *pubnonces, - size_t n_pubnonces -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Takes the public nonces of all signers and computes a session that is - * required for signing and verification of partial signatures. - * - * If the adaptor argument is non-NULL, then the output of - * musig_partial_sig_agg will be a pre-signature which is not a valid Schnorr - * signature. In order to create a valid signature, the pre-signature and the - * secret adaptor must be provided to `musig_adapt`. - * - * Returns: 0 if the arguments are invalid or if some signer sent invalid - * pubnonces, 1 otherwise - * Args: ctx: pointer to a context object - * Out: session: pointer to a struct to store the session - * In: aggnonce: pointer to an aggregate public nonce object that is the - * output of musig_nonce_agg - * msg32: the 32-byte message to sign - * keyagg_cache: pointer to the keyagg_cache that was used to create the - * aggregate (and potentially tweaked) pubkey - * adaptor: optional pointer to an adaptor point encoded as a public - * key if this signing session is part of an adaptor - * signature protocol (can be NULL) - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process( - const secp256k1_context *ctx, - secp256k1_musig_session *session, - const secp256k1_musig_aggnonce *aggnonce, - const unsigned char *msg32, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_pubkey *adaptor -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); - -/** Produces a partial signature - * - * This function overwrites the given secnonce with zeros and will abort if given a - * secnonce that is all zeros. This is a best effort attempt to protect against nonce - * reuse. However, this is of course easily defeated if the secnonce has been - * copied (or serialized). Remember that nonce reuse will leak the secret key! - * - * For signing to succeed, the secnonce provided to this function must have - * been generated for the provided keypair. This means that when signing for a - * keypair consisting of a seckey and pubkey, the secnonce must have been - * created by calling musig_nonce_gen with that pubkey. Otherwise, the - * illegal_callback is called. - * - * This function does not verify the output partial signature, deviating from - * the BIP 327 specification. It is recommended to verify the output partial - * signature with `secp256k1_musig_partial_sig_verify` to prevent random or - * adversarially provoked computation errors. - * - * Returns: 0 if the arguments are invalid or the provided secnonce has already - * been used for signing, 1 otherwise - * Args: ctx: pointer to a context object - * Out: partial_sig: pointer to struct to store the partial signature - * In/Out: secnonce: pointer to the secnonce struct created in - * musig_nonce_gen that has been never used in a - * partial_sign call before and has been created for the - * keypair - * In: keypair: pointer to keypair to sign the message with - * keyagg_cache: pointer to the keyagg_cache that was output when the - * aggregate public key for this session - * session: pointer to the session that was created with - * musig_nonce_process - */ -SECP256K1_API int secp256k1_musig_partial_sign( - const secp256k1_context *ctx, - secp256k1_musig_partial_sig *partial_sig, - secp256k1_musig_secnonce *secnonce, - const secp256k1_keypair *keypair, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_musig_session *session -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); - -/** Verifies an individual signer's partial signature - * - * The signature is verified for a specific signing session. In order to avoid - * accidentally verifying a signature from a different or non-existing signing - * session, you must ensure the following: - * 1. The `keyagg_cache` argument is identical to the one used to create the - * `session` with `musig_nonce_process`. - * 2. The `pubkey` argument must be identical to the one sent by the signer - * before aggregating it with `musig_pubkey_agg` to create the - * `keyagg_cache`. - * 3. The `pubnonce` argument must be identical to the one sent by the signer - * before aggregating it with `musig_nonce_agg` and using the result to - * create the `session` with `musig_nonce_process`. - * - * This function is essential when using protocols with adaptor signatures. - * However, it is not essential for regular MuSig sessions, in the sense that if any - * partial signature does not verify, the full signature will not verify either, so the - * problem will be caught. But this function allows determining the specific party - * who produced an invalid signature. - * - * Returns: 0 if the arguments are invalid or the partial signature does not - * verify, 1 otherwise - * Args ctx: pointer to a context object - * In: partial_sig: pointer to partial signature to verify, sent by - * the signer associated with `pubnonce` and `pubkey` - * pubnonce: public nonce of the signer in the signing session - * pubkey: public key of the signer in the signing session - * keyagg_cache: pointer to the keyagg_cache that was output when the - * aggregate public key for this signing session - * session: pointer to the session that was created with - * `musig_nonce_process` - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify( - const secp256k1_context *ctx, - const secp256k1_musig_partial_sig *partial_sig, - const secp256k1_musig_pubnonce *pubnonce, - const secp256k1_pubkey *pubkey, - const secp256k1_musig_keyagg_cache *keyagg_cache, - const secp256k1_musig_session *session -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); - -/** Aggregates partial signatures - * - * Returns: 0 if the arguments are invalid, 1 otherwise (which does NOT mean - * the resulting signature verifies). - * Args: ctx: pointer to a context object - * Out: sig64: complete (but possibly invalid) Schnorr signature - * In: session: pointer to the session that was created with - * musig_nonce_process - * partial_sigs: array of pointers to partial signatures to aggregate - * n_sigs: number of elements in the partial_sigs array. Must be - * greater than 0. - */ -SECP256K1_API int secp256k1_musig_partial_sig_agg( - const secp256k1_context *ctx, - unsigned char *sig64, - const secp256k1_musig_session *session, - const secp256k1_musig_partial_sig * const *partial_sigs, - size_t n_sigs -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Extracts the nonce_parity bit from a session - * - * This is used for adaptor signatures. - * - * Returns: 0 if the arguments are invalid, 1 otherwise - * Args: ctx: pointer to a context object - * Out: nonce_parity: pointer to an integer that indicates the parity - * of the aggregate public nonce. Used for adaptor - * signatures. - * In: session: pointer to the session that was created with - * musig_nonce_process - */ -SECP256K1_API int secp256k1_musig_nonce_parity( - const secp256k1_context *ctx, - int *nonce_parity, - const secp256k1_musig_session *session -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); - -/** Creates a signature from a pre-signature and an adaptor. - * - * If the sec_adaptor32 argument is incorrect, the output signature will be - * invalid. This function does not verify the signature. - * - * Returns: 0 if the arguments are invalid, or pre_sig64 or sec_adaptor32 contain - * invalid (overflowing) values. 1 otherwise (which does NOT mean the - * signature or the adaptor are valid!) - * Args: ctx: pointer to a context object - * Out: sig64: 64-byte signature. This pointer may point to the same - * memory area as `pre_sig`. - * In: pre_sig64: 64-byte pre-signature - * sec_adaptor32: 32-byte secret adaptor to add to the pre-signature - * nonce_parity: the output of `musig_nonce_parity` called with the - * session used for producing the pre-signature - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_adapt( - const secp256k1_context *ctx, - unsigned char *sig64, - const unsigned char *pre_sig64, - const unsigned char *sec_adaptor32, - int nonce_parity -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -/** Extracts a secret adaptor from a MuSig pre-signature and corresponding - * signature - * - * This function will not fail unless given grossly invalid data; if it is - * merely given signatures that do not verify, the returned value will be - * nonsense. It is therefore important that all data be verified at earlier - * steps of any protocol that uses this function. In particular, this includes - * verifying all partial signatures that were aggregated into pre_sig64. - * - * Returns: 0 if the arguments are NULL, or sig64 or pre_sig64 contain - * grossly invalid (overflowing) values. 1 otherwise (which does NOT - * mean the signatures or the adaptor are valid!) - * Args: ctx: pointer to a context object - * Out:sec_adaptor32: 32-byte secret adaptor - * In: sig64: complete, valid 64-byte signature - * pre_sig64: the pre-signature corresponding to sig64, i.e., the - * aggregate of partial signatures without the secret - * adaptor - * nonce_parity: the output of `musig_nonce_parity` called with the - * session used for producing sig64 - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_adaptor( - const secp256k1_context *ctx, - unsigned char *sec_adaptor32, - const unsigned char *sig64, - const unsigned char *pre_sig64, - int nonce_parity -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 27e90204..7c0871ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -129,9 +129,6 @@ if(SECP256K1_INSTALL) if(SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR) list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdsa_adaptor.h") endif() - if(SECP256K1_ENABLE_MODULE_MUSIG) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_musig.h") - endif() if(SECP256K1_ENABLE_MODULE_WHITELIST) list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_whitelist.h") endif() diff --git a/src/ctime_tests.c b/src/ctime_tests.c index 407d2cc6..0b72f281 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -43,10 +43,6 @@ #include "../include/secp256k1_ecdsa_adaptor.h" #endif -#ifdef ENABLE_MODULE_MUSIG -#include "../include/secp256k1_musig.h" -#endif - static void run_tests(secp256k1_context *ctx, unsigned char *key); int main(void) { @@ -281,72 +277,4 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { CHECK(ret == 0); } #endif - -#ifdef ENABLE_MODULE_MUSIG - { - secp256k1_pubkey pk; - const secp256k1_pubkey *pk_ptr[1]; - secp256k1_xonly_pubkey agg_pk; - unsigned char session_id[32]; - secp256k1_musig_secnonce secnonce; - secp256k1_musig_pubnonce pubnonce; - const secp256k1_musig_pubnonce *pubnonce_ptr[1]; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_keyagg_cache cache; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - const secp256k1_musig_partial_sig *partial_sig_ptr[1]; - unsigned char extra_input[32]; - unsigned char sec_adaptor[32]; - secp256k1_pubkey adaptor; - unsigned char pre_sig[64]; - int nonce_parity; - - pk_ptr[0] = &pk; - pubnonce_ptr[0] = &pubnonce; - SECP256K1_CHECKMEM_DEFINE(key, 32); - memcpy(session_id, key, sizeof(session_id)); - session_id[0] = session_id[0] + 1; - memcpy(extra_input, key, sizeof(extra_input)); - extra_input[0] = extra_input[0] + 2; - memcpy(sec_adaptor, key, sizeof(sec_adaptor)); - sec_adaptor[0] = extra_input[0] + 3; - partial_sig_ptr[0] = &partial_sig; - - CHECK(secp256k1_keypair_create(ctx, &keypair, key)); - CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair)); - CHECK(secp256k1_musig_pubkey_agg(ctx, NULL, &agg_pk, &cache, pk_ptr, 1)); - CHECK(secp256k1_ec_pubkey_create(ctx, &adaptor, sec_adaptor)); - SECP256K1_CHECKMEM_UNDEFINE(key, 32); - SECP256K1_CHECKMEM_UNDEFINE(session_id, sizeof(session_id)); - SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input)); - SECP256K1_CHECKMEM_UNDEFINE(sec_adaptor, sizeof(sec_adaptor)); - ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_id, key, &pk, msg, &cache, extra_input); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1)); - /* Make sure that previous tests don't undefine msg. It's not used as a secret here. */ - SECP256K1_CHECKMEM_DEFINE(msg, sizeof(msg)); - CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache, &adaptor) == 1); - - ret = secp256k1_keypair_create(ctx, &keypair, key); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - ret = secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &cache, &session); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - - SECP256K1_CHECKMEM_DEFINE(&partial_sig, sizeof(partial_sig)); - CHECK(secp256k1_musig_partial_sig_agg(ctx, pre_sig, &session, partial_sig_ptr, 1)); - SECP256K1_CHECKMEM_DEFINE(pre_sig, sizeof(pre_sig)); - - CHECK(secp256k1_musig_nonce_parity(ctx, &nonce_parity, &session)); - ret = secp256k1_musig_adapt(ctx, sig, pre_sig, sec_adaptor, nonce_parity); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - ret = secp256k1_musig_extract_adaptor(ctx, sec_adaptor, sig, pre_sig, nonce_parity); - SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); - CHECK(ret == 1); - } -#endif } diff --git a/src/modules/musig/Makefile.am.include b/src/modules/musig/Makefile.am.include deleted file mode 100644 index dc2f77f1..00000000 --- a/src/modules/musig/Makefile.am.include +++ /dev/null @@ -1,8 +0,0 @@ -include_HEADERS += include/secp256k1_musig.h -noinst_HEADERS += src/modules/musig/main_impl.h -noinst_HEADERS += src/modules/musig/keyagg.h -noinst_HEADERS += src/modules/musig/keyagg_impl.h -noinst_HEADERS += src/modules/musig/session.h -noinst_HEADERS += src/modules/musig/session_impl.h -noinst_HEADERS += src/modules/musig/adaptor_impl.h -noinst_HEADERS += src/modules/musig/tests_impl.h diff --git a/src/modules/musig/adaptor_impl.h b/src/modules/musig/adaptor_impl.h deleted file mode 100644 index 3830e8a2..00000000 --- a/src/modules/musig/adaptor_impl.h +++ /dev/null @@ -1,101 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H -#define SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H - -#include - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_musig.h" - -#include "session.h" -#include "../../scalar.h" - -int secp256k1_musig_nonce_parity(const secp256k1_context* ctx, int *nonce_parity, const secp256k1_musig_session *session) { - secp256k1_musig_session_internal session_i; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(nonce_parity != NULL); - ARG_CHECK(session != NULL); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - return 0; - } - *nonce_parity = session_i.fin_nonce_parity; - return 1; -} - -int secp256k1_musig_adapt(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *pre_sig64, const unsigned char *sec_adaptor32, int nonce_parity) { - secp256k1_scalar s; - secp256k1_scalar t; - int overflow; - int ret = 1; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(pre_sig64 != NULL); - ARG_CHECK(sec_adaptor32 != NULL); - ARG_CHECK(nonce_parity == 0 || nonce_parity == 1); - - secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow); - if (overflow) { - return 0; - } - secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow); - ret &= !overflow; - - /* Determine if the secret adaptor should be negated. - * - * The musig_session stores the X-coordinate and the parity of the "final nonce" - * (r + t)*G, where r*G is the aggregate public nonce and t is the secret adaptor. - * - * Since a BIP340 signature requires an x-only public nonce, in the case where - * (r + t)*G has odd Y-coordinate (i.e. nonce_parity == 1), the x-only public nonce - * corresponding to the signature is actually (-r - t)*G. Thus adapting a - * pre-signature requires negating t in this case. - */ - if (nonce_parity) { - secp256k1_scalar_negate(&t, &t); - } - - secp256k1_scalar_add(&s, &s, &t); - secp256k1_scalar_get_b32(&sig64[32], &s); - memmove(sig64, pre_sig64, 32); - secp256k1_scalar_clear(&t); - return ret; -} - -int secp256k1_musig_extract_adaptor(const secp256k1_context* ctx, unsigned char *sec_adaptor32, const unsigned char *sig64, const unsigned char *pre_sig64, int nonce_parity) { - secp256k1_scalar t; - secp256k1_scalar s; - int overflow; - int ret = 1; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sec_adaptor32 != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(pre_sig64 != NULL); - ARG_CHECK(nonce_parity == 0 || nonce_parity == 1); - - secp256k1_scalar_set_b32(&t, &sig64[32], &overflow); - ret &= !overflow; - secp256k1_scalar_negate(&t, &t); - - secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow); - if (overflow) { - return 0; - } - secp256k1_scalar_add(&t, &t, &s); - - if (!nonce_parity) { - secp256k1_scalar_negate(&t, &t); - } - secp256k1_scalar_get_b32(sec_adaptor32, &t); - secp256k1_scalar_clear(&t); - return ret; -} - -#endif diff --git a/src/modules/musig/keyagg.h b/src/modules/musig/keyagg.h deleted file mode 100644 index 620522fe..00000000 --- a/src/modules/musig/keyagg.h +++ /dev/null @@ -1,40 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_KEYAGG_H -#define SECP256K1_MODULE_MUSIG_KEYAGG_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_musig.h" - -#include "../../field.h" -#include "../../group.h" -#include "../../scalar.h" - -typedef struct { - secp256k1_ge pk; - /* If there is no "second" public key, second_pk is set to the point at - * infinity */ - secp256k1_ge second_pk; - unsigned char pk_hash[32]; - /* tweak is identical to value tacc[v] in the specification. */ - secp256k1_scalar tweak; - /* parity_acc corresponds to gacc[v] in the spec. If gacc[v] is -1, - * parity_acc is 1. Otherwise, parity_acc is 0. */ - int parity_acc; -} secp256k1_keyagg_cache_internal; - -/* point_save_ext and point_load_ext are identical to point_save and point_load - * except that they allow saving and loading the point at infinity */ -static void secp256k1_point_save_ext(unsigned char *data, secp256k1_ge *ge); - -static void secp256k1_point_load_ext(secp256k1_ge *ge, const unsigned char *data); - -static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); - -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); - -#endif diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h deleted file mode 100644 index aff95542..00000000 --- a/src/modules/musig/keyagg_impl.h +++ /dev/null @@ -1,311 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H -#define SECP256K1_MODULE_MUSIG_KEYAGG_IMPL_H - -#include - -#include "keyagg.h" -#include "../../eckey.h" -#include "../../ecmult.h" -#include "../../field.h" -#include "../../group.h" -#include "../../hash.h" -#include "../../util.h" - -static void secp256k1_point_save_ext(unsigned char *data, secp256k1_ge *ge) { - if (secp256k1_ge_is_infinity(ge)) { - memset(data, 0, 64); - } else { - secp256k1_ge_to_bytes(data, ge); - } -} - -static void secp256k1_point_load_ext(secp256k1_ge *ge, const unsigned char *data) { - unsigned char zeros[64] = { 0 }; - if (secp256k1_memcmp_var(data, zeros, sizeof(zeros)) == 0) { - secp256k1_ge_set_infinity(ge); - } else { - secp256k1_ge_from_bytes(ge, data); - } -} - -static const unsigned char secp256k1_musig_keyagg_cache_magic[4] = { 0xf4, 0xad, 0xbb, 0xdf }; - -/* A keyagg cache consists of - * - 4 byte magic set during initialization to allow detecting an uninitialized - * object. - * - 64 byte aggregate (and potentially tweaked) public key - * - 64 byte "second" public key (set to the point at infinity if not present) - * - 32 byte hash of all public keys - * - 1 byte the parity of the internal key (if tweaked, otherwise 0) - * - 32 byte tweak - */ -/* Requires that cache_i->pk is not infinity and cache_i->second_pk_x to be normalized. */ -static void secp256k1_keyagg_cache_save(secp256k1_musig_keyagg_cache *cache, secp256k1_keyagg_cache_internal *cache_i) { - unsigned char *ptr = cache->data; - memcpy(ptr, secp256k1_musig_keyagg_cache_magic, 4); - ptr += 4; - secp256k1_ge_to_bytes(ptr, &cache_i->pk); - ptr += 64; - secp256k1_point_save_ext(ptr, &cache_i->second_pk); - ptr += 64; - memcpy(ptr, cache_i->pk_hash, 32); - ptr += 32; - *ptr = cache_i->parity_acc; - ptr += 1; - secp256k1_scalar_get_b32(ptr, &cache_i->tweak); -} - -static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache) { - const unsigned char *ptr = cache->data; - ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_keyagg_cache_magic, 4) == 0); - ptr += 4; - secp256k1_ge_from_bytes(&cache_i->pk, ptr); - ptr += 64; - secp256k1_point_load_ext(&cache_i->second_pk, ptr); - ptr += 64; - memcpy(cache_i->pk_hash, ptr, 32); - ptr += 32; - cache_i->parity_acc = *ptr & 1; - ptr += 1; - secp256k1_scalar_set_b32(&cache_i->tweak, ptr, NULL); - return 1; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */ -static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0xb399d5e0ul; - sha->s[1] = 0xc8fff302ul; - sha->s[2] = 0x6badac71ul; - sha->s[3] = 0x07c5b7f1ul; - sha->s[4] = 0x9701e2eful; - sha->s[5] = 0x2a72ecf8ul; - sha->s[6] = 0x201a4c7bul; - sha->s[7] = 0xab148a38ul; - sha->bytes = 64; -} - -/* Computes pk_hash = tagged_hash(pk[0], ..., pk[np-1]) */ -static int secp256k1_musig_compute_pk_hash(const secp256k1_context *ctx, unsigned char *pk_hash, const secp256k1_pubkey * const* pk, size_t np) { - secp256k1_sha256 sha; - size_t i; - - secp256k1_musig_keyagglist_sha256(&sha); - for (i = 0; i < np; i++) { - unsigned char ser[33]; - size_t ser_len = sizeof(ser); - if (!secp256k1_ec_pubkey_serialize(ctx, ser, &ser_len, pk[i], SECP256K1_EC_COMPRESSED)) { - return 0; - } - VERIFY_CHECK(ser_len == sizeof(ser)); - secp256k1_sha256_write(&sha, ser, sizeof(ser)); - } - secp256k1_sha256_finalize(&sha, pk_hash); - return 1; -} - -/* Initializes SHA256 with fixed midstate. This midstate was computed by applying - * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */ -static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0x6ef02c5aul; - sha->s[1] = 0x06a480deul; - sha->s[2] = 0x1f298665ul; - sha->s[3] = 0x1d1134f2ul; - sha->s[4] = 0x56a0b063ul; - sha->s[5] = 0x52da4147ul; - sha->s[6] = 0xf280d9d4ul; - sha->s[7] = 0x4484be15ul; - sha->bytes = 64; -} - -/* Compute KeyAgg coefficient which is constant 1 for the second pubkey and - * otherwise tagged_hash(pk_hash, x) where pk_hash is the hash of public keys. - * second_pk is the point at infinity in case there is no second_pk. Assumes - * that pk is not the point at infinity and that the Y-coordinates of pk and - * second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pk_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { - secp256k1_sha256 sha; - - VERIFY_CHECK(!secp256k1_ge_is_infinity(pk)); - - if (!secp256k1_ge_is_infinity(second_pk) - && secp256k1_fe_equal(&pk->x, &second_pk->x) - && secp256k1_fe_is_odd(&pk->y) == secp256k1_fe_is_odd(&second_pk->y)) { - secp256k1_scalar_set_int(r, 1); - } else { - unsigned char buf[33]; - size_t buflen = sizeof(buf); - int ret; - secp256k1_musig_keyaggcoef_sha256(&sha); - secp256k1_sha256_write(&sha, pk_hash, 32); - ret = secp256k1_eckey_pubkey_serialize(pk, buf, &buflen, 1); -#ifdef VERIFY - /* Serialization does not fail since the pk is not the point at infinity - * (according to this function's precondition). */ - VERIFY_CHECK(ret && buflen == sizeof(buf)); -#else - (void) ret; -#endif - secp256k1_sha256_write(&sha, buf, sizeof(buf)); - secp256k1_sha256_finalize(&sha, buf); - secp256k1_scalar_set_b32(r, buf, NULL); - } -} - -/* Assumes both field elements x and second_pk_x are normalized. */ -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { - secp256k1_musig_keyaggcoef_internal(r, cache_i->pk_hash, pk, &cache_i->second_pk); -} - -typedef struct { - const secp256k1_context *ctx; - /* pk_hash is the hash of the public keys */ - unsigned char pk_hash[32]; - const secp256k1_pubkey * const* pks; - secp256k1_ge second_pk; -} secp256k1_musig_pubkey_agg_ecmult_data; - -/* Callback for batch EC multiplication to compute keyaggcoef_0*P0 + keyaggcoef_1*P1 + ... */ -static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data) { - secp256k1_musig_pubkey_agg_ecmult_data *ctx = (secp256k1_musig_pubkey_agg_ecmult_data *) data; - int ret; - ret = secp256k1_pubkey_load(ctx->ctx, pt, ctx->pks[idx]); -#ifdef VERIFY - /* pubkey_load can't fail because the same pks have already been loaded in - * `musig_compute_pk_hash` (and we test this). */ - VERIFY_CHECK(ret); -#else - (void) ret; -#endif - secp256k1_musig_keyaggcoef_internal(sc, ctx->pk_hash, pt, &ctx->second_pk); - return 1; -} - -int secp256k1_musig_pubkey_agg(const secp256k1_context* ctx, secp256k1_scratch_space *scratch, secp256k1_xonly_pubkey *agg_pk, secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey * const* pubkeys, size_t n_pubkeys) { - secp256k1_musig_pubkey_agg_ecmult_data ecmult_data; - secp256k1_gej pkj; - secp256k1_ge pkp; - size_t i; - (void) scratch; - - VERIFY_CHECK(ctx != NULL); - if (agg_pk != NULL) { - memset(agg_pk, 0, sizeof(*agg_pk)); - } - ARG_CHECK(pubkeys != NULL); - ARG_CHECK(n_pubkeys > 0); - - ecmult_data.ctx = ctx; - ecmult_data.pks = pubkeys; - - secp256k1_ge_set_infinity(&ecmult_data.second_pk); - for (i = 1; i < n_pubkeys; i++) { - if (secp256k1_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) { - secp256k1_ge pk; - if (!secp256k1_pubkey_load(ctx, &pk, pubkeys[i])) { - return 0; - } - ecmult_data.second_pk = pk; - break; - } - } - - if (!secp256k1_musig_compute_pk_hash(ctx, ecmult_data.pk_hash, pubkeys, n_pubkeys)) { - return 0; - } - /* TODO: actually use optimized ecmult_multi algorithms by providing a - * scratch space */ - if (!secp256k1_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, secp256k1_musig_pubkey_agg_callback, (void *) &ecmult_data, n_pubkeys)) { - /* In order to reach this line with the current implementation of - * ecmult_multi_var one would need to provide a callback that can - * fail. */ - return 0; - } - secp256k1_ge_set_gej(&pkp, &pkj); - secp256k1_fe_normalize_var(&pkp.y); - /* The resulting public key is infinity with negligible probability */ - VERIFY_CHECK(!secp256k1_ge_is_infinity(&pkp)); - if (keyagg_cache != NULL) { - secp256k1_keyagg_cache_internal cache_i = { 0 }; - cache_i.pk = pkp; - cache_i.second_pk = ecmult_data.second_pk; - memcpy(cache_i.pk_hash, ecmult_data.pk_hash, sizeof(cache_i.pk_hash)); - secp256k1_keyagg_cache_save(keyagg_cache, &cache_i); - } - - secp256k1_extrakeys_ge_even_y(&pkp); - if (agg_pk != NULL) { - secp256k1_xonly_pubkey_save(agg_pk, &pkp); - } - return 1; -} - -int secp256k1_musig_pubkey_get(const secp256k1_context* ctx, secp256k1_pubkey *agg_pk, const secp256k1_musig_keyagg_cache *keyagg_cache) { - secp256k1_keyagg_cache_internal cache_i; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(agg_pk != NULL); - memset(agg_pk, 0, sizeof(*agg_pk)); - ARG_CHECK(keyagg_cache != NULL); - - if(!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - secp256k1_pubkey_save(agg_pk, &cache_i.pk); - return 1; -} - -static int secp256k1_musig_pubkey_tweak_add_internal(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32, int xonly) { - secp256k1_keyagg_cache_internal cache_i; - int overflow = 0; - secp256k1_scalar tweak; - - VERIFY_CHECK(ctx != NULL); - if (output_pubkey != NULL) { - memset(output_pubkey, 0, sizeof(*output_pubkey)); - } - ARG_CHECK(keyagg_cache != NULL); - ARG_CHECK(tweak32 != NULL); - - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - secp256k1_scalar_set_b32(&tweak, tweak32, &overflow); - if (overflow) { - return 0; - } - if (xonly && secp256k1_extrakeys_ge_even_y(&cache_i.pk)) { - cache_i.parity_acc ^= 1; - secp256k1_scalar_negate(&cache_i.tweak, &cache_i.tweak); - } - secp256k1_scalar_add(&cache_i.tweak, &cache_i.tweak, &tweak); - if (!secp256k1_eckey_pubkey_tweak_add(&cache_i.pk, &tweak)) { - return 0; - } - /* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */ - VERIFY_CHECK(!secp256k1_ge_is_infinity(&cache_i.pk)); - secp256k1_keyagg_cache_save(keyagg_cache, &cache_i); - if (output_pubkey != NULL) { - secp256k1_pubkey_save(output_pubkey, &cache_i.pk); - } - return 1; -} - -int secp256k1_musig_pubkey_ec_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { - return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0); -} - -int secp256k1_musig_pubkey_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { - return secp256k1_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1); -} - -#endif diff --git a/src/modules/musig/main_impl.h b/src/modules/musig/main_impl.h deleted file mode 100644 index e69afed5..00000000 --- a/src/modules/musig/main_impl.h +++ /dev/null @@ -1,14 +0,0 @@ -/********************************************************************** - * Copyright (c) 2018 Andrew Poelstra, Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_MAIN_H -#define SECP256K1_MODULE_MUSIG_MAIN_H - -#include "keyagg_impl.h" -#include "session_impl.h" -#include "adaptor_impl.h" - -#endif diff --git a/src/modules/musig/musig.md b/src/modules/musig/musig.md deleted file mode 100644 index 44b0de4f..00000000 --- a/src/modules/musig/musig.md +++ /dev/null @@ -1,63 +0,0 @@ -Notes on the musig module API -=========================== - -The following sections contain additional notes on the API of the musig module (`include/secp256k1_musig.h`). -A usage example can be found in `examples/musig.c`. - -# API misuse - -The musig API is designed to be as misuse resistant as possible. -However, the MuSig protocol has some additional failure modes (mainly due to interactivity) that do not appear in single-signing. -While the results can be catastrophic (e.g. leaking of the secret key), it is unfortunately not possible for the musig implementation to rule out all such failure modes. - -Therefore, users of the musig module must take great care to make sure of the following: - -1. A unique nonce per signing session is generated in `secp256k1_musig_nonce_gen`. - See the corresponding comment in `include/secp256k1_musig.h` for how to ensure that. -2. The `secp256k1_musig_secnonce` structure is never copied or serialized. - See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`. -3. Opaque data structures are never written to or read from directly. - Instead, only the provided accessor functions are used. -4. If adaptor signatures are used, all partial signatures are verified. - -# Key Aggregation and (Taproot) Tweaking - -Given a set of public keys, the aggregate public key is computed with `secp256k1_musig_pubkey_agg`. -A (Taproot) tweak can be added to the resulting public key with `secp256k1_xonly_pubkey_tweak_add` and a plain tweak can be added with `secp256k1_ec_pubkey_tweak_add`. - -# Signing - -This is covered by `examples/musig.c`. -Essentially, the protocol proceeds in the following steps: - -1. Generate a keypair with `secp256k1_keypair_create` and obtain the public key with `secp256k1_keypair_pub`. -2. Call `secp256k1_musig_pubkey_agg` with the pubkeys of all participants. -3. Optionally add a (Taproot) tweak with `secp256k1_musig_pubkey_xonly_tweak_add` and a plain tweak with `secp256k1_musig_pubkey_ec_tweak_add`. -4. Generate a pair of secret and public nonce with `secp256k1_musig_nonce_gen` and send the public nonce to the other signers. -5. Someone (not necessarily the signer) aggregates the public nonce with `secp256k1_musig_nonce_agg` and sends it to the signers. -6. Process the aggregate nonce with `secp256k1_musig_nonce_process`. -7. Create a partial signature with `secp256k1_musig_partial_sign`. -8. Verify the partial signatures (optional in some scenarios) with `secp256k1_musig_partial_sig_verify`. -9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `secp256k1_musig_partial_sig_agg`. - -The aggregate signature can be verified with `secp256k1_schnorrsig_verify`. - -Note that steps 1 to 5 can happen before the message to be signed is known to the signers. -Therefore, the communication round to exchange nonces can be viewed as a pre-processing step that is run whenever convenient to the signers. -This disables some of the defense-in-depth measures that may protect against API misuse in some cases. -Similarly, the API supports an alternative protocol flow where generating the aggregate key (steps 1 to 3) is allowed to happen after exchanging nonces (steps 4 to 5). - -# Verification - -A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. - -# Atomic Swaps - -The signing API supports the production of "adaptor signatures", modified partial signatures -which are offset by an auxiliary secret known to one party. That is, -1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`. -2. When calling `secp256k1_musig_nonce_process`, the public adaptor `T` is provided as the `adaptor` argument. -3. The party who is going to extract the secret adaptor `t` later must verify all partial signatures. -4. Due to step 2, the signature output of `secp256k1_musig_partial_sig_agg` is a pre-signature and not a valid Schnorr signature. All parties involved extract this session's `nonce_parity` with `secp256k1_musig_nonce_parity`. -5. The party who knows `t` must "adapt" the pre-signature with `t` (and the `nonce_parity` using `secp256k1_musig_adapt` to complete the signature. -6. Any party who sees both the final signature and the pre-signature (and has the `nonce_parity`) can extract `t` with `secp256k1_musig_extract_adaptor`. diff --git a/src/modules/musig/session.h b/src/modules/musig/session.h deleted file mode 100644 index dfaa5e0d..00000000 --- a/src/modules/musig/session.h +++ /dev/null @@ -1,25 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_SESSION_H -#define SECP256K1_MODULE_MUSIG_SESSION_H - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_musig.h" - -#include "../../scalar.h" - -typedef struct { - int fin_nonce_parity; - unsigned char fin_nonce[32]; - secp256k1_scalar noncecoef; - secp256k1_scalar challenge; - secp256k1_scalar s_part; -} secp256k1_musig_session_internal; - -static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session); - -#endif diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h deleted file mode 100644 index ff87f2fd..00000000 --- a/src/modules/musig/session_impl.h +++ /dev/null @@ -1,705 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2021 Jonas Nick * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_SESSION_IMPL_H -#define SECP256K1_MODULE_MUSIG_SESSION_IMPL_H - -#include - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_extrakeys.h" -#include "../../../include/secp256k1_musig.h" - -#include "keyagg.h" -#include "session.h" -#include "../../eckey.h" -#include "../../hash.h" -#include "../../scalar.h" -#include "../../util.h" - -static const unsigned char secp256k1_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 }; - -static void secp256k1_musig_secnonce_save(secp256k1_musig_secnonce *secnonce, const secp256k1_scalar *k, secp256k1_ge *pk) { - memcpy(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4); - secp256k1_scalar_get_b32(&secnonce->data[4], &k[0]); - secp256k1_scalar_get_b32(&secnonce->data[36], &k[1]); - secp256k1_ge_to_bytes(&secnonce->data[68], pk); -} - -static int secp256k1_musig_secnonce_load(const secp256k1_context* ctx, secp256k1_scalar *k, secp256k1_ge *pk, secp256k1_musig_secnonce *secnonce) { - int is_zero; - ARG_CHECK(secp256k1_memcmp_var(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4) == 0); - secp256k1_scalar_set_b32(&k[0], &secnonce->data[4], NULL); - secp256k1_scalar_set_b32(&k[1], &secnonce->data[36], NULL); - secp256k1_ge_from_bytes(pk, &secnonce->data[68]); - /* We make very sure that the nonce isn't invalidated by checking the values - * in addition to the magic. */ - is_zero = secp256k1_scalar_is_zero(&k[0]) & secp256k1_scalar_is_zero(&k[1]); - secp256k1_declassify(ctx, &is_zero, sizeof(is_zero)); - ARG_CHECK(!is_zero); - return 1; -} - -/* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */ -static void secp256k1_musig_secnonce_invalidate(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, int flag) { - secp256k1_memczero(secnonce->data, sizeof(secnonce->data), flag); - /* The flag argument is usually classified. So, the line above makes the - * magic and public key classified. However, we need both to be - * declassified. Note that we don't declassify the entire object, because if - * flag is 0, then k[0] and k[1] have not been zeroed. */ - secp256k1_declassify(ctx, secnonce->data, sizeof(secp256k1_musig_secnonce_magic)); - secp256k1_declassify(ctx, &secnonce->data[68], 64); -} - -static const unsigned char secp256k1_musig_pubnonce_magic[4] = { 0xf5, 0x7a, 0x3d, 0xa0 }; - -/* Saves two group elements into a pubnonce. Requires that none of the provided - * group elements is infinity. */ -static void secp256k1_musig_pubnonce_save(secp256k1_musig_pubnonce* nonce, secp256k1_ge* ge) { - int i; - memcpy(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4); - for (i = 0; i < 2; i++) { - secp256k1_ge_to_bytes(nonce->data + 4+64*i, &ge[i]); - } -} - -/* Loads two group elements from a pubnonce. Returns 1 unless the nonce wasn't - * properly initialized */ -static int secp256k1_musig_pubnonce_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_musig_pubnonce* nonce) { - int i; - - ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_pubnonce_magic, 4) == 0); - for (i = 0; i < 2; i++) { - secp256k1_ge_from_bytes(&ge[i], nonce->data + 4 + 64*i); - } - return 1; -} - -static const unsigned char secp256k1_musig_aggnonce_magic[4] = { 0xa8, 0xb7, 0xe4, 0x67 }; - -static void secp256k1_musig_aggnonce_save(secp256k1_musig_aggnonce* nonce, secp256k1_ge* ge) { - int i; - memcpy(&nonce->data[0], secp256k1_musig_aggnonce_magic, 4); - for (i = 0; i < 2; i++) { - secp256k1_point_save_ext(&nonce->data[4 + 64*i], &ge[i]); - } -} - -static int secp256k1_musig_aggnonce_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_musig_aggnonce* nonce) { - int i; - - ARG_CHECK(secp256k1_memcmp_var(&nonce->data[0], secp256k1_musig_aggnonce_magic, 4) == 0); - for (i = 0; i < 2; i++) { - secp256k1_point_load_ext(&ge[i], &nonce->data[4 + 64*i]); - } - return 1; -} - -static const unsigned char secp256k1_musig_session_cache_magic[4] = { 0x9d, 0xed, 0xe9, 0x17 }; - -/* A session consists of - * - 4 byte session cache magic - * - 1 byte the parity of the final nonce - * - 32 byte serialized x-only final nonce - * - 32 byte nonce coefficient b - * - 32 byte signature challenge hash e - * - 32 byte scalar s that is added to the partial signatures of the signers - */ -static void secp256k1_musig_session_save(secp256k1_musig_session *session, const secp256k1_musig_session_internal *session_i) { - unsigned char *ptr = session->data; - - memcpy(ptr, secp256k1_musig_session_cache_magic, 4); - ptr += 4; - *ptr = session_i->fin_nonce_parity; - ptr += 1; - memcpy(ptr, session_i->fin_nonce, 32); - ptr += 32; - secp256k1_scalar_get_b32(ptr, &session_i->noncecoef); - ptr += 32; - secp256k1_scalar_get_b32(ptr, &session_i->challenge); - ptr += 32; - secp256k1_scalar_get_b32(ptr, &session_i->s_part); -} - -static int secp256k1_musig_session_load(const secp256k1_context* ctx, secp256k1_musig_session_internal *session_i, const secp256k1_musig_session *session) { - const unsigned char *ptr = session->data; - - ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_musig_session_cache_magic, 4) == 0); - ptr += 4; - session_i->fin_nonce_parity = *ptr; - ptr += 1; - memcpy(session_i->fin_nonce, ptr, 32); - ptr += 32; - secp256k1_scalar_set_b32(&session_i->noncecoef, ptr, NULL); - ptr += 32; - secp256k1_scalar_set_b32(&session_i->challenge, ptr, NULL); - ptr += 32; - secp256k1_scalar_set_b32(&session_i->s_part, ptr, NULL); - return 1; -} - -static const unsigned char secp256k1_musig_partial_sig_magic[4] = { 0xeb, 0xfb, 0x1a, 0x32 }; - -static void secp256k1_musig_partial_sig_save(secp256k1_musig_partial_sig* sig, secp256k1_scalar *s) { - memcpy(&sig->data[0], secp256k1_musig_partial_sig_magic, 4); - secp256k1_scalar_get_b32(&sig->data[4], s); -} - -static int secp256k1_musig_partial_sig_load(const secp256k1_context* ctx, secp256k1_scalar *s, const secp256k1_musig_partial_sig* sig) { - int overflow; - - ARG_CHECK(secp256k1_memcmp_var(&sig->data[0], secp256k1_musig_partial_sig_magic, 4) == 0); - secp256k1_scalar_set_b32(s, &sig->data[4], &overflow); - /* Parsed signatures can not overflow */ - VERIFY_CHECK(!overflow); - return 1; -} - -int secp256k1_musig_pubnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_pubnonce* nonce) { - secp256k1_ge ge[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(out66 != NULL); - memset(out66, 0, 66); - ARG_CHECK(nonce != NULL); - - if (!secp256k1_musig_pubnonce_load(ctx, ge, nonce)) { - return 0; - } - for (i = 0; i < 2; i++) { - int ret; - size_t size = 33; - ret = secp256k1_eckey_pubkey_serialize(&ge[i], &out66[33*i], &size, 1); -#ifdef VERIFY - /* serialize must succeed because the point was just loaded */ - VERIFY_CHECK(ret && size == 33); -#else - (void) ret; -#endif - } - return 1; -} - -int secp256k1_musig_pubnonce_parse(const secp256k1_context* ctx, secp256k1_musig_pubnonce* nonce, const unsigned char *in66) { - secp256k1_ge ge[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(nonce != NULL); - ARG_CHECK(in66 != NULL); - - for (i = 0; i < 2; i++) { - if (!secp256k1_eckey_pubkey_parse(&ge[i], &in66[33*i], 33)) { - return 0; - } - if (!secp256k1_ge_is_in_correct_subgroup(&ge[i])) { - return 0; - } - } - secp256k1_musig_pubnonce_save(nonce, ge); - return 1; -} - -int secp256k1_musig_aggnonce_serialize(const secp256k1_context* ctx, unsigned char *out66, const secp256k1_musig_aggnonce* nonce) { - secp256k1_ge ge[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(out66 != NULL); - memset(out66, 0, 66); - ARG_CHECK(nonce != NULL); - - if (!secp256k1_musig_aggnonce_load(ctx, ge, nonce)) { - return 0; - } - for (i = 0; i < 2; i++) { - secp256k1_ge_serialize_ext(&out66[33*i], &ge[i]); - } - return 1; -} - -int secp256k1_musig_aggnonce_parse(const secp256k1_context* ctx, secp256k1_musig_aggnonce* nonce, const unsigned char *in66) { - secp256k1_ge ge[2]; - int i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(nonce != NULL); - ARG_CHECK(in66 != NULL); - - for (i = 0; i < 2; i++) { - if (!secp256k1_ge_parse_ext(&ge[i], &in66[33*i])) { - return 0; - } - } - secp256k1_musig_aggnonce_save(nonce, ge); - return 1; -} - -int secp256k1_musig_partial_sig_serialize(const secp256k1_context* ctx, unsigned char *out32, const secp256k1_musig_partial_sig* sig) { - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(out32 != NULL); - ARG_CHECK(sig != NULL); - memcpy(out32, &sig->data[4], 32); - return 1; -} - -int secp256k1_musig_partial_sig_parse(const secp256k1_context* ctx, secp256k1_musig_partial_sig* sig, const unsigned char *in32) { - secp256k1_scalar tmp; - int overflow; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig != NULL); - ARG_CHECK(in32 != NULL); - - secp256k1_scalar_set_b32(&tmp, in32, &overflow); - if (overflow) { - return 0; - } - secp256k1_musig_partial_sig_save(sig, &tmp); - return 1; -} - -/* Write optional inputs into the hash */ -static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigned int prefix_size, const unsigned char *data, unsigned char len) { - unsigned char zero[7] = { 0 }; - /* The spec requires length prefixes to be between 1 and 8 bytes - * (inclusive) */ - VERIFY_CHECK(prefix_size <= 8); - /* Since the length of all input data fits in a byte, we can always pad the - * length prefix with prefix_size - 1 zero bytes. */ - secp256k1_sha256_write(sha, zero, prefix_size - 1); - if (data != NULL) { - secp256k1_sha256_write(sha, &len, 1); - secp256k1_sha256_write(sha, data, len); - } else { - len = 0; - secp256k1_sha256_write(sha, &len, 1); - } -} - -static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_id, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { - secp256k1_sha256 sha; - unsigned char rand[32]; - unsigned char i; - unsigned char msg_present; - - if (seckey32 != NULL) { - secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"MuSig/aux", sizeof("MuSig/aux") - 1); - secp256k1_sha256_write(&sha, session_id, 32); - secp256k1_sha256_finalize(&sha, rand); - for (i = 0; i < 32; i++) { - rand[i] ^= seckey32[i]; - } - } else { - memcpy(rand, session_id, sizeof(rand)); - } - - /* Subtract one from `sizeof` to avoid hashing the implicit null byte */ - secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"MuSig/nonce", sizeof("MuSig/nonce") - 1); - secp256k1_sha256_write(&sha, rand, sizeof(rand)); - secp256k1_nonce_function_musig_helper(&sha, 1, pk33, 33); - secp256k1_nonce_function_musig_helper(&sha, 1, agg_pk32, 32); - msg_present = msg32 != NULL; - secp256k1_sha256_write(&sha, &msg_present, 1); - if (msg_present) { - secp256k1_nonce_function_musig_helper(&sha, 8, msg32, 32); - } - secp256k1_nonce_function_musig_helper(&sha, 4, extra_input32, 32); - - for (i = 0; i < 2; i++) { - unsigned char buf[32]; - secp256k1_sha256 sha_tmp = sha; - secp256k1_sha256_write(&sha_tmp, &i, 1); - secp256k1_sha256_finalize(&sha_tmp, buf); - secp256k1_scalar_set_b32(&k[i], buf, NULL); - } -} - -int secp256k1_musig_nonce_gen(const secp256k1_context* ctx, secp256k1_musig_secnonce *secnonce, secp256k1_musig_pubnonce *pubnonce, const unsigned char *session_id32, const unsigned char *seckey, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { - secp256k1_keyagg_cache_internal cache_i; - secp256k1_scalar k[2]; - secp256k1_ge nonce_pt[2]; - int i; - unsigned char pk_ser[33]; - size_t pk_ser_len = sizeof(pk_ser); - unsigned char aggpk_ser[32]; - unsigned char *aggpk_ser_ptr = NULL; - secp256k1_ge pk; - int pk_serialize_success; - int ret = 1; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(secnonce != NULL); - memset(secnonce, 0, sizeof(*secnonce)); - ARG_CHECK(pubnonce != NULL); - memset(pubnonce, 0, sizeof(*pubnonce)); - ARG_CHECK(session_id32 != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); - if (seckey == NULL) { - /* Check in constant time that the session_id is not 0 as a - * defense-in-depth measure that may protect against a faulty RNG. */ - unsigned char acc = 0; - for (i = 0; i < 32; i++) { - acc |= session_id32[i]; - } - ret &= !!acc; - memset(&acc, 0, sizeof(acc)); - } - - /* Check that the seckey is valid to be able to sign for it later. */ - if (seckey != NULL) { - secp256k1_scalar sk; - ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey); - secp256k1_scalar_clear(&sk); - } - - if (keyagg_cache != NULL) { - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - /* The loaded point cache_i.pk can not be the point at infinity. */ - secp256k1_fe_get_b32(aggpk_ser, &cache_i.pk.x); - aggpk_ser_ptr = aggpk_ser; - } - if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { - return 0; - } - pk_serialize_success = secp256k1_eckey_pubkey_serialize(&pk, pk_ser, &pk_ser_len, SECP256K1_EC_COMPRESSED); - -#ifdef VERIFY - /* A pubkey cannot be the point at infinity */ - VERIFY_CHECK(pk_serialize_success); - VERIFY_CHECK(pk_ser_len == sizeof(pk_ser)); -#else - (void) pk_serialize_success; -#endif - - secp256k1_nonce_function_musig(k, session_id32, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); - VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); - VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); - VERIFY_CHECK(!secp256k1_scalar_eq(&k[0], &k[1])); - secp256k1_musig_secnonce_save(secnonce, k, &pk); - secp256k1_musig_secnonce_invalidate(ctx, secnonce, !ret); - - for (i = 0; i < 2; i++) { - secp256k1_gej nonce_ptj; - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); - secp256k1_ge_set_gej(&nonce_pt[i], &nonce_ptj); - secp256k1_declassify(ctx, &nonce_pt[i], sizeof(nonce_pt)); - secp256k1_scalar_clear(&k[i]); - } - /* nonce_pt won't be infinity because k != 0 with overwhelming probability */ - secp256k1_musig_pubnonce_save(pubnonce, nonce_pt); - return ret; -} - -static int secp256k1_musig_sum_nonces(const secp256k1_context* ctx, secp256k1_gej *summed_nonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { - size_t i; - int j; - - secp256k1_gej_set_infinity(&summed_nonces[0]); - secp256k1_gej_set_infinity(&summed_nonces[1]); - - for (i = 0; i < n_pubnonces; i++) { - secp256k1_ge nonce_pt[2]; - if (!secp256k1_musig_pubnonce_load(ctx, nonce_pt, pubnonces[i])) { - return 0; - } - for (j = 0; j < 2; j++) { - secp256k1_gej_add_ge_var(&summed_nonces[j], &summed_nonces[j], &nonce_pt[j], NULL); - } - } - return 1; -} - -int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggnonce *aggnonce, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { - secp256k1_gej aggnonce_ptj[2]; - secp256k1_ge aggnonce_pt[2]; - int i; - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(aggnonce != NULL); - ARG_CHECK(pubnonces != NULL); - ARG_CHECK(n_pubnonces > 0); - - if (!secp256k1_musig_sum_nonces(ctx, aggnonce_ptj, pubnonces, n_pubnonces)) { - return 0; - } - for (i = 0; i < 2; i++) { - secp256k1_ge_set_gej(&aggnonce_pt[i], &aggnonce_ptj[i]); - } - secp256k1_musig_aggnonce_save(aggnonce, aggnonce_pt); - return 1; -} - -/* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ -static int secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { - unsigned char buf[33]; - secp256k1_sha256 sha; - int i; - - secp256k1_sha256_initialize_tagged(&sha, (unsigned char*)"MuSig/noncecoef", sizeof("MuSig/noncecoef") - 1); - for (i = 0; i < 2; i++) { - secp256k1_ge_serialize_ext(buf, &aggnonce[i]); - secp256k1_sha256_write(&sha, buf, sizeof(buf)); - } - secp256k1_sha256_write(&sha, agg_pk32, 32); - secp256k1_sha256_write(&sha, msg, 32); - secp256k1_sha256_finalize(&sha, noncehash); - return 1; -} - -static int secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_gej *aggnoncej, const unsigned char *agg_pk32, const unsigned char *msg) { - unsigned char noncehash[32]; - secp256k1_ge fin_nonce_pt; - secp256k1_gej fin_nonce_ptj; - secp256k1_ge aggnonce[2]; - - secp256k1_ge_set_gej(&aggnonce[0], &aggnoncej[0]); - secp256k1_ge_set_gej(&aggnonce[1], &aggnoncej[1]); - if (!secp256k1_musig_compute_noncehash(noncehash, aggnonce, agg_pk32, msg)) { - return 0; - } - /* fin_nonce = aggnonce[0] + b*aggnonce[1] */ - secp256k1_scalar_set_b32(b, noncehash, NULL); - secp256k1_gej_set_infinity(&fin_nonce_ptj); - secp256k1_ecmult(&fin_nonce_ptj, &aggnoncej[1], b, NULL); - secp256k1_gej_add_ge_var(&fin_nonce_ptj, &fin_nonce_ptj, &aggnonce[0], NULL); - secp256k1_ge_set_gej(&fin_nonce_pt, &fin_nonce_ptj); - if (secp256k1_ge_is_infinity(&fin_nonce_pt)) { - fin_nonce_pt = secp256k1_ge_const_g; - } - /* fin_nonce_pt is not the point at infinity */ - secp256k1_fe_normalize_var(&fin_nonce_pt.x); - secp256k1_fe_get_b32(fin_nonce, &fin_nonce_pt.x); - secp256k1_fe_normalize_var(&fin_nonce_pt.y); - *fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y); - return 1; -} - -int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey *adaptor) { - secp256k1_keyagg_cache_internal cache_i; - secp256k1_ge aggnonce_pt[2]; - secp256k1_gej aggnonce_ptj[2]; - unsigned char fin_nonce[32]; - secp256k1_musig_session_internal session_i; - unsigned char agg_pk32[32]; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(session != NULL); - ARG_CHECK(aggnonce != NULL); - ARG_CHECK(msg32 != NULL); - ARG_CHECK(keyagg_cache != NULL); - - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - secp256k1_fe_get_b32(agg_pk32, &cache_i.pk.x); - - if (!secp256k1_musig_aggnonce_load(ctx, aggnonce_pt, aggnonce)) { - return 0; - } - secp256k1_gej_set_ge(&aggnonce_ptj[0], &aggnonce_pt[0]); - secp256k1_gej_set_ge(&aggnonce_ptj[1], &aggnonce_pt[1]); - /* Add public adaptor to nonce */ - if (adaptor != NULL) { - secp256k1_ge adaptorp; - if (!secp256k1_pubkey_load(ctx, &adaptorp, adaptor)) { - return 0; - } - secp256k1_gej_add_ge_var(&aggnonce_ptj[0], &aggnonce_ptj[0], &adaptorp, NULL); - } - if (!secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_ptj, agg_pk32, msg32)) { - return 0; - } - - secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32); - - /* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/ - secp256k1_scalar_set_int(&session_i.s_part, 0); - if (!secp256k1_scalar_is_zero(&cache_i.tweak)) { - secp256k1_scalar e_tmp; - secp256k1_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak); - if (secp256k1_fe_is_odd(&cache_i.pk.y)) { - secp256k1_scalar_negate(&e_tmp, &e_tmp); - } - secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &e_tmp); - } - memcpy(session_i.fin_nonce, fin_nonce, sizeof(session_i.fin_nonce)); - secp256k1_musig_session_save(session, &session_i); - return 1; -} - -static void secp256k1_musig_partial_sign_clear(secp256k1_scalar *sk, secp256k1_scalar *k) { - secp256k1_scalar_clear(sk); - secp256k1_scalar_clear(&k[0]); - secp256k1_scalar_clear(&k[1]); -} - -int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_partial_sig *partial_sig, secp256k1_musig_secnonce *secnonce, const secp256k1_keypair *keypair, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { - secp256k1_scalar sk; - secp256k1_ge pk, keypair_pk; - secp256k1_scalar k[2]; - secp256k1_scalar mu, s; - secp256k1_keyagg_cache_internal cache_i; - secp256k1_musig_session_internal session_i; - int ret; - - VERIFY_CHECK(ctx != NULL); - - ARG_CHECK(secnonce != NULL); - /* Fails if the magic doesn't match */ - ret = secp256k1_musig_secnonce_load(ctx, k, &pk, secnonce); - /* Set nonce to zero to avoid nonce reuse. This will cause subsequent calls - * of this function to fail */ - memset(secnonce, 0, sizeof(*secnonce)); - if (!ret) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - - ARG_CHECK(partial_sig != NULL); - ARG_CHECK(keypair != NULL); - ARG_CHECK(keyagg_cache != NULL); - ARG_CHECK(session != NULL); - - if (!secp256k1_keypair_load(ctx, &sk, &keypair_pk, keypair)) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - ARG_CHECK(secp256k1_fe_equal(&pk.x, &keypair_pk.x) - && secp256k1_fe_equal(&pk.y, &keypair_pk.y)); - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - secp256k1_fe_normalize_var(&pk.y); - - /* Negate sk if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. - * This corresponds to the line "Let d = g⋅gacc⋅d' mod n" in the - * specification. */ - if ((secp256k1_fe_is_odd(&cache_i.pk.y) - != cache_i.parity_acc)) { - secp256k1_scalar_negate(&sk, &sk); - } - - /* Multiply KeyAgg coefficient */ - secp256k1_fe_normalize_var(&pk.x); - /* TODO Cache mu */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pk); - secp256k1_scalar_mul(&sk, &sk, &mu); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - secp256k1_musig_partial_sign_clear(&sk, k); - return 0; - } - - if (session_i.fin_nonce_parity) { - secp256k1_scalar_negate(&k[0], &k[0]); - secp256k1_scalar_negate(&k[1], &k[1]); - } - - /* Sign */ - secp256k1_scalar_mul(&s, &session_i.challenge, &sk); - secp256k1_scalar_mul(&k[1], &session_i.noncecoef, &k[1]); - secp256k1_scalar_add(&k[0], &k[0], &k[1]); - secp256k1_scalar_add(&s, &s, &k[0]); - secp256k1_musig_partial_sig_save(partial_sig, &s); - secp256k1_musig_partial_sign_clear(&sk, k); - return 1; -} - -int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp256k1_musig_partial_sig *partial_sig, const secp256k1_musig_pubnonce *pubnonce, const secp256k1_pubkey *pubkey, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_musig_session *session) { - secp256k1_keyagg_cache_internal cache_i; - secp256k1_musig_session_internal session_i; - secp256k1_scalar mu, e, s; - secp256k1_gej pkj; - secp256k1_ge nonce_pt[2]; - secp256k1_gej rj; - secp256k1_gej tmp; - secp256k1_ge pkp; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(partial_sig != NULL); - ARG_CHECK(pubnonce != NULL); - ARG_CHECK(pubkey != NULL); - ARG_CHECK(keyagg_cache != NULL); - ARG_CHECK(session != NULL); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - return 0; - } - - /* Compute "effective" nonce rj = aggnonce[0] + b*aggnonce[1] */ - /* TODO: use multiexp to compute -s*G + e*mu*pubkey + aggnonce[0] + b*aggnonce[1] */ - if (!secp256k1_musig_pubnonce_load(ctx, nonce_pt, pubnonce)) { - return 0; - } - secp256k1_gej_set_ge(&rj, &nonce_pt[1]); - secp256k1_ecmult(&rj, &rj, &session_i.noncecoef, NULL); - secp256k1_gej_add_ge_var(&rj, &rj, &nonce_pt[0], NULL); - - if (!secp256k1_pubkey_load(ctx, &pkp, pubkey)) { - return 0; - } - if (!secp256k1_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { - return 0; - } - /* Multiplying the challenge by the KeyAgg coefficient is equivalent - * to multiplying the signer's public key by the coefficient, except - * much easier to do. */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp); - secp256k1_scalar_mul(&e, &session_i.challenge, &mu); - - /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. - * This corresponds to the line "Let g' = g⋅gacc mod n" and the multiplication "g'⋅e" - * in the specification. */ - if (secp256k1_fe_is_odd(&cache_i.pk.y) - != cache_i.parity_acc) { - secp256k1_scalar_negate(&e, &e); - } - - if (!secp256k1_musig_partial_sig_load(ctx, &s, partial_sig)) { - return 0; - } - /* Compute -s*G + e*pkj + rj (e already includes the keyagg coefficient mu) */ - secp256k1_scalar_negate(&s, &s); - secp256k1_gej_set_ge(&pkj, &pkp); - secp256k1_ecmult(&tmp, &pkj, &e, &s); - if (session_i.fin_nonce_parity) { - secp256k1_gej_neg(&rj, &rj); - } - secp256k1_gej_add_var(&tmp, &tmp, &rj, NULL); - - return secp256k1_gej_is_infinity(&tmp); -} - -int secp256k1_musig_partial_sig_agg(const secp256k1_context* ctx, unsigned char *sig64, const secp256k1_musig_session *session, const secp256k1_musig_partial_sig * const* partial_sigs, size_t n_sigs) { - size_t i; - secp256k1_musig_session_internal session_i; - - VERIFY_CHECK(ctx != NULL); - ARG_CHECK(sig64 != NULL); - ARG_CHECK(session != NULL); - ARG_CHECK(partial_sigs != NULL); - ARG_CHECK(n_sigs > 0); - - if (!secp256k1_musig_session_load(ctx, &session_i, session)) { - return 0; - } - for (i = 0; i < n_sigs; i++) { - secp256k1_scalar term; - if (!secp256k1_musig_partial_sig_load(ctx, &term, partial_sigs[i])) { - return 0; - } - secp256k1_scalar_add(&session_i.s_part, &session_i.s_part, &term); - } - secp256k1_scalar_get_b32(&sig64[32], &session_i.s_part); - memcpy(&sig64[0], session_i.fin_nonce, 32); - return 1; -} - -#endif diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h deleted file mode 100644 index 13b41249..00000000 --- a/src/modules/musig/tests_impl.h +++ /dev/null @@ -1,1193 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2018 Andrew Poelstra * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or https://www.opensource.org/licenses/mit-license.php.* - ***********************************************************************/ - -#ifndef SECP256K1_MODULE_MUSIG_TESTS_IMPL_H -#define SECP256K1_MODULE_MUSIG_TESTS_IMPL_H - -#include -#include - -#include "../../../include/secp256k1.h" -#include "../../../include/secp256k1_extrakeys.h" -#include "../../../include/secp256k1_musig.h" - -#include "session.h" -#include "keyagg.h" -#include "../../scalar.h" -#include "../../scratch.h" -#include "../../field.h" -#include "../../group.h" -#include "../../hash.h" -#include "../../util.h" - -#include "vectors.h" - -static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *pk, const unsigned char *sk) { - int ret; - secp256k1_keypair keypair_tmp; - ret = secp256k1_keypair_create(CTX, &keypair_tmp, sk); - ret &= secp256k1_keypair_pub(CTX, pk, &keypair_tmp); - if (keypair != NULL) { - *keypair = keypair_tmp; - } - return ret; -} - -/* Just a simple (non-adaptor, non-tweaked) 2-of-2 MuSig aggregate, sign, verify - * test. */ -static void musig_simple_test(secp256k1_scratch_space *scratch) { - unsigned char sk[2][32]; - secp256k1_keypair keypair[2]; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - secp256k1_musig_aggnonce aggnonce; - unsigned char msg[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - unsigned char session_id[2][32]; - secp256k1_musig_secnonce secnonce[2]; - secp256k1_pubkey pk[2]; - const secp256k1_pubkey *pk_ptr[2]; - secp256k1_musig_partial_sig partial_sig[2]; - const secp256k1_musig_partial_sig *partial_sig_ptr[2]; - unsigned char final_sig[64]; - secp256k1_musig_session session; - int i; - - testrand256(msg); - for (i = 0; i < 2; i++) { - testrand256(session_id[i]); - testrand256(sk[i]); - pk_ptr[i] = &pk[i]; - pubnonce_ptr[i] = &pubnonce[i]; - partial_sig_ptr[i] = &partial_sig[i]; - - CHECK(create_keypair_and_pk(&keypair[i], &pk[i], sk[i])); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[i], &pubnonce[i], session_id[i], sk[i], &pk[i], NULL, NULL, NULL) == 1); - } - - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, NULL) == 1); - - for (i = 0; i < 2; i++) { - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[i], &secnonce[i], &keypair[i], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[i], &pubnonce[i], &pk[i], &keyagg_cache, &session) == 1); - } - - CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); -} - -static void pubnonce_summing_to_inf(secp256k1_musig_pubnonce *pubnonce) { - secp256k1_ge ge[2]; - int i; - secp256k1_gej summed_nonces[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - - ge[0] = secp256k1_ge_const_g; - ge[1] = secp256k1_ge_const_g; - - for (i = 0; i < 2; i++) { - secp256k1_musig_pubnonce_save(&pubnonce[i], ge); - pubnonce_ptr[i] = &pubnonce[i]; - secp256k1_ge_neg(&ge[0], &ge[0]); - secp256k1_ge_neg(&ge[1], &ge[1]); - } - - secp256k1_musig_sum_nonces(CTX, summed_nonces, pubnonce_ptr, 2); - CHECK(secp256k1_gej_is_infinity(&summed_nonces[0])); - CHECK(secp256k1_gej_is_infinity(&summed_nonces[1])); -} - -int memcmp_and_randomize(unsigned char *value, const unsigned char *expected, size_t len) { - int ret; - size_t i; - ret = secp256k1_memcmp_var(value, expected, len); - for (i = 0; i < len; i++) { - value[i] = testrand_bits(8); - } - return ret; -} - -static void musig_api_tests(secp256k1_scratch_space *scratch) { - secp256k1_scratch_space *scratch_small; - secp256k1_musig_partial_sig partial_sig[2]; - const secp256k1_musig_partial_sig *partial_sig_ptr[2]; - secp256k1_musig_partial_sig invalid_partial_sig; - const secp256k1_musig_partial_sig *invalid_partial_sig_ptr[2]; - unsigned char final_sig[64]; - unsigned char pre_sig[64]; - unsigned char buf[32]; - unsigned char sk[2][32]; - secp256k1_keypair keypair[2]; - secp256k1_keypair invalid_keypair; - unsigned char max64[64]; - unsigned char zeros132[132] = { 0 }; - unsigned char session_id[2][32]; - secp256k1_musig_secnonce secnonce[2]; - secp256k1_musig_secnonce secnonce_tmp; - secp256k1_musig_secnonce invalid_secnonce; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - unsigned char pubnonce_ser[66]; - secp256k1_musig_pubnonce inf_pubnonce[2]; - const secp256k1_musig_pubnonce *inf_pubnonce_ptr[2]; - secp256k1_musig_pubnonce invalid_pubnonce; - const secp256k1_musig_pubnonce *invalid_pubnonce_ptr[1]; - secp256k1_musig_aggnonce aggnonce; - unsigned char aggnonce_ser[66]; - unsigned char msg[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_pubkey full_agg_pk; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_keyagg_cache invalid_keyagg_cache; - secp256k1_musig_session session; - secp256k1_musig_session invalid_session; - secp256k1_pubkey pk[2]; - const secp256k1_pubkey *pk_ptr[2]; - secp256k1_pubkey invalid_pk; - const secp256k1_pubkey *invalid_pk_ptr2[2]; - const secp256k1_pubkey *invalid_pk_ptr3[3]; - unsigned char tweak[32]; - int nonce_parity; - unsigned char sec_adaptor[32]; - unsigned char sec_adaptor1[32]; - secp256k1_pubkey adaptor; - int i; - - /** setup **/ - memset(max64, 0xff, sizeof(max64)); - memset(&invalid_keypair, 0, sizeof(invalid_keypair)); - memset(&invalid_pk, 0, sizeof(invalid_pk)); - memset(&invalid_secnonce, 0, sizeof(invalid_secnonce)); - memset(&invalid_partial_sig, 0, sizeof(invalid_partial_sig)); - pubnonce_summing_to_inf(inf_pubnonce); - /* Simulate structs being uninitialized by setting it to 0s. We don't want - * to produce undefined behavior by actually providing uninitialized - * structs. */ - memset(&invalid_keyagg_cache, 0, sizeof(invalid_keyagg_cache)); - memset(&invalid_pk, 0, sizeof(invalid_pk)); - memset(&invalid_pubnonce, 0, sizeof(invalid_pubnonce)); - memset(&invalid_session, 0, sizeof(invalid_session)); - - testrand256(sec_adaptor); - testrand256(msg); - testrand256(tweak); - CHECK(secp256k1_ec_pubkey_create(CTX, &adaptor, sec_adaptor) == 1); - for (i = 0; i < 2; i++) { - pk_ptr[i] = &pk[i]; - invalid_pk_ptr2[i] = &invalid_pk; - invalid_pk_ptr3[i] = &pk[i]; - pubnonce_ptr[i] = &pubnonce[i]; - inf_pubnonce_ptr[i] = &inf_pubnonce[i]; - partial_sig_ptr[i] = &partial_sig[i]; - invalid_partial_sig_ptr[i] = &partial_sig[i]; - testrand256(session_id[i]); - testrand256(sk[i]); - CHECK(create_keypair_and_pk(&keypair[i], &pk[i], sk[i])); - } - invalid_pubnonce_ptr[0] = &invalid_pubnonce; - invalid_partial_sig_ptr[0] = &invalid_partial_sig; - /* invalid_pk_ptr3 has two valid, one invalid pk, which is important to test - * musig_pubkey_agg */ - invalid_pk_ptr3[2] = &invalid_pk; - - /** main test body **/ - - /** Key aggregation **/ - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - /* pubkey_agg does not require a scratch space */ - CHECK(secp256k1_musig_pubkey_agg(CTX, NULL, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - /* A small scratch space works too, but will result in using an ineffecient algorithm */ - scratch_small = secp256k1_scratch_space_create(CTX, 1); - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch_small, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - secp256k1_scratch_space_destroy(CTX, scratch_small); - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, NULL, &keyagg_cache, pk_ptr, 2) == 1); - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, NULL, pk_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, NULL, 2)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, invalid_pk_ptr2, 2)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, invalid_pk_ptr3, 3)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, pk_ptr, 0)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, NULL, 0)); - CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); - - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); - - /* pubkey_get */ - CHECK(secp256k1_musig_pubkey_get(CTX, &full_agg_pk, &keyagg_cache) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_get(CTX, NULL, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubkey_get(CTX, &full_agg_pk, NULL)); - CHECK(secp256k1_memcmp_var(&full_agg_pk, zeros132, sizeof(full_agg_pk)) == 0); - - /** Tweaking **/ - { - int (*tweak_func[2]) (const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, secp256k1_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32); - tweak_func[0] = secp256k1_musig_pubkey_ec_tweak_add; - tweak_func[1] = secp256k1_musig_pubkey_xonly_tweak_add; - for (i = 0; i < 2; i++) { - secp256k1_pubkey tmp_output_pk; - secp256k1_musig_keyagg_cache tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1); - /* Reset keyagg_cache */ - tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, tweak) == 1); - tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, NULL, &tmp_keyagg_cache, tweak) == 1); - tmp_keyagg_cache = keyagg_cache; - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, NULL, tweak)); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - tmp_keyagg_cache = keyagg_cache; - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, NULL)); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - tmp_keyagg_cache = keyagg_cache; - CHECK((*tweak_func[i])(CTX, &tmp_output_pk, &tmp_keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - tmp_keyagg_cache = keyagg_cache; - /* Uninitialized keyagg_cache */ - CHECK_ILLEGAL(CTX, (*tweak_func[i])(CTX, &tmp_output_pk, &invalid_keyagg_cache, tweak)); - CHECK(memcmp_and_randomize(tmp_output_pk.data, zeros132, sizeof(tmp_output_pk.data)) == 0); - } - } - - /** Session creation **/ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &keyagg_cache, max64) == 1); - CHECK_ILLEGAL(STATIC_CTX, secp256k1_musig_nonce_gen(STATIC_CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, NULL, &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], NULL, session_id[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], NULL, sk[0], &pk[0], msg, &keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - /* no seckey and session_id is 0 */ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros132, NULL, &pk[0], msg, &keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - /* session_id 0 is fine when a seckey is provided */ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], zeros132, sk[0], &pk[0], msg, &keyagg_cache, max64) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], NULL, &pk[0], msg, &keyagg_cache, max64) == 1); - /* invalid seckey */ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], max64, &pk[0], msg, &keyagg_cache, max64) == 0); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], NULL, msg, &keyagg_cache, max64)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &invalid_pk, msg, &keyagg_cache, max64)); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], NULL, &keyagg_cache, max64) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, NULL, max64) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &invalid_keyagg_cache, max64)); - CHECK(memcmp_and_randomize(secnonce[0].data, zeros132, sizeof(secnonce[0].data)) == 0); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk[0], &pk[0], msg, &keyagg_cache, NULL) == 1); - - /* Every in-argument except session_id and pubkey can be NULL */ - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], NULL, &pk[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_id[1], sk[1], &pk[1], NULL, NULL, NULL) == 1); - - /** Serialize and parse public nonces **/ - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, NULL, &pubnonce[0])); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, NULL)); - CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &invalid_pubnonce)); - CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); - - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_parse(CTX, NULL, pubnonce_ser)); - CHECK_ILLEGAL(CTX, secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], NULL)); - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], zeros132) == 0); - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); - - { - /* Check that serialize and parse results in the same value */ - secp256k1_musig_pubnonce tmp; - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); - CHECK(secp256k1_musig_pubnonce_parse(CTX, &tmp, pubnonce_ser) == 1); - CHECK(secp256k1_memcmp_var(&tmp, &pubnonce[0], sizeof(tmp)) == 0); - } - - /** Receive nonces and aggregate **/ - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, NULL, pubnonce_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, NULL, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 0)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_agg(CTX, &aggnonce, invalid_pubnonce_ptr, 1)); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, inf_pubnonce_ptr, 2) == 1); - { - /* Check that the aggnonce encodes two points at infinity */ - secp256k1_ge aggnonce_pt[2]; - secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce); - for (i = 0; i < 2; i++) { - secp256k1_ge_is_infinity(&aggnonce_pt[i]); - } - } - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - - /** Serialize and parse aggregate nonces **/ - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, NULL, &aggnonce)); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, NULL)); - CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, (secp256k1_musig_aggnonce*) &invalid_pubnonce)); - CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); - - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_parse(CTX, NULL, aggnonce_ser)); - CHECK_ILLEGAL(CTX, secp256k1_musig_aggnonce_parse(CTX, &aggnonce, NULL)); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, zeros132) == 1); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); - - { - /* Check that serialize and parse results in the same value */ - secp256k1_musig_aggnonce tmp; - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &tmp, aggnonce_ser) == 1); - CHECK(secp256k1_memcmp_var(&tmp, &aggnonce, sizeof(tmp)) == 0); - } - - /** Process nonces **/ - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, &adaptor) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL, &adaptor)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache, &adaptor)); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, NULL) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, (secp256k1_pubkey *)&invalid_pk)); - - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, &adaptor) == 1); - - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 1); - /* The secnonce is set to 0 and subsequent signing attempts fail */ - CHECK(secp256k1_memcmp_var(&secnonce_tmp, zeros132, sizeof(secnonce_tmp)) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, NULL, &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], NULL, &keypair[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &invalid_secnonce, &keypair[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, NULL, &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &invalid_keypair, &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - { - unsigned char sk_tmp[32]; - secp256k1_keypair keypair_tmp; - testrand256(sk_tmp); - CHECK(secp256k1_keypair_create(CTX, &keypair_tmp, sk_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair_tmp, &keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - } - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], NULL, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &invalid_keyagg_cache, &session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, NULL)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &invalid_session)); - memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); - - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], &keyagg_cache, &session) == 1); - - CHECK(secp256k1_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, NULL, &partial_sig[0])); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_serialize(CTX, buf, NULL)); - CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], buf) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_parse(CTX, NULL, buf)); - CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], max64) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_parse(CTX, &partial_sig[0], NULL)); - - { - /* Check that serialize and parse results in the same value */ - secp256k1_musig_partial_sig tmp; - CHECK(secp256k1_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); - CHECK(secp256k1_musig_partial_sig_parse(CTX, &tmp, buf) == 1); - CHECK(secp256k1_memcmp_var(&tmp, &partial_sig[0], sizeof(tmp)) == 0); - } - - /** Partial signature verification */ - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, NULL, &pubnonce[0], &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &invalid_partial_sig, &pubnonce[0], &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], NULL, &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &invalid_pubnonce, &pk[0], &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], NULL, &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &invalid_pk, &keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], NULL, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &invalid_keyagg_cache, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &invalid_session)); - - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], &keyagg_cache, &session) == 1); - - /** Signature aggregation and verification */ - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, NULL, &session, partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, NULL, partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &invalid_session, partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, NULL, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, invalid_partial_sig_ptr, 2)); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 0)); - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 1) == 1); - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); - - /** Adaptor signature verification */ - CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity, &session) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, NULL, &session)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, &nonce_parity, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, &nonce_parity, &invalid_session)); - - CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, NULL, pre_sig, sec_adaptor, 0)); - CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, NULL, sec_adaptor, 0)); - CHECK(secp256k1_musig_adapt(CTX, final_sig, max64, sec_adaptor, 0) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, pre_sig, NULL, 0)); - CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, max64, 0) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, 2)); - /* sig and pre_sig argument point to the same location */ - memcpy(final_sig, pre_sig, sizeof(final_sig)); - CHECK(secp256k1_musig_adapt(CTX, final_sig, final_sig, sec_adaptor, nonce_parity) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); - - CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); - - /** Secret adaptor can be extracted from signature */ - CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, nonce_parity) == 1); - CHECK(secp256k1_memcmp_var(sec_adaptor, sec_adaptor1, 32) == 0); - /* wrong nonce parity */ - CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, !nonce_parity) == 1); - CHECK(secp256k1_memcmp_var(sec_adaptor, sec_adaptor1, 32) != 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, NULL, final_sig, pre_sig, 0)); - CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, NULL, pre_sig, 0)); - CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, max64, pre_sig, 0) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, NULL, 0)); - CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, max64, 0) == 0); - CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, 2)); -} - -static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { - secp256k1_scalar k1[2], k2[2]; - - secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); - testrand_flip(args[n_flip], n_bytes); - secp256k1_nonce_function_musig(k2, args[0], args[1], args[2], args[3], args[4], args[5]); - CHECK(secp256k1_scalar_eq(&k1[0], &k2[0]) == 0); - CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0); -} - -static void musig_nonce_test(void) { - unsigned char *args[6]; - unsigned char session_id[32]; - unsigned char sk[32]; - unsigned char pk[33]; - unsigned char msg[32]; - unsigned char agg_pk[32]; - unsigned char extra_input[32]; - int i, j; - secp256k1_scalar k[6][2]; - - testrand_bytes_test(session_id, sizeof(session_id)); - testrand_bytes_test(sk, sizeof(sk)); - testrand_bytes_test(pk, sizeof(pk)); - testrand_bytes_test(msg, sizeof(msg)); - testrand_bytes_test(agg_pk, sizeof(agg_pk)); - testrand_bytes_test(extra_input, sizeof(extra_input)); - - /* Check that a bitflip in an argument results in different nonces. */ - args[0] = session_id; - args[1] = msg; - args[2] = sk; - args[3] = pk; - args[4] = agg_pk; - args[5] = extra_input; - for (i = 0; i < COUNT; i++) { - musig_nonce_bitflip(args, 0, sizeof(session_id)); - musig_nonce_bitflip(args, 1, sizeof(msg)); - musig_nonce_bitflip(args, 2, sizeof(sk)); - musig_nonce_bitflip(args, 3, sizeof(pk)); - musig_nonce_bitflip(args, 4, sizeof(agg_pk)); - musig_nonce_bitflip(args, 5, sizeof(extra_input)); - } - /* Check that if any argument is NULL, a different nonce is produced than if - * any other argument is NULL. */ - memcpy(msg, session_id, sizeof(msg)); - memcpy(sk, session_id, sizeof(sk)); - memcpy(pk, session_id, sizeof(session_id)); - memcpy(agg_pk, session_id, sizeof(agg_pk)); - memcpy(extra_input, session_id, sizeof(extra_input)); - secp256k1_nonce_function_musig(k[0], args[0], args[1], args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[1], args[0], NULL, args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[2], args[0], args[1], NULL, args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[3], args[0], args[1], args[2], NULL, args[4], args[5]); - secp256k1_nonce_function_musig(k[4], args[0], args[1], args[2], args[3], NULL, args[5]); - secp256k1_nonce_function_musig(k[5], args[0], args[1], args[2], args[3], args[4], NULL); - for (i = 0; i < 6; i++) { - CHECK(!secp256k1_scalar_eq(&k[i][0], &k[i][1])); - for (j = i+1; j < 6; j++) { - CHECK(!secp256k1_scalar_eq(&k[i][0], &k[j][0])); - CHECK(!secp256k1_scalar_eq(&k[i][1], &k[j][1])); - } - } -} - -static void scriptless_atomic_swap(secp256k1_scratch_space *scratch) { - /* Throughout this test "a" and "b" refer to two hypothetical blockchains, - * while the indices 0 and 1 refer to the two signers. Here signer 0 is - * sending a-coins to signer 1, while signer 1 is sending b-coins to signer - * 0. Signer 0 produces the adaptor signatures. */ - unsigned char pre_sig_a[64]; - unsigned char final_sig_a[64]; - unsigned char pre_sig_b[64]; - unsigned char final_sig_b[64]; - secp256k1_musig_partial_sig partial_sig_a[2]; - const secp256k1_musig_partial_sig *partial_sig_a_ptr[2]; - secp256k1_musig_partial_sig partial_sig_b[2]; - const secp256k1_musig_partial_sig *partial_sig_b_ptr[2]; - unsigned char sec_adaptor[32]; - unsigned char sec_adaptor_extracted[32]; - secp256k1_pubkey pub_adaptor; - unsigned char sk_a[2][32]; - unsigned char sk_b[2][32]; - secp256k1_keypair keypair_a[2]; - secp256k1_keypair keypair_b[2]; - secp256k1_pubkey pk_a[2]; - const secp256k1_pubkey *pk_a_ptr[2]; - secp256k1_pubkey pk_b[2]; - const secp256k1_pubkey *pk_b_ptr[2]; - secp256k1_musig_keyagg_cache keyagg_cache_a; - secp256k1_musig_keyagg_cache keyagg_cache_b; - secp256k1_xonly_pubkey agg_pk_a; - secp256k1_xonly_pubkey agg_pk_b; - secp256k1_musig_secnonce secnonce_a[2]; - secp256k1_musig_secnonce secnonce_b[2]; - secp256k1_musig_pubnonce pubnonce_a[2]; - secp256k1_musig_pubnonce pubnonce_b[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr_a[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr_b[2]; - secp256k1_musig_aggnonce aggnonce_a; - secp256k1_musig_aggnonce aggnonce_b; - secp256k1_musig_session session_a, session_b; - int nonce_parity_a; - int nonce_parity_b; - unsigned char seed_a[2][32] = { "a0", "a1" }; - unsigned char seed_b[2][32] = { "b0", "b1" }; - const unsigned char msg32_a[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'a'}; - const unsigned char msg32_b[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'b'}; - int i; - - /* Step 1: key setup */ - for (i = 0; i < 2; i++) { - pk_a_ptr[i] = &pk_a[i]; - pk_b_ptr[i] = &pk_b[i]; - pubnonce_ptr_a[i] = &pubnonce_a[i]; - pubnonce_ptr_b[i] = &pubnonce_b[i]; - partial_sig_a_ptr[i] = &partial_sig_a[i]; - partial_sig_b_ptr[i] = &partial_sig_b[i]; - - testrand256(sk_a[i]); - testrand256(sk_b[i]); - CHECK(create_keypair_and_pk(&keypair_a[i], &pk_a[i], sk_a[i]) == 1); - CHECK(create_keypair_and_pk(&keypair_b[i], &pk_b[i], sk_b[i]) == 1); - } - testrand256(sec_adaptor); - CHECK(secp256k1_ec_pubkey_create(CTX, &pub_adaptor, sec_adaptor) == 1); - - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk_a, &keyagg_cache_a, pk_a_ptr, 2) == 1); - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &agg_pk_b, &keyagg_cache_b, pk_b_ptr, 2) == 1); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_a[0], &pubnonce_a[0], seed_a[0], sk_a[0], &pk_a[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_a[1], &pubnonce_a[1], seed_a[1], sk_a[1], &pk_a[1], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_b[0], &pubnonce_b[0], seed_b[0], sk_b[0], &pk_b[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_b[1], &pubnonce_b[1], seed_b[1], sk_b[1], &pk_b[1], NULL, NULL, NULL) == 1); - - /* Step 2: Exchange nonces */ - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce_a, pubnonce_ptr_a, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session_a, &aggnonce_a, msg32_a, &keyagg_cache_a, &pub_adaptor) == 1); - CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity_a, &session_a) == 1); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce_b, pubnonce_ptr_b, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session_b, &aggnonce_b, msg32_b, &keyagg_cache_b, &pub_adaptor) == 1); - CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity_b, &session_b) == 1); - - /* Step 3: Signer 0 produces partial signatures for both chains. */ - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_a[0], &secnonce_a[0], &keypair_a[0], &keyagg_cache_a, &session_a) == 1); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_b[0], &secnonce_b[0], &keypair_b[0], &keyagg_cache_b, &session_b) == 1); - - /* Step 4: Signer 1 receives partial signatures, verifies them and creates a - * partial signature to send B-coins to signer 0. */ - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig_a[0], &pubnonce_a[0], &pk_a[0], &keyagg_cache_a, &session_a) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig_b[0], &pubnonce_b[0], &pk_b[0], &keyagg_cache_b, &session_b) == 1); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_b[1], &secnonce_b[1], &keypair_b[1], &keyagg_cache_b, &session_b) == 1); - - /* Step 5: Signer 0 aggregates its own partial signature with the partial - * signature from signer 1 and adapts it. This results in a complete - * signature which is broadcasted by signer 0 to take B-coins. */ - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig_b, &session_b, partial_sig_b_ptr, 2) == 1); - CHECK(secp256k1_musig_adapt(CTX, final_sig_b, pre_sig_b, sec_adaptor, nonce_parity_b) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_b, msg32_b, sizeof(msg32_b), &agg_pk_b) == 1); - - /* Step 6: Signer 1 signs, extracts adaptor from the published signature, - * and adapts the signature to take A-coins. */ - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_a[1], &secnonce_a[1], &keypair_a[1], &keyagg_cache_a, &session_a) == 1); - CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig_a, &session_a, partial_sig_a_ptr, 2) == 1); - CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor_extracted, final_sig_b, pre_sig_b, nonce_parity_b) == 1); - CHECK(secp256k1_memcmp_var(sec_adaptor_extracted, sec_adaptor, sizeof(sec_adaptor)) == 0); /* in real life we couldn't check this, of course */ - CHECK(secp256k1_musig_adapt(CTX, final_sig_a, pre_sig_a, sec_adaptor_extracted, nonce_parity_a) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_a, msg32_a, sizeof(msg32_a), &agg_pk_a) == 1); -} - -static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { - secp256k1_sha256 sha; - unsigned char buf[32]; - unsigned char buf2[32]; - size_t i; - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, tag, taglen); - secp256k1_sha256_finalize(&sha, buf); - /* buf = SHA256(tag) */ - - secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, buf, 32); - secp256k1_sha256_write(&sha, buf, 32); - /* Is buffer fully consumed? */ - CHECK((sha.bytes & 0x3F) == 0); - - /* Compare with tagged SHA */ - for (i = 0; i < 8; i++) { - CHECK(sha_tagged->s[i] == sha.s[i]); - } - secp256k1_sha256_write(&sha, buf, 32); - secp256k1_sha256_write(sha_tagged, buf, 32); - secp256k1_sha256_finalize(&sha, buf); - secp256k1_sha256_finalize(sha_tagged, buf2); - CHECK(secp256k1_memcmp_var(buf, buf2, 32) == 0); -} - -/* Checks that the initialized tagged hashes initialized have the expected - * state. */ -static void sha256_tag_test(void) { - secp256k1_sha256 sha_tagged; - { - char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'l', 'i', 's', 't'}; - secp256k1_musig_keyagglist_sha256(&sha_tagged); - sha256_tag_test_internal(&sha_tagged, (unsigned char*)tag, sizeof(tag)); - } - { - char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'c', 'o', 'e', 'f', 'f', 'i', 'c', 'i', 'e', 'n', 't'}; - secp256k1_musig_keyaggcoef_sha256(&sha_tagged); - sha256_tag_test_internal(&sha_tagged, (unsigned char*)tag, sizeof(tag)); - } -} - -/* Attempts to create a signature for the aggregate public key using given secret - * keys and keyagg_cache. */ -static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const unsigned char *sk0, const unsigned char *sk1, secp256k1_musig_keyagg_cache *keyagg_cache) { - secp256k1_pubkey pk[2]; - unsigned char session_id[2][32]; - unsigned char msg[32]; - secp256k1_musig_secnonce secnonce[2]; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - secp256k1_musig_aggnonce aggnonce; - secp256k1_keypair keypair[2]; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig[2]; - const secp256k1_musig_partial_sig *partial_sig_ptr[2]; - unsigned char final_sig[64]; - int i; - - for (i = 0; i < 2; i++) { - pubnonce_ptr[i] = &pubnonce[i]; - partial_sig_ptr[i] = &partial_sig[i]; - - testrand256(session_id[i]); - } - CHECK(create_keypair_and_pk(&keypair[0], &pk[0], sk0) == 1); - CHECK(create_keypair_and_pk(&keypair[1], &pk[1], sk1) == 1); - testrand256(msg); - - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_id[0], sk0, &pk[0], NULL, NULL, NULL) == 1); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_id[1], sk1, &pk[1], NULL, NULL, NULL) == 1); - - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache, NULL) == 1); - - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], keyagg_cache, &session) == 1); - - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], keyagg_cache, &session) == 1); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], keyagg_cache, &session) == 1); - - CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), agg_pk) == 1); -} - -/* Create aggregate public key P[0], tweak multiple times (using xonly and - * plain tweaking) and test signing. */ -static void musig_tweak_test(secp256k1_scratch_space *scratch) { - unsigned char sk[2][32]; - secp256k1_pubkey pk[2]; - const secp256k1_pubkey *pk_ptr[2]; - secp256k1_musig_keyagg_cache keyagg_cache; - enum { N_TWEAKS = 8 }; - secp256k1_pubkey P[N_TWEAKS + 1]; - secp256k1_xonly_pubkey P_xonly[N_TWEAKS + 1]; - int i; - - /* Key Setup */ - for (i = 0; i < 2; i++) { - pk_ptr[i] = &pk[i]; - testrand256(sk[i]); - CHECK(create_keypair_and_pk(NULL, &pk[i], sk[i]) == 1); - } - /* Compute P0 = keyagg(pk0, pk1) and test signing for it */ - CHECK(secp256k1_musig_pubkey_agg(CTX, scratch, &P_xonly[0], &keyagg_cache, pk_ptr, 2) == 1); - musig_tweak_test_helper(&P_xonly[0], sk[0], sk[1], &keyagg_cache); - CHECK(secp256k1_musig_pubkey_get(CTX, &P[0], &keyagg_cache)); - - /* Compute Pi = f(Pj) + tweaki*G where where j = i-1 and try signing for - * that key. If xonly is set to true, the function f is normalizes the input - * point to have an even X-coordinate ("xonly-tweaking"). - * Otherwise, the function f is the identity function. */ - for (i = 1; i <= N_TWEAKS; i++) { - unsigned char tweak[32]; - int P_parity; - int xonly = testrand_bits(1); - - testrand256(tweak); - if (xonly) { - CHECK(secp256k1_musig_pubkey_xonly_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); - } else { - CHECK(secp256k1_musig_pubkey_ec_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); - } - CHECK(secp256k1_xonly_pubkey_from_pubkey(CTX, &P_xonly[i], &P_parity, &P[i])); - /* Check that musig_pubkey_tweak_add produces same result as - * xonly_pubkey_tweak_add or ec_pubkey_tweak_add. */ - if (xonly) { - unsigned char P_serialized[32]; - CHECK(secp256k1_xonly_pubkey_serialize(CTX, P_serialized, &P_xonly[i])); - CHECK(secp256k1_xonly_pubkey_tweak_add_check(CTX, P_serialized, P_parity, &P_xonly[i-1], tweak) == 1); - } else { - secp256k1_pubkey tmp_key = P[i-1]; - CHECK(secp256k1_ec_pubkey_tweak_add(CTX, &tmp_key, tweak)); - CHECK(secp256k1_memcmp_var(&tmp_key, &P[i], sizeof(tmp_key)) == 0); - } - /* Test signing for P[i] */ - musig_tweak_test_helper(&P_xonly[i], sk[0], sk[1], &keyagg_cache); - } -} - -int musig_vectors_keyagg_and_tweak(enum MUSIG_ERROR *error, - secp256k1_musig_keyagg_cache *keyagg_cache, - unsigned char *agg_pk_ser, - const unsigned char pubkeys33[][33], - const unsigned char tweaks32[][32], - size_t key_indices_len, - const size_t *key_indices, - size_t tweak_indices_len, - const size_t *tweak_indices, - const int *is_xonly) { - secp256k1_pubkey pubkeys[MUSIG_VECTORS_MAX_PUBKEYS]; - const secp256k1_pubkey *pk_ptr[MUSIG_VECTORS_MAX_PUBKEYS]; - int i; - secp256k1_pubkey agg_pk; - secp256k1_xonly_pubkey agg_pk_xonly; - - for (i = 0; i < (int)key_indices_len; i++) { - if (!secp256k1_ec_pubkey_parse(CTX, &pubkeys[i], pubkeys33[key_indices[i]], 33)) { - *error = MUSIG_PUBKEY; - return 0; - } - pk_ptr[i] = &pubkeys[i]; - } - if (!secp256k1_musig_pubkey_agg(CTX, NULL, NULL, keyagg_cache, pk_ptr, key_indices_len)) { - *error = MUSIG_OTHER; - return 0; - } - - for (i = 0; i < (int)tweak_indices_len; i++) { - if (is_xonly[i]) { - if (!secp256k1_musig_pubkey_xonly_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { - *error = MUSIG_TWEAK; - return 0; - } - } else { - if (!secp256k1_musig_pubkey_ec_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { - *error = MUSIG_TWEAK; - return 0; - } - } - } - if (!secp256k1_musig_pubkey_get(CTX, &agg_pk, keyagg_cache)) { - *error = MUSIG_OTHER; - return 0; - } - - if (!secp256k1_xonly_pubkey_from_pubkey(CTX, &agg_pk_xonly, NULL, &agg_pk)) { - *error = MUSIG_OTHER; - return 0; - } - - if (agg_pk_ser != NULL) { - if (!secp256k1_xonly_pubkey_serialize(CTX, agg_pk_ser, &agg_pk_xonly)) { - *error = MUSIG_OTHER; - return 0; - } - } - - return 1; -} - -static void musig_test_vectors_keyagg(void) { - size_t i; - const struct musig_key_agg_vector *vector = &musig_key_agg_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_key_agg_valid_test_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - unsigned char agg_pk[32]; - - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(secp256k1_memcmp_var(agg_pk, c->expected, sizeof(agg_pk)) == 0); - } - - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_key_agg_error_test_case *c = &vector->error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - - CHECK(!musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(c->error == error); - } -} - -static void musig_test_vectors_noncegen(void) { - size_t i; - const struct musig_nonce_gen_vector *vector = &musig_nonce_gen_vector; - - for (i = 0; i < sizeof(vector->test_case)/sizeof(vector->test_case[0]); i++) { - const struct musig_nonce_gen_test_case *c = &vector->test_case[i]; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_keyagg_cache *keyagg_cache_ptr = NULL; - secp256k1_musig_secnonce secnonce; - secp256k1_musig_pubnonce pubnonce; - const unsigned char *sk = NULL; - const unsigned char *msg = NULL; - const unsigned char *extra_in = NULL; - secp256k1_pubkey pk; - unsigned char pubnonce66[66]; - - if (c->has_sk) { - sk = c->sk; - } - if (c->has_aggpk) { - /* Create keyagg_cache from aggpk */ - secp256k1_keyagg_cache_internal cache_i; - secp256k1_xonly_pubkey aggpk; - memset(&cache_i, 0, sizeof(cache_i)); - CHECK(secp256k1_xonly_pubkey_parse(CTX, &aggpk, c->aggpk)); - CHECK(secp256k1_xonly_pubkey_load(CTX, &cache_i.pk, &aggpk)); - secp256k1_keyagg_cache_save(&keyagg_cache, &cache_i); - keyagg_cache_ptr = &keyagg_cache; - } - if (c->has_msg) { - msg = c->msg; - } - if (c->has_extra_in) { - extra_in = c->extra_in; - } - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pk, c->pk, sizeof(c->pk))); - CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce, &pubnonce, c->rand_, sk, &pk, msg, keyagg_cache_ptr, extra_in) == 1); - CHECK(secp256k1_memcmp_var(&secnonce.data[4], c->expected_secnonce, 2*32) == 0); - CHECK(secp256k1_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); - - CHECK(secp256k1_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); - CHECK(sizeof(c->expected_pubnonce) == sizeof(pubnonce66)); - CHECK(secp256k1_memcmp_var(pubnonce66, c->expected_pubnonce, sizeof(pubnonce66)) == 0); - } -} - - -static void musig_test_vectors_nonceagg(void) { - size_t i; - int j; - const struct musig_nonce_agg_vector *vector = &musig_nonce_agg_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_nonce_agg_test_case *c = &vector->valid_case[i]; - secp256k1_musig_pubnonce pubnonce[2]; - const secp256k1_musig_pubnonce *pubnonce_ptr[2]; - secp256k1_musig_aggnonce aggnonce; - unsigned char aggnonce66[66]; - - for (j = 0; j < 2; j++) { - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]]) == 1); - pubnonce_ptr[j] = &pubnonce[j]; - } - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2)); - CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce)); - CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, 33) == 0); - } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_nonce_agg_test_case *c = &vector->error_case[i]; - secp256k1_musig_pubnonce pubnonce[2]; - for (j = 0; j < 2; j++) { - int expected = c->invalid_nonce_idx != j; - CHECK(expected == secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]])); - } - } -} - -static void musig_test_set_secnonce(secp256k1_musig_secnonce *secnonce, const unsigned char *secnonce64, const secp256k1_pubkey *pubkey) { - secp256k1_ge pk; - secp256k1_scalar k[2]; - - secp256k1_scalar_set_b32(&k[0], &secnonce64[0], NULL); - secp256k1_scalar_set_b32(&k[1], &secnonce64[32], NULL); - CHECK(secp256k1_pubkey_load(CTX, &pk, pubkey)); - secp256k1_musig_secnonce_save(secnonce, k, &pk); -} - -static void musig_test_vectors_signverify(void) { - size_t i; - const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_valid_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_pubkey pubkey; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - secp256k1_musig_secnonce secnonce; - secp256k1_keypair keypair; - unsigned char partial_sig32[32]; - - CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey); - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); - CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); - - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[0])); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->sign_error_case)/sizeof(vector->sign_error_case[0]); i++) { - const struct musig_sign_error_case *c = &vector->sign_error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_pubkey pubkey; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - secp256k1_musig_secnonce secnonce; - secp256k1_keypair keypair; - int expected; - - if (i == 0) { - /* Skip this vector since the implementation does not error out when - * the signing key does not belong to any pubkey. */ - continue; - } - expected = c->error != MUSIG_PUBKEY; - CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(expected || c->error == error); - if (!expected) { - continue; - } - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); - - expected = c->error != MUSIG_AGGNONCE; - CHECK(expected == secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); - if (!expected) { - continue; - } - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - expected = c->error != MUSIG_SECNONCE; - CHECK(!expected); - musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); - CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) { - const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - enum { NUM_PUBNONCES = 3 }; - secp256k1_musig_pubnonce pubnonce[NUM_PUBNONCES]; - const secp256k1_musig_pubnonce *pubnonce_ptr[NUM_PUBNONCES]; - secp256k1_pubkey pubkey; - int expected; - size_t j; - - CHECK(NUM_PUBNONCES <= c->nonce_indices_len); - for (j = 0; j < c->nonce_indices_len; j++) { - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pubnonces[c->nonce_indices[j]])); - pubnonce_ptr[j] = &pubnonce[j]; - } - - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, c->nonce_indices_len) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); - - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[c->signer_index], sizeof(vector->pubkeys[0]))); - - expected = c->error != MUSIG_SIG; - CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig, c->sig)); - if (!expected) { - continue; - } - expected = c->error != MUSIG_SIG_VERIFY; - CHECK(expected == secp256k1_musig_partial_sig_verify(CTX, &partial_sig, pubnonce, &pubkey, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->verify_error_case)/sizeof(vector->verify_error_case[0]); i++) { - const struct musig_verify_fail_error_case *c = &vector->verify_error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_pubnonce pubnonce; - int expected; - - expected = c->error != MUSIG_PUBKEY; - CHECK(expected == musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); - CHECK(expected || c->error == error); - if (!expected) { - continue; - } - expected = c->error != MUSIG_PUBNONCE; - CHECK(expected == secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); - } -} - -static void musig_test_vectors_tweak(void) { - size_t i; - const struct musig_tweak_vector *vector = &musig_tweak_vector; - secp256k1_pubkey pubkey; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_secnonce secnonce; - - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonce)); - CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_tweak_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - secp256k1_musig_pubnonce pubnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig; - secp256k1_keypair keypair; - unsigned char partial_sig32[32]; - - musig_test_set_secnonce(&secnonce, vector->secnonce, &pubkey); - - CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache, NULL)); - - CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); - CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); - CHECK(secp256k1_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); - - CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); - CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); - } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_tweak_case *c = &vector->error_case[i]; - enum MUSIG_ERROR error; - secp256k1_musig_keyagg_cache keyagg_cache; - CHECK(!musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(error == MUSIG_TWEAK); - } -} - -static void musig_test_vectors_sigagg(void) { - size_t i, j; - const struct musig_sig_agg_vector *vector = &musig_sig_agg_vector; - - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { - const struct musig_sig_agg_case *c = &vector->valid_case[i]; - enum MUSIG_ERROR error; - unsigned char final_sig[64]; - secp256k1_musig_keyagg_cache keyagg_cache; - unsigned char agg_pk32[32]; - secp256k1_xonly_pubkey agg_pk; - secp256k1_musig_aggnonce aggnonce; - secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - const secp256k1_musig_partial_sig *partial_sig_ptr[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - - CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk32, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce)); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache, NULL)); - for (j = 0; j < c->psig_indices_len; j++) { - CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); - partial_sig_ptr[j] = &partial_sig[j]; - } - - CHECK(secp256k1_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, c->psig_indices_len) == 1); - CHECK(secp256k1_memcmp_var(final_sig, c->expected, sizeof(final_sig)) == 0); - - CHECK(secp256k1_xonly_pubkey_parse(CTX, &agg_pk, agg_pk32)); - CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, vector->msg, sizeof(vector->msg), &agg_pk) == 1); - } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { - const struct musig_sig_agg_case *c = &vector->error_case[i]; - secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - for (j = 0; j < c->psig_indices_len; j++) { - int expected = c->invalid_sig_idx != (int)j; - CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); - } - } -} - -static void run_musig_tests(void) { - int i; - secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 1024 * 1024); - - for (i = 0; i < COUNT; i++) { - musig_simple_test(scratch); - } - musig_api_tests(scratch); - musig_nonce_test(); - for (i = 0; i < COUNT; i++) { - /* Run multiple times to ensure that pk and nonce have different y - * parities */ - scriptless_atomic_swap(scratch); - musig_tweak_test(scratch); - } - sha256_tag_test(); - musig_test_vectors_keyagg(); - musig_test_vectors_noncegen(); - musig_test_vectors_nonceagg(); - musig_test_vectors_signverify(); - musig_test_vectors_tweak(); - musig_test_vectors_sigagg(); - - secp256k1_scratch_space_destroy(CTX, scratch); -} - -#endif diff --git a/src/modules/musig/vectors.h b/src/modules/musig/vectors.h deleted file mode 100644 index b959e0a2..00000000 --- a/src/modules/musig/vectors.h +++ /dev/null @@ -1,346 +0,0 @@ -/** - * Automatically generated by contrib/musig2-vectors.py. - * - * The test vectors for the KeySort function are included in this file. They can - * be found in src/modules/extrakeys/tests_impl.h. */ - -enum MUSIG_ERROR { - MUSIG_PUBKEY, - MUSIG_TWEAK, - MUSIG_PUBNONCE, - MUSIG_AGGNONCE, - MUSIG_SECNONCE, - MUSIG_SIG, - MUSIG_SIG_VERIFY, - MUSIG_OTHER -}; - -struct musig_key_agg_valid_test_case { - size_t key_indices_len; - size_t key_indices[4]; - unsigned char expected[32]; -}; - -struct musig_key_agg_error_test_case { - size_t key_indices_len; - size_t key_indices[4]; - size_t tweak_indices_len; - size_t tweak_indices[1]; - int is_xonly[1]; - enum MUSIG_ERROR error; -}; - -struct musig_key_agg_vector { - unsigned char pubkeys[7][33]; - unsigned char tweaks[2][32]; - struct musig_key_agg_valid_test_case valid_case[4]; - struct musig_key_agg_error_test_case error_case[5]; -}; - -static const struct musig_key_agg_vector musig_key_agg_vector = { - { - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }, - { 0x02, 0x35, 0x90, 0xA9, 0x4E, 0x76, 0x8F, 0x8E, 0x18, 0x15, 0xC2, 0xF2, 0x4B, 0x4D, 0x80, 0xA8, 0xE3, 0x14, 0x93, 0x16, 0xC3, 0x51, 0x8C, 0xE7, 0xB7, 0xAD, 0x33, 0x83, 0x68, 0xD0, 0x38, 0xCA, 0x66 }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 }, - { 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 }, - { 0x04, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 } - }, - { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }, - { 0x25, 0x2E, 0x4B, 0xD6, 0x74, 0x10, 0xA7, 0x6C, 0xDF, 0x93, 0x3D, 0x30, 0xEA, 0xA1, 0x60, 0x82, 0x14, 0x03, 0x7F, 0x1B, 0x10, 0x5A, 0x01, 0x3E, 0xCC, 0xD3, 0xC5, 0xC1, 0x84, 0xA6, 0x11, 0x0B } - }, - { - { 3, { 0, 1, 2 }, { 0x90, 0x53, 0x9E, 0xED, 0xE5, 0x65, 0xF5, 0xD0, 0x54, 0xF3, 0x2C, 0xC0, 0xC2, 0x20, 0x12, 0x68, 0x89, 0xED, 0x1E, 0x5D, 0x19, 0x3B, 0xAF, 0x15, 0xAE, 0xF3, 0x44, 0xFE, 0x59, 0xD4, 0x61, 0x0C }}, - { 3, { 2, 1, 0 }, { 0x62, 0x04, 0xDE, 0x8B, 0x08, 0x34, 0x26, 0xDC, 0x6E, 0xAF, 0x95, 0x02, 0xD2, 0x70, 0x24, 0xD5, 0x3F, 0xC8, 0x26, 0xBF, 0x7D, 0x20, 0x12, 0x14, 0x8A, 0x05, 0x75, 0x43, 0x5D, 0xF5, 0x4B, 0x2B }}, - { 3, { 0, 0, 0 }, { 0xB4, 0x36, 0xE3, 0xBA, 0xD6, 0x2B, 0x8C, 0xD4, 0x09, 0x96, 0x9A, 0x22, 0x47, 0x31, 0xC1, 0x93, 0xD0, 0x51, 0x16, 0x2D, 0x8C, 0x5A, 0xE8, 0xB1, 0x09, 0x30, 0x61, 0x27, 0xDA, 0x3A, 0xA9, 0x35 }}, - { 4, { 0, 0, 1, 1 }, { 0x69, 0xBC, 0x22, 0xBF, 0xA5, 0xD1, 0x06, 0x30, 0x6E, 0x48, 0xA2, 0x06, 0x79, 0xDE, 0x1D, 0x73, 0x89, 0x38, 0x61, 0x24, 0xD0, 0x75, 0x71, 0xD0, 0xD8, 0x72, 0x68, 0x60, 0x28, 0xC2, 0x6A, 0x3E }}, - }, - { - { 2, { 0, 3 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, - { 2, { 0, 4 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, - { 2, { 5, 0 }, 0, { 0 }, { 0 }, MUSIG_PUBKEY }, - { 2, { 0, 1 }, 1, { 0 }, { 1 }, MUSIG_TWEAK }, - { 1, { 6 }, 1, { 1 }, { 0 }, MUSIG_TWEAK }, - }, -}; - -struct musig_nonce_gen_test_case { - unsigned char rand_[32]; - int has_sk; - unsigned char sk[32]; - unsigned char pk[33]; - int has_aggpk; - unsigned char aggpk[32]; - int has_msg; - unsigned char msg[32]; - int has_extra_in; - unsigned char extra_in[32]; - unsigned char expected_secnonce[97]; - unsigned char expected_pubnonce[66]; -}; - -struct musig_nonce_gen_vector { - struct musig_nonce_gen_test_case test_case[2]; -}; - -static const struct musig_nonce_gen_vector musig_nonce_gen_vector = { - { - { { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }, 1 , { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }, { 0x02, 0x4D, 0x4B, 0x6C, 0xD1, 0x36, 0x10, 0x32, 0xCA, 0x9B, 0xD2, 0xAE, 0xB9, 0xD9, 0x00, 0xAA, 0x4D, 0x45, 0xD9, 0xEA, 0xD8, 0x0A, 0xC9, 0x42, 0x33, 0x74, 0xC4, 0x51, 0xA7, 0x25, 0x4D, 0x07, 0x66 }, 1 , { 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07 }, 1 , { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, 1 , { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0xB1, 0x14, 0xE5, 0x02, 0xBE, 0xAA, 0x4E, 0x30, 0x1D, 0xD0, 0x8A, 0x50, 0x26, 0x41, 0x72, 0xC8, 0x4E, 0x41, 0x65, 0x0E, 0x6C, 0xB7, 0x26, 0xB4, 0x10, 0xC0, 0x69, 0x4D, 0x59, 0xEF, 0xFB, 0x64, 0x95, 0xB5, 0xCA, 0xF2, 0x8D, 0x04, 0x5B, 0x97, 0x3D, 0x63, 0xE3, 0xC9, 0x9A, 0x44, 0xB8, 0x07, 0xBD, 0xE3, 0x75, 0xFD, 0x6C, 0xB3, 0x9E, 0x46, 0xDC, 0x4A, 0x51, 0x17, 0x08, 0xD0, 0xE9, 0xD2, 0x02, 0x4D, 0x4B, 0x6C, 0xD1, 0x36, 0x10, 0x32, 0xCA, 0x9B, 0xD2, 0xAE, 0xB9, 0xD9, 0x00, 0xAA, 0x4D, 0x45, 0xD9, 0xEA, 0xD8, 0x0A, 0xC9, 0x42, 0x33, 0x74, 0xC4, 0x51, 0xA7, 0x25, 0x4D, 0x07, 0x66 }, { 0x02, 0xF7, 0xBE, 0x70, 0x89, 0xE8, 0x37, 0x6E, 0xB3, 0x55, 0x27, 0x23, 0x68, 0x76, 0x6B, 0x17, 0xE8, 0x8E, 0x7D, 0xB7, 0x20, 0x47, 0xD0, 0x5E, 0x56, 0xAA, 0x88, 0x1E, 0xA5, 0x2B, 0x3B, 0x35, 0xDF, 0x02, 0xC2, 0x9C, 0x80, 0x46, 0xFD, 0xD0, 0xDE, 0xD4, 0xC7, 0xE5, 0x58, 0x69, 0x13, 0x72, 0x00, 0xFB, 0xDB, 0xFE, 0x2E, 0xB6, 0x54, 0x26, 0x7B, 0x6D, 0x70, 0x13, 0x60, 0x2C, 0xAE, 0xD3, 0x11, 0x5A } }, - { { 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F }, 0 , { 0 }, { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, 0 , { 0 }, 0 , { 0 }, 0 , { 0 }, { 0x89, 0xBD, 0xD7, 0x87, 0xD0, 0x28, 0x4E, 0x5E, 0x4D, 0x5F, 0xC5, 0x72, 0xE4, 0x9E, 0x31, 0x6B, 0xAB, 0x7E, 0x21, 0xE3, 0xB1, 0x83, 0x0D, 0xE3, 0x7D, 0xFE, 0x80, 0x15, 0x6F, 0xA4, 0x1A, 0x6D, 0x0B, 0x17, 0xAE, 0x8D, 0x02, 0x4C, 0x53, 0x67, 0x96, 0x99, 0xA6, 0xFD, 0x79, 0x44, 0xD9, 0xC4, 0xA3, 0x66, 0xB5, 0x14, 0xBA, 0xF4, 0x30, 0x88, 0xE0, 0x70, 0x8B, 0x10, 0x23, 0xDD, 0x28, 0x97, 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, { 0x02, 0xC9, 0x6E, 0x7C, 0xB1, 0xE8, 0xAA, 0x5D, 0xAC, 0x64, 0xD8, 0x72, 0x94, 0x79, 0x14, 0x19, 0x8F, 0x60, 0x7D, 0x90, 0xEC, 0xDE, 0x52, 0x00, 0xDE, 0x52, 0x97, 0x8A, 0xD5, 0xDE, 0xD6, 0x3C, 0x00, 0x02, 0x99, 0xEC, 0x51, 0x17, 0xC2, 0xD2, 0x9E, 0xDE, 0xE8, 0xA2, 0x09, 0x25, 0x87, 0xC3, 0x90, 0x9B, 0xE6, 0x94, 0xD5, 0xCF, 0xF0, 0x66, 0x7D, 0x6C, 0x02, 0xEA, 0x40, 0x59, 0xF7, 0xCD, 0x97, 0x86 } }, - }, -}; - -struct musig_nonce_agg_test_case { - size_t pnonce_indices[2]; - /* if valid case */ - unsigned char expected[66]; - /* if error case */ - int invalid_nonce_idx; -}; - -struct musig_nonce_agg_vector { - unsigned char pnonces[7][66]; - struct musig_nonce_agg_test_case valid_case[2]; - struct musig_nonce_agg_test_case error_case[3]; -}; - -static const struct musig_nonce_agg_vector musig_nonce_agg_vector = { - { - { 0x02, 0x01, 0x51, 0xC8, 0x0F, 0x43, 0x56, 0x48, 0xDF, 0x67, 0xA2, 0x2B, 0x74, 0x9C, 0xD7, 0x98, 0xCE, 0x54, 0xE0, 0x32, 0x1D, 0x03, 0x4B, 0x92, 0xB7, 0x09, 0xB5, 0x67, 0xD6, 0x0A, 0x42, 0xE6, 0x66, 0x03, 0xBA, 0x47, 0xFB, 0xC1, 0x83, 0x44, 0x37, 0xB3, 0x21, 0x2E, 0x89, 0xA8, 0x4D, 0x84, 0x25, 0xE7, 0xBF, 0x12, 0xE0, 0x24, 0x5D, 0x98, 0x26, 0x22, 0x68, 0xEB, 0xDC, 0xB3, 0x85, 0xD5, 0x06, 0x41 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x33 }, - { 0x02, 0x01, 0x51, 0xC8, 0x0F, 0x43, 0x56, 0x48, 0xDF, 0x67, 0xA2, 0x2B, 0x74, 0x9C, 0xD7, 0x98, 0xCE, 0x54, 0xE0, 0x32, 0x1D, 0x03, 0x4B, 0x92, 0xB7, 0x09, 0xB5, 0x67, 0xD6, 0x0A, 0x42, 0xE6, 0x66, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x03, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x04, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x33 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0x48, 0xC2, 0x64, 0xCD, 0xD5, 0x7D, 0x3C, 0x24, 0xD7, 0x99, 0x90, 0xB0, 0xF8, 0x65, 0x67, 0x4E, 0xB6, 0x2A, 0x0F, 0x90, 0x18, 0x27, 0x7A, 0x95, 0x01, 0x1B, 0x41, 0xBF, 0xC1, 0x93, 0xB8, 0x31 }, - { 0x03, 0xFF, 0x40, 0x6F, 0xFD, 0x8A, 0xDB, 0x9C, 0xD2, 0x98, 0x77, 0xE4, 0x98, 0x50, 0x14, 0xF6, 0x6A, 0x59, 0xF6, 0xCD, 0x01, 0xC0, 0xE8, 0x8C, 0xAA, 0x8E, 0x5F, 0x31, 0x66, 0xB1, 0xF6, 0x76, 0xA6, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 } - }, - { - { { 0, 1 }, { 0x03, 0x5F, 0xE1, 0x87, 0x3B, 0x4F, 0x29, 0x67, 0xF5, 0x2F, 0xEA, 0x4A, 0x06, 0xAD, 0x5A, 0x8E, 0xCC, 0xBE, 0x9D, 0x0F, 0xD7, 0x30, 0x68, 0x01, 0x2C, 0x89, 0x4E, 0x2E, 0x87, 0xCC, 0xB5, 0x80, 0x4B, 0x02, 0x47, 0x25, 0x37, 0x73, 0x45, 0xBD, 0xE0, 0xE9, 0xC3, 0x3A, 0xF3, 0xC4, 0x3C, 0x0A, 0x29, 0xA9, 0x24, 0x9F, 0x2F, 0x29, 0x56, 0xFA, 0x8C, 0xFE, 0xB5, 0x5C, 0x85, 0x73, 0xD0, 0x26, 0x2D, 0xC8 }, 0 }, - { { 2, 3 }, { 0x03, 0x5F, 0xE1, 0x87, 0x3B, 0x4F, 0x29, 0x67, 0xF5, 0x2F, 0xEA, 0x4A, 0x06, 0xAD, 0x5A, 0x8E, 0xCC, 0xBE, 0x9D, 0x0F, 0xD7, 0x30, 0x68, 0x01, 0x2C, 0x89, 0x4E, 0x2E, 0x87, 0xCC, 0xB5, 0x80, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0 }, - }, - { - { { 0, 4 }, { 0 }, 1 }, - { { 5, 1 }, { 0 }, 0 }, - { { 6, 1 }, { 0 }, 0 }, - }, -}; - -/* Omit pubnonces in the test vectors because our partial signature verification - * implementation is able to accept the aggnonce directly. */ -struct musig_valid_case { - size_t key_indices_len; - size_t key_indices[3]; - size_t aggnonce_index; - size_t msg_index; - size_t signer_index; - unsigned char expected[32]; -}; - -struct musig_sign_error_case { - size_t key_indices_len; - size_t key_indices[3]; - size_t aggnonce_index; - size_t msg_index; - size_t secnonce_index; - enum MUSIG_ERROR error; -}; - -struct musig_verify_fail_error_case { - unsigned char sig[32]; - size_t key_indices_len; - size_t key_indices[3]; - size_t nonce_indices_len; - size_t nonce_indices[3]; - size_t msg_index; - size_t signer_index; - enum MUSIG_ERROR error; -}; - -struct musig_sign_verify_vector { - unsigned char sk[32]; - unsigned char pubkeys[4][33]; - unsigned char secnonces[2][194]; - unsigned char pubnonces[5][194]; - unsigned char aggnonces[5][66]; - unsigned char msgs[1][32]; - struct musig_valid_case valid_case[4]; - struct musig_sign_error_case sign_error_case[6]; - struct musig_verify_fail_error_case verify_fail_case[3]; - struct musig_verify_fail_error_case verify_error_case[2]; -}; - -static const struct musig_sign_verify_vector musig_sign_verify_vector = { - { 0x7F, 0xB9, 0xE0, 0xE6, 0x87, 0xAD, 0xA1, 0xEE, 0xBF, 0x7E, 0xCF, 0xE2, 0xF2, 0x1E, 0x73, 0xEB, 0xDB, 0x51, 0xA7, 0xD4, 0x50, 0x94, 0x8D, 0xFE, 0x8D, 0x76, 0xD7, 0xF2, 0xD1, 0x00, 0x76, 0x71 }, - { - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x61 }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07 } - }, - { - { 0x50, 0x8B, 0x81, 0xA6, 0x11, 0xF1, 0x00, 0xA6, 0xB2, 0xB6, 0xB2, 0x96, 0x56, 0x59, 0x08, 0x98, 0xAF, 0x48, 0x8B, 0xCF, 0x2E, 0x1F, 0x55, 0xCF, 0x22, 0xE5, 0xCF, 0xB8, 0x44, 0x21, 0xFE, 0x61, 0xFA, 0x27, 0xFD, 0x49, 0xB1, 0xD5, 0x00, 0x85, 0xB4, 0x81, 0x28, 0x5E, 0x1C, 0xA2, 0x05, 0xD5, 0x5C, 0x82, 0xCC, 0x1B, 0x31, 0xFF, 0x5C, 0xD5, 0x4A, 0x48, 0x98, 0x29, 0x35, 0x59, 0x01, 0xF7, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 } - }, - { - { 0x03, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, - { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x03, 0x2D, 0xE2, 0x66, 0x26, 0x28, 0xC9, 0x0B, 0x03, 0xF5, 0xE7, 0x20, 0x28, 0x4E, 0xB5, 0x2F, 0xF7, 0xD7, 0x1F, 0x42, 0x84, 0xF6, 0x27, 0xB6, 0x8A, 0x85, 0x3D, 0x78, 0xC7, 0x8E, 0x1F, 0xFE, 0x93, 0x03, 0xE4, 0xC5, 0x52, 0x4E, 0x83, 0xFF, 0xE1, 0x49, 0x3B, 0x90, 0x77, 0xCF, 0x1C, 0xA6, 0xBE, 0xB2, 0x09, 0x0C, 0x93, 0xD9, 0x30, 0x32, 0x10, 0x71, 0xAD, 0x40, 0xB2, 0xF4, 0x4E, 0x59, 0x90, 0x46 }, - { 0x02, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x03, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, - { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 } - }, - { - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x04, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 }, - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 } - }, - { - { 0xF9, 0x54, 0x66, 0xD0, 0x86, 0x77, 0x0E, 0x68, 0x99, 0x64, 0x66, 0x42, 0x19, 0x26, 0x6F, 0xE5, 0xED, 0x21, 0x5C, 0x92, 0xAE, 0x20, 0xBA, 0xB5, 0xC9, 0xD7, 0x9A, 0xDD, 0xDD, 0xF3, 0xC0, 0xCF } - }, - { - { 3, { 0, 1, 2 }, 0, 0, 0, { 0x01, 0x2A, 0xBB, 0xCB, 0x52, 0xB3, 0x01, 0x6A, 0xC0, 0x3A, 0xD8, 0x23, 0x95, 0xA1, 0xA4, 0x15, 0xC4, 0x8B, 0x93, 0xDE, 0xF7, 0x87, 0x18, 0xE6, 0x2A, 0x7A, 0x90, 0x05, 0x2F, 0xE2, 0x24, 0xFB }}, - { 3, { 1, 0, 2 }, 0, 0, 1, { 0x9F, 0xF2, 0xF7, 0xAA, 0xA8, 0x56, 0x15, 0x0C, 0xC8, 0x81, 0x92, 0x54, 0x21, 0x8D, 0x3A, 0xDE, 0xEB, 0x05, 0x35, 0x26, 0x90, 0x51, 0x89, 0x77, 0x24, 0xF9, 0xDB, 0x37, 0x89, 0x51, 0x3A, 0x52 }}, - { 3, { 1, 2, 0 }, 0, 0, 2, { 0xFA, 0x23, 0xC3, 0x59, 0xF6, 0xFA, 0xC4, 0xE7, 0x79, 0x6B, 0xB9, 0x3B, 0xC9, 0xF0, 0x53, 0x2A, 0x95, 0x46, 0x8C, 0x53, 0x9B, 0xA2, 0x0F, 0xF8, 0x6D, 0x7C, 0x76, 0xED, 0x92, 0x22, 0x79, 0x00 }}, - { 2, { 0, 1 }, 1, 0, 0, { 0xAE, 0x38, 0x60, 0x64, 0xB2, 0x61, 0x05, 0x40, 0x47, 0x98, 0xF7, 0x5D, 0xE2, 0xEB, 0x9A, 0xF5, 0xED, 0xA5, 0x38, 0x7B, 0x06, 0x4B, 0x83, 0xD0, 0x49, 0xCB, 0x7C, 0x5E, 0x08, 0x87, 0x95, 0x31 }}, - }, - { - { 2, { 1, 2 }, 0, 0, 0, MUSIG_PUBKEY }, - { 3, { 1, 0, 3 }, 0, 0, 0, MUSIG_PUBKEY }, - { 3, { 1, 2, 0 }, 2, 0, 0, MUSIG_AGGNONCE }, - { 3, { 1, 2, 0 }, 3, 0, 0, MUSIG_AGGNONCE }, - { 3, { 1, 2, 0 }, 4, 0, 0, MUSIG_AGGNONCE }, - { 3, { 0, 1, 2 }, 0, 0, 1, MUSIG_SECNONCE }, - }, - { - { { 0x97, 0xAC, 0x83, 0x3A, 0xDC, 0xB1, 0xAF, 0xA4, 0x2E, 0xBF, 0x9E, 0x07, 0x25, 0x61, 0x6F, 0x3C, 0x9A, 0x0D, 0x5B, 0x61, 0x4F, 0x6F, 0xE2, 0x83, 0xCE, 0xAA, 0xA3, 0x7A, 0x8F, 0xFA, 0xF4, 0x06 }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_SIG_VERIFY }, - { { 0x68, 0x53, 0x7C, 0xC5, 0x23, 0x4E, 0x50, 0x5B, 0xD1, 0x40, 0x61, 0xF8, 0xDA, 0x9E, 0x90, 0xC2, 0x20, 0xA1, 0x81, 0x85, 0x5F, 0xD8, 0xBD, 0xB7, 0xF1, 0x27, 0xBB, 0x12, 0x40, 0x3B, 0x4D, 0x3B }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 1, MUSIG_SIG_VERIFY }, - { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }, 3, { 0, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_SIG }, - }, - { - { { 0x68, 0x53, 0x7C, 0xC5, 0x23, 0x4E, 0x50, 0x5B, 0xD1, 0x40, 0x61, 0xF8, 0xDA, 0x9E, 0x90, 0xC2, 0x20, 0xA1, 0x81, 0x85, 0x5F, 0xD8, 0xBD, 0xB7, 0xF1, 0x27, 0xBB, 0x12, 0x40, 0x3B, 0x4D, 0x3B }, 3, { 0, 1, 2 }, 3, { 4, 1, 2 }, 0, 0, MUSIG_PUBNONCE }, - { { 0x68, 0x53, 0x7C, 0xC5, 0x23, 0x4E, 0x50, 0x5B, 0xD1, 0x40, 0x61, 0xF8, 0xDA, 0x9E, 0x90, 0xC2, 0x20, 0xA1, 0x81, 0x85, 0x5F, 0xD8, 0xBD, 0xB7, 0xF1, 0x27, 0xBB, 0x12, 0x40, 0x3B, 0x4D, 0x3B }, 3, { 3, 1, 2 }, 3, { 0, 1, 2 }, 0, 0, MUSIG_PUBKEY }, - }, -}; - -struct musig_tweak_case { - size_t key_indices_len; - size_t key_indices[3]; - size_t nonce_indices_len; - size_t nonce_indices[3]; - size_t tweak_indices_len; - size_t tweak_indices[4]; - int is_xonly[4]; - size_t signer_index; - unsigned char expected[32]; -}; - -struct musig_tweak_vector { - unsigned char sk[32]; - unsigned char secnonce[97]; - unsigned char aggnonce[66]; - unsigned char msg[32]; - unsigned char pubkeys[3][33]; - unsigned char pubnonces[3][194]; - unsigned char tweaks[5][32]; - struct musig_tweak_case valid_case[5]; - struct musig_tweak_case error_case[1]; -}; - -static const struct musig_tweak_vector musig_tweak_vector = { - { 0x7F, 0xB9, 0xE0, 0xE6, 0x87, 0xAD, 0xA1, 0xEE, 0xBF, 0x7E, 0xCF, 0xE2, 0xF2, 0x1E, 0x73, 0xEB, 0xDB, 0x51, 0xA7, 0xD4, 0x50, 0x94, 0x8D, 0xFE, 0x8D, 0x76, 0xD7, 0xF2, 0xD1, 0x00, 0x76, 0x71 }, - { 0x50, 0x8B, 0x81, 0xA6, 0x11, 0xF1, 0x00, 0xA6, 0xB2, 0xB6, 0xB2, 0x96, 0x56, 0x59, 0x08, 0x98, 0xAF, 0x48, 0x8B, 0xCF, 0x2E, 0x1F, 0x55, 0xCF, 0x22, 0xE5, 0xCF, 0xB8, 0x44, 0x21, 0xFE, 0x61, 0xFA, 0x27, 0xFD, 0x49, 0xB1, 0xD5, 0x00, 0x85, 0xB4, 0x81, 0x28, 0x5E, 0x1C, 0xA2, 0x05, 0xD5, 0x5C, 0x82, 0xCC, 0x1B, 0x31, 0xFF, 0x5C, 0xD5, 0x4A, 0x48, 0x98, 0x29, 0x35, 0x59, 0x01, 0xF7, 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0x84, 0x65, 0xFC, 0xF0, 0xBB, 0xDB, 0xCF, 0x44, 0x3A, 0xAB, 0xCC, 0xE5, 0x33, 0xD4, 0x2B, 0x4B, 0x5A, 0x10, 0x96, 0x6A, 0xC0, 0x9A, 0x49, 0x65, 0x5E, 0x8C, 0x42, 0xDA, 0xAB, 0x8F, 0xCD, 0x61, 0x03, 0x74, 0x96, 0xA3, 0xCC, 0x86, 0x92, 0x6D, 0x45, 0x2C, 0xAF, 0xCF, 0xD5, 0x5D, 0x25, 0x97, 0x2C, 0xA1, 0x67, 0x5D, 0x54, 0x93, 0x10, 0xDE, 0x29, 0x6B, 0xFF, 0x42, 0xF7, 0x2E, 0xEE, 0xA8, 0xC9 }, - { 0xF9, 0x54, 0x66, 0xD0, 0x86, 0x77, 0x0E, 0x68, 0x99, 0x64, 0x66, 0x42, 0x19, 0x26, 0x6F, 0xE5, 0xED, 0x21, 0x5C, 0x92, 0xAE, 0x20, 0xBA, 0xB5, 0xC9, 0xD7, 0x9A, 0xDD, 0xDD, 0xF3, 0xC0, 0xCF }, - { - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }, - { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 } - }, - { - { 0x03, 0x37, 0xC8, 0x78, 0x21, 0xAF, 0xD5, 0x0A, 0x86, 0x44, 0xD8, 0x20, 0xA8, 0xF3, 0xE0, 0x2E, 0x49, 0x9C, 0x93, 0x18, 0x65, 0xC2, 0x36, 0x0F, 0xB4, 0x3D, 0x0A, 0x0D, 0x20, 0xDA, 0xFE, 0x07, 0xEA, 0x02, 0x87, 0xBF, 0x89, 0x1D, 0x2A, 0x6D, 0xEA, 0xEB, 0xAD, 0xC9, 0x09, 0x35, 0x2A, 0xA9, 0x40, 0x5D, 0x14, 0x28, 0xC1, 0x5F, 0x4B, 0x75, 0xF0, 0x4D, 0xAE, 0x64, 0x2A, 0x95, 0xC2, 0x54, 0x84, 0x80 }, - { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98 }, - { 0x03, 0x2D, 0xE2, 0x66, 0x26, 0x28, 0xC9, 0x0B, 0x03, 0xF5, 0xE7, 0x20, 0x28, 0x4E, 0xB5, 0x2F, 0xF7, 0xD7, 0x1F, 0x42, 0x84, 0xF6, 0x27, 0xB6, 0x8A, 0x85, 0x3D, 0x78, 0xC7, 0x8E, 0x1F, 0xFE, 0x93, 0x03, 0xE4, 0xC5, 0x52, 0x4E, 0x83, 0xFF, 0xE1, 0x49, 0x3B, 0x90, 0x77, 0xCF, 0x1C, 0xA6, 0xBE, 0xB2, 0x09, 0x0C, 0x93, 0xD9, 0x30, 0x32, 0x10, 0x71, 0xAD, 0x40, 0xB2, 0xF4, 0x4E, 0x59, 0x90, 0x46 } - }, - { - { 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB }, - { 0xAE, 0x2E, 0xA7, 0x97, 0xCC, 0x0F, 0xE7, 0x2A, 0xC5, 0xB9, 0x7B, 0x97, 0xF3, 0xC6, 0x95, 0x7D, 0x7E, 0x41, 0x99, 0xA1, 0x67, 0xA5, 0x8E, 0xB0, 0x8B, 0xCA, 0xFF, 0xDA, 0x70, 0xAC, 0x04, 0x55 }, - { 0xF5, 0x2E, 0xCB, 0xC5, 0x65, 0xB3, 0xD8, 0xBE, 0xA2, 0xDF, 0xD5, 0xB7, 0x5A, 0x4F, 0x45, 0x7E, 0x54, 0x36, 0x98, 0x09, 0x32, 0x2E, 0x41, 0x20, 0x83, 0x16, 0x26, 0xF2, 0x90, 0xFA, 0x87, 0xE0 }, - { 0x19, 0x69, 0xAD, 0x73, 0xCC, 0x17, 0x7F, 0xA0, 0xB4, 0xFC, 0xED, 0x6D, 0xF1, 0xF7, 0xBF, 0x99, 0x07, 0xE6, 0x65, 0xFD, 0xE9, 0xBA, 0x19, 0x6A, 0x74, 0xFE, 0xD0, 0xA3, 0xCF, 0x5A, 0xEF, 0x9D }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 } - }, - { - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 0 }, { 1 }, 2, { 0xE2, 0x8A, 0x5C, 0x66, 0xE6, 0x1E, 0x17, 0x8C, 0x2B, 0xA1, 0x9D, 0xB7, 0x7B, 0x6C, 0xF9, 0xF7, 0xE2, 0xF0, 0xF5, 0x6C, 0x17, 0x91, 0x8C, 0xD1, 0x31, 0x35, 0xE6, 0x0C, 0xC8, 0x48, 0xFE, 0x91 }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 0 }, { 0 }, 2, { 0x38, 0xB0, 0x76, 0x77, 0x98, 0x25, 0x2F, 0x21, 0xBF, 0x57, 0x02, 0xC4, 0x80, 0x28, 0xB0, 0x95, 0x42, 0x83, 0x20, 0xF7, 0x3A, 0x4B, 0x14, 0xDB, 0x1E, 0x25, 0xDE, 0x58, 0x54, 0x3D, 0x2D, 0x2D }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 2, { 0, 1 }, { 0, 1 }, 2, { 0x40, 0x8A, 0x0A, 0x21, 0xC4, 0xA0, 0xF5, 0xDA, 0xCA, 0xF9, 0x64, 0x6A, 0xD6, 0xEB, 0x6F, 0xEC, 0xD7, 0xF7, 0xA1, 0x1F, 0x03, 0xED, 0x1F, 0x48, 0xDF, 0xFF, 0x21, 0x85, 0xBC, 0x2C, 0x24, 0x08 }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 4, { 0, 1, 2, 3 }, { 0, 0, 1, 1 }, 2, { 0x45, 0xAB, 0xD2, 0x06, 0xE6, 0x1E, 0x3D, 0xF2, 0xEC, 0x9E, 0x26, 0x4A, 0x6F, 0xEC, 0x82, 0x92, 0x14, 0x1A, 0x63, 0x3C, 0x28, 0x58, 0x63, 0x88, 0x23, 0x55, 0x41, 0xF9, 0xAD, 0xE7, 0x54, 0x35 }}, - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 4, { 0, 1, 2, 3 }, { 1, 0, 1, 0 }, 2, { 0xB2, 0x55, 0xFD, 0xCA, 0xC2, 0x7B, 0x40, 0xC7, 0xCE, 0x78, 0x48, 0xE2, 0xD3, 0xB7, 0xBF, 0x5E, 0xA0, 0xED, 0x75, 0x6D, 0xA8, 0x15, 0x65, 0xAC, 0x80, 0x4C, 0xCC, 0xA3, 0xE1, 0xD5, 0xD2, 0x39 }}, - }, - { - { 3, { 1, 2, 0 }, 3, { 1, 2, 0 }, 1, { 4 }, { 0 }, 2, { 0 }}, - }, -}; - -/* Omit pubnonces in the test vectors because they're only needed for - * implementations that do not directly accept an aggnonce. */ -struct musig_sig_agg_case { - size_t key_indices_len; - size_t key_indices[2]; - size_t tweak_indices_len; - size_t tweak_indices[3]; - int is_xonly[3]; - unsigned char aggnonce[66]; - size_t psig_indices_len; - size_t psig_indices[2]; - /* if valid case */ - unsigned char expected[64]; - /* if error case */ - int invalid_sig_idx; -}; - -struct musig_sig_agg_vector { - unsigned char pubkeys[4][33]; - unsigned char tweaks[3][32]; - unsigned char psigs[9][32]; - unsigned char msg[32]; - struct musig_sig_agg_case valid_case[4]; - struct musig_sig_agg_case error_case[1]; -}; - -static const struct musig_sig_agg_vector musig_sig_agg_vector = { - { - { 0x03, 0x93, 0x5F, 0x97, 0x2D, 0xA0, 0x13, 0xF8, 0x0A, 0xE0, 0x11, 0x89, 0x0F, 0xA8, 0x9B, 0x67, 0xA2, 0x7B, 0x7B, 0xE6, 0xCC, 0xB2, 0x4D, 0x32, 0x74, 0xD1, 0x8B, 0x2D, 0x40, 0x67, 0xF2, 0x61, 0xA9 }, - { 0x02, 0xD2, 0xDC, 0x6F, 0x5D, 0xF7, 0xC5, 0x6A, 0xCF, 0x38, 0xC7, 0xFA, 0x0A, 0xE7, 0xA7, 0x59, 0xAE, 0x30, 0xE1, 0x9B, 0x37, 0x35, 0x9D, 0xFD, 0xE0, 0x15, 0x87, 0x23, 0x24, 0xC7, 0xEF, 0x6E, 0x05 }, - { 0x03, 0xC7, 0xFB, 0x10, 0x1D, 0x97, 0xFF, 0x93, 0x0A, 0xCD, 0x0C, 0x67, 0x60, 0x85, 0x2E, 0xF6, 0x4E, 0x69, 0x08, 0x3D, 0xE0, 0xB0, 0x6A, 0xC6, 0x33, 0x57, 0x24, 0x75, 0x4B, 0xB4, 0xB0, 0x52, 0x2C }, - { 0x02, 0x35, 0x24, 0x33, 0xB2, 0x1E, 0x7E, 0x05, 0xD3, 0xB4, 0x52, 0xB8, 0x1C, 0xAE, 0x56, 0x6E, 0x06, 0xD2, 0xE0, 0x03, 0xEC, 0xE1, 0x6D, 0x10, 0x74, 0xAA, 0xBA, 0x42, 0x89, 0xE0, 0xE3, 0xD5, 0x81 } - }, - { - { 0xB5, 0x11, 0xDA, 0x49, 0x21, 0x82, 0xA9, 0x1B, 0x0F, 0xFB, 0x9A, 0x98, 0x02, 0x0D, 0x55, 0xF2, 0x60, 0xAE, 0x86, 0xD7, 0xEC, 0xBD, 0x03, 0x99, 0xC7, 0x38, 0x3D, 0x59, 0xA5, 0xF2, 0xAF, 0x7C }, - { 0xA8, 0x15, 0xFE, 0x04, 0x9E, 0xE3, 0xC5, 0xAA, 0xB6, 0x63, 0x10, 0x47, 0x7F, 0xBC, 0x8B, 0xCC, 0xCA, 0xC2, 0xF3, 0x39, 0x5F, 0x59, 0xF9, 0x21, 0xC3, 0x64, 0xAC, 0xD7, 0x8A, 0x2F, 0x48, 0xDC }, - { 0x75, 0x44, 0x8A, 0x87, 0x27, 0x4B, 0x05, 0x64, 0x68, 0xB9, 0x77, 0xBE, 0x06, 0xEB, 0x1E, 0x9F, 0x65, 0x75, 0x77, 0xB7, 0x32, 0x0B, 0x0A, 0x33, 0x76, 0xEA, 0x51, 0xFD, 0x42, 0x0D, 0x18, 0xA8 } - }, - { - { 0xB1, 0x5D, 0x2C, 0xD3, 0xC3, 0xD2, 0x2B, 0x04, 0xDA, 0xE4, 0x38, 0xCE, 0x65, 0x3F, 0x6B, 0x4E, 0xCF, 0x04, 0x2F, 0x42, 0xCF, 0xDE, 0xD7, 0xC4, 0x1B, 0x64, 0xAA, 0xF9, 0xB4, 0xAF, 0x53, 0xFB }, - { 0x61, 0x93, 0xD6, 0xAC, 0x61, 0xB3, 0x54, 0xE9, 0x10, 0x5B, 0xBD, 0xC8, 0x93, 0x7A, 0x34, 0x54, 0xA6, 0xD7, 0x05, 0xB6, 0xD5, 0x73, 0x22, 0xA5, 0xA4, 0x72, 0xA0, 0x2C, 0xE9, 0x9F, 0xCB, 0x64 }, - { 0x9A, 0x87, 0xD3, 0xB7, 0x9E, 0xC6, 0x72, 0x28, 0xCB, 0x97, 0x87, 0x8B, 0x76, 0x04, 0x9B, 0x15, 0xDB, 0xD0, 0x5B, 0x81, 0x58, 0xD1, 0x7B, 0x5B, 0x91, 0x14, 0xD3, 0xC2, 0x26, 0x88, 0x75, 0x05 }, - { 0x66, 0xF8, 0x2E, 0xA9, 0x09, 0x23, 0x68, 0x9B, 0x85, 0x5D, 0x36, 0xC6, 0xB7, 0xE0, 0x32, 0xFB, 0x99, 0x70, 0x30, 0x14, 0x81, 0xB9, 0x9E, 0x01, 0xCD, 0xB4, 0xD6, 0xAC, 0x7C, 0x34, 0x7A, 0x15 }, - { 0x4F, 0x5A, 0xEE, 0x41, 0x51, 0x08, 0x48, 0xA6, 0x44, 0x7D, 0xCD, 0x1B, 0xBC, 0x78, 0x45, 0x7E, 0xF6, 0x90, 0x24, 0x94, 0x4C, 0x87, 0xF4, 0x02, 0x50, 0xD3, 0xEF, 0x2C, 0x25, 0xD3, 0x3E, 0xFE }, - { 0xDD, 0xEF, 0x42, 0x7B, 0xBB, 0x84, 0x7C, 0xC0, 0x27, 0xBE, 0xFF, 0x4E, 0xDB, 0x01, 0x03, 0x81, 0x48, 0x91, 0x78, 0x32, 0x25, 0x3E, 0xBC, 0x35, 0x5F, 0xC3, 0x3F, 0x4A, 0x8E, 0x2F, 0xCC, 0xE4 }, - { 0x97, 0xB8, 0x90, 0xA2, 0x6C, 0x98, 0x1D, 0xA8, 0x10, 0x2D, 0x3B, 0xC2, 0x94, 0x15, 0x9D, 0x17, 0x1D, 0x72, 0x81, 0x0F, 0xDF, 0x7C, 0x6A, 0x69, 0x1D, 0xEF, 0x02, 0xF0, 0xF7, 0xAF, 0x3F, 0xDC }, - { 0x53, 0xFA, 0x9E, 0x08, 0xBA, 0x52, 0x43, 0xCB, 0xCB, 0x0D, 0x79, 0x7C, 0x5E, 0xE8, 0x3B, 0xC6, 0x72, 0x8E, 0x53, 0x9E, 0xB7, 0x6C, 0x2D, 0x0B, 0xF0, 0xF9, 0x71, 0xEE, 0x4E, 0x90, 0x99, 0x71 }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 } - }, - { 0x59, 0x9C, 0x67, 0xEA, 0x41, 0x0D, 0x00, 0x5B, 0x9D, 0xA9, 0x08, 0x17, 0xCF, 0x03, 0xED, 0x3B, 0x1C, 0x86, 0x8E, 0x4D, 0xA4, 0xED, 0xF0, 0x0A, 0x58, 0x80, 0xB0, 0x08, 0x2C, 0x23, 0x78, 0x69 }, - { - { 2, { 0, 1 }, 0, { 0 }, { 0 }, { 0x03, 0x41, 0x43, 0x27, 0x22, 0xC5, 0xCD, 0x02, 0x68, 0xD8, 0x29, 0xC7, 0x02, 0xCF, 0x0D, 0x1C, 0xBC, 0xE5, 0x70, 0x33, 0xEE, 0xD2, 0x01, 0xFD, 0x33, 0x51, 0x91, 0x38, 0x52, 0x27, 0xC3, 0x21, 0x0C, 0x03, 0xD3, 0x77, 0xF2, 0xD2, 0x58, 0xB6, 0x4A, 0xAD, 0xC0, 0xE1, 0x6F, 0x26, 0x46, 0x23, 0x23, 0xD7, 0x01, 0xD2, 0x86, 0x04, 0x6A, 0x2E, 0xA9, 0x33, 0x65, 0x65, 0x6A, 0xFD, 0x98, 0x75, 0x98, 0x2B }, 2, { 0, 1 }, { 0x04, 0x1D, 0xA2, 0x22, 0x23, 0xCE, 0x65, 0xC9, 0x2C, 0x9A, 0x0D, 0x6C, 0x2C, 0xAC, 0x82, 0x8A, 0xAF, 0x1E, 0xEE, 0x56, 0x30, 0x4F, 0xEC, 0x37, 0x1D, 0xDF, 0x91, 0xEB, 0xB2, 0xB9, 0xEF, 0x09, 0x12, 0xF1, 0x03, 0x80, 0x25, 0x85, 0x7F, 0xED, 0xEB, 0x3F, 0xF6, 0x96, 0xF8, 0xB9, 0x9F, 0xA4, 0xBB, 0x2C, 0x58, 0x12, 0xF6, 0x09, 0x5A, 0x2E, 0x00, 0x04, 0xEC, 0x99, 0xCE, 0x18, 0xDE, 0x1E }, 0 }, - { 2, { 0, 2 }, 0, { 0 }, { 0 }, { 0x02, 0x24, 0xAF, 0xD3, 0x6C, 0x90, 0x20, 0x84, 0x05, 0x8B, 0x51, 0xB5, 0xD3, 0x66, 0x76, 0xBB, 0xA4, 0xDC, 0x97, 0xC7, 0x75, 0x87, 0x37, 0x68, 0xE5, 0x88, 0x22, 0xF8, 0x7F, 0xE4, 0x37, 0xD7, 0x92, 0x02, 0x8C, 0xB1, 0x59, 0x29, 0x09, 0x9E, 0xEE, 0x2F, 0x5D, 0xAE, 0x40, 0x4C, 0xD3, 0x93, 0x57, 0x59, 0x1B, 0xA3, 0x2E, 0x9A, 0xF4, 0xE1, 0x62, 0xB8, 0xD3, 0xE7, 0xCB, 0x5E, 0xFE, 0x31, 0xCB, 0x20 }, 2, { 2, 3 }, { 0x10, 0x69, 0xB6, 0x7E, 0xC3, 0xD2, 0xF3, 0xC7, 0xC0, 0x82, 0x91, 0xAC, 0xCB, 0x17, 0xA9, 0xC9, 0xB8, 0xF2, 0x81, 0x9A, 0x52, 0xEB, 0x5D, 0xF8, 0x72, 0x6E, 0x17, 0xE7, 0xD6, 0xB5, 0x2E, 0x9F, 0x01, 0x80, 0x02, 0x60, 0xA7, 0xE9, 0xDA, 0xC4, 0x50, 0xF4, 0xBE, 0x52, 0x2D, 0xE4, 0xCE, 0x12, 0xBA, 0x91, 0xAE, 0xAF, 0x2B, 0x42, 0x79, 0x21, 0x9E, 0xF7, 0x4B, 0xE1, 0xD2, 0x86, 0xAD, 0xD9 }, 0 }, - { 2, { 0, 2 }, 1, { 0 }, { 0 }, { 0x02, 0x08, 0xC5, 0xC4, 0x38, 0xC7, 0x10, 0xF4, 0xF9, 0x6A, 0x61, 0xE9, 0xFF, 0x3C, 0x37, 0x75, 0x88, 0x14, 0xB8, 0xC3, 0xAE, 0x12, 0xBF, 0xEA, 0x0E, 0xD2, 0xC8, 0x7F, 0xF6, 0x95, 0x4F, 0xF1, 0x86, 0x02, 0x0B, 0x18, 0x16, 0xEA, 0x10, 0x4B, 0x4F, 0xCA, 0x2D, 0x30, 0x4D, 0x73, 0x3E, 0x0E, 0x19, 0xCE, 0xAD, 0x51, 0x30, 0x3F, 0xF6, 0x42, 0x0B, 0xFD, 0x22, 0x23, 0x35, 0xCA, 0xA4, 0x02, 0x91, 0x6D }, 2, { 4, 5 }, { 0x5C, 0x55, 0x8E, 0x1D, 0xCA, 0xDE, 0x86, 0xDA, 0x0B, 0x2F, 0x02, 0x62, 0x6A, 0x51, 0x2E, 0x30, 0xA2, 0x2C, 0xF5, 0x25, 0x5C, 0xAE, 0xA7, 0xEE, 0x32, 0xC3, 0x8E, 0x9A, 0x71, 0xA0, 0xE9, 0x14, 0x8B, 0xA6, 0xC0, 0xE6, 0xEC, 0x76, 0x83, 0xB6, 0x42, 0x20, 0xF0, 0x29, 0x86, 0x96, 0xF1, 0xB8, 0x78, 0xCD, 0x47, 0xB1, 0x07, 0xB8, 0x1F, 0x71, 0x88, 0x81, 0x2D, 0x59, 0x39, 0x71, 0xE0, 0xCC }, 0 }, - { 2, { 0, 3 }, 3, { 0, 1, 2 }, { 1, 0, 1 }, { 0x02, 0xB5, 0xAD, 0x07, 0xAF, 0xCD, 0x99, 0xB6, 0xD9, 0x2C, 0xB4, 0x33, 0xFB, 0xD2, 0xA2, 0x8F, 0xDE, 0xB9, 0x8E, 0xAE, 0x2E, 0xB0, 0x9B, 0x60, 0x14, 0xEF, 0x0F, 0x81, 0x97, 0xCD, 0x58, 0x40, 0x33, 0x02, 0xE8, 0x61, 0x69, 0x10, 0xF9, 0x29, 0x3C, 0xF6, 0x92, 0xC4, 0x9F, 0x35, 0x1D, 0xB8, 0x6B, 0x25, 0xE3, 0x52, 0x90, 0x1F, 0x0E, 0x23, 0x7B, 0xAF, 0xDA, 0x11, 0xF1, 0xC1, 0xCE, 0xF2, 0x9F, 0xFD }, 2, { 6, 7 }, { 0x83, 0x9B, 0x08, 0x82, 0x0B, 0x68, 0x1D, 0xBA, 0x8D, 0xAF, 0x4C, 0xC7, 0xB1, 0x04, 0xE8, 0xF2, 0x63, 0x8F, 0x93, 0x88, 0xF8, 0xD7, 0xA5, 0x55, 0xDC, 0x17, 0xB6, 0xE6, 0x97, 0x1D, 0x74, 0x26, 0xCE, 0x07, 0xBF, 0x6A, 0xB0, 0x1F, 0x1D, 0xB5, 0x0E, 0x4E, 0x33, 0x71, 0x92, 0x95, 0xF4, 0x09, 0x45, 0x72, 0xB7, 0x98, 0x68, 0xE4, 0x40, 0xFB, 0x3D, 0xEF, 0xD3, 0xFA, 0xC1, 0xDB, 0x58, 0x9E }, 0 }, - }, - { - { 2, { 0, 3 }, 3, { 0, 1, 2 }, { 1, 0, 1 }, { 0x02, 0xB5, 0xAD, 0x07, 0xAF, 0xCD, 0x99, 0xB6, 0xD9, 0x2C, 0xB4, 0x33, 0xFB, 0xD2, 0xA2, 0x8F, 0xDE, 0xB9, 0x8E, 0xAE, 0x2E, 0xB0, 0x9B, 0x60, 0x14, 0xEF, 0x0F, 0x81, 0x97, 0xCD, 0x58, 0x40, 0x33, 0x02, 0xE8, 0x61, 0x69, 0x10, 0xF9, 0x29, 0x3C, 0xF6, 0x92, 0xC4, 0x9F, 0x35, 0x1D, 0xB8, 0x6B, 0x25, 0xE3, 0x52, 0x90, 0x1F, 0x0E, 0x23, 0x7B, 0xAF, 0xDA, 0x11, 0xF1, 0xC1, 0xCE, 0xF2, 0x9F, 0xFD }, 2, { 7, 8 }, { 0 }, 1 }, - }, -}; -enum { MUSIG_VECTORS_MAX_PUBKEYS = 7 }; diff --git a/src/secp256k1.c b/src/secp256k1.c index b9567015..cfd129cc 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -918,10 +918,6 @@ static int secp256k1_ge_parse_ext(secp256k1_ge* ge, const unsigned char *in33) { # include "modules/ecdsa_adaptor/main_impl.h" #endif -#ifdef ENABLE_MODULE_MUSIG -# include "modules/musig/main_impl.h" -#endif - #ifdef ENABLE_MODULE_GENERATOR # include "modules/generator/main_impl.h" #endif diff --git a/src/tests.c b/src/tests.c index aef75618..7663527c 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7592,10 +7592,6 @@ static void run_ecdsa_wycheproof(void) { # include "modules/ecdh/tests_impl.h" #endif -#ifdef ENABLE_MODULE_MUSIG -# include "modules/musig/tests_impl.h" -#endif - #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/tests_impl.h" #endif @@ -7972,10 +7968,6 @@ int main(int argc, char **argv) { run_ecdh_tests(); #endif -#ifdef ENABLE_MODULE_MUSIG - run_musig_tests(); -#endif - /* ecdsa tests */ run_ec_illegal_argument_tests(); run_pubkey_comparison(); From 8d443b8030836fbf1561284866b41c42ff099ad7 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 13 Feb 2026 14:03:05 +0200 Subject: [PATCH 286/383] musig: Re-add adaptor signatures support --- doc/musig.md | 12 ++ examples/musig.c | 2 +- include/secp256k1_musig.h | 85 +++++++++++- src/ctime_tests.c | 24 +++- src/modules/musig/Makefile.am.include | 1 + src/modules/musig/adaptor_impl.h | 101 ++++++++++++++ src/modules/musig/main_impl.h | 1 + src/modules/musig/session_impl.h | 14 +- src/modules/musig/tests_impl.h | 182 +++++++++++++++++++++++--- 9 files changed, 401 insertions(+), 21 deletions(-) create mode 100644 src/modules/musig/adaptor_impl.h diff --git a/doc/musig.md b/doc/musig.md index ae21f9b1..ad09d983 100644 --- a/doc/musig.md +++ b/doc/musig.md @@ -18,6 +18,7 @@ Therefore, users of the musig module must take great care to make sure of the fo See also the comment on `secp256k1_musig_secnonce` in `include/secp256k1_musig.h`. 3. Opaque data structures are never written to or read from directly. Instead, only the provided accessor functions are used. +4. If adaptor signatures are used, all partial signatures are verified. ## Key Aggregation and (Taproot) Tweaking @@ -52,3 +53,14 @@ Similarly, the API supports an alternative protocol flow where generating the ag ## Verification A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. + +# Atomic Swaps + +The signing API supports the production of "adaptor signatures", modified partial signatures +which are offset by an auxiliary secret known to one party. That is, +1. One party generates a (secret) adaptor `t` with corresponding (public) adaptor `T = t*G`. +2. When calling `secp256k1_musig_nonce_process`, the public adaptor `T` is provided as the `adaptor` argument. +3. The party who is going to extract the secret adaptor `t` later must verify all partial signatures. +4. Due to step 2, the signature output of `secp256k1_musig_partial_sig_agg` is a pre-signature and not a valid Schnorr signature. All parties involved extract this session's `nonce_parity` with `secp256k1_musig_nonce_parity`. +5. The party who knows `t` must "adapt" the pre-signature with `t` (and the `nonce_parity` using `secp256k1_musig_adapt` to complete the signature. +6. Any party who sees both the final signature and the pre-signature (and has the `nonce_parity`) can extract `t` with `secp256k1_musig_extract_adaptor`. diff --git a/examples/musig.c b/examples/musig.c index 396dbb9f..3450cf82 100644 --- a/examples/musig.c +++ b/examples/musig.c @@ -139,7 +139,7 @@ static int sign(const secp256k1_context* ctx, struct signer_secrets *signer_secr /* Every signer creates a partial signature */ for (i = 0; i < N_SIGNERS; i++) { /* Initialize the signing session by processing the aggregate nonce */ - if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache)) { + if (!secp256k1_musig_nonce_process(ctx, &session, &agg_pubnonce, msg32, cache, NULL)) { return 0; } /* partial_sign will clear the secnonce by setting it to 0. That's because diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index 53501814..97243033 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -16,7 +16,7 @@ extern "C" { * v1.0.0. You can find an example demonstrating the musig module in * examples/musig.c. * - * The module also supports BIP 341 ("Taproot") public key tweaking. + * The module also supports BIP 341 ("Taproot") public key tweaking and adaptor signatures. * * It is recommended to read the documentation in this include file carefully. * Further notes on API usage can be found in doc/musig.md @@ -462,6 +462,11 @@ SECP256K1_API int secp256k1_musig_nonce_agg( /** Takes the aggregate nonce and creates a session that is required for signing * and verification of partial signatures. * + * If the adaptor argument is non-NULL, then the output of + * musig_partial_sig_agg will be a pre-signature which is not a valid Schnorr + * signature. In order to create a valid signature, the pre-signature and the + * secret adaptor must be provided to `musig_adapt`. + * * Returns: 0 if the arguments are invalid, 1 otherwise * Args: ctx: pointer to a context object * Out: session: pointer to a struct to store the session @@ -470,13 +475,17 @@ SECP256K1_API int secp256k1_musig_nonce_agg( * msg32: the 32-byte message to sign * keyagg_cache: pointer to the keyagg_cache that was used to create the * aggregate (and potentially tweaked) pubkey + * adaptor: optional pointer to an adaptor point encoded as a public + * key if this signing session is part of an adaptor + * signature protocol (can be NULL) */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process( const secp256k1_context *ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, - const secp256k1_musig_keyagg_cache *keyagg_cache + const secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_pubkey *adaptor ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); /** Produces a partial signature @@ -534,6 +543,7 @@ SECP256K1_API int secp256k1_musig_partial_sign( * before aggregating it with `musig_nonce_agg` and using the result to * create the `session` with `musig_nonce_process`. * + * This function is essential when using protocols with adaptor signatures. * It is not required to call this function in regular MuSig sessions, because * if any partial signature does not verify, the final signature will not * verify either, so the problem will be caught. However, this function @@ -581,6 +591,77 @@ SECP256K1_API int secp256k1_musig_partial_sig_agg( size_t n_sigs ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); +/** Extracts the nonce_parity bit from a session + * + * This is used for adaptor signatures. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: nonce_parity: pointer to an integer that indicates the parity + * of the aggregate public nonce. Used for adaptor + * signatures. + * In: session: pointer to the session that was created with + * musig_nonce_process + */ +SECP256K1_API int secp256k1_musig_nonce_parity( + const secp256k1_context *ctx, + int *nonce_parity, + const secp256k1_musig_session *session +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Creates a signature from a pre-signature and an adaptor. + * + * If the sec_adaptor32 argument is incorrect, the output signature will be + * invalid. This function does not verify the signature. + * + * Returns: 0 if the arguments are invalid, or pre_sig64 or sec_adaptor32 contain + * invalid (overflowing) values. 1 otherwise (which does NOT mean the + * signature or the adaptor are valid!) + * Args: ctx: pointer to a context object + * Out: sig64: 64-byte signature. This pointer may point to the same + * memory area as `pre_sig`. + * In: pre_sig64: 64-byte pre-signature + * sec_adaptor32: 32-byte secret adaptor to add to the pre-signature + * nonce_parity: the output of `musig_nonce_parity` called with the + * session used for producing the pre-signature + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_adapt( + const secp256k1_context *ctx, + unsigned char *sig64, + const unsigned char *pre_sig64, + const unsigned char *sec_adaptor32, + int nonce_parity +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Extracts a secret adaptor from a MuSig pre-signature and corresponding + * signature + * + * This function will not fail unless given grossly invalid data; if it is + * merely given signatures that do not verify, the returned value will be + * nonsense. It is therefore important that all data be verified at earlier + * steps of any protocol that uses this function. In particular, this includes + * verifying all partial signatures that were aggregated into pre_sig64. + * + * Returns: 0 if the arguments are NULL, or sig64 or pre_sig64 contain + * grossly invalid (overflowing) values. 1 otherwise (which does NOT + * mean the signatures or the adaptor are valid!) + * Args: ctx: pointer to a context object + * Out:sec_adaptor32: 32-byte secret adaptor + * In: sig64: complete, valid 64-byte signature + * pre_sig64: the pre-signature corresponding to sig64, i.e., the + * aggregate of partial signatures without the secret + * adaptor + * nonce_parity: the output of `musig_nonce_parity` called with the + * session used for producing sig64 + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_extract_adaptor( + const secp256k1_context *ctx, + unsigned char *sec_adaptor32, + const unsigned char *sig64, + const unsigned char *pre_sig64, + int nonce_parity +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + #ifdef __cplusplus } #endif diff --git a/src/ctime_tests.c b/src/ctime_tests.c index 14d18e47..a4aef214 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -207,7 +207,12 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { secp256k1_musig_keyagg_cache cache; secp256k1_musig_session session; secp256k1_musig_partial_sig partial_sig; + const secp256k1_musig_partial_sig *partial_sig_ptr[1]; unsigned char extra_input[32]; + unsigned char sec_adaptor[32]; + secp256k1_pubkey adaptor; + unsigned char pre_sig[64]; + int nonce_parity; pk_ptr[0] = &pk; pubnonce_ptr[0] = &pubnonce; @@ -216,14 +221,19 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { session_secrand[0] = session_secrand[0] + 1; memcpy(extra_input, key, sizeof(extra_input)); extra_input[0] = extra_input[0] + 2; + memcpy(sec_adaptor, key, sizeof(sec_adaptor)); + sec_adaptor[0] = extra_input[0] + 3; + partial_sig_ptr[0] = &partial_sig; CHECK(secp256k1_keypair_create(ctx, &keypair, key)); CHECK(secp256k1_keypair_pub(ctx, &pk, &keypair)); CHECK(secp256k1_musig_pubkey_agg(ctx, &agg_pk, &cache, pk_ptr, 1)); + CHECK(secp256k1_ec_pubkey_create(ctx, &adaptor, sec_adaptor)); SECP256K1_CHECKMEM_UNDEFINE(key, 32); SECP256K1_CHECKMEM_UNDEFINE(session_secrand, sizeof(session_secrand)); SECP256K1_CHECKMEM_UNDEFINE(extra_input, sizeof(extra_input)); + SECP256K1_CHECKMEM_UNDEFINE(sec_adaptor, sizeof(sec_adaptor)); ret = secp256k1_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_secrand, key, &pk, msg, &cache, extra_input); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); @@ -234,7 +244,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { CHECK(secp256k1_musig_nonce_agg(ctx, &aggnonce, pubnonce_ptr, 1)); /* Make sure that previous tests don't undefine msg. It's not used as a secret here. */ SECP256K1_CHECKMEM_DEFINE(msg, sizeof(msg)); - CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache) == 1); + CHECK(secp256k1_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache, &adaptor) == 1); ret = secp256k1_keypair_create(ctx, &keypair, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); @@ -242,6 +252,18 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { ret = secp256k1_musig_partial_sign(ctx, &partial_sig, &secnonce, &keypair, &cache, &session); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); + + SECP256K1_CHECKMEM_DEFINE(&partial_sig, sizeof(partial_sig)); + CHECK(secp256k1_musig_partial_sig_agg(ctx, pre_sig, &session, partial_sig_ptr, 1)); + SECP256K1_CHECKMEM_DEFINE(pre_sig, sizeof(pre_sig)); + + CHECK(secp256k1_musig_nonce_parity(ctx, &nonce_parity, &session)); + ret = secp256k1_musig_adapt(ctx, sig, pre_sig, sec_adaptor, nonce_parity); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + ret = secp256k1_musig_extract_adaptor(ctx, sec_adaptor, sig, pre_sig, nonce_parity); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); } #endif diff --git a/src/modules/musig/Makefile.am.include b/src/modules/musig/Makefile.am.include index 796443c9..cd60e67f 100644 --- a/src/modules/musig/Makefile.am.include +++ b/src/modules/musig/Makefile.am.include @@ -4,5 +4,6 @@ noinst_HEADERS += src/modules/musig/keyagg.h noinst_HEADERS += src/modules/musig/keyagg_impl.h noinst_HEADERS += src/modules/musig/session.h noinst_HEADERS += src/modules/musig/session_impl.h +noinst_HEADERS += src/modules/musig/adaptor_impl.h noinst_HEADERS += src/modules/musig/tests_impl.h noinst_HEADERS += src/modules/musig/vectors.h diff --git a/src/modules/musig/adaptor_impl.h b/src/modules/musig/adaptor_impl.h new file mode 100644 index 00000000..3830e8a2 --- /dev/null +++ b/src/modules/musig/adaptor_impl.h @@ -0,0 +1,101 @@ +/*********************************************************************** + * Copyright (c) 2021 Jonas Nick * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H +#define SECP256K1_MODULE_MUSIG_ADAPTOR_IMPL_H + +#include + +#include "../../../include/secp256k1.h" +#include "../../../include/secp256k1_musig.h" + +#include "session.h" +#include "../../scalar.h" + +int secp256k1_musig_nonce_parity(const secp256k1_context* ctx, int *nonce_parity, const secp256k1_musig_session *session) { + secp256k1_musig_session_internal session_i; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(nonce_parity != NULL); + ARG_CHECK(session != NULL); + + if (!secp256k1_musig_session_load(ctx, &session_i, session)) { + return 0; + } + *nonce_parity = session_i.fin_nonce_parity; + return 1; +} + +int secp256k1_musig_adapt(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *pre_sig64, const unsigned char *sec_adaptor32, int nonce_parity) { + secp256k1_scalar s; + secp256k1_scalar t; + int overflow; + int ret = 1; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig64 != NULL); + ARG_CHECK(pre_sig64 != NULL); + ARG_CHECK(sec_adaptor32 != NULL); + ARG_CHECK(nonce_parity == 0 || nonce_parity == 1); + + secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow); + if (overflow) { + return 0; + } + secp256k1_scalar_set_b32(&t, sec_adaptor32, &overflow); + ret &= !overflow; + + /* Determine if the secret adaptor should be negated. + * + * The musig_session stores the X-coordinate and the parity of the "final nonce" + * (r + t)*G, where r*G is the aggregate public nonce and t is the secret adaptor. + * + * Since a BIP340 signature requires an x-only public nonce, in the case where + * (r + t)*G has odd Y-coordinate (i.e. nonce_parity == 1), the x-only public nonce + * corresponding to the signature is actually (-r - t)*G. Thus adapting a + * pre-signature requires negating t in this case. + */ + if (nonce_parity) { + secp256k1_scalar_negate(&t, &t); + } + + secp256k1_scalar_add(&s, &s, &t); + secp256k1_scalar_get_b32(&sig64[32], &s); + memmove(sig64, pre_sig64, 32); + secp256k1_scalar_clear(&t); + return ret; +} + +int secp256k1_musig_extract_adaptor(const secp256k1_context* ctx, unsigned char *sec_adaptor32, const unsigned char *sig64, const unsigned char *pre_sig64, int nonce_parity) { + secp256k1_scalar t; + secp256k1_scalar s; + int overflow; + int ret = 1; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sec_adaptor32 != NULL); + ARG_CHECK(sig64 != NULL); + ARG_CHECK(pre_sig64 != NULL); + ARG_CHECK(nonce_parity == 0 || nonce_parity == 1); + + secp256k1_scalar_set_b32(&t, &sig64[32], &overflow); + ret &= !overflow; + secp256k1_scalar_negate(&t, &t); + + secp256k1_scalar_set_b32(&s, &pre_sig64[32], &overflow); + if (overflow) { + return 0; + } + secp256k1_scalar_add(&t, &t, &s); + + if (!nonce_parity) { + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_get_b32(sec_adaptor32, &t); + secp256k1_scalar_clear(&t); + return ret; +} + +#endif diff --git a/src/modules/musig/main_impl.h b/src/modules/musig/main_impl.h index a1311e41..044bd30e 100644 --- a/src/modules/musig/main_impl.h +++ b/src/modules/musig/main_impl.h @@ -8,5 +8,6 @@ #include "keyagg_impl.h" #include "session_impl.h" +#include "adaptor_impl.h" #endif diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 2715b09d..76f04c53 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -608,7 +608,7 @@ static void secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsign *fin_nonce_parity = secp256k1_fe_is_odd(&fin_nonce_pt.y); } -int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache) { +int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_session *session, const secp256k1_musig_aggnonce *aggnonce, const unsigned char *msg32, const secp256k1_musig_keyagg_cache *keyagg_cache, const secp256k1_pubkey *adaptor) { secp256k1_keyagg_cache_internal cache_i; secp256k1_ge aggnonce_pts[2]; unsigned char fin_nonce[32]; @@ -630,6 +630,18 @@ int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_ return 0; } + /* Add public adaptor to nonce */ + if (adaptor != NULL) { + secp256k1_ge adaptorp; + secp256k1_gej tmp; + if (!secp256k1_pubkey_load(ctx, &adaptorp, adaptor)) { + return 0; + } + secp256k1_gej_set_ge(&tmp, &aggnonce_pts[0]); + secp256k1_gej_add_ge_var(&tmp, &tmp, &adaptorp, NULL); + secp256k1_ge_set_gej(&aggnonce_pts[0], &tmp); + } + secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32); diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index ce6ae178..f4ae1585 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -34,7 +34,7 @@ static int create_keypair_and_pk(secp256k1_keypair *keypair, secp256k1_pubkey *p return ret; } -/* Just a simple (non-tweaked) 2-of-2 MuSig aggregate, sign, verify +/* Just a simple (non-adaptor, non-tweaked) 2-of-2 MuSig aggregate, sign, verify * test. */ static void musig_simple_test(void) { unsigned char sk[2][32]; @@ -74,7 +74,7 @@ static void musig_simple_test(void) { CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, NULL) == 1); for (i = 0; i < 2; i++) { CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[i], &secnonce[i], &keypair[i], &keyagg_cache, &session) == 1); @@ -123,6 +123,7 @@ static void musig_api_tests(void) { const secp256k1_musig_partial_sig *partial_sig_ptr[2]; secp256k1_musig_partial_sig invalid_partial_sig; const secp256k1_musig_partial_sig *invalid_partial_sig_ptr[2]; + unsigned char final_sig[64]; unsigned char pre_sig[64]; unsigned char buf[32]; unsigned char sk[2][32]; @@ -157,6 +158,10 @@ static void musig_api_tests(void) { const secp256k1_pubkey *invalid_pk_ptr2[2]; const secp256k1_pubkey *invalid_pk_ptr3[3]; unsigned char tweak[32]; + int nonce_parity; + unsigned char sec_adaptor[32]; + unsigned char sec_adaptor1[32]; + secp256k1_pubkey adaptor; int i; /** setup **/ @@ -174,8 +179,10 @@ static void musig_api_tests(void) { memset(&invalid_pubnonce, 0, sizeof(invalid_pubnonce)); memset(&invalid_session, 0, sizeof(invalid_session)); + testrand256(sec_adaptor); testrand256(msg); testrand256(tweak); + CHECK(secp256k1_ec_pubkey_create(CTX, &adaptor, sec_adaptor) == 1); for (i = 0; i < 2; i++) { pk_ptr[i] = &pk[i]; invalid_pk_ptr2[i] = &invalid_pk; @@ -388,15 +395,17 @@ static void musig_api_tests(void) { } /** Process nonces **/ - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL)); - CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, &adaptor) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, (secp256k1_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL, &adaptor)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache, &adaptor)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, NULL) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, (secp256k1_pubkey *)&invalid_pk)); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache, &adaptor) == 1); memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &session) == 1); @@ -481,6 +490,40 @@ static void musig_api_tests(void) { CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 0)); CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 1) == 1); CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); + + /** Adaptor signature verification */ + CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity, &session) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, NULL, &session)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, &nonce_parity, NULL)); + CHECK_ILLEGAL(CTX, secp256k1_musig_nonce_parity(CTX, &nonce_parity, &invalid_session)); + + CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1); + CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, NULL, pre_sig, sec_adaptor, 0)); + CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, NULL, sec_adaptor, 0)); + CHECK(secp256k1_musig_adapt(CTX, final_sig, max64, sec_adaptor, 0) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, pre_sig, NULL, 0)); + CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, max64, 0) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, 2)); + /* sig and pre_sig argument point to the same location */ + memcpy(final_sig, pre_sig, sizeof(final_sig)); + CHECK(secp256k1_musig_adapt(CTX, final_sig, final_sig, sec_adaptor, nonce_parity) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); + + CHECK(secp256k1_musig_adapt(CTX, final_sig, pre_sig, sec_adaptor, nonce_parity) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); + + /** Secret adaptor can be extracted from signature */ + CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, nonce_parity) == 1); + CHECK(secp256k1_memcmp_var(sec_adaptor, sec_adaptor1, 32) == 0); + /* wrong nonce parity */ + CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, !nonce_parity) == 1); + CHECK(secp256k1_memcmp_var(sec_adaptor, sec_adaptor1, 32) != 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, NULL, final_sig, pre_sig, 0)); + CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, NULL, pre_sig, 0)); + CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, max64, pre_sig, 0) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, NULL, 0)); + CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, max64, 0) == 0); + CHECK_ILLEGAL(CTX, secp256k1_musig_extract_adaptor(CTX, sec_adaptor1, final_sig, pre_sig, 2)); } static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { @@ -548,6 +591,111 @@ static void musig_nonce_test(void) { } } +static void scriptless_atomic_swap(void) { + /* Throughout this test "a" and "b" refer to two hypothetical blockchains, + * while the indices 0 and 1 refer to the two signers. Here signer 0 is + * sending a-coins to signer 1, while signer 1 is sending b-coins to signer + * 0. Signer 0 produces the adaptor signatures. */ + unsigned char pre_sig_a[64]; + unsigned char final_sig_a[64]; + unsigned char pre_sig_b[64]; + unsigned char final_sig_b[64]; + secp256k1_musig_partial_sig partial_sig_a[2]; + const secp256k1_musig_partial_sig *partial_sig_a_ptr[2]; + secp256k1_musig_partial_sig partial_sig_b[2]; + const secp256k1_musig_partial_sig *partial_sig_b_ptr[2]; + unsigned char sec_adaptor[32]; + unsigned char sec_adaptor_extracted[32]; + secp256k1_pubkey pub_adaptor; + unsigned char sk_a[2][32]; + unsigned char sk_b[2][32]; + secp256k1_keypair keypair_a[2]; + secp256k1_keypair keypair_b[2]; + secp256k1_pubkey pk_a[2]; + const secp256k1_pubkey *pk_a_ptr[2]; + secp256k1_pubkey pk_b[2]; + const secp256k1_pubkey *pk_b_ptr[2]; + secp256k1_musig_keyagg_cache keyagg_cache_a; + secp256k1_musig_keyagg_cache keyagg_cache_b; + secp256k1_xonly_pubkey agg_pk_a; + secp256k1_xonly_pubkey agg_pk_b; + secp256k1_musig_secnonce secnonce_a[2]; + secp256k1_musig_secnonce secnonce_b[2]; + secp256k1_musig_pubnonce pubnonce_a[2]; + secp256k1_musig_pubnonce pubnonce_b[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr_a[2]; + const secp256k1_musig_pubnonce *pubnonce_ptr_b[2]; + secp256k1_musig_aggnonce aggnonce_a; + secp256k1_musig_aggnonce aggnonce_b; + secp256k1_musig_session session_a, session_b; + int nonce_parity_a; + int nonce_parity_b; + unsigned char seed_a[2][32] = { "a0", "a1" }; + unsigned char seed_b[2][32] = { "b0", "b1" }; + const unsigned char msg32_a[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'a'}; + const unsigned char msg32_b[32] = {'t', 'h', 'i', 's', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e', ' ', 'b', 'l', 'o', 'c', 'k', 'c', 'h', 'a', 'i', 'n', ' ', 'b'}; + int i; + + /* Step 1: key setup */ + for (i = 0; i < 2; i++) { + pk_a_ptr[i] = &pk_a[i]; + pk_b_ptr[i] = &pk_b[i]; + pubnonce_ptr_a[i] = &pubnonce_a[i]; + pubnonce_ptr_b[i] = &pubnonce_b[i]; + partial_sig_a_ptr[i] = &partial_sig_a[i]; + partial_sig_b_ptr[i] = &partial_sig_b[i]; + + testrand256(sk_a[i]); + testrand256(sk_b[i]); + CHECK(create_keypair_and_pk(&keypair_a[i], &pk_a[i], sk_a[i]) == 1); + CHECK(create_keypair_and_pk(&keypair_b[i], &pk_b[i], sk_b[i]) == 1); + } + testrand256(sec_adaptor); + CHECK(secp256k1_ec_pubkey_create(CTX, &pub_adaptor, sec_adaptor) == 1); + + CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk_a, &keyagg_cache_a, pk_a_ptr, 2) == 1); + CHECK(secp256k1_musig_pubkey_agg(CTX, &agg_pk_b, &keyagg_cache_b, pk_b_ptr, 2) == 1); + + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_a[0], &pubnonce_a[0], seed_a[0], sk_a[0], &pk_a[0], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_a[1], &pubnonce_a[1], seed_a[1], sk_a[1], &pk_a[1], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_b[0], &pubnonce_b[0], seed_b[0], sk_b[0], &pk_b[0], NULL, NULL, NULL) == 1); + CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce_b[1], &pubnonce_b[1], seed_b[1], sk_b[1], &pk_b[1], NULL, NULL, NULL) == 1); + + /* Step 2: Exchange nonces */ + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce_a, pubnonce_ptr_a, 2) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session_a, &aggnonce_a, msg32_a, &keyagg_cache_a, &pub_adaptor) == 1); + CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity_a, &session_a) == 1); + CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce_b, pubnonce_ptr_b, 2) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session_b, &aggnonce_b, msg32_b, &keyagg_cache_b, &pub_adaptor) == 1); + CHECK(secp256k1_musig_nonce_parity(CTX, &nonce_parity_b, &session_b) == 1); + + /* Step 3: Signer 0 produces partial signatures for both chains. */ + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_a[0], &secnonce_a[0], &keypair_a[0], &keyagg_cache_a, &session_a) == 1); + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_b[0], &secnonce_b[0], &keypair_b[0], &keyagg_cache_b, &session_b) == 1); + + /* Step 4: Signer 1 receives partial signatures, verifies them and creates a + * partial signature to send B-coins to signer 0. */ + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig_a[0], &pubnonce_a[0], &pk_a[0], &keyagg_cache_a, &session_a) == 1); + CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig_b[0], &pubnonce_b[0], &pk_b[0], &keyagg_cache_b, &session_b) == 1); + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_b[1], &secnonce_b[1], &keypair_b[1], &keyagg_cache_b, &session_b) == 1); + + /* Step 5: Signer 0 aggregates its own partial signature with the partial + * signature from signer 1 and adapts it. This results in a complete + * signature which is broadcasted by signer 0 to take B-coins. */ + CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig_b, &session_b, partial_sig_b_ptr, 2) == 1); + CHECK(secp256k1_musig_adapt(CTX, final_sig_b, pre_sig_b, sec_adaptor, nonce_parity_b) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_b, msg32_b, sizeof(msg32_b), &agg_pk_b) == 1); + + /* Step 6: Signer 1 signs, extracts adaptor from the published signature, + * and adapts the signature to take A-coins. */ + CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig_a[1], &secnonce_a[1], &keypair_a[1], &keyagg_cache_a, &session_a) == 1); + CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig_a, &session_a, partial_sig_a_ptr, 2) == 1); + CHECK(secp256k1_musig_extract_adaptor(CTX, sec_adaptor_extracted, final_sig_b, pre_sig_b, nonce_parity_b) == 1); + CHECK(secp256k1_memcmp_var(sec_adaptor_extracted, sec_adaptor, sizeof(sec_adaptor)) == 0); /* in real life we couldn't check this, of course */ + CHECK(secp256k1_musig_adapt(CTX, final_sig_a, pre_sig_a, sec_adaptor_extracted, nonce_parity_a) == 1); + CHECK(secp256k1_schnorrsig_verify(CTX, final_sig_a, msg32_a, sizeof(msg32_a), &agg_pk_a) == 1); +} + static void sha256_tag_test_internal(secp256k1_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { secp256k1_sha256 sha; secp256k1_sha256_initialize_tagged(&sha, tag, taglen); @@ -616,7 +764,7 @@ static void musig_tweak_test_helper(const secp256k1_xonly_pubkey* agg_pk, const CHECK(secp256k1_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk1, &pk[1], NULL, NULL, NULL) == 1); CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache) == 1); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache, NULL) == 1); CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], keyagg_cache, &session) == 1); CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], keyagg_cache, &session) == 1); @@ -882,7 +1030,7 @@ static void musig_test_vectors_signverify(void) { CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey); @@ -922,8 +1070,9 @@ static void musig_test_vectors_signverify(void) { if (!expected) { continue; } - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); + CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); expected = c->error != MUSIG_SECNONCE; @@ -955,7 +1104,7 @@ static void musig_test_vectors_signverify(void) { CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, NULL, c->key_indices_len, c->key_indices, 0, NULL, NULL)); CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, c->nonce_indices_len) == 1); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache, NULL)); CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[c->signer_index], sizeof(vector->pubkeys[0]))); @@ -1010,7 +1159,7 @@ static void musig_test_vectors_tweak(void) { CHECK(secp256k1_keypair_create(CTX, &keypair, vector->sk)); CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, NULL, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache, NULL)); CHECK(secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); CHECK(secp256k1_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); @@ -1046,7 +1195,7 @@ static void musig_test_vectors_sigagg(void) { CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk32, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce)); - CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); + CHECK(secp256k1_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache, NULL)); for (j = 0; j < c->psig_indices_len; j++) { CHECK(secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); partial_sig_ptr[j] = &partial_sig[j]; @@ -1127,6 +1276,7 @@ static void run_musig_tests(void) { for (i = 0; i < COUNT; i++) { /* Run multiple times to ensure that pk and nonce have different y * parities */ + scriptless_atomic_swap(); musig_tweak_test(); } sha256_tag_test(); From ed02466d3f9c07afc8bcd56aa9f295cfa8e3c4ed Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 13 Feb 2026 21:38:35 +0000 Subject: [PATCH 287/383] ci: Load Docker image by ID from builder step --- .github/actions/run-in-docker-action/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index 0884d3a4..bbbcf324 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -44,7 +44,7 @@ runs: $(echo '${{ toJSON(env) }}' | jq -r 'keys[] | "--env \(.) "') \ --volume ${{ github.workspace }}:${{ github.workspace }} \ --workdir ${{ github.workspace }} \ - $(docker images -q | head -n1) \ + ${{ case(steps.main_builder.outcome == 'success', steps.main_builder.outputs.imageid, steps.retry_builder.outputs.imageid) }} \ bash -c " git config --global --add safe.directory ${{ github.workspace }} ${{ inputs.command }} From 8c7c24eb8a00c9d9122d6f9a6ec30b4f8fca20b4 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 16 Feb 2026 13:01:42 +0200 Subject: [PATCH 288/383] docs: simplify README description, fix musig docs --- README.md | 2 +- doc/musig.md | 2 +- include/secp256k1_musig.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 488044b4..675c2da2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ libsecp256k1-zkp ![Dependencies: None](https://img.shields.io/badge/dependencies-none-success) -A fork of [libsecp256k1](https://github.com/bitcoin-core/secp256k1) with support for advanced and experimental features such as Confidential Assets and Bulletproofs++ range proofs +A fork of [libsecp256k1](https://github.com/bitcoin-core/secp256k1) with support for advanced and experimental features Added features: * Experimental module for ECDSA adaptor signatures. diff --git a/doc/musig.md b/doc/musig.md index ad09d983..3732782f 100644 --- a/doc/musig.md +++ b/doc/musig.md @@ -54,7 +54,7 @@ Similarly, the API supports an alternative protocol flow where generating the ag A participant who wants to verify the partial signatures, but does not sign itself may do so using the above instructions except that the verifier skips steps 1, 4 and 7. -# Atomic Swaps +## Atomic Swaps The signing API supports the production of "adaptor signatures", modified partial signatures which are offset by an auxiliary secret known to one party. That is, diff --git a/include/secp256k1_musig.h b/include/secp256k1_musig.h index 97243033..d49f2e09 100644 --- a/include/secp256k1_musig.h +++ b/include/secp256k1_musig.h @@ -544,7 +544,7 @@ SECP256K1_API int secp256k1_musig_partial_sign( * create the `session` with `musig_nonce_process`. * * This function is essential when using protocols with adaptor signatures. - * It is not required to call this function in regular MuSig sessions, because + * Without adaptor signatures, it is not required to call this function in regular MuSig sessions, because * if any partial signature does not verify, the final signature will not * verify either, so the problem will be caught. However, this function * provides the ability to identify which specific partial signature fails From 307b49f1b996024d458a9b69e9df8d15b628d34a Mon Sep 17 00:00:00 2001 From: gzJx0DuTRHytnHe7P5RmMbPf3wKy2BztweVGXTf <249832636+gzJx0DuTRHytnHe7P5RmMbPf3wKy2BztweVGXTf@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:35:26 +0100 Subject: [PATCH 289/383] ellswift: fix overflow flag handling in secp256k1_ellswift_xdh The secp256k1_ellswift_xdh function uses overflow = secp256k1_scalar_is_zero(&s) which overwrites the overflow flag from the preceding secp256k1_scalar_set_b32 call. This means secret keys >= the curve order are silently accepted (reduced mod n) instead of being rejected. The fix changes = to |=, matching the correct pattern already used in secp256k1_ecdh (main_impl.h, line 51). The ECDH module's test suite explicitly tests overflow rejection (passes secp256k1_group_order_bytes as a key and checks the function returns 0). The ellswift test suite has no corresponding test, which is why this went undetected. --- src/modules/ellswift/main_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 096f4a3c..4a425665 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -564,7 +564,7 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, /* Load private key (using one if invalid). */ secp256k1_scalar_set_b32(&s, seckey32, &overflow); - overflow = secp256k1_scalar_is_zero(&s); + overflow |= secp256k1_scalar_is_zero(&s); secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow); /* Compute shared X coordinate. */ From a8e6a3cc347b80908227020ed315ab43b894942a Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 16 Feb 2026 16:12:41 +0200 Subject: [PATCH 290/383] Port bitcoin-core/secp256k1#1628 to zkp public API --- include/secp256k1_ecdsa_s2c.h | 2 +- include/secp256k1_generator.h | 4 ++-- include/secp256k1_surjectionproof.h | 4 ++-- include/secp256k1_whitelist.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/secp256k1_ecdsa_s2c.h b/include/secp256k1_ecdsa_s2c.h index ea4219fe..c931457d 100644 --- a/include/secp256k1_ecdsa_s2c.h +++ b/include/secp256k1_ecdsa_s2c.h @@ -25,7 +25,7 @@ extern "C" { * If you need to convert to a format suitable for storage, transmission, or * comparison, use secp256k1_ecdsa_s2c_opening_serialize and secp256k1_ecdsa_s2c_opening_parse. */ -typedef struct { +typedef struct secp256k1_ecdsa_s2c_opening { unsigned char data[64]; } secp256k1_ecdsa_s2c_opening; diff --git a/include/secp256k1_generator.h b/include/secp256k1_generator.h index 0a59c363..7bf32314 100644 --- a/include/secp256k1_generator.h +++ b/include/secp256k1_generator.h @@ -17,7 +17,7 @@ extern "C" { * If you need to convert to a format suitable for storage, transmission, or * comparison, use secp256k1_generator_serialize and secp256k1_generator_parse. */ -typedef struct { +typedef struct secp256k1_generator { unsigned char data[64]; } secp256k1_generator; @@ -100,7 +100,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_generator_generate_blin * comparison, use secp256k1_pedersen_commitment_serialize and * secp256k1_pedersen_commitment_parse. */ -typedef struct { +typedef struct secp256k1_pedersen_commitment { unsigned char data[64]; } secp256k1_pedersen_commitment; diff --git a/include/secp256k1_surjectionproof.h b/include/secp256k1_surjectionproof.h index c9a4aaee..95c58384 100644 --- a/include/secp256k1_surjectionproof.h +++ b/include/secp256k1_surjectionproof.h @@ -39,7 +39,7 @@ extern "C" { * The representation is exposed to allow creation of these objects on the * stack; please *do not* use these internals directly. */ -typedef struct { +typedef struct secp256k1_surjectionproof { #ifdef VERIFY /** Mark whether this proof has gone through `secp256k1_surjectionproof_initialize` */ int initialized; @@ -100,7 +100,7 @@ SECP256K1_API int secp256k1_surjectionproof_serialize( * data the API user wants to use as an asset tag. Its contents have no * semantic meaning to libsecp whatsoever. */ -typedef struct { +typedef struct secp256k1_fixed_asset_tag { unsigned char data[32]; } secp256k1_fixed_asset_tag; diff --git a/include/secp256k1_whitelist.h b/include/secp256k1_whitelist.h index 9f9decce..20d495d3 100644 --- a/include/secp256k1_whitelist.h +++ b/include/secp256k1_whitelist.h @@ -31,7 +31,7 @@ extern "C" { * stack; please *do not* use these internals directly. To learn the number * of keys for a signature, use `secp256k1_whitelist_signature_n_keys`. */ -typedef struct { +typedef struct secp256k1_whitelist_signature { size_t n_keys; /* e0, scalars */ unsigned char data[32 * (1 + SECP256K1_WHITELIST_MAX_N_KEYS)]; From b99a94c3827e1b8e8505648758512eb3cf4aae03 Mon Sep 17 00:00:00 2001 From: gzJx0DuTRHytnHe7P5RmMbPf3wKy2BztweVGXTf <249832636+gzJx0DuTRHytnHe7P5RmMbPf3wKy2BztweVGXTf@users.noreply.github.com> Date: Fri, 13 Feb 2026 00:19:54 +0100 Subject: [PATCH 291/383] Add tests for bad scalar inputs in ellswift XDH --- src/modules/ellswift/tests_impl.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 4cc7f4b5..e3090411 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -460,6 +460,33 @@ void ellswift_hash_init_tests(void) { test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); } +void ellswift_xdh_bad_scalar_tests(void) { + unsigned char s_zero[32] = { 0 }; + unsigned char s_overflow_minus1[32] = { 0 }; + unsigned char s_overflow_plus1[32] = { 0 }; + unsigned char s_good[32] = { 0 }; + unsigned char ell_a64[64], ell_b64[64]; + unsigned char output[32]; + secp256k1_scalar rand_scalar; + + testutil_random_scalar_order(&rand_scalar); + secp256k1_scalar_get_b32(s_good, &rand_scalar); + + CHECK(secp256k1_ellswift_create(CTX, ell_a64, s_good, NULL) == 1); + + testrand256_test(ell_b64); + testrand256_test(ell_b64 + 32); + + memcpy(s_overflow_minus1, secp256k1_group_order_bytes, 32); + s_overflow_minus1[31] -= 1; + memcpy(s_overflow_plus1, secp256k1_group_order_bytes, 32); + s_overflow_plus1[31] += 1; + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, s_zero, 0, &ellswift_xdh_hash_x32, NULL) == 0); + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, secp256k1_group_order_bytes, 0, &ellswift_xdh_hash_x32, NULL) == 0); + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, s_overflow_plus1, 0, &ellswift_xdh_hash_x32, NULL) == 0); + CHECK(secp256k1_ellswift_xdh(CTX, output, ell_a64, ell_b64, s_overflow_minus1, 0, &ellswift_xdh_hash_x32, NULL) == 1); +} + /* --- Test registry --- */ static const struct tf_test_entry tests_ellswift[] = { CASE1(ellswift_encoding_test_vectors_tests), @@ -470,6 +497,7 @@ static const struct tf_test_entry tests_ellswift[] = { CASE1(ellswift_compute_shared_secret_tests), CASE1(ellswift_xdh_correctness_tests), CASE1(ellswift_hash_init_tests), + CASE1(ellswift_xdh_bad_scalar_tests), }; #endif From 921b9711eadbdba16a3f980c29c4156448fd2d68 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 16 Feb 2026 23:47:51 +0100 Subject: [PATCH 292/383] util: introduce and use `ARRAY_SIZE` macro The macro definition matches the one used in Linux, see e.g. https://github.com/torvalds/linux/blob/9702969978695d9a699a1f34771580cdbb153b33/include/linux/array_size.h#L11 (without the additional check rejecting pointers, as we would need GNU C for that, see e.g. https://stackoverflow.com/a/19455169) --- src/bench.c | 3 +- src/modules/ellswift/tests_impl.h | 7 ++-- src/modules/musig/tests_impl.h | 32 +++++++++---------- .../schnorrsig/tests_exhaustive_impl.h | 2 +- src/precompute_ecmult_gen.c | 2 +- src/tests.c | 28 ++++++++-------- src/unit_test.h | 4 ++- src/util.h | 2 ++ 8 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/bench.c b/src/bench.c index a5231b71..db72bd8d 100644 --- a/src/bench.c +++ b/src/bench.c @@ -183,8 +183,7 @@ int main(int argc, char** argv) { "ecdsa_recover", "schnorrsig", "schnorrsig_verify", "schnorrsig_sign", "ec", "keygen", "ec_keygen", "ellswift", "encode", "ellswift_encode", "decode", "ellswift_decode", "ellswift_keygen", "ellswift_ecdh"}; - size_t valid_args_size = sizeof(valid_args)/sizeof(valid_args[0]); - int invalid_args = have_invalid_args(argc, argv, valid_args, valid_args_size); + int invalid_args = have_invalid_args(argc, argv, valid_args, ARRAY_SIZE(valid_args)); int default_iters = 20000; int iters = get_iters(default_iters); diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 4cc7f4b5..63aad1e0 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -8,6 +8,7 @@ #include "../../../include/secp256k1_ellswift.h" #include "../../unit_test.h" +#include "../../util.h" struct ellswift_xswiftec_inv_test { int enc_bitmap; @@ -180,7 +181,7 @@ static int ellswift_xdh_hash_x32(unsigned char *output, const unsigned char *x32 /* Run the test vectors for ellswift encoding */ void ellswift_encoding_test_vectors_tests(void) { int i; - for (i = 0; (unsigned)i < sizeof(ellswift_xswiftec_inv_tests) / sizeof(ellswift_xswiftec_inv_tests[0]); ++i) { + for (i = 0; (unsigned)i < ARRAY_SIZE(ellswift_xswiftec_inv_tests); ++i) { const struct ellswift_xswiftec_inv_test *testcase = &ellswift_xswiftec_inv_tests[i]; int c; for (c = 0; c < 8; ++c) { @@ -200,7 +201,7 @@ void ellswift_encoding_test_vectors_tests(void) { /* Run the test vectors for ellswift decoding */ void ellswift_decoding_test_vectors_tests(void) { int i; - for (i = 0; (unsigned)i < sizeof(ellswift_decode_tests) / sizeof(ellswift_decode_tests[0]); ++i) { + for (i = 0; (unsigned)i < ARRAY_SIZE(ellswift_decode_tests); ++i) { const struct ellswift_decode_test *testcase = &ellswift_decode_tests[i]; secp256k1_pubkey pubkey; secp256k1_ge ge; @@ -217,7 +218,7 @@ void ellswift_decoding_test_vectors_tests(void) { /* Run the test vectors for ellswift expected xdh BIP324 shared secrets */ void ellswift_xdh_test_vectors_tests(void) { int i; - for (i = 0; (unsigned)i < sizeof(ellswift_xdh_tests_bip324) / sizeof(ellswift_xdh_tests_bip324[0]); ++i) { + for (i = 0; (unsigned)i < ARRAY_SIZE(ellswift_xdh_tests_bip324); ++i) { const struct ellswift_xdh_test *test = &ellswift_xdh_tests_bip324[i]; unsigned char shared_secret[32]; int ret; diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index de09c5e2..98d2d9b6 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -769,7 +769,7 @@ static void musig_test_vectors_keyagg(void) { size_t i; const struct musig_key_agg_vector *vector = &musig_key_agg_vector; - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->valid_case); i++) { const struct musig_key_agg_valid_test_case *c = &vector->valid_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -779,7 +779,7 @@ static void musig_test_vectors_keyagg(void) { CHECK(secp256k1_memcmp_var(agg_pk, c->expected, sizeof(agg_pk)) == 0); } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->error_case); i++) { const struct musig_key_agg_error_test_case *c = &vector->error_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -793,7 +793,7 @@ static void musig_test_vectors_noncegen(void) { size_t i; const struct musig_nonce_gen_vector *vector = &musig_nonce_gen_vector; - for (i = 0; i < sizeof(vector->test_case)/sizeof(vector->test_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->test_case); i++) { const struct musig_nonce_gen_test_case *c = &vector->test_case[i]; secp256k1_musig_keyagg_cache keyagg_cache; secp256k1_musig_keyagg_cache *keyagg_cache_ptr = NULL; @@ -847,7 +847,7 @@ static void musig_test_vectors_nonceagg(void) { int j; const struct musig_nonce_agg_vector *vector = &musig_nonce_agg_vector; - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->valid_case); i++) { const struct musig_nonce_agg_test_case *c = &vector->valid_case[i]; secp256k1_musig_pubnonce pubnonce[2]; const secp256k1_musig_pubnonce *pubnonce_ptr[2]; @@ -862,7 +862,7 @@ static void musig_test_vectors_nonceagg(void) { CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce)); CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, 33) == 0); } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->error_case); i++) { const struct musig_nonce_agg_test_case *c = &vector->error_case[i]; secp256k1_musig_pubnonce pubnonce[2]; for (j = 0; j < 2; j++) { @@ -886,7 +886,7 @@ static void musig_test_vectors_signverify(void) { size_t i; const struct musig_sign_verify_vector *vector = &musig_sign_verify_vector; - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->valid_case); i++) { const struct musig_valid_case *c = &vector->valid_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -914,7 +914,7 @@ static void musig_test_vectors_signverify(void) { CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[0])); CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); } - for (i = 0; i < sizeof(vector->sign_error_case)/sizeof(vector->sign_error_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->sign_error_case); i++) { const struct musig_sign_error_case *c = &vector->sign_error_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -953,7 +953,7 @@ static void musig_test_vectors_signverify(void) { musig_test_set_secnonce(&secnonce, vector->secnonces[c->secnonce_index], &pubkey); CHECK_ILLEGAL(CTX, secp256k1_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); } - for (i = 0; i < sizeof(vector->verify_fail_case)/sizeof(vector->verify_fail_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->verify_fail_case); i++) { const struct musig_verify_fail_error_case *c = &vector->verify_fail_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -987,7 +987,7 @@ static void musig_test_vectors_signverify(void) { expected = c->error != MUSIG_SIG_VERIFY; CHECK(expected == secp256k1_musig_partial_sig_verify(CTX, &partial_sig, pubnonce, &pubkey, &keyagg_cache, &session)); } - for (i = 0; i < sizeof(vector->verify_error_case)/sizeof(vector->verify_error_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->verify_error_case); i++) { const struct musig_verify_fail_error_case *c = &vector->verify_error_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -1015,7 +1015,7 @@ static void musig_test_vectors_tweak(void) { CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonce)); CHECK(secp256k1_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->valid_case); i++) { const struct musig_tweak_case *c = &vector->valid_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -1039,7 +1039,7 @@ static void musig_test_vectors_tweak(void) { CHECK(secp256k1_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); CHECK(secp256k1_musig_partial_sig_verify(CTX, &partial_sig, &pubnonce, &pubkey, &keyagg_cache, &session)); } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->error_case); i++) { const struct musig_tweak_case *c = &vector->error_case[i]; enum MUSIG_ERROR error; secp256k1_musig_keyagg_cache keyagg_cache; @@ -1052,7 +1052,7 @@ static void musig_test_vectors_sigagg(void) { size_t i, j; const struct musig_sig_agg_vector *vector = &musig_sig_agg_vector; - for (i = 0; i < sizeof(vector->valid_case)/sizeof(vector->valid_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->valid_case); i++) { const struct musig_sig_agg_case *c = &vector->valid_case[i]; enum MUSIG_ERROR error; unsigned char final_sig[64]; @@ -1061,8 +1061,8 @@ static void musig_test_vectors_sigagg(void) { secp256k1_xonly_pubkey agg_pk; secp256k1_musig_aggnonce aggnonce; secp256k1_musig_session session; - secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; - const secp256k1_musig_partial_sig *partial_sig_ptr[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; + secp256k1_musig_partial_sig partial_sig[ARRAY_SIZE(vector->psigs)]; + const secp256k1_musig_partial_sig *partial_sig_ptr[ARRAY_SIZE(vector->psigs)]; CHECK(musig_vectors_keyagg_and_tweak(&error, &keyagg_cache, agg_pk32, vector->pubkeys, vector->tweaks, c->key_indices_len, c->key_indices, c->tweak_indices_len, c->tweak_indices, c->is_xonly)); CHECK(secp256k1_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce)); @@ -1078,9 +1078,9 @@ static void musig_test_vectors_sigagg(void) { CHECK(secp256k1_xonly_pubkey_parse(CTX, &agg_pk, agg_pk32)); CHECK(secp256k1_schnorrsig_verify(CTX, final_sig, vector->msg, sizeof(vector->msg), &agg_pk) == 1); } - for (i = 0; i < sizeof(vector->error_case)/sizeof(vector->error_case[0]); i++) { + for (i = 0; i < ARRAY_SIZE(vector->error_case); i++) { const struct musig_sig_agg_case *c = &vector->error_case[i]; - secp256k1_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; + secp256k1_musig_partial_sig partial_sig[ARRAY_SIZE(vector->psigs)]; for (j = 0; j < c->psig_indices_len; j++) { int expected = c->invalid_sig_idx != (int)j; CHECK(expected == secp256k1_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); diff --git a/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/modules/schnorrsig/tests_exhaustive_impl.h index 601b5497..4b97b58d 100644 --- a/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -56,7 +56,7 @@ static const unsigned char invalid_pubkey_bytes[][32] = { } }; -#define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) +#define NUM_INVALID_KEYS (ARRAY_SIZE(invalid_pubkey_bytes)) static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg, size_t msglen, diff --git a/src/precompute_ecmult_gen.c b/src/precompute_ecmult_gen.c index cd0fe70f..a03abdb5 100644 --- a/src/precompute_ecmult_gen.c +++ b/src/precompute_ecmult_gen.c @@ -80,7 +80,7 @@ int main(int argc, char **argv) { fprintf(fp, "const secp256k1_ge_storage secp256k1_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = {\n"); fprintf(fp, "#if 0\n"); - for (config = 0; config < sizeof(CONFIGS) / sizeof(*CONFIGS); ++config) { + for (config = 0; config < ARRAY_SIZE(CONFIGS); ++config) { print_table(fp, CONFIGS[config][0], CONFIGS[config][1]); if (CONFIGS[config][0] == COMB_BLOCKS && CONFIGS[config][1] == COMB_TEETH) { did_current_config = 1; diff --git a/src/tests.c b/src/tests.c index b1a78049..c7f2e4dd 100644 --- a/src/tests.c +++ b/src/tests.c @@ -92,7 +92,7 @@ static void run_xoshiro256pp_tests(void) { { size_t i; /* Sanity check that we run before the actual seeding. */ - for (i = 0; i < sizeof(secp256k1_test_state)/sizeof(secp256k1_test_state[0]); i++) { + for (i = 0; i < ARRAY_SIZE(secp256k1_test_state); i++) { CHECK(secp256k1_test_state[i] == 0); } } @@ -146,7 +146,7 @@ static void run_deprecated_context_flags_test(void) { SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY }; secp256k1_context *none_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); int i; - for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) { + for (i = 0; i < (int)(ARRAY_SIZE(flags)); i++) { secp256k1_context *tmp_ctx; CHECK(secp256k1_context_preallocated_size(SECP256K1_CONTEXT_NONE) == secp256k1_context_preallocated_size(flags[i])); tmp_ctx = secp256k1_context_create(flags[i]); @@ -437,13 +437,13 @@ static void run_ctz_tests(void) { static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef}; int shift; unsigned i; - for (i = 0; i < sizeof(b32) / sizeof(b32[0]); ++i) { + for (i = 0; i < ARRAY_SIZE(b32); ++i) { for (shift = 0; shift < 32; ++shift) { CHECK(secp256k1_ctz32_var_debruijn(b32[i] << shift) == shift); CHECK(secp256k1_ctz32_var(b32[i] << shift) == shift); } } - for (i = 0; i < sizeof(b64) / sizeof(b64[0]); ++i) { + for (i = 0; i < ARRAY_SIZE(b64); ++i) { for (shift = 0; shift < 64; ++shift) { CHECK(secp256k1_ctz64_var_debruijn(b64[i] << shift) == shift); CHECK(secp256k1_ctz64_var(b64[i] << shift) == shift); @@ -478,7 +478,7 @@ static void run_sha256_known_output_tests(void) { unsigned int i, ninputs; /* Skip last input vector for low iteration counts */ - ninputs = sizeof(inputs)/sizeof(inputs[0]) - 1; + ninputs = ARRAY_SIZE(inputs) - 1; CONDITIONAL_TEST(16, "run_sha256_known_output_tests 1000000") ninputs++; for (i = 0; i < ninputs; i++) { @@ -603,7 +603,7 @@ static void run_sha256_counter_tests(void) { {0xec, 0x12, 0x24, 0x9f, 0x35, 0xa4, 0x29, 0x8b, 0x9e, 0x4a, 0x95, 0xf8, 0x61, 0xaf, 0x61, 0xc5, 0x66, 0x55, 0x3e, 0x3f, 0x2a, 0x98, 0xea, 0x71, 0x16, 0x6b, 0x1c, 0xd9, 0xe4, 0x09, 0xd2, 0x8e}, }; unsigned int i; - for (i = 0; i < sizeof(midstates)/sizeof(midstates[0]); i++) { + for (i = 0; i < ARRAY_SIZE(midstates); i++) { unsigned char out[32]; secp256k1_sha256 hasher = midstates[i]; secp256k1_sha256_write(&hasher, (const unsigned char*)input, strlen(input)); @@ -1649,7 +1649,7 @@ static void run_modinv_tests(void) { int i, j, ok; /* Test known inputs/outputs */ - for (i = 0; (size_t)i < sizeof(CASES) / sizeof(CASES[0]); ++i) { + for (i = 0; (size_t)i < ARRAY_SIZE(CASES); ++i) { uint16_t out[16]; test_modinv32_uint16(out, CASES[i][0], CASES[i][1]); for (j = 0; j < 16; ++j) CHECK(out[j] == CASES[i][2][j]); @@ -2297,7 +2297,7 @@ static void run_scalar_tests(void) { SECP256K1_SCALAR_CONST(0x7ffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful, 0xfffffffful), }; unsigned n; - for (n = 0; n < sizeof(HALF_TESTS) / sizeof(HALF_TESTS[0]); ++n) { + for (n = 0; n < ARRAY_SIZE(HALF_TESTS); ++n) { secp256k1_scalar s; secp256k1_scalar_half(&s, &HALF_TESTS[n]); secp256k1_scalar_add(&s, &s, &s); @@ -3565,7 +3565,7 @@ static void run_inverse_tests(void) secp256k1_scalar x_scalar; memset(b32, 0, sizeof(b32)); /* Test fixed test cases through test_inverse_{scalar,field}, both ways. */ - for (i = 0; (size_t)i < sizeof(fe_cases)/sizeof(fe_cases[0]); ++i) { + for (i = 0; (size_t)i < ARRAY_SIZE(fe_cases); ++i) { for (var = 0; var <= 1; ++var) { test_inverse_field(&x_fe, &fe_cases[i][0], var); CHECK(fe_equal(&x_fe, &fe_cases[i][1])); @@ -3573,7 +3573,7 @@ static void run_inverse_tests(void) CHECK(fe_equal(&x_fe, &fe_cases[i][0])); } } - for (i = 0; (size_t)i < sizeof(scalar_cases)/sizeof(scalar_cases[0]); ++i) { + for (i = 0; (size_t)i < ARRAY_SIZE(scalar_cases); ++i) { for (var = 0; var <= 1; ++var) { test_inverse_scalar(&x_scalar, &scalar_cases[i][0], var); CHECK(secp256k1_scalar_eq(&x_scalar, &scalar_cases[i][1])); @@ -4449,7 +4449,7 @@ static void run_ecmult_near_split_bound(void) { int i; unsigned j; for (i = 0; i < 4*COUNT; ++i) { - for (j = 0; j < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++j) { + for (j = 0; j < ARRAY_SIZE(scalars_near_split_bounds); ++j) { test_ecmult_target(&scalars_near_split_bounds[j], 0); test_ecmult_target(&scalars_near_split_bounds[j], 1); test_ecmult_target(&scalars_near_split_bounds[j], 2); @@ -4573,7 +4573,7 @@ static void ecmult_const_edges(void) { secp256k1_ge point; secp256k1_gej res; size_t i; - size_t cases = 1 + sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); + size_t cases = 1 + ARRAY_SIZE(scalars_near_split_bounds); /* We are trying to reach the following edge cases (variables are defined as * in ecmult_const_impl.h): @@ -5725,7 +5725,7 @@ static void run_endomorphism_tests(void) { testutil_random_scalar_order_test(&full); test_scalar_split(&full); } - for (i = 0; i < sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); ++i) { + for (i = 0; i < ARRAY_SIZE(scalars_near_split_bounds); ++i) { test_scalar_split(&scalars_near_split_bounds[i]); } } @@ -7878,7 +7878,7 @@ static int teardown(void) { int main(int argc, char **argv) { struct tf_framework tf = {0}; tf.registry_modules = registry_modules; - tf.num_modules = sizeof(registry_modules) / sizeof(registry_modules[0]); + tf.num_modules = ARRAY_SIZE(registry_modules); tf.registry_no_rng = ®istry_modules_no_rng; /* Add context creation/destruction functions */ diff --git a/src/unit_test.h b/src/unit_test.h index bf301e53..5259efbf 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -6,6 +6,8 @@ #ifndef SECP256K1_UNIT_TEST_H #define SECP256K1_UNIT_TEST_H +#include "util.h" + /* --------------------------------------------------------- */ /* Configurable constants */ /* --------------------------------------------------------- */ @@ -27,7 +29,7 @@ #define MAKE_TEST_MODULE(name) { \ #name, \ tests_##name, \ - sizeof(tests_##name) / sizeof(tests_##name[0]) \ + ARRAY_SIZE(tests_##name) \ } /* Macro to wrap a test internal function with a COUNT loop (iterations number) */ diff --git a/src/util.h b/src/util.h index 46ab3810..5d03e4c7 100644 --- a/src/util.h +++ b/src/util.h @@ -181,6 +181,8 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_ #define ROUND_TO_ALIGN(size) (CEIL_DIV(size, ALIGNMENT) * ALIGNMENT) +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + /* Macro for restrict, when available and not in a VERIFY build. */ #if defined(SECP256K1_BUILD) && defined(VERIFY) # define SECP256K1_RESTRICT From e3bddfa750064bd9ed6a90819790b149fff62aa8 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Wed, 18 Feb 2026 16:26:07 +0200 Subject: [PATCH 293/383] modules: Port bitcoin-core/secp256k1#1579 to zkp-specific code --- src/modules/bppp/bppp_transcript_impl.h | 1 + src/modules/ecdsa_adaptor/dleq_impl.h | 2 ++ src/modules/ecdsa_adaptor/main_impl.h | 2 ++ src/modules/ecdsa_s2c/main_impl.h | 4 +++- src/modules/generator/main_impl.h | 2 ++ src/modules/generator/pedersen_impl.h | 2 +- src/modules/rangeproof/borromean_impl.h | 5 ++++- src/modules/rangeproof/rangeproof_impl.h | 13 ++++++++----- src/modules/schnorrsig_halfagg/main_impl.h | 2 ++ src/modules/surjection/main_impl.h | 1 + src/modules/surjection/surjection_impl.h | 6 ++++-- src/modules/whitelist/main_impl.h | 4 ++-- src/modules/whitelist/whitelist_impl.h | 2 ++ 13 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/modules/bppp/bppp_transcript_impl.h b/src/modules/bppp/bppp_transcript_impl.h index 5fe9b96c..d53e9023 100644 --- a/src/modules/bppp/bppp_transcript_impl.h +++ b/src/modules/bppp/bppp_transcript_impl.h @@ -34,6 +34,7 @@ static void secp256k1_bppp_challenge_scalar(secp256k1_scalar* ch, const secp256k secp256k1_bppp_le64(buf, idx); secp256k1_sha256_write(&sha, buf, 8); secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_clear(&sha); secp256k1_scalar_set_b32(ch, buf, NULL); } diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index ff946c2c..53b3003e 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -46,6 +46,7 @@ static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, secp256k1_sha256_write(&sha, p1_33, size); secp256k1_sha256_write(&sha, p2_33, size); secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_clear(&sha); if (!noncefp(nonce, buf, sk32, gen2_33, dleq_algo, sizeof(dleq_algo), ndata)) { return 0; @@ -71,6 +72,7 @@ static void secp256k1_dleq_challenge(secp256k1_scalar *e, secp256k1_ge *gen2, se secp256k1_dleq_hash_point(&sha, r1); secp256k1_dleq_hash_point(&sha, r2); secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_clear(&sha); secp256k1_scalar_set_b32(e, buf, NULL); } diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index d75764f4..5d16e011 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -114,6 +114,7 @@ static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned c secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(&sha); secp256k1_sha256_write(&sha, data, 32); secp256k1_sha256_finalize(&sha, masked_key); + secp256k1_sha256_clear(&sha); for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; } @@ -141,6 +142,7 @@ static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned c secp256k1_sha256_write(&sha, pk33, 33); secp256k1_sha256_write(&sha, msg32, 32); secp256k1_sha256_finalize(&sha, nonce32); + secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/modules/ecdsa_s2c/main_impl.h b/src/modules/ecdsa_s2c/main_impl.h index 95cb088d..471ae8fb 100644 --- a/src/modules/ecdsa_s2c/main_impl.h +++ b/src/modules/ecdsa_s2c/main_impl.h @@ -86,6 +86,7 @@ int secp256k1_ecdsa_s2c_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signa secp256k1_s2c_ecdsa_data_sha256_tagged(&s2c_sha); secp256k1_sha256_write(&s2c_sha, s2c_data32, 32); secp256k1_sha256_finalize(&s2c_sha, ndata); + secp256k1_sha256_clear(&s2c_sha); secp256k1_s2c_ecdsa_point_sha256_tagged(&s2c_sha); ret = secp256k1_ecdsa_sign_inner(ctx, &r, &s, NULL, &s2c_sha, s2c_opening, s2c_data32, msg32, seckey, NULL, ndata); @@ -147,6 +148,7 @@ int secp256k1_ecdsa_anti_exfil_host_commit(const secp256k1_context* ctx, unsigne secp256k1_s2c_ecdsa_data_sha256_tagged(&sha); secp256k1_sha256_write(&sha, rand32, 32); secp256k1_sha256_finalize(&sha, rand_commitment32); + secp256k1_sha256_clear(&sha); return 1; } @@ -180,7 +182,7 @@ int secp256k1_ecdsa_anti_exfil_signer_commit(const secp256k1_context* ctx, secp2 secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); secp256k1_ge_set_gej(&r, &rj); secp256k1_ecdsa_s2c_opening_save(opening, &r); - memset(nonce32, 0, 32); + secp256k1_memclear(nonce32, 32); secp256k1_scalar_clear(&k); return 1; } diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index d3dce9fa..c3f1c027 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -222,6 +222,7 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s secp256k1_sha256_write(&sha256, prefix1, 16); secp256k1_sha256_write(&sha256, key32, 32); secp256k1_sha256_finalize(&sha256, b32); + secp256k1_sha256_clear(&sha256); ret &= secp256k1_fe_set_b32_limit(&t, b32); shallue_van_de_woestijne(&add, &t); if (blind32) { @@ -234,6 +235,7 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s secp256k1_sha256_write(&sha256, prefix2, 16); secp256k1_sha256_write(&sha256, key32, 32); secp256k1_sha256_finalize(&sha256, b32); + secp256k1_sha256_clear(&sha256); ret &= secp256k1_fe_set_b32_limit(&t, b32); shallue_van_de_woestijne(&add, &t); secp256k1_gej_add_ge(&accum, &accum, &add); diff --git a/src/modules/generator/pedersen_impl.h b/src/modules/generator/pedersen_impl.h index 6b859fc5..f5526eb6 100644 --- a/src/modules/generator/pedersen_impl.h +++ b/src/modules/generator/pedersen_impl.h @@ -28,7 +28,7 @@ static void secp256k1_pedersen_scalar_set_u64(secp256k1_scalar *sec, uint64_t va value <<= 8; } secp256k1_scalar_set_b32(sec, data, NULL); - memset(data, 0, 32); + secp256k1_memclear(data, 32); } static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn, const secp256k1_ge* genp) { diff --git a/src/modules/rangeproof/borromean_impl.h b/src/modules/rangeproof/borromean_impl.h index 3a3b74e2..3ca86108 100644 --- a/src/modules/rangeproof/borromean_impl.h +++ b/src/modules/rangeproof/borromean_impl.h @@ -33,6 +33,7 @@ SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const secp256k1_sha256_write(&sha256_en, ring, 4); secp256k1_sha256_write(&sha256_en, epos, 4); secp256k1_sha256_finalize(&sha256_en, hash); + secp256k1_sha256_clear(&sha256_en); } /** "Borromean" ring signature. @@ -99,6 +100,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e } secp256k1_sha256_write(&sha256_e0, m, mlen); secp256k1_sha256_finalize(&sha256_e0, tmp); + secp256k1_sha256_clear(&sha256_e0); return secp256k1_memcmp_var(e0, tmp, 32) == 0; } @@ -157,6 +159,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, } secp256k1_sha256_write(&sha256_e0, m, mlen); secp256k1_sha256_finalize(&sha256_e0, e0); + secp256k1_sha256_clear(&sha256_e0); count = 0; for (i = 0; i < nrings; i++) { VERIFY_CHECK(INT_MAX - count > rsizes[i]); @@ -189,7 +192,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar_clear(&ens); secp256k1_ge_clear(&rge); secp256k1_gej_clear(&rgej); - memset(tmp, 0, 33); + secp256k1_memclear(tmp, 33); return 1; } diff --git a/src/modules/rangeproof/rangeproof_impl.h b/src/modules/rangeproof/rangeproof_impl.h index 5fa55372..fc12ad4f 100644 --- a/src/modules/rangeproof/rangeproof_impl.h +++ b/src/modules/rangeproof/rangeproof_impl.h @@ -76,7 +76,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, secp256k1_rangeproof_serialize_point(rngseed + 32 + 33, genp); memcpy(rngseed + 33 + 33 + 32, proof, len); secp256k1_rfc6979_hmac_sha256_initialize(&rng, rngseed, 32 + 33 + 33 + len); - secp256k1_scalar_clear(&acc); + secp256k1_scalar_set_int(&acc, 0); npub = 0; ret = 1; for (i = 0; i < rings; i++) { @@ -105,8 +105,9 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, } } secp256k1_rfc6979_hmac_sha256_finalize(&rng); + secp256k1_rfc6979_hmac_sha256_clear(&rng); secp256k1_scalar_clear(&acc); - memset(tmp, 0, 32); + secp256k1_memclear(tmp, 32); return ret; } @@ -269,7 +270,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul if (!secp256k1_rangeproof_genrand(sec, s, prep, rsizes, rings, nonce, commit, proof, len, genp)) { return 0; } - memset(prep, 0, 4096); + secp256k1_memclear(prep, 4096); for (i = 0; i < rings; i++) { /* Sign will overwrite the non-forged signature, move that random value into the nonce. */ k[i] = s[i * 4 + secidx[i]]; @@ -320,6 +321,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len); } secp256k1_sha256_finalize(&sha256_m, tmp); + secp256k1_sha256_clear(&sha256_m); if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { return 0; } @@ -330,7 +332,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul } VERIFY_CHECK(len <= *plen); *plen = len; - memset(prep, 0, 4096); + secp256k1_memclear(prep, 4096); return 1; } @@ -471,7 +473,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(secp256k1_scalar * } } *mlen = offset; - memset(prep, 0, 4096); + secp256k1_memclear(prep, 4096); for (i = 0; i < 128; i++) { secp256k1_scalar_clear(&s_orig[i]); } @@ -646,6 +648,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len); } secp256k1_sha256_finalize(&sha256_m, m); + secp256k1_sha256_clear(&sha256_m); ret = secp256k1_borromean_verify(nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32); if (ret && nonce) { /* Given the nonce, try rewinding the witness to recover its initial state. */ diff --git a/src/modules/schnorrsig_halfagg/main_impl.h b/src/modules/schnorrsig_halfagg/main_impl.h index 7eac1079..0d3662ba 100644 --- a/src/modules/schnorrsig_halfagg/main_impl.h +++ b/src/modules/schnorrsig_halfagg/main_impl.h @@ -85,6 +85,7 @@ int secp256k1_schnorrsig_inc_aggregate(const secp256k1_context *ctx, unsigned ch hashcopy = hash; /* 1.c) Finalize the copy to get zi*/ secp256k1_sha256_finalize(&hashcopy, hashoutput); + secp256k1_sha256_clear(&hashcopy); /* Note: No need to check overflow, comes from hash */ secp256k1_scalar_set_b32(&zi, hashoutput, NULL); @@ -162,6 +163,7 @@ int secp256k1_schnorrsig_aggverify(const secp256k1_context *ctx, const secp256k1 hashcopy = hash; /* 1.c) Finalize the copy to get zi*/ secp256k1_sha256_finalize(&hashcopy, hashoutput); + secp256k1_sha256_clear(&hashcopy); secp256k1_scalar_set_b32(&zi, hashoutput, NULL); /* Step 2: T_i = R_i+e_i*P_i */ diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index f1d7d42f..1d35219a 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -153,6 +153,7 @@ static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_cs secp256k1_sha256_initialize(&sha); secp256k1_sha256_write(&sha, csprng->state, 32); secp256k1_sha256_finalize(&sha, csprng->state); + secp256k1_sha256_clear(&sha); csprng->state_i = 0; } val = csprng->state[csprng->state_i]; diff --git a/src/modules/surjection/surjection_impl.h b/src/modules/surjection/surjection_impl.h index e125cbc0..cc0ad300 100644 --- a/src/modules/surjection/surjection_impl.h +++ b/src/modules/surjection/surjection_impl.h @@ -32,6 +32,7 @@ SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg3 memcpy(&pk_ser[1], &ephemeral_output_tag->data[0], 32); secp256k1_sha256_write(&sha256_en, pk_ser, pk_len); secp256k1_sha256_finalize(&sha256_en, msg32); + secp256k1_sha256_clear(&sha256_en); } SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) { @@ -51,13 +52,14 @@ SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, si secp256k1_sha256_initialize(&sha256_en); secp256k1_sha256_write(&sha256_en, sec_input, 36); secp256k1_sha256_finalize(&sha256_en, sec_input); + secp256k1_sha256_clear(&sha256_en); secp256k1_scalar_set_b32(&s[i], sec_input, &overflow); if (overflow == 1) { - memset(sec_input, 0, 32); + secp256k1_memclear(sec_input, 32); return 0; } } - memset(sec_input, 0, 32); + secp256k1_memclear(sec_input, 32); return 1; } diff --git a/src/modules/whitelist/main_impl.h b/src/modules/whitelist/main_impl.h index da631522..ce94d23a 100644 --- a/src/modules/whitelist/main_impl.h +++ b/src/modules/whitelist/main_impl.h @@ -54,7 +54,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s break; } secp256k1_scalar_set_b32(&non, nonce32, &overflow); - memset(nonce32, 0, 32); + secp256k1_memclear(nonce32, 32); if (overflow || secp256k1_scalar_is_zero(&non)) { count++; continue; @@ -80,7 +80,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s break; } } - memset(seckey32, 0, 32); + secp256k1_memclear(seckey32, 32); } /* Actually sign */ if (ret) { diff --git a/src/modules/whitelist/whitelist_impl.h b/src/modules/whitelist/whitelist_impl.h index 8d691127..48f8bcca 100644 --- a/src/modules/whitelist/whitelist_impl.h +++ b/src/modules/whitelist/whitelist_impl.h @@ -23,6 +23,7 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g } secp256k1_sha256_write(&sha, c, size); secp256k1_sha256_finalize(&sha, h); + secp256k1_sha256_clear(&sha); secp256k1_scalar_set_b32(output, h, &overflow); if (overflow || secp256k1_scalar_is_zero(output)) { @@ -122,6 +123,7 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* secp256k1_gej_add_ge_var(&keys[i], &tweaked_gej, &online_ge, NULL); } secp256k1_sha256_finalize(&sha, msg32); + secp256k1_sha256_clear(&sha); return 1; } From 76e92cfeeaf67aa3fd780f83e780b92518012c84 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Fri, 20 Feb 2026 08:42:32 +0000 Subject: [PATCH 294/383] Revert "ci, docker: Fix LLVM repository signature failure" This reverts commit 0ffb1749a5811bb63902f00c9fa73b49588d0557. --- ci/linux-debian.Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index a862f1b1..a575d9b1 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -67,9 +67,6 @@ RUN \ wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ # Add repository for this Debian release . /etc/os-release && echo "deb http://apt.llvm.org/${VERSION_CODENAME} llvm-toolchain-${VERSION_CODENAME} main" >> /etc/apt/sources.list && \ - # Temporarily work around Sequoia PGP policy deadline for legacy repositories. - # See https://github.com/llvm/llvm-project/issues/153385. - sed -i 's/\(sha1\.second_preimage_resistance =\).*/\1 9999-01-01/' /usr/share/apt/default-sequoia.config && \ apt-get update && \ # Determine the version number of the LLVM development branch LLVM_VERSION=$(apt-cache search --names-only '^clang-[0-9]+$' | sort -V | tail -1 | cut -f1 -d" " | cut -f2 -d"-" ) && \ From ec343f0b2fa9ad0b5746fd60636c17be9a8186d7 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 20 Feb 2026 18:41:10 +0200 Subject: [PATCH 295/383] Port bitcoin-core/secp256k1#1642 to zkp-specific code --- src/modules/ecdsa_adaptor/main_impl.h | 2 +- src/modules/whitelist/whitelist_impl.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index 5d16e011..25232b48 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -341,7 +341,7 @@ int secp256k1_ecdsa_adaptor_recover(const secp256k1_context* ctx, unsigned char /* We declassify non-secret enckey_expected_ge to allow using it as a * branch point. */ secp256k1_declassify(ctx, &enckey_expected_ge, sizeof(enckey_expected_ge)); - if (!secp256k1_eckey_pubkey_serialize(&enckey_expected_ge, enckey_expected33, &size, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_eckey_pubkey_serialize(&enckey_expected_ge, enckey_expected33, &size, 1)) { /* Unreachable from tests (and other VERIFY builds) and therefore this * branch should be ignored in test coverage analysis. * diff --git a/src/modules/whitelist/whitelist_impl.h b/src/modules/whitelist/whitelist_impl.h index 48f8bcca..bb244907 100644 --- a/src/modules/whitelist/whitelist_impl.h +++ b/src/modules/whitelist/whitelist_impl.h @@ -18,7 +18,7 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g secp256k1_ge_set_gej(&ge, pubkey); secp256k1_sha256_initialize(&sha); - if (!secp256k1_eckey_pubkey_serialize(&ge, c, &size, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_eckey_pubkey_serialize(&ge, c, &size, 1)) { return 0; } secp256k1_sha256_write(&sha, c, size); @@ -95,7 +95,7 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* secp256k1_pubkey_load(ctx, &subkey_ge, sub_pubkey); /* commit to sub-key */ - if (!secp256k1_eckey_pubkey_serialize(&subkey_ge, c, &size, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_eckey_pubkey_serialize(&subkey_ge, c, &size, 1)) { return 0; } secp256k1_sha256_write(&sha, c, size); @@ -106,12 +106,12 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* /* commit to fixed keys */ secp256k1_pubkey_load(ctx, &offline_ge, &offline_pubkeys[i]); - if (!secp256k1_eckey_pubkey_serialize(&offline_ge, c, &size, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_eckey_pubkey_serialize(&offline_ge, c, &size, 1)) { return 0; } secp256k1_sha256_write(&sha, c, size); secp256k1_pubkey_load(ctx, &online_ge, &online_pubkeys[i]); - if (!secp256k1_eckey_pubkey_serialize(&online_ge, c, &size, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_eckey_pubkey_serialize(&online_ge, c, &size, 1)) { return 0; } secp256k1_sha256_write(&sha, c, size); From 17ad19601850ee3c0e2dc107a44c196fecede60e Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 20 Feb 2026 18:50:53 +0200 Subject: [PATCH 296/383] schnorrsig_halfagg: Fix symbol visibility for internal function --- src/modules/schnorrsig_halfagg/main_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/schnorrsig_halfagg/main_impl.h b/src/modules/schnorrsig_halfagg/main_impl.h index 0d3662ba..af612195 100644 --- a/src/modules/schnorrsig_halfagg/main_impl.h +++ b/src/modules/schnorrsig_halfagg/main_impl.h @@ -8,7 +8,7 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("HalfAgg/randomizer")||SHA256("HalfAgg/randomizer"). */ -void secp256k1_schnorrsig_sha256_tagged_aggregation(secp256k1_sha256 *sha) { +static void secp256k1_schnorrsig_sha256_tagged_aggregation(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0xd11f5532ul; sha->s[1] = 0xfa57f70ful; From 2f057a145fbb304342d517c3fe0b6a40fef0e15b Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 21 Jul 2025 16:35:16 +0200 Subject: [PATCH 297/383] ci: Don't hardcode ABI version --- .github/workflows/ci.yml | 3 ++- ci/ci.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a930e997..9e25a909 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -704,10 +704,11 @@ jobs: - name: Symbol check if: ${{ matrix.configuration.symbol_check }} + shell: bash run: | py -3 --version py -3 -m pip install lief - py -3 .\tools\symbol-check.py build\bin\RelWithDebInfo\libsecp256k1-5.dll + py -3 ./tools/symbol-check.py build/bin/RelWithDebInfo/libsecp256k1-*.dll - name: Check run: | diff --git a/ci/ci.sh b/ci/ci.sh index 170f04df..c0252493 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -118,7 +118,7 @@ then case "$HOST" in *mingw*) ls -l .libs - python3 ./tools/symbol-check.py .libs/libsecp256k1-5.dll + python3 ./tools/symbol-check.py .libs/libsecp256k1-*.dll ;; *) python3 ./tools/symbol-check.py .libs/libsecp256k1.so From 795f19af1f683642ede445d644a652298757e115 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Wed, 15 Oct 2025 15:31:21 +0100 Subject: [PATCH 298/383] ci: Switch to macOS 15 Sequoia Intel-based image The `macos-13` image has been deprecated and will be unavailable soon. See: https://github.com/actions/runner-images/issues/13045. --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e25a909..e255fe6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -557,9 +557,8 @@ jobs: if: ${{ !cancelled() }} x86_64-macos-native: - name: "x86_64: macOS Ventura, Valgrind" - # See: https://github.com/actions/runner-images#available-images. - runs-on: macos-13 + name: "x86_64: macOS Sequoia, Valgrind" + runs-on: macos-15-intel env: CC: 'clang' From 4dda31229e047066b9a8b3fab6f4a8320b9e30dd Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 23 Feb 2026 15:03:08 +0200 Subject: [PATCH 299/383] ci: Use Python virtual environment in x86_64-macos-native job --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e255fe6e..b3922355 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -598,8 +598,12 @@ jobs: run: ./ci/ci.sh - name: Symbol check + env: + VIRTUAL_ENV: '${{ github.workspace }}/venv' run: | python3 --version + python3 -m venv $VIRTUAL_ENV + export PATH="$VIRTUAL_ENV/bin:$PATH" python3 -m pip install lief python3 ./tools/symbol-check.py .libs/libsecp256k1.dylib From 79e9f252379d426ff4da586c9a1fcae35287587f Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 25 Feb 2026 08:42:29 +0100 Subject: [PATCH 300/383] ci: Fix leftover use of old ECMULTGENPRECISION --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f8c9734..44c2754b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -514,7 +514,7 @@ jobs: matrix: env_vars: - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - - { WIDEMUL: 'int128_struct', ECMULTGENPRECISION: 2, ECMULTWINDOW: 4 } + - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } From 01b1b916ebe101c619c68026196bac5f1e41e4c8 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Wed, 25 Feb 2026 13:11:18 +0200 Subject: [PATCH 301/383] modules: Port bitcoin-core/secp256k1#1725 to zkp-specific code --- src/modules/ecdsa_adaptor/tests_impl.h | 27 +++++---------------- src/modules/schnorrsig_halfagg/tests_impl.h | 6 ++--- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index fcdee325..a3360223 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -718,24 +718,12 @@ static void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_ CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0); } -/* Tests for the equality of two sha256 structs. This function only produces a - * correct result if an integer multiple of 64 many bytes have been written - * into the hash functions. */ -static void ecdsa_adaptor_test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) { - /* Is buffer fully consumed? */ - CHECK((sha1->bytes & 0x3F) == 0); - - CHECK(sha1->bytes == sha2->bytes); - CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); -} - static void run_nonce_function_ecdsa_adaptor_tests(void) { - unsigned char tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; - unsigned char aux_tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'a', 'u', 'x'}; + static const unsigned char tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; + static const unsigned char aux_tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'a', 'u', 'x'}; unsigned char algo[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; size_t algolen = sizeof(algo); - unsigned char dleq_tag[] = {'D', 'L', 'E', 'Q'}; - secp256k1_sha256 sha; + static const unsigned char dleq_tag[] = {'D', 'L', 'E', 'Q'}; secp256k1_sha256 sha_optimized; unsigned char nonce[32]; unsigned char msg[32]; @@ -748,23 +736,20 @@ static void run_nonce_function_ecdsa_adaptor_tests(void) { /* Check that hash initialized by * secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, tag, sizeof(tag)); secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged(&sha_optimized); - ecdsa_adaptor_test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); /* Check that hash initialized by * secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(&sha_optimized); - ecdsa_adaptor_test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, aux_tag, sizeof(aux_tag)); /* Check that hash initialized by * secp256k1_nonce_function_dleq_sha256_tagged_aux has the expected * state. */ - secp256k1_sha256_initialize_tagged(&sha, dleq_tag, sizeof(dleq_tag)); secp256k1_nonce_function_dleq_sha256_tagged(&sha_optimized); - ecdsa_adaptor_test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, dleq_tag, sizeof(dleq_tag)); testrand_bytes_test(msg, sizeof(msg)); testrand_bytes_test(key, sizeof(key)); diff --git a/src/modules/schnorrsig_halfagg/tests_impl.h b/src/modules/schnorrsig_halfagg/tests_impl.h index 49ab51e4..b93999b6 100644 --- a/src/modules/schnorrsig_halfagg/tests_impl.h +++ b/src/modules/schnorrsig_halfagg/tests_impl.h @@ -8,13 +8,11 @@ /* We test that the hash initialized by secp256k1_schnorrsig_sha256_tagged_aggregate * has the expected state. */ void test_schnorrsig_sha256_tagged_aggregate(void) { - unsigned char tag[] = {'H', 'a', 'l', 'f', 'A', 'g', 'g', '/', 'r', 'a', 'n', 'd', 'o', 'm', 'i', 'z', 'e', 'r'}; - secp256k1_sha256 sha; + static const unsigned char tag[] = {'H', 'a', 'l', 'f', 'A', 'g', 'g', '/', 'r', 'a', 'n', 'd', 'o', 'm', 'i', 'z', 'e', 'r'}; secp256k1_sha256 sha_optimized; - secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); secp256k1_schnorrsig_sha256_tagged_aggregation(&sha_optimized); - test_sha256_eq(&sha, &sha_optimized); + test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); } /* Create n many x-only pubkeys and sigs for random messages */ From f48b1bfa5d40a4d7303b196017d2e298520d1066 Mon Sep 17 00:00:00 2001 From: w0xlt <94266259+w0xlt@users.noreply.github.com> Date: Wed, 18 Feb 2026 15:21:54 -0800 Subject: [PATCH 302/383] hash: add midstate initializer and use it for tagged hashes Introduce secp256k1_sha256_initialize_midstate() in the hash layer and use it at all tagged-hash midstate call sites across schnorrsig, musig, and ellswift. Document the byte-counter contract at the declaration site in hash.h and add run_sha256_initialize_midstate_tests() to directly verify helper behavior against initialize_tagged. Also switch the helper to take const uint32_t state[8] to reduce argument-order risk at call sites. --- src/hash.h | 4 +++ src/hash_impl.h | 7 +++++ src/modules/ellswift/main_impl.h | 48 ++++++++++-------------------- src/modules/musig/keyagg_impl.h | 32 +++++++------------- src/modules/musig/session_impl.h | 45 ++++++++++------------------ src/modules/schnorrsig/main_impl.h | 47 ++++++++++------------------- src/tests.c | 15 +++++++++- 7 files changed, 80 insertions(+), 118 deletions(-) diff --git a/src/hash.h b/src/hash.h index 6d903ca7..43cdd60c 100644 --- a/src/hash.h +++ b/src/hash.h @@ -17,6 +17,10 @@ typedef struct { } secp256k1_sha256; static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); +/* Initialize a SHA256 hash state with a precomputed midstate. + * The byte counter must be a multiple of 64, i.e., there must be no unwritten + * bytes in the buffer. */ +static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]); static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); static void secp256k1_sha256_clear(secp256k1_sha256 *hash); diff --git a/src/hash_impl.h b/src/hash_impl.h index 43419177..da3b4660 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -40,6 +40,13 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { hash->bytes = 0; } +static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]) { + VERIFY_CHECK((bytes & 0x3F) == 0); + VERIFY_CHECK(state != NULL); + memcpy(hash->s, state, sizeof(hash->s)); + hash->bytes = bytes; +} + /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) { uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 096f4a3c..2a378255 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -383,17 +383,11 @@ static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_ /** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_encode". */ static void secp256k1_ellswift_sha256_init_encode(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0xd1a6524bul; - hash->s[1] = 0x028594b3ul; - hash->s[2] = 0x96e42f4eul; - hash->s[3] = 0x1037a177ul; - hash->s[4] = 0x1b8fcb8bul; - hash->s[5] = 0x56023885ul; - hash->s[6] = 0x2560ede1ul; - hash->s[7] = 0xd626b715ul; - - hash->bytes = 64; + static const uint32_t midstate[8] = { + 0xd1a6524bul, 0x028594b3ul, 0x96e42f4eul, 0x1037a177ul, + 0x1b8fcb8bul, 0x56023885ul, 0x2560ede1ul, 0xd626b715ul + }; + secp256k1_sha256_initialize_midstate(hash, 64, midstate); } int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64, const secp256k1_pubkey *pubkey, const unsigned char *rnd32) { @@ -427,17 +421,11 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64 /** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_create". */ static void secp256k1_ellswift_sha256_init_create(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0xd29e1bf5ul; - hash->s[1] = 0xf7025f42ul; - hash->s[2] = 0x9b024773ul; - hash->s[3] = 0x094cb7d5ul; - hash->s[4] = 0xe59ed789ul; - hash->s[5] = 0x03bc9786ul; - hash->s[6] = 0x68335b35ul; - hash->s[7] = 0x4e363b53ul; - - hash->bytes = 64; + static const uint32_t midstate[8] = { + 0xd29e1bf5ul, 0xf7025f42ul, 0x9b024773ul, 0x094cb7d5ul, + 0xe59ed789ul, 0x03bc9786ul, 0x68335b35ul, 0x4e363b53ul + }; + secp256k1_sha256_initialize_midstate(hash, 64, midstate); } int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) { @@ -510,17 +498,11 @@ static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsign /** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { - secp256k1_sha256_initialize(hash); - hash->s[0] = 0x8c12d730ul; - hash->s[1] = 0x827bd392ul; - hash->s[2] = 0x9e4fb2eeul; - hash->s[3] = 0x207b373eul; - hash->s[4] = 0x2292bd7aul; - hash->s[5] = 0xaa5441bcul; - hash->s[6] = 0x15c3779ful; - hash->s[7] = 0xcfb52549ul; - - hash->bytes = 64; + static const uint32_t midstate[8] = { + 0x8c12d730ul, 0x827bd392ul, 0x9e4fb2eeul, 0x207b373eul, + 0x2292bd7aul, 0xaa5441bcul, 0x15c3779ful, 0xcfb52549ul + }; + secp256k1_sha256_initialize_midstate(hash, 64, midstate); } static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h index e412a27e..4eb48ddc 100644 --- a/src/modules/musig/keyagg_impl.h +++ b/src/modules/musig/keyagg_impl.h @@ -62,17 +62,11 @@ static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_k /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("KeyAgg list")||SHA256("KeyAgg list"). */ static void secp256k1_musig_keyagglist_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0xb399d5e0ul; - sha->s[1] = 0xc8fff302ul; - sha->s[2] = 0x6badac71ul; - sha->s[3] = 0x07c5b7f1ul; - sha->s[4] = 0x9701e2eful; - sha->s[5] = 0x2a72ecf8ul; - sha->s[6] = 0x201a4c7bul; - sha->s[7] = 0xab148a38ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xb399d5e0ul, 0xc8fff302ul, 0x6badac71ul, 0x07c5b7f1ul, + 0x9701e2eful, 0x2a72ecf8ul, 0x201a4c7bul, 0xab148a38ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Computes pks_hash = tagged_hash(pk[0], ..., pk[np-1]) */ @@ -97,17 +91,11 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("KeyAgg coefficient")||SHA256("KeyAgg coefficient"). */ static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - - sha->s[0] = 0x6ef02c5aul; - sha->s[1] = 0x06a480deul; - sha->s[2] = 0x1f298665ul; - sha->s[3] = 0x1d1134f2ul; - sha->s[4] = 0x56a0b063ul; - sha->s[5] = 0x52da4147ul; - sha->s[6] = 0xf280d9d4ul; - sha->s[7] = 0x4484be15ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x6ef02c5aul, 0x06a480deul, 0x1f298665ul, 0x1d1134f2ul, + 0x56a0b063ul, 0x52da4147ul, 0xf280d9d4ul, 0x4484be15ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Compute KeyAgg coefficient which is constant 1 for the second pubkey and diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 05c96310..42fcd81e 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -309,31 +309,21 @@ static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigne /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/aux")||SHA256("MuSig/aux"). */ static void secp256k1_nonce_function_musig_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xa19e884bul; - sha->s[1] = 0xf463fe7eul; - sha->s[2] = 0x2f18f9a2ul; - sha->s[3] = 0xbeb0f9fful; - sha->s[4] = 0x0f37e8b0ul; - sha->s[5] = 0x06ebd26ful; - sha->s[6] = 0xe3b243d2ul; - sha->s[7] = 0x522fb150ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xa19e884bul, 0xf463fe7eul, 0x2f18f9a2ul, 0xbeb0f9fful, + 0x0f37e8b0ul, 0x06ebd26ful, 0xe3b243d2ul, 0x522fb150ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/nonce")||SHA256("MuSig/nonce"). */ static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x07101b64ul; - sha->s[1] = 0x18003414ul; - sha->s[2] = 0x0391bc43ul; - sha->s[3] = 0x0e6258eeul; - sha->s[4] = 0x29d26b72ul; - sha->s[5] = 0x8343937eul; - sha->s[6] = 0xb7a0a4fbul; - sha->s[7] = 0xff568a30ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x07101b64ul, 0x18003414ul, 0x0391bc43ul, 0x0e6258eeul, + 0x29d26b72ul, 0x8343937eul, 0xb7a0a4fbul, 0xff568a30ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { @@ -543,16 +533,11 @@ int secp256k1_musig_nonce_agg(const secp256k1_context* ctx, secp256k1_musig_aggn /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("MuSig/noncecoef")||SHA256("MuSig/noncecoef"). */ static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x2c7d5a45ul; - sha->s[1] = 0x06bf7e53ul; - sha->s[2] = 0x89be68a6ul; - sha->s[3] = 0x971254c0ul; - sha->s[4] = 0x60ac12d2ul; - sha->s[5] = 0x72846dcdul; - sha->s[6] = 0x6c81212ful; - sha->s[7] = 0xde7a2500ul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x2c7d5a45ul, 0x06bf7e53ul, 0x89be68a6ul, 0x971254c0ul, + 0x60ac12d2ul, 0x72846dcdul, 0x6c81212ful, 0xde7a2500ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index b410b19e..21c1f412 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -14,33 +14,21 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x46615b35ul; - sha->s[1] = 0xf4bfbff7ul; - sha->s[2] = 0x9f8dc671ul; - sha->s[3] = 0x83627ab3ul; - sha->s[4] = 0x60217180ul; - sha->s[5] = 0x57358661ul; - sha->s[6] = 0x21a29e54ul; - sha->s[7] = 0x68b07b4cul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x46615b35ul, 0xf4bfbff7ul, 0x9f8dc671ul, 0x83627ab3ul, + 0x60217180ul, 0x57358661ul, 0x21a29e54ul, 0x68b07b4cul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x24dd3219ul; - sha->s[1] = 0x4eba7e70ul; - sha->s[2] = 0xca0fabb9ul; - sha->s[3] = 0x0fa3166dul; - sha->s[4] = 0x3afbe4b1ul; - sha->s[5] = 0x4c44df97ul; - sha->s[6] = 0x4aac2739ul; - sha->s[7] = 0x249e850aul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x24dd3219ul, 0x4eba7e70ul, 0xca0fabb9ul, 0x0fa3166dul, + 0x3afbe4b1ul, 0x4c44df97ul, 0x4aac2739ul, 0x249e850aul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 @@ -104,16 +92,11 @@ const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x9cecba11ul; - sha->s[1] = 0x23925381ul; - sha->s[2] = 0x11679112ul; - sha->s[3] = 0xd1627e0ful; - sha->s[4] = 0x97c87550ul; - sha->s[5] = 0x003cc765ul; - sha->s[6] = 0x90f61164ul; - sha->s[7] = 0x33e9b66aul; - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x9cecba11ul, 0x23925381ul, 0x11679112ul, 0xd1627e0ful, + 0x97c87550ul, 0x003cc765ul, 0x90f61164ul, 0x33e9b66aul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) diff --git a/src/tests.c b/src/tests.c index e09f5c7d..2e855790 100644 --- a/src/tests.c +++ b/src/tests.c @@ -739,6 +739,19 @@ static void run_tagged_sha256_tests(void) { CHECK(secp256k1_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0); } +static void run_sha256_initialize_midstate_tests(void) { + /* Midstate for the tagged hash with tag "sha256_midstate_test_tag". */ + static const unsigned char tag[] = "sha256_midstate_test_tag"; + static const uint32_t midstate[8] = { + 0xa9ec59eaul, 0x9b4c2ffful, 0x400821e2ul, 0x0dcf3847ul, + 0xbe7ea179ul, 0xa5772bdcul, 0x7d29bfe3ul, 0xa486b855ul + }; + secp256k1_sha256 sha; + + secp256k1_sha256_initialize_midstate(&sha, 64, midstate); + test_sha256_tag_midstate(&sha, tag, sizeof(tag) - 1); +} + /***** MODINV TESTS *****/ /* Compute the modular inverse of (odd) x mod 2^64. */ @@ -7709,6 +7722,7 @@ static const struct tf_test_entry tests_hash[] = { CASE(hmac_sha256_tests), CASE(rfc6979_hmac_sha256_tests), CASE(tagged_sha256_tests), + CASE(sha256_initialize_midstate_tests), }; static const struct tf_test_entry tests_scalar[] = { @@ -7848,4 +7862,3 @@ int main(int argc, char **argv) { if (tf_init(&tf, argc, argv) != 0) return EXIT_FAILURE; return tf_run(&tf); } - From 7699fe9aa6dbf9f7b3273ae919c0ca6eafba953e Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Thu, 26 Feb 2026 14:35:11 +0200 Subject: [PATCH 303/383] modules: Port bitcoin-core/secp256k1#1735 to zkp-specific code --- src/modules/ecdsa_s2c/main_impl.h | 2 +- src/modules/generator/pedersen_impl.h | 2 +- src/modules/rangeproof/borromean_impl.h | 2 +- src/modules/rangeproof/rangeproof_impl.h | 8 ++++---- src/modules/surjection/surjection_impl.h | 4 ++-- src/modules/whitelist/main_impl.h | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/modules/ecdsa_s2c/main_impl.h b/src/modules/ecdsa_s2c/main_impl.h index 471ae8fb..59a4cdfa 100644 --- a/src/modules/ecdsa_s2c/main_impl.h +++ b/src/modules/ecdsa_s2c/main_impl.h @@ -182,7 +182,7 @@ int secp256k1_ecdsa_anti_exfil_signer_commit(const secp256k1_context* ctx, secp2 secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); secp256k1_ge_set_gej(&r, &rj); secp256k1_ecdsa_s2c_opening_save(opening, &r); - secp256k1_memclear(nonce32, 32); + secp256k1_memclear_explicit(nonce32, 32); secp256k1_scalar_clear(&k); return 1; } diff --git a/src/modules/generator/pedersen_impl.h b/src/modules/generator/pedersen_impl.h index f5526eb6..7d2a8a27 100644 --- a/src/modules/generator/pedersen_impl.h +++ b/src/modules/generator/pedersen_impl.h @@ -28,7 +28,7 @@ static void secp256k1_pedersen_scalar_set_u64(secp256k1_scalar *sec, uint64_t va value <<= 8; } secp256k1_scalar_set_b32(sec, data, NULL); - secp256k1_memclear(data, 32); + secp256k1_memclear_explicit(data, 32); } static void secp256k1_pedersen_ecmult_small(secp256k1_gej *r, uint64_t gn, const secp256k1_ge* genp) { diff --git a/src/modules/rangeproof/borromean_impl.h b/src/modules/rangeproof/borromean_impl.h index 3ca86108..4906ce85 100644 --- a/src/modules/rangeproof/borromean_impl.h +++ b/src/modules/rangeproof/borromean_impl.h @@ -192,7 +192,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar_clear(&ens); secp256k1_ge_clear(&rge); secp256k1_gej_clear(&rgej); - secp256k1_memclear(tmp, 33); + secp256k1_memclear_explicit(tmp, 33); return 1; } diff --git a/src/modules/rangeproof/rangeproof_impl.h b/src/modules/rangeproof/rangeproof_impl.h index fc12ad4f..476da5eb 100644 --- a/src/modules/rangeproof/rangeproof_impl.h +++ b/src/modules/rangeproof/rangeproof_impl.h @@ -107,7 +107,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, secp256k1_rfc6979_hmac_sha256_finalize(&rng); secp256k1_rfc6979_hmac_sha256_clear(&rng); secp256k1_scalar_clear(&acc); - secp256k1_memclear(tmp, 32); + secp256k1_memclear_explicit(tmp, 32); return ret; } @@ -270,7 +270,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul if (!secp256k1_rangeproof_genrand(sec, s, prep, rsizes, rings, nonce, commit, proof, len, genp)) { return 0; } - secp256k1_memclear(prep, 4096); + secp256k1_memclear_explicit(prep, 4096); for (i = 0; i < rings; i++) { /* Sign will overwrite the non-forged signature, move that random value into the nonce. */ k[i] = s[i * 4 + secidx[i]]; @@ -332,7 +332,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul } VERIFY_CHECK(len <= *plen); *plen = len; - secp256k1_memclear(prep, 4096); + secp256k1_memclear_explicit(prep, 4096); return 1; } @@ -473,7 +473,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(secp256k1_scalar * } } *mlen = offset; - secp256k1_memclear(prep, 4096); + secp256k1_memclear_explicit(prep, 4096); for (i = 0; i < 128; i++) { secp256k1_scalar_clear(&s_orig[i]); } diff --git a/src/modules/surjection/surjection_impl.h b/src/modules/surjection/surjection_impl.h index cc0ad300..0776e4c8 100644 --- a/src/modules/surjection/surjection_impl.h +++ b/src/modules/surjection/surjection_impl.h @@ -55,11 +55,11 @@ SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, si secp256k1_sha256_clear(&sha256_en); secp256k1_scalar_set_b32(&s[i], sec_input, &overflow); if (overflow == 1) { - secp256k1_memclear(sec_input, 32); + secp256k1_memclear_explicit(sec_input, 32); return 0; } } - secp256k1_memclear(sec_input, 32); + secp256k1_memclear_explicit(sec_input, 32); return 1; } diff --git a/src/modules/whitelist/main_impl.h b/src/modules/whitelist/main_impl.h index ce94d23a..301d2476 100644 --- a/src/modules/whitelist/main_impl.h +++ b/src/modules/whitelist/main_impl.h @@ -54,7 +54,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s break; } secp256k1_scalar_set_b32(&non, nonce32, &overflow); - secp256k1_memclear(nonce32, 32); + secp256k1_memclear_explicit(nonce32, 32); if (overflow || secp256k1_scalar_is_zero(&non)) { count++; continue; @@ -80,7 +80,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s break; } } - secp256k1_memclear(seckey32, 32); + secp256k1_memclear_explicit(seckey32, 32); } /* Actually sign */ if (ret) { From 7111d365fbe210fb346f31abf68121b9911c7f0f Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Thu, 26 Feb 2026 15:28:51 +0200 Subject: [PATCH 304/383] modules, tests: Port bitcoin-core/secp256k1#1734 to zkp-specific code --- src/modules/bppp/tests_impl.h | 28 +++++++++------- src/modules/ecdsa_adaptor/tests_impl.h | 34 +++++++++---------- src/modules/ecdsa_s2c/tests_impl.h | 21 ++++++------ src/modules/generator/tests_impl.h | 27 ++++++++-------- src/modules/rangeproof/tests_impl.h | 36 +++++++++++---------- src/modules/schnorrsig_halfagg/tests_impl.h | 34 ++++++++++--------- src/modules/surjection/tests_impl.h | 32 +++++++++++------- src/modules/whitelist/tests_impl.h | 25 ++++++++------ src/tests.c | 25 ++++++++++++++ 9 files changed, 153 insertions(+), 109 deletions(-) diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index 6764694c..85d1c1ca 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -15,6 +15,7 @@ #include "bppp_transcript_impl.h" #include "test_vectors/verify.h" #include "test_vectors/prove.h" +#include "../../unit_test.h" static void test_bppp_generators_api(void) { secp256k1_bppp_generators *gens; @@ -649,15 +650,7 @@ static void norm_arg_prove_vectors(void) { #undef IDX_TO_TEST -static void run_bppp_tests(void) { - test_log_exp(); - test_norm_util_helpers(); - test_serialize_two_points(); - test_bppp_generators_api(); - test_bppp_generators_fixed(); - test_bppp_tagged_hash(); - - norm_arg_verify_zero_len(); +static void norm_arg_test_all(void) { norm_arg_test(1, 1); norm_arg_test(1, 64); norm_arg_test(64, 1); @@ -665,9 +658,20 @@ static void run_bppp_tests(void) { norm_arg_test(32, 64); norm_arg_test(64, 32); norm_arg_test(64, 64); - - norm_arg_verify_vectors(); - norm_arg_prove_vectors(); } +/* --- Test registry --- */ +static const struct tf_test_entry tests_bppp[] = { + CASE1(test_log_exp), + CASE1(test_norm_util_helpers), + CASE1(test_serialize_two_points), + CASE1(test_bppp_generators_api), + CASE1(test_bppp_generators_fixed), + CASE1(test_bppp_tagged_hash), + CASE1(norm_arg_verify_zero_len), + CASE1(norm_arg_test_all), + CASE1(norm_arg_verify_vectors), + CASE1(norm_arg_prove_vectors), +}; + #endif diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index a3360223..e2293adc 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -2,6 +2,7 @@ #define SECP256K1_MODULE_ECDSA_ADAPTOR_TESTS_H #include "../../../include/secp256k1_ecdsa_adaptor.h" +#include "../../unit_test.h" static void rand_scalar(secp256k1_scalar *scalar) { unsigned char buf32[32]; @@ -27,7 +28,7 @@ static void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_byt CHECK(secp256k1_scalar_eq(&k1, &k2) == 0); } -static void dleq_tests(void) { +static void dleq_tests_internal(void) { secp256k1_scalar s, e, sk, k; secp256k1_ge gen2, p1, p2; unsigned char *args[5]; @@ -850,7 +851,7 @@ static void test_ecdsa_adaptor_api(void) { CHECK_ILLEGAL(CTX, secp256k1_ecdsa_adaptor_recover(CTX, deckey, &sig, asig, &zero_pk)); } -static void adaptor_tests(void) { +static void adaptor_tests_internal(void) { unsigned char seckey[32]; secp256k1_pubkey pubkey; unsigned char msg[32]; @@ -1050,7 +1051,7 @@ static void adaptor_tests(void) { } } -static void multi_hop_lock_tests(void) { +static void multi_hop_lock_tests_internal(void) { unsigned char seckey_a[32]; unsigned char seckey_b[32]; unsigned char pop[32]; @@ -1124,21 +1125,18 @@ static void multi_hop_lock_tests(void) { CHECK(secp256k1_memcmp_var(buf, pop, 32) == 0); } -static void run_ecdsa_adaptor_tests(void) { - int i; - run_nonce_function_ecdsa_adaptor_tests(); +/* --- Test registry --- */ +REPEAT_TEST(dleq_tests) +REPEAT_TEST(adaptor_tests) +REPEAT_TEST(multi_hop_lock_tests) - test_ecdsa_adaptor_api(); - test_ecdsa_adaptor_spec_vectors(); - for (i = 0; i < COUNT; i++) { - dleq_tests(); - } - for (i = 0; i < COUNT; i++) { - adaptor_tests(); - } - for (i = 0; i < COUNT; i++) { - multi_hop_lock_tests(); - } -} +static const struct tf_test_entry tests_ecdsa_adaptor[] = { + CASE1(run_nonce_function_ecdsa_adaptor_tests), + CASE1(test_ecdsa_adaptor_api), + CASE1(test_ecdsa_adaptor_spec_vectors), + CASE1(dleq_tests), + CASE1(adaptor_tests), + CASE1(multi_hop_lock_tests), +}; #endif /* SECP256K1_MODULE_ECDSA_ADAPTOR_TESTS_H */ diff --git a/src/modules/ecdsa_s2c/tests_impl.h b/src/modules/ecdsa_s2c/tests_impl.h index f84443f3..d13e5164 100644 --- a/src/modules/ecdsa_s2c/tests_impl.h +++ b/src/modules/ecdsa_s2c/tests_impl.h @@ -8,6 +8,7 @@ #define SECP256K1_MODULE_ECDSA_S2C_TESTS_H #include "../../../include/secp256k1_ecdsa_s2c.h" +#include "../../unit_test.h" static void test_ecdsa_s2c_tagged_hash(void) { unsigned char tag_data[] = {'s', '2', 'c', '/', 'e', 'c', 'd', 's', 'a', '/', 'd', 'a', 't', 'a'}; @@ -323,15 +324,15 @@ static void test_ecdsa_anti_exfil(void) { } } -static void run_ecdsa_s2c_tests(void) { - run_s2c_opening_test(); - test_ecdsa_s2c_tagged_hash(); - test_ecdsa_s2c_api(); - test_ecdsa_s2c_fixed_vectors(); - test_ecdsa_s2c_sign_verify(); - - test_ecdsa_anti_exfil_signer_commit(); - test_ecdsa_anti_exfil(); -} +/* --- Test registry --- */ +static const struct tf_test_entry tests_ecdsa_s2c[] = { + CASE1(run_s2c_opening_test), + CASE1(test_ecdsa_s2c_tagged_hash), + CASE1(test_ecdsa_s2c_api), + CASE1(test_ecdsa_s2c_fixed_vectors), + CASE1(test_ecdsa_s2c_sign_verify), + CASE1(test_ecdsa_anti_exfil_signer_commit), + CASE1(test_ecdsa_anti_exfil) +}; #endif /* SECP256K1_MODULE_ECDSA_S2C_TESTS_H */ diff --git a/src/modules/generator/tests_impl.h b/src/modules/generator/tests_impl.h index bd8a0d92..c9f60c0f 100644 --- a/src/modules/generator/tests_impl.h +++ b/src/modules/generator/tests_impl.h @@ -14,6 +14,7 @@ #include "../../scalar.h" #include "../../testrand.h" #include "../../util.h" +#include "../../unit_test.h" #include "../../../include/secp256k1_generator.h" @@ -228,7 +229,7 @@ static void test_pedersen_api(void) { CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_generator_blind_sum(CTX, &val, &blind_ptr, NULL, 1, 0)); } -static void test_pedersen(void) { +static void test_pedersen_internal(void) { secp256k1_pedersen_commitment commits[19]; const secp256k1_pedersen_commitment *cptr[19]; unsigned char blinds[32*19]; @@ -310,19 +311,17 @@ static void test_pedersen_commitment_fixed_vector(void) { CHECK(!secp256k1_pedersen_commitment_parse(CTX, &parse, result)); } +/* --- Test registry --- */ +REPEAT_TEST(test_pedersen) -static void run_generator_tests(void) { - int i; - - test_shallue_van_de_woestijne(); - test_generator_fixed_vector(); - test_generator_api(); - test_generator_generate(); - test_pedersen_api(); - test_pedersen_commitment_fixed_vector(); - for (i = 0; i < COUNT / 2 + 1; i++) { - test_pedersen(); - } -} +static const struct tf_test_entry tests_generator[] = { + CASE1(test_shallue_van_de_woestijne), + CASE1(test_generator_fixed_vector), + CASE1(test_generator_api), + CASE1(test_generator_generate), + CASE1(test_pedersen), + CASE1(test_pedersen_api), + CASE1(test_pedersen_commitment_fixed_vector), +}; #endif diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index e0686f90..74d9f3fd 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -13,10 +13,11 @@ #include "../../scalar.h" #include "../../testrand.h" #include "../../util.h" +#include "../../unit_test.h" #include "../../../include/secp256k1_rangeproof.h" -static void test_rangeproof_api(void) { +static void test_rangeproof_api_internal(void) { unsigned char proof[5134]; unsigned char blind[32]; secp256k1_pedersen_commitment commit; @@ -121,7 +122,7 @@ static void test_rangeproof_api(void) { CHECK(secp256k1_rangeproof_max_size(CTX, UINT64_MAX, 0) == 5134); } -static void test_borromean(void) { +static void test_borromean_internal(void) { unsigned char e0[32]; secp256k1_scalar s[64]; secp256k1_gej pubs[64]; @@ -1346,24 +1347,25 @@ static void test_rangeproof_fixed_vectors_reproducible(void) { } } -static void run_rangeproof_tests(void) { - int i; - for (i = 0; i < COUNT; i++) { - test_rangeproof_api(); - } - +static void test_single_value_proof_all(void) { test_single_value_proof(0); test_single_value_proof(12345678); test_single_value_proof(UINT64_MAX); - - test_rangeproof_fixed_vectors(); - test_rangeproof_fixed_vectors_reproducible(); - for (i = 0; i < COUNT / 2 + 1; i++) { - test_borromean(); - } - test_rangeproof(); - test_rangeproof_null_blinder(); - test_multiple_generators(); } +/* --- Test registry --- */ +REPEAT_TEST(test_rangeproof_api) +REPEAT_TEST(test_borromean) + +static const struct tf_test_entry tests_rangeproof[] = { + CASE1(test_rangeproof_api), + CASE1(test_single_value_proof_all), + CASE1(test_rangeproof_fixed_vectors), + CASE1(test_rangeproof_fixed_vectors_reproducible), + CASE1(test_borromean), + CASE1(test_rangeproof), + CASE1(test_rangeproof_null_blinder), + CASE1(test_multiple_generators), +}; + #endif diff --git a/src/modules/schnorrsig_halfagg/tests_impl.h b/src/modules/schnorrsig_halfagg/tests_impl.h index b93999b6..29d39b2c 100644 --- a/src/modules/schnorrsig_halfagg/tests_impl.h +++ b/src/modules/schnorrsig_halfagg/tests_impl.h @@ -2,6 +2,7 @@ #define SECP256K1_MODULE_SCHNORRSIG_HALFAGG_TESTS_H #include "../../../include/secp256k1_schnorrsig_halfagg.h" +#include "../../unit_test.h" #define N_MAX 50 @@ -34,7 +35,7 @@ void test_schnorrsig_aggregate_input_helper(secp256k1_xonly_pubkey *pubkeys, uns * aggregate some of them in one shot, and then * aggregate the others incrementally to the already aggregated ones. * The aggregate signature should verify after both steps. */ -void test_schnorrsig_aggregate(void) { +void test_schnorrsig_aggregate_internal(void) { secp256k1_xonly_pubkey pubkeys[N_MAX]; unsigned char msgs32[N_MAX*32]; unsigned char sigs64[N_MAX*64]; @@ -165,7 +166,7 @@ void test_schnorrsig_aggverify_spec_vectors(void) { } } -static void test_schnorrsig_aggregate_api(void) { +static void test_schnorrsig_aggregate_api_internal(void) { size_t n = testrand_int(N_MAX + 1); size_t n_initial = testrand_int(n + 1); size_t n_new = n - n_initial; @@ -241,7 +242,7 @@ static void test_schnorrsig_aggregate_api(void) { /* In this test, we make sure that trivial attempts to break * the security of verification do not work. */ -static void test_schnorrsig_aggregate_unforge(void) { +static void test_schnorrsig_aggregate_unforge_internal(void) { secp256k1_xonly_pubkey pubkeys[N_MAX]; unsigned char msgs32[N_MAX*32]; unsigned char sigs64[N_MAX*64]; @@ -297,7 +298,7 @@ static void test_schnorrsig_aggregate_unforge(void) { /* In this test, we make sure that the algorithms properly reject * for overflowing and non parseable values. */ -static void test_schnorrsig_aggregate_overflow(void) { +static void test_schnorrsig_aggregate_overflow_internal(void) { secp256k1_xonly_pubkey pubkeys[N_MAX]; unsigned char msgs32[N_MAX*32]; unsigned char sigs64[N_MAX*64]; @@ -317,19 +318,20 @@ static void test_schnorrsig_aggregate_overflow(void) { } } -static void run_schnorrsig_halfagg_tests(void) { - int i; +/* --- Test registry --- */ +REPEAT_TEST(test_schnorrsig_aggregate) +REPEAT_TEST(test_schnorrsig_aggregate_api) +REPEAT_TEST(test_schnorrsig_aggregate_unforge) +REPEAT_TEST(test_schnorrsig_aggregate_overflow) - test_schnorrsig_sha256_tagged_aggregate(); - test_schnorrsig_aggverify_spec_vectors(); - - for (i = 0; i < COUNT; i++) { - test_schnorrsig_aggregate(); - test_schnorrsig_aggregate_api(); - test_schnorrsig_aggregate_unforge(); - test_schnorrsig_aggregate_overflow(); - } -} +static const struct tf_test_entry tests_schnorrsig_halfagg[] = { + CASE1(test_schnorrsig_sha256_tagged_aggregate), + CASE1(test_schnorrsig_aggverify_spec_vectors), + CASE1(test_schnorrsig_aggregate), + CASE1(test_schnorrsig_aggregate_api), + CASE1(test_schnorrsig_aggregate_unforge), + CASE1(test_schnorrsig_aggregate_overflow), +}; #undef N_MAX diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index e609d170..731e2fd4 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -9,6 +9,7 @@ #include "../../testrand.h" #include "../../group.h" +#include "../../unit_test.h" #include "../../../include/secp256k1_generator.h" #include "../../../include/secp256k1_rangeproof.h" #include "../../../include/secp256k1_surjectionproof.h" @@ -627,22 +628,29 @@ static void test_fixed_vectors(void) { CHECK(!secp256k1_surjectionproof_parse(CTX, &proof, bad, total5_used3_len)); } -static void run_surjection_tests(void) { - test_surjectionproof_api(); - test_input_eq_output(); - test_fixed_vectors(); - +static void test_input_selection_all(void) { test_input_selection(0); test_input_selection(1); test_input_selection(5); test_input_selection(SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS); - - test_input_selection_distribution(); - test_gen_verify(10, 3); - test_gen_verify(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS); - test_no_used_inputs_verify(); - test_bad_serialize(); - test_bad_parse(); } +static void test_gen_verify_all(void) { + test_gen_verify(10, 3); + test_gen_verify(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS); +} + +/* --- Test registry --- */ +static const struct tf_test_entry tests_surjection[] = { + CASE1(test_surjectionproof_api), + CASE1(test_input_eq_output), + CASE1(test_fixed_vectors), + CASE1(test_input_selection_all), + CASE1(test_input_selection_distribution), + CASE1(test_gen_verify_all), + CASE1(test_no_used_inputs_verify), + CASE1(test_bad_serialize), + CASE1(test_bad_parse), +}; + #endif diff --git a/src/modules/whitelist/tests_impl.h b/src/modules/whitelist/tests_impl.h index 38f91e18..9cbb8287 100644 --- a/src/modules/whitelist/tests_impl.h +++ b/src/modules/whitelist/tests_impl.h @@ -8,6 +8,7 @@ #define SECP256K1_MODULE_WHITELIST_TESTS_H #include "../../../include/secp256k1_whitelist.h" +#include "../../unit_test.h" static void test_whitelist_end_to_end_internal(const unsigned char *summed_seckey, const unsigned char *online_seckey, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const secp256k1_pubkey *sub_pubkey, const size_t signer_i, const size_t n_keys) { unsigned char serialized[32 + 4 + 32 * SECP256K1_WHITELIST_MAX_N_KEYS] = {0}; @@ -148,16 +149,20 @@ static void test_whitelist_bad_serialize(void) { CHECK(secp256k1_whitelist_signature_serialize(CTX, serialized, &serialized_len, &sig) == 0); } -static void run_whitelist_tests(void) { - int i; - test_whitelist_bad_parse(); - test_whitelist_bad_serialize(); - for (i = 0; i < COUNT; i++) { - test_whitelist_end_to_end(1, 1); - test_whitelist_end_to_end(10, 1); - test_whitelist_end_to_end(50, 1); - test_whitelist_end_to_end(SECP256K1_WHITELIST_MAX_N_KEYS, 0); - } +static void test_whitelist_end_to_end_all_internal(void) { + test_whitelist_end_to_end(1, 1); + test_whitelist_end_to_end(10, 1); + test_whitelist_end_to_end(50, 1); + test_whitelist_end_to_end(SECP256K1_WHITELIST_MAX_N_KEYS, 0); } +/* --- Test registry --- */ +REPEAT_TEST(test_whitelist_end_to_end_all) + +static const struct tf_test_entry tests_whitelist[] = { + CASE1(test_whitelist_bad_parse), + CASE1(test_whitelist_bad_serialize), + CASE1(test_whitelist_end_to_end_all), +}; + #endif diff --git a/src/tests.c b/src/tests.c index f7ef46fe..7c1a03f8 100644 --- a/src/tests.c +++ b/src/tests.c @@ -7982,6 +7982,31 @@ static const struct tf_test_module registry_modules[] = { #endif #ifdef ENABLE_MODULE_ELLSWIFT MAKE_TEST_MODULE(ellswift), +#endif + /* --- ZKP-SPECIFIC MODULES --- */ +#ifdef ENABLE_MODULE_SCHNORRSIG_HALFAGG + MAKE_TEST_MODULE(schnorrsig_halfagg), +#endif +#ifdef ENABLE_MODULE_BPPP + MAKE_TEST_MODULE(bppp), +#endif +#ifdef ENABLE_MODULE_GENERATOR + MAKE_TEST_MODULE(generator), +#endif +#ifdef ENABLE_MODULE_RANGEPROOF + MAKE_TEST_MODULE(rangeproof), +#endif +#ifdef ENABLE_MODULE_WHITELIST + MAKE_TEST_MODULE(whitelist), +#endif +#ifdef ENABLE_MODULE_SURJECTIONPROOF + MAKE_TEST_MODULE(surjection), +#endif +#ifdef ENABLE_MODULE_ECDSA_ADAPTOR + MAKE_TEST_MODULE(ecdsa_adaptor), +#endif +#ifdef ENABLE_MODULE_ECDSA_S2C + MAKE_TEST_MODULE(ecdsa_s2c), #endif MAKE_TEST_MODULE(utils), }; From d380549e388709efeeaf29e116f41d27bb6f5ddf Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 25 Feb 2026 15:08:56 +0200 Subject: [PATCH 305/383] ecdsa_adaptor: optimize encrypt with batch affine conversion --- src/modules/ecdsa_adaptor/main_impl.h | 37 +++++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index 25232b48..ee0b09a7 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -150,8 +150,8 @@ const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_e int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char *adaptor_sig162, unsigned char *seckey32, const secp256k1_pubkey *enckey, const unsigned char *msg32, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { secp256k1_scalar k; - secp256k1_gej rj, rpj; - secp256k1_ge r, rp; + secp256k1_ge nonce_pts[2]; + secp256k1_gej nonce_ptj[2]; secp256k1_ge enckey_ge; secp256k1_scalar dleq_proof_s; secp256k1_scalar dleq_proof_e; @@ -179,32 +179,35 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char noncefp = secp256k1_nonce_function_ecdsa_adaptor; } - ret &= secp256k1_pubkey_load(ctx, &enckey_ge, enckey); - ret &= secp256k1_eckey_pubkey_serialize(&enckey_ge, buf33, &size, 1); + if (!secp256k1_pubkey_load(ctx, &enckey_ge, enckey)) { + return 0; + } + + secp256k1_eckey_pubkey_serialize(&enckey_ge, buf33, &size, 1); ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata); secp256k1_scalar_set_b32(&k, nonce32, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); /* R' := k*G */ - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rpj, &k); - secp256k1_ge_set_gej(&rp, &rpj); - /* R = k*Y; */ - secp256k1_ecmult_const(&rj, &enckey_ge, &k); - secp256k1_ge_set_gej(&r, &rj); - /* We declassify the non-secret values rp and r to allow using them - * as branch points. */ - secp256k1_declassify(ctx, &rp, sizeof(rp)); - secp256k1_declassify(ctx, &r, sizeof(r)); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[0], &k); + /* R := k*Y */ + secp256k1_ecmult_const(&nonce_ptj[1], &enckey_ge, &k); + + secp256k1_ge_set_all_gej(nonce_pts, nonce_ptj, 2); + + /* We declassify the non-secret nonce values to allow using them as branch points. */ + secp256k1_declassify(ctx, &nonce_pts[0], sizeof(nonce_pts[0])); + secp256k1_declassify(ctx, &nonce_pts[1], sizeof(nonce_pts[1])); /* dleq_proof = DLEQ_prove(k, (R', Y, R)) */ - ret &= secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &rp, &r, noncefp, ndata); + ret &= secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &nonce_pts[0], &nonce_pts[1], noncefp, ndata); ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey32); secp256k1_scalar_cmov(&sk, &secp256k1_scalar_one, !ret); secp256k1_scalar_set_b32(&msg, msg32, NULL); - secp256k1_fe_normalize(&r.x); - secp256k1_fe_get_b32(buf33, &r.x); + secp256k1_fe_normalize(&nonce_pts[1].x); + secp256k1_fe_get_b32(buf33, &nonce_pts[1].x); secp256k1_scalar_set_b32(&sigr, buf33, NULL); ret &= !secp256k1_scalar_is_zero(&sigr); /* s' = k⁻¹(m + R.x * x) */ @@ -215,7 +218,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= !secp256k1_scalar_is_zero(&sp); /* return (R, R', s', dleq_proof) */ - ret &= secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s); + ret &= secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s); secp256k1_memczero(adaptor_sig162, 162, !ret); secp256k1_scalar_clear(&n); From 3f7a9429adccf16e192cd792c1f92b42ad83aaea Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 25 Feb 2026 16:14:32 +0200 Subject: [PATCH 306/383] ecdsa_adaptor: batch affine conversion in dleq_pair and dleq_prove --- src/modules/ecdsa_adaptor/dleq_impl.h | 62 ++++++++++++++------------ src/modules/ecdsa_adaptor/main_impl.h | 9 +++- src/modules/ecdsa_adaptor/tests_impl.h | 5 ++- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index 53b3003e..11d2d667 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -77,29 +77,27 @@ static void secp256k1_dleq_challenge(secp256k1_scalar *e, secp256k1_ge *gen2, se secp256k1_scalar_set_b32(e, buf, NULL); } -/* P1 = x*G, P2 = x*Y */ -static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge *p1, secp256k1_ge *p2, const secp256k1_scalar *sk, const secp256k1_ge *gen2) { - secp256k1_gej p1j, p2j; +/* p[0] = x*G, p[1] = x*Y */ +static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge *p, const secp256k1_scalar *sk, const secp256k1_ge *gen2) { + secp256k1_gej pj[2]; - secp256k1_ecmult_gen(ecmult_gen_ctx, &p1j, sk); - secp256k1_ge_set_gej(p1, &p1j); - secp256k1_ecmult_const(&p2j, gen2, sk); - secp256k1_ge_set_gej(p2, &p2j); + secp256k1_ecmult_gen(ecmult_gen_ctx, &pj[0], sk); + secp256k1_ecmult_const(&pj[1], gen2, sk); + secp256k1_ge_set_all_gej(p, pj, 2); } /* Generates a proof that the discrete logarithm of P1 to the secp256k1 base G is the * same as the discrete logarithm of P2 to the base Y */ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { - secp256k1_ge r1, r2; + secp256k1_ge r[2]; secp256k1_scalar k = { 0 }; unsigned char sk32[32]; unsigned char gen2_33[33]; unsigned char p1_33[33]; unsigned char p2_33[33]; - int ret = 1; size_t pubkey_size = 33; + int ret; - secp256k1_scalar_get_b32(sk32, sk); if (!secp256k1_eckey_pubkey_serialize(gen2, gen2_33, &pubkey_size, 1)) { return 0; } @@ -110,22 +108,30 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar * return 0; } - ret &= secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, noncefp, ndata); - /* R1 = k*G, R2 = k*Y */ - secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, &r1, &r2, &k, gen2); - /* We declassify the non-secret values r1 and r2 to allow using them as - * branch points. */ - secp256k1_declassify(ctx, &r1, sizeof(r1)); - secp256k1_declassify(ctx, &r2, sizeof(r2)); + secp256k1_scalar_get_b32(sk32, sk); - /* e = tagged hash(p1, gen2, p2, r1, r2) */ + ret = secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, noncefp, ndata); + secp256k1_declassify(ctx, &ret, sizeof(ret)); + if (!ret) { + secp256k1_memclear_explicit(sk32, sizeof(sk32)); + return 0; + } + /* R1 = k*G, R2 = k*Y */ + secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, r, &k, gen2); + /* We declassify the non-secret values r[0] and r[1] to allow using them as + * branch points. */ + secp256k1_declassify(ctx, &r[0], sizeof(r[0])); + secp256k1_declassify(ctx, &r[1], sizeof(r[1])); + + /* e = tagged hash(p1, gen2, p2, r[0], r[1]) */ /* s = k + e * sk */ - secp256k1_dleq_challenge(e, gen2, &r1, &r2, p1, p2); + secp256k1_dleq_challenge(e, gen2, &r[0], &r[1], p1, p2); secp256k1_scalar_mul(s, e, sk); secp256k1_scalar_add(s, s, &k); secp256k1_scalar_clear(&k); - return ret; + secp256k1_memclear_explicit(sk32, sizeof(sk32)); + return 1; } static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scalar *e, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2) { @@ -133,8 +139,8 @@ static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scal secp256k1_scalar e_expected; secp256k1_gej gen2j; secp256k1_gej p1j, p2j; - secp256k1_gej r1j, r2j; - secp256k1_ge r1, r2; + secp256k1_gej rj[2]; + secp256k1_ge r[2]; secp256k1_gej tmpj; secp256k1_gej_set_ge(&p1j, p1); @@ -142,16 +148,16 @@ static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scal secp256k1_scalar_negate(&e_neg, e); /* R1 = s*G - e*P1 */ - secp256k1_ecmult(&r1j, &p1j, &e_neg, s); + secp256k1_ecmult(&rj[0], &p1j, &e_neg, s); /* R2 = s*gen2 - e*P2 */ secp256k1_ecmult(&tmpj, &p2j, &e_neg, &secp256k1_scalar_zero); secp256k1_gej_set_ge(&gen2j, gen2); - secp256k1_ecmult(&r2j, &gen2j, s, &secp256k1_scalar_zero); - secp256k1_gej_add_var(&r2j, &r2j, &tmpj, NULL); + secp256k1_ecmult(&rj[1], &gen2j, s, &secp256k1_scalar_zero); + secp256k1_gej_add_var(&rj[1], &rj[1], &tmpj, NULL); - secp256k1_ge_set_gej(&r1, &r1j); - secp256k1_ge_set_gej(&r2, &r2j); - secp256k1_dleq_challenge(&e_expected, gen2, &r1, &r2, p1, p2); + secp256k1_ge_set_all_gej_var(r, rj, 2); + + secp256k1_dleq_challenge(&e_expected, gen2, &r[0], &r[1], p1, p2); secp256k1_scalar_add(&e_expected, &e_expected, &e_neg); return secp256k1_scalar_is_zero(&e_expected); diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index ee0b09a7..e97bb5a0 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -201,8 +201,12 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char secp256k1_declassify(ctx, &nonce_pts[1], sizeof(nonce_pts[1])); /* dleq_proof = DLEQ_prove(k, (R', Y, R)) */ - ret &= secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &nonce_pts[0], &nonce_pts[1], noncefp, ndata); - + if (!secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &nonce_pts[0], &nonce_pts[1], noncefp, ndata)) { + memset(adaptor_sig162, 0, 162); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); + secp256k1_scalar_clear(&k); + return 0; + } ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey32); secp256k1_scalar_cmov(&sk, &secp256k1_scalar_one, !ret); secp256k1_scalar_set_b32(&msg, msg32, NULL); @@ -221,6 +225,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s); secp256k1_memczero(adaptor_sig162, 162, !ret); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&n); secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index e2293adc..5e41a9c0 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -31,6 +31,7 @@ static void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_byt static void dleq_tests_internal(void) { secp256k1_scalar s, e, sk, k; secp256k1_ge gen2, p1, p2; + secp256k1_ge p[2]; unsigned char *args[5]; unsigned char sk32[32]; unsigned char gen2_33[33]; @@ -42,7 +43,9 @@ static void dleq_tests_internal(void) { rand_point(&gen2); rand_scalar(&sk); - secp256k1_dleq_pair(&CTX->ecmult_gen_ctx, &p1, &p2, &sk, &gen2); + secp256k1_dleq_pair(&CTX->ecmult_gen_ctx, p, &sk, &gen2); + p1 = p[0]; + p2 = p[1]; CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p1, &p2, NULL, NULL) == 1); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p2) == 1); From 8d0eda07e9eae7418ce6d23f904faca3ddfb0eb0 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 2 Mar 2026 15:06:39 +0100 Subject: [PATCH 307/383] testrand: Remove testrand_finish This removes printing of the "random run = " at the end of the tests. I haven't seen a single case where this proved to be useful. And as of 48789dafc2a866bbc639184f0387637c0decb8c5, this is anyway printed only at the end of the exhaustive tests and not the normal tests, so the probability that this will be useful in the future is very low. --- src/testrand.h | 3 --- src/testrand_impl.h | 6 ------ src/tests_exhaustive.c | 2 -- 3 files changed, 11 deletions(-) diff --git a/src/testrand.h b/src/testrand.h index 3c1ed3d4..215b6fc7 100644 --- a/src/testrand.h +++ b/src/testrand.h @@ -42,7 +42,4 @@ static void testrand_flip(unsigned char *b, size_t len); /** Initialize the test RNG using (hex encoded) array up to 16 bytes, or randomly if hexseed is NULL. */ static void testrand_init(const char* hexseed); -/** Print final test information. */ -static void testrand_finish(void); - #endif /* SECP256K1_TESTRAND_H */ diff --git a/src/testrand_impl.h b/src/testrand_impl.h index b84f5730..6d9fd63a 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -158,10 +158,4 @@ static void testrand_init(const char* hexseed) { testrand_seed(seed16); } -static void testrand_finish(void) { - unsigned char run32[32]; - testrand256(run32); - printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); -} - #endif /* SECP256K1_TESTRAND_IMPL_H */ diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 13bda611..68d4bec3 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -459,8 +459,6 @@ int main(int argc, char** argv) { secp256k1_context_destroy(ctx); } - testrand_finish(); - printf("no problems found\n"); return EXIT_SUCCESS; } From 6f7c112cc8b99cb1d8113bbbb5096bfafc58eb52 Mon Sep 17 00:00:00 2001 From: Mykyta Date: Wed, 25 Feb 2026 18:34:44 +0200 Subject: [PATCH 308/383] include: add description of range proofs focusing on the differences between the implementation and the CA paper --- include/secp256k1_rangeproof.h | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/include/secp256k1_rangeproof.h b/include/secp256k1_rangeproof.h index 03315277..8816bdcf 100644 --- a/include/secp256k1_rangeproof.h +++ b/include/secp256k1_rangeproof.h @@ -10,6 +10,41 @@ extern "C" { #include +/** This module implements a variant of Back-Maxwell range proofs as described + * in the Confidential Assets paper (https://blockstream.com/bitcoin17-final41.pdf). + * The construction is based on Borromean ring signatures. + * (https://nt4tn.net/papers/borromean_draft_0.01_34241bb.pdf) + * + * This implementation differs from the variant in the paper mainly in that it + * omits an optimization that saves one scalar per ring. This optimization complicates + * the protocol and security analysis, as it requires differentiating cases where + * the i-th bit v_i = 0 versus otherwise, and makes calculating response points R_i less + * straightforward. The implemented version uses Borromean ring signatures in + * an unmodified way. + * + * Another difference is that the implementation omits the last ring's commitment + * from the proof and recovered by the verifier by subtracting all other digit + * commitments from the total, reducing proof size by one group element. + * + * Furthermore, in the implementation every hash calculation includes a message + * m=SHA256(C||H||header||C_0||...||C_(n-2)||extra_commit), binding the commitment C, + * generator H, proof header, the n-1 explicit digit commitments, and any extra data. + * This prevents an attack that would compromise non-malleability. In the paper's + * version of the protocol, a prover could pick distinct indices i, j and a scalar y, + * and modify digit commitments in the original proof by setting C'_i = C_i + yG and + * C'_j = C_j - yG, obtaining a different valid proof for the same commitment and + * witness. + * + * In the current implementation, up to 3968 bytes of message data can be + * embedded and recovered within maximally-sized proofs. The implemented embedding + * method using the forged parts of ring signatures could also be applied to the + * construction in the paper, but is not mentioned there. Message embedding is used + * in Confidential Assets to transmit values and blinding factors of the corresponding + * commitments. This is possible because randomness is generated by seeding HMAC-DRBG + * with the shared ECDH key, allowing the receiver to rewind the proof using the same + * random values the sender used. + */ + /** Length of a message that can be embedded into a maximally-sized rangeproof * * It is not be possible to fit a message of this size into a non-maximally-sized From 2542b4345196fba49dec0d794c6b94f80f3f8275 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 2 Mar 2026 16:40:12 +0200 Subject: [PATCH 309/383] modules: Port bitcoin-core/secp256k1#1774 to zkp-specific code --- src/modules/bppp/bppp_util.h | 7 +++- src/modules/ecdsa_adaptor/dleq_impl.h | 20 +++------- src/modules/ecdsa_adaptor/main_impl.h | 49 ++++++++++--------------- src/modules/ecdsa_adaptor/tests_impl.h | 24 +++--------- src/modules/rangeproof/borromean_impl.h | 14 +++---- src/modules/whitelist/whitelist_impl.h | 15 +++----- src/secp256k1.c | 10 +---- 7 files changed, 46 insertions(+), 93 deletions(-) diff --git a/src/modules/bppp/bppp_util.h b/src/modules/bppp/bppp_util.h index 1debfb92..ec979c69 100644 --- a/src/modules/bppp/bppp_util.h +++ b/src/modules/bppp/bppp_util.h @@ -47,8 +47,11 @@ static int secp256k1_bppp_parse_one_of_points(secp256k1_ge *pt, const unsigned c /* Outputs a serialized point in compressed form. Returns 0 at point at infinity. */ static int secp256k1_bppp_serialize_pt(unsigned char *output, secp256k1_ge *lpt) { - size_t size; - return secp256k1_eckey_pubkey_serialize(lpt, output, &size, 1 /*compressed*/); + if (secp256k1_ge_is_infinity(lpt)) { + return 0; + } + secp256k1_eckey_pubkey_serialize33(lpt, output); + return 1; } /* little-endian encodes a uint64 */ diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index 11d2d667..60e63a34 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -20,16 +20,13 @@ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) { /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ static const unsigned char dleq_algo[] = {'D','L','E','Q'}; -static int secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) { +static void secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) { unsigned char buf[33]; size_t size = 33; - if (!secp256k1_eckey_pubkey_serialize(p, buf, &size, 1)) { - return 0; - } + secp256k1_eckey_pubkey_serialize33(p, buf); secp256k1_sha256_write(sha, buf, size); - return 1; } static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, const unsigned char *gen2_33, const unsigned char *p1_33, const unsigned char *p2_33, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { @@ -95,18 +92,11 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar * unsigned char gen2_33[33]; unsigned char p1_33[33]; unsigned char p2_33[33]; - size_t pubkey_size = 33; int ret; - if (!secp256k1_eckey_pubkey_serialize(gen2, gen2_33, &pubkey_size, 1)) { - return 0; - } - if (!secp256k1_eckey_pubkey_serialize(p1, p1_33, &pubkey_size, 1)) { - return 0; - } - if (!secp256k1_eckey_pubkey_serialize(p2, p2_33, &pubkey_size, 1)) { - return 0; - } + secp256k1_eckey_pubkey_serialize33(gen2, gen2_33); + secp256k1_eckey_pubkey_serialize33(p1, p1_33); + secp256k1_eckey_pubkey_serialize33(p2, p2_33); secp256k1_scalar_get_b32(sk32, sk); diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index e97bb5a0..e43a4222 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -11,20 +11,12 @@ #include "dleq_impl.h" /* (R, R', s', dleq_proof) */ -static int secp256k1_ecdsa_adaptor_sig_serialize(unsigned char *adaptor_sig162, secp256k1_ge *r, secp256k1_ge *rp, const secp256k1_scalar *sp, const secp256k1_scalar *dleq_proof_e, const secp256k1_scalar *dleq_proof_s) { - size_t size = 33; - - if (!secp256k1_eckey_pubkey_serialize(r, adaptor_sig162, &size, 1)) { - return 0; - } - if (!secp256k1_eckey_pubkey_serialize(rp, &adaptor_sig162[33], &size, 1)) { - return 0; - } +static void secp256k1_ecdsa_adaptor_sig_serialize(unsigned char *adaptor_sig162, secp256k1_ge *r, secp256k1_ge *rp, const secp256k1_scalar *sp, const secp256k1_scalar *dleq_proof_e, const secp256k1_scalar *dleq_proof_s) { + secp256k1_eckey_pubkey_serialize33(r, adaptor_sig162); + secp256k1_eckey_pubkey_serialize33(rp, &adaptor_sig162[33]); secp256k1_scalar_get_b32(&adaptor_sig162[66], sp); secp256k1_scalar_get_b32(&adaptor_sig162[98], dleq_proof_e); secp256k1_scalar_get_b32(&adaptor_sig162[130], dleq_proof_s); - - return 1; } static int secp256k1_ecdsa_adaptor_sig_deserialize(secp256k1_ge *r, secp256k1_scalar *sigr, secp256k1_ge *rp, secp256k1_scalar *sp, secp256k1_scalar *dleq_proof_e, secp256k1_scalar *dleq_proof_s, const unsigned char *adaptor_sig162) { @@ -162,7 +154,6 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char secp256k1_scalar n; unsigned char nonce32[32] = { 0 }; unsigned char buf33[33]; - size_t size = 33; int ret = 1; VERIFY_CHECK(ctx != NULL); @@ -183,7 +174,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char return 0; } - secp256k1_eckey_pubkey_serialize(&enckey_ge, buf33, &size, 1); + secp256k1_eckey_pubkey_serialize33(&enckey_ge, buf33); ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata); secp256k1_scalar_set_b32(&k, nonce32, NULL); ret &= !secp256k1_scalar_is_zero(&k); @@ -222,7 +213,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= !secp256k1_scalar_is_zero(&sp); /* return (R, R', s', dleq_proof) */ - ret &= secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s); + secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s); secp256k1_memczero(adaptor_sig162, 162, !ret); secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); @@ -319,10 +310,10 @@ int secp256k1_ecdsa_adaptor_recover(const secp256k1_context* ctx, unsigned char secp256k1_scalar s, r; secp256k1_scalar deckey; secp256k1_ge enckey_expected_ge; + secp256k1_ge enckey_ge; secp256k1_gej enckey_expected_gej; unsigned char enckey33[33]; unsigned char enckey_expected33[33]; - size_t size = 33; int ret = 1; VERIFY_CHECK(ctx != NULL); @@ -349,23 +340,21 @@ int secp256k1_ecdsa_adaptor_recover(const secp256k1_context* ctx, unsigned char /* We declassify non-secret enckey_expected_ge to allow using it as a * branch point. */ secp256k1_declassify(ctx, &enckey_expected_ge, sizeof(enckey_expected_ge)); - if (!secp256k1_eckey_pubkey_serialize(&enckey_expected_ge, enckey_expected33, &size, 1)) { - /* Unreachable from tests (and other VERIFY builds) and therefore this - * branch should be ignored in test coverage analysis. - * - * Proof: - * eckey_pubkey_serialize fails <=> deckey = 0 - * deckey = 0 <=> s^-1 = 0 or sp = 0 - * case 1: s^-1 = 0 impossible by the definition of multiplicative - * inverse and because the scalar_inverse implementation - * VERIFY_CHECKs that the inputs are valid scalars. - * case 2: sp = 0 impossible because ecdsa_adaptor_sig_deserialize would have already failed - */ - return 0; - } - if (!secp256k1_ec_pubkey_serialize(ctx, enckey33, &size, enckey, SECP256K1_EC_COMPRESSED)) { + /* enckey_expected_ge cannot be infinity: + * + * Proof: + * enckey_expected_ge is infinity <=> deckey = 0 + * deckey = 0 <=> s^-1 = 0 or sp = 0 + * case 1: s^-1 = 0 impossible by the definition of multiplicative + * inverse and because the scalar_inverse implementation + * VERIFY_CHECKs that the inputs are valid scalars. + * case 2: sp = 0 impossible because ecdsa_adaptor_sig_deserialize would have already failed + */ + secp256k1_eckey_pubkey_serialize33(&enckey_expected_ge, enckey_expected33); + if (!secp256k1_pubkey_load(ctx, &enckey_ge, enckey)) { return 0; } + secp256k1_eckey_pubkey_serialize33(&enckey_ge, enckey33); if (secp256k1_memcmp_var(&enckey_expected33[1], &enckey33[1], 32) != 0) { return 0; } diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index 5e41a9c0..3abc8127 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -39,7 +39,6 @@ static void dleq_tests_internal(void) { unsigned char p2_33[33]; unsigned char aux_rand[32]; int i; - size_t pubkey_size = 33; rand_point(&gen2); rand_scalar(&sk); @@ -62,19 +61,12 @@ static void dleq_tests_internal(void) { CHECK(secp256k1_dleq_verify(&s, &e, &p1, &p_tmp, &p2) == 0); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p_tmp) == 0); } - { - secp256k1_ge p_inf; - secp256k1_ge_set_infinity(&p_inf); - CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &p_inf, &p1, &p2, NULL, NULL) == 0); - CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p_inf, &p2, NULL, NULL) == 0); - CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p1, &p_inf, NULL, NULL) == 0); - } /* Nonce tests */ secp256k1_scalar_get_b32(sk32, &sk); - CHECK(secp256k1_eckey_pubkey_serialize(&gen2, gen2_33, &pubkey_size, 1)); - CHECK(secp256k1_eckey_pubkey_serialize(&p1, p1_33, &pubkey_size, 1)); - CHECK(secp256k1_eckey_pubkey_serialize(&p2, p2_33, &pubkey_size, 1)); + secp256k1_eckey_pubkey_serialize33(&gen2, gen2_33); + secp256k1_eckey_pubkey_serialize33(&p1, p1_33); + secp256k1_eckey_pubkey_serialize33(&p2, p2_33); CHECK(secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1); testrand_bytes_test(sk32, sizeof(sk32)); @@ -165,7 +157,7 @@ static void test_ecdsa_adaptor_spec_vectors_check_serialization(const unsigned c CHECK(expected == secp256k1_ecdsa_adaptor_sig_deserialize(&r, &sigr, &rp, &sp, &dleq_proof_e, &dleq_proof_s, adaptor_sig162)); if (expected == 1) { - CHECK(secp256k1_ecdsa_adaptor_sig_serialize(buf, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s) == 1); + secp256k1_ecdsa_adaptor_sig_serialize(buf, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s); CHECK(secp256k1_memcmp_var(buf, adaptor_sig162, 162) == 0); } } @@ -896,18 +888,12 @@ static void adaptor_tests_internal(void) { secp256k1_scalar sigr; secp256k1_scalar sp; secp256k1_scalar dleq_proof_s, dleq_proof_e; - secp256k1_ge p_inf; unsigned char adaptor_sig_tmp[162]; CHECK(secp256k1_ecdsa_adaptor_sig_deserialize(&r, &sigr, &rp, &sp, &dleq_proof_e, &dleq_proof_s, adaptor_sig) == 1); - CHECK(secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s) == 1); + secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s); CHECK(secp256k1_memcmp_var(adaptor_sig_tmp, adaptor_sig, sizeof(adaptor_sig_tmp)) == 0); - - /* Test adaptor_sig_serialize points at infinity */ - secp256k1_ge_set_infinity(&p_inf); - CHECK(secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &p_inf, &rp, &sp, &dleq_proof_e, &dleq_proof_s) == 0); - CHECK(secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &r, &p_inf, &sp, &dleq_proof_e, &dleq_proof_s) == 0); } { /* Test adaptor_sig_deserialize */ diff --git a/src/modules/rangeproof/borromean_impl.h b/src/modules/rangeproof/borromean_impl.h index 4906ce85..2fff3c28 100644 --- a/src/modules/rangeproof/borromean_impl.h +++ b/src/modules/rangeproof/borromean_impl.h @@ -60,7 +60,6 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e size_t i; size_t j; size_t count; - size_t size; int overflow; VERIFY_CHECK(e0 != NULL); VERIFY_CHECK(s != NULL); @@ -88,12 +87,12 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e } /* OPT: loop can be hoisted and split to use batch inversion across all the rings; this would make it much faster. */ secp256k1_ge_set_gej_var(&rge, &rgej); - secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); + secp256k1_eckey_pubkey_serialize33(&rge, tmp); if (j != rsizes[i] - 1) { secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1); secp256k1_scalar_set_b32(&ens, tmp, &overflow); } else { - secp256k1_sha256_write(&sha256_e0, tmp, size); + secp256k1_sha256_write(&sha256_e0, tmp, 33); } count++; } @@ -115,7 +114,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, size_t i; size_t j; size_t count; - size_t size; int overflow; VERIFY_CHECK(ecmult_gen_ctx != NULL); VERIFY_CHECK(e0 != NULL); @@ -136,7 +134,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, if (secp256k1_gej_is_infinity(&rgej)) { return 0; } - secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); + secp256k1_eckey_pubkey_serialize33(&rge, tmp); for (j = secidx[i] + 1; j < rsizes[i]; j++) { secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j); secp256k1_scalar_set_b32(&ens, tmp, &overflow); @@ -152,9 +150,9 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, return 0; } secp256k1_ge_set_gej_var(&rge, &rgej); - secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); + secp256k1_eckey_pubkey_serialize33(&rge, tmp); } - secp256k1_sha256_write(&sha256_e0, tmp, size); + secp256k1_sha256_write(&sha256_e0, tmp, 33); count += rsizes[i]; } secp256k1_sha256_write(&sha256_e0, m, mlen); @@ -174,7 +172,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, return 0; } secp256k1_ge_set_gej_var(&rge, &rgej); - secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1); + secp256k1_eckey_pubkey_serialize33(&rge, tmp); secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1); secp256k1_scalar_set_b32(&ens, tmp, &overflow); if (overflow || secp256k1_scalar_is_zero(&ens)) { diff --git a/src/modules/whitelist/whitelist_impl.h b/src/modules/whitelist/whitelist_impl.h index bb244907..edb90b4f 100644 --- a/src/modules/whitelist/whitelist_impl.h +++ b/src/modules/whitelist/whitelist_impl.h @@ -18,9 +18,10 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g secp256k1_ge_set_gej(&ge, pubkey); secp256k1_sha256_initialize(&sha); - if (!secp256k1_eckey_pubkey_serialize(&ge, c, &size, 1)) { + if (secp256k1_ge_is_infinity(&ge)) { return 0; } + secp256k1_eckey_pubkey_serialize33(&ge, c); secp256k1_sha256_write(&sha, c, size); secp256k1_sha256_finalize(&sha, h); secp256k1_sha256_clear(&sha); @@ -95,9 +96,7 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* secp256k1_pubkey_load(ctx, &subkey_ge, sub_pubkey); /* commit to sub-key */ - if (!secp256k1_eckey_pubkey_serialize(&subkey_ge, c, &size, 1)) { - return 0; - } + secp256k1_eckey_pubkey_serialize33(&subkey_ge, c); secp256k1_sha256_write(&sha, c, size); for (i = 0; i < n_keys; i++) { secp256k1_ge offline_ge; @@ -106,14 +105,10 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* /* commit to fixed keys */ secp256k1_pubkey_load(ctx, &offline_ge, &offline_pubkeys[i]); - if (!secp256k1_eckey_pubkey_serialize(&offline_ge, c, &size, 1)) { - return 0; - } + secp256k1_eckey_pubkey_serialize33(&offline_ge, c); secp256k1_sha256_write(&sha, c, size); secp256k1_pubkey_load(ctx, &online_ge, &online_pubkeys[i]); - if (!secp256k1_eckey_pubkey_serialize(&online_ge, c, &size, 1)) { - return 0; - } + secp256k1_eckey_pubkey_serialize33(&online_ge, c); secp256k1_sha256_write(&sha, c, size); /* compute tweaked keys */ diff --git a/src/secp256k1.c b/src/secp256k1.c index 9245c126..69bc9d94 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -858,15 +858,7 @@ static void secp256k1_ge_serialize_ext(unsigned char *out33, secp256k1_ge* ge) { if (secp256k1_ge_is_infinity(ge)) { memset(out33, 0, 33); } else { - int ret; - size_t size = 33; - ret = secp256k1_eckey_pubkey_serialize(ge, out33, &size, 1); -#ifdef VERIFY - /* Serialize must succeed because the point is not at infinity */ - VERIFY_CHECK(ret && size == 33); -#else - (void) ret; -#endif + secp256k1_eckey_pubkey_serialize33(ge, out33); } } From d8e87e45f33c151949d7decfb9e8a0d02c1029a6 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 2 Mar 2026 16:42:19 +0200 Subject: [PATCH 310/383] unit_test: bump MAX_ARGS from 150 to 200 --- src/unit_test.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unit_test.h b/src/unit_test.h index bf301e53..d3b0f153 100644 --- a/src/unit_test.h +++ b/src/unit_test.h @@ -13,7 +13,7 @@ /* Maximum number of command-line arguments. * Must be at least as large as the total number of tests * to allow specifying all tests individually. */ -#define MAX_ARGS 150 +#define MAX_ARGS 200 /* Maximum number of parallel jobs */ #define MAX_SUBPROCESSES 16 From d111d31293b479832c767946145702151897785d Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 2 Mar 2026 16:53:18 +0200 Subject: [PATCH 311/383] generator: Port bitcoin-core/secp256k1#1779 to zkp-specific code --- src/modules/generator/main_impl.h | 13 +++++++++++++ src/modules/generator/tests_impl.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index c3f1c027..9ce2defb 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -343,6 +343,9 @@ int secp256k1_pedersen_blind_sum(const secp256k1_context* ctx, unsigned char *bl VERIFY_CHECK(ctx != NULL); ARG_CHECK(blind_out != NULL); ARG_CHECK(blinds != NULL); + for (i = 0; i < n; i++) { + ARG_CHECK(blinds[i] != NULL); + } ARG_CHECK(npositive <= n); (void) ctx; secp256k1_scalar_set_int(&acc, 0); @@ -370,6 +373,12 @@ int secp256k1_pedersen_verify_tally(const secp256k1_context* ctx, const secp256k VERIFY_CHECK(ctx != NULL); ARG_CHECK(!pcnt || (commits != NULL)); ARG_CHECK(!ncnt || (ncommits != NULL)); + for (i = 0; i < pcnt; i++) { + ARG_CHECK(commits[i] != NULL); + } + for (i = 0; i < ncnt; i++) { + ARG_CHECK(ncommits[i] != NULL); + } (void) ctx; secp256k1_gej_set_infinity(&accj); for (i = 0; i < ncnt; i++) { @@ -394,6 +403,10 @@ int secp256k1_pedersen_blind_generator_blind_sum(const secp256k1_context* ctx, c ARG_CHECK(n_total == 0 || generator_blind != NULL); ARG_CHECK(n_total == 0 || blinding_factor != NULL); ARG_CHECK(n_total > n_inputs); + for (i = 0; i < n_total; i++) { + ARG_CHECK(generator_blind[i] != NULL); + ARG_CHECK(blinding_factor[i] != NULL); + } (void) ctx; if (n_total == 0) { diff --git a/src/modules/generator/tests_impl.h b/src/modules/generator/tests_impl.h index c9f60c0f..14ec95dc 100644 --- a/src/modules/generator/tests_impl.h +++ b/src/modules/generator/tests_impl.h @@ -227,6 +227,13 @@ static void test_pedersen_api(void) { CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_generator_blind_sum(CTX, NULL, &blind_ptr, &blind_out_ptr, 1, 0)); CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_generator_blind_sum(CTX, &val, NULL, &blind_out_ptr, 1, 0)); CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_generator_blind_sum(CTX, &val, &blind_ptr, NULL, 1, 0)); + /* check that NULL in array of generator_blind pointers is not allowed */ + blind_ptr = NULL; + CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_generator_blind_sum(CTX, &val, &blind_ptr, &blind_out_ptr, 1, 0)); + blind_ptr = blind; + /* check that NULL in array of blinding_factor pointers is not allowed */ + blind_out_ptr = NULL; + CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_generator_blind_sum(CTX, &val, &blind_ptr, &blind_out_ptr, 1, 0)); } static void test_pedersen_internal(void) { @@ -264,6 +271,14 @@ static void test_pedersen_internal(void) { secp256k1_scalar_get_b32(&blinds[i * 32], &s); } CHECK(secp256k1_pedersen_blind_sum(CTX, &blinds[(total - 1) * 32], bptr, total - 1, inputs)); + /* check that NULL in array of blind pointers is not allowed */ + for (i = 0; i < total - 1; i++) { + unsigned char blind_out[32]; + const unsigned char *original_ptr = bptr[i]; + bptr[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_pedersen_blind_sum(CTX, blind_out, bptr, total - 1, inputs)); + bptr[i] = original_ptr; + } for (i = 0; i < total; i++) { unsigned char result[33]; secp256k1_pedersen_commitment parse; @@ -275,6 +290,20 @@ static void test_pedersen_internal(void) { } CHECK(secp256k1_pedersen_verify_tally(CTX, cptr, inputs, &cptr[inputs], outputs)); CHECK(secp256k1_pedersen_verify_tally(CTX, &cptr[inputs], outputs, cptr, inputs)); + /* check that NULL in array of commits pointers is not allowed */ + for (i = 0; i < inputs; i++) { + const secp256k1_pedersen_commitment *original_ptr = cptr[i]; + cptr[i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_pedersen_verify_tally(CTX, cptr, inputs, &cptr[inputs], outputs)); + cptr[i] = original_ptr; + } + /* check that NULL in array of ncommits pointers is not allowed */ + for (i = 0; i < outputs; i++) { + const secp256k1_pedersen_commitment *original_ptr = cptr[inputs + i]; + cptr[inputs + i] = NULL; + CHECK_ILLEGAL(CTX, secp256k1_pedersen_verify_tally(CTX, cptr, inputs, &cptr[inputs], outputs)); + cptr[inputs + i] = original_ptr; + } if (inputs > 0 && values[0] > 0) { CHECK(!secp256k1_pedersen_verify_tally(CTX, cptr, inputs - 1, &cptr[inputs], outputs)); } From fe48cc9fa5d99a7d046e86a96c5dd270e1b7061c Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 2 Mar 2026 16:58:33 +0200 Subject: [PATCH 312/383] generator: Port bitcoin-core/secp256k1#1764 to zkp-specific code --- src/modules/generator/main_impl.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index 9ce2defb..c58d66fe 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -38,12 +38,13 @@ const secp256k1_generator *secp256k1_generator_h = &secp256k1_generator_h_intern static void secp256k1_generator_load(secp256k1_ge* ge, const secp256k1_generator* gen) { + secp256k1_fe x, y; int succeed; - succeed = secp256k1_fe_set_b32_limit(&ge->x, &gen->data[0]); + succeed = secp256k1_fe_set_b32_limit(&x, &gen->data[0]); VERIFY_CHECK(succeed != 0); - succeed = secp256k1_fe_set_b32_limit(&ge->y, &gen->data[32]); + succeed = secp256k1_fe_set_b32_limit(&y, &gen->data[32]); VERIFY_CHECK(succeed != 0); - ge->infinity = 0; + secp256k1_ge_set_xy(ge, &x, &y); (void) succeed; } From dc0bda5731c756a66786eccec96d9dc419b62d0f Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 2 Mar 2026 17:15:31 +0200 Subject: [PATCH 313/383] bench: Port bitcoin-core/secp256k1#1796 to zkp-specific code --- src/bench_bppp.c | 3 +++ src/bench_generator.c | 3 +++ src/bench_rangeproof.c | 3 +++ src/bench_whitelist.c | 3 +++ 4 files changed, 12 insertions(+) diff --git a/src/bench_bppp.c b/src/bench_bppp.c index b74aec6c..63ad8cea 100644 --- a/src/bench_bppp.c +++ b/src/bench_bppp.c @@ -29,6 +29,9 @@ static void bench_bppp(void* arg, int iters) { int main(void) { bench_bppp_data data; int iters = get_iters(32); + if (iters == 0) { + return EXIT_FAILURE; + } data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); diff --git a/src/bench_generator.c b/src/bench_generator.c index ecccecb7..93af6129 100644 --- a/src/bench_generator.c +++ b/src/bench_generator.c @@ -50,6 +50,9 @@ static void bench_generator_generate_blinded(void* arg, int iters) { int main(void) { bench_generator_t data; int iters = get_iters(20000); + if (iters == 0) { + return EXIT_FAILURE; + } data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); diff --git a/src/bench_rangeproof.c b/src/bench_rangeproof.c index 76893456..add1e1e1 100644 --- a/src/bench_rangeproof.c +++ b/src/bench_rangeproof.c @@ -58,6 +58,9 @@ int main(void) { data.min_bits = 32; iters = data.min_bits*get_iters(32); + if (iters == 0) { + return EXIT_FAILURE; + } run_benchmark("rangeproof_verify_bit", bench_rangeproof, bench_rangeproof_setup, NULL, &data, 10, iters); diff --git a/src/bench_whitelist.c b/src/bench_whitelist.c index 6cbe6fd6..f02f1e86 100644 --- a/src/bench_whitelist.c +++ b/src/bench_whitelist.c @@ -69,6 +69,9 @@ int main(void) { size_t n_keys = 30; secp256k1_scalar ssub; int iters = get_iters(5); + if (iters == 0) { + return EXIT_FAILURE; + } data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); From 126501f58b41f2374d6a75a183f01d14a2d548dc Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Tue, 3 Mar 2026 15:16:04 +0200 Subject: [PATCH 314/383] modules: Port bitcoin-core/secp256k1#1815 to zkp-specific code --- src/modules/bppp/main_impl.h | 8 ++++---- src/modules/bppp/tests_impl.h | 4 ++-- src/modules/rangeproof/tests_impl.h | 4 ++-- src/modules/surjection/main_impl.h | 2 +- src/modules/whitelist/tests_impl.h | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/modules/bppp/main_impl.h b/src/modules/bppp/main_impl.h index 49a09447..e8e9e30a 100644 --- a/src/modules/bppp/main_impl.h +++ b/src/modules/bppp/main_impl.h @@ -23,11 +23,11 @@ secp256k1_bppp_generators *secp256k1_bppp_generators_create(const secp256k1_cont VERIFY_CHECK(ctx != NULL); - ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret)); + ret = checked_malloc(&ctx->error_callback, sizeof(*ret)); if (ret == NULL) { return NULL; } - ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); + ret->gens = checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); if (ret->gens == NULL) { free(ret); return NULL; @@ -60,12 +60,12 @@ secp256k1_bppp_generators* secp256k1_bppp_generators_parse(const secp256k1_conte return NULL; } - ret = (secp256k1_bppp_generators *)checked_malloc(&ctx->error_callback, sizeof(*ret)); + ret = checked_malloc(&ctx->error_callback, sizeof(*ret)); if (ret == NULL) { return NULL; } ret->n = n; - ret->gens = (secp256k1_ge*)checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); + ret->gens = checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); if (ret->gens == NULL) { free(ret); return NULL; diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index 85d1c1ca..dda9a8c0 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -514,12 +514,12 @@ secp256k1_bppp_generators* bppp_generators_parse_regular(const unsigned char* da return NULL; } - ret = (secp256k1_bppp_generators *)checked_malloc(&CTX->error_callback, sizeof(*ret)); + ret = checked_malloc(&CTX->error_callback, sizeof(*ret)); if (ret == NULL) { return NULL; } ret->n = n; - ret->gens = (secp256k1_ge*)checked_malloc(&CTX->error_callback, n * sizeof(*ret->gens)); + ret->gens = checked_malloc(&CTX->error_callback, n * sizeof(*ret->gens)); if (ret->gens == NULL) { free(ret); return NULL; diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index 74d9f3fd..7538558e 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -544,8 +544,8 @@ static void test_multiple_generators(void) { secp256k1_scalar_get_b32(generator_seed, &s); /* Create all the needed generators */ for (i = 0; i < n_generators; i++) { - generator_blind[i] = (unsigned char*) malloc(32); - pedersen_blind[i] = (unsigned char*) malloc(32); + generator_blind[i] = malloc(32); + pedersen_blind[i] = malloc(32); testutil_random_scalar_order(&s); secp256k1_scalar_get_b32(generator_blind[i], &s); diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index 1d35219a..2bd2c2cd 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -182,7 +182,7 @@ int secp256k1_surjectionproof_allocate_initialized(const secp256k1_context* ctx, ARG_CHECK(proof_out_p != NULL); *proof_out_p = 0; - proof = (secp256k1_surjectionproof*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_surjectionproof)); + proof = checked_malloc(&ctx->error_callback, sizeof(secp256k1_surjectionproof)); if (proof != NULL) { ret = secp256k1_surjectionproof_initialize(ctx, proof, input_index, fixed_input_tags, n_input_tags, n_input_tags_to_use, fixed_output_tag, n_max_iterations, random_seed32); if (ret) { diff --git a/src/modules/whitelist/tests_impl.h b/src/modules/whitelist/tests_impl.h index 9cbb8287..dad8a479 100644 --- a/src/modules/whitelist/tests_impl.h +++ b/src/modules/whitelist/tests_impl.h @@ -43,10 +43,10 @@ static void test_whitelist_end_to_end_internal(const unsigned char *summed_secke } static void test_whitelist_end_to_end(const size_t n_keys, int test_all_keys) { - unsigned char **online_seckey = (unsigned char **) malloc(n_keys * sizeof(*online_seckey)); - unsigned char **summed_seckey = (unsigned char **) malloc(n_keys * sizeof(*summed_seckey)); - secp256k1_pubkey *online_pubkeys = (secp256k1_pubkey *) malloc(n_keys * sizeof(*online_pubkeys)); - secp256k1_pubkey *offline_pubkeys = (secp256k1_pubkey *) malloc(n_keys * sizeof(*offline_pubkeys)); + unsigned char **online_seckey = malloc(n_keys * sizeof(*online_seckey)); + unsigned char **summed_seckey = malloc(n_keys * sizeof(*summed_seckey)); + secp256k1_pubkey *online_pubkeys = malloc(n_keys * sizeof(*online_pubkeys)); + secp256k1_pubkey *offline_pubkeys = malloc(n_keys * sizeof(*offline_pubkeys)); secp256k1_scalar ssub; unsigned char csub[32]; @@ -63,8 +63,8 @@ static void test_whitelist_end_to_end(const size_t n_keys, int test_all_keys) { for (i = 0; i < n_keys; i++) { secp256k1_scalar son, soff; - online_seckey[i] = (unsigned char *) malloc(32); - summed_seckey[i] = (unsigned char *) malloc(32); + online_seckey[i] = malloc(32); + summed_seckey[i] = malloc(32); /* Create two keys */ testutil_random_scalar_order_test(&son); From fdb6a91a5eb980eab3d3db7307b5aec9ee645370 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 17 Dec 2025 11:15:33 -0500 Subject: [PATCH 315/383] Introduce hash context to support pluggable SHA256 compression This is purely a mechanical change with no behavior change. It introduces a secp256k1_hash_ctx struct inside secp256k1_context and propagates it to all SHA256-related operations. This sets up the ability to provide a hardware-optimized SHA256 compression function at runtime in a follow-up commit. --- src/bench_ecmult.c | 8 +- src/bench_internal.c | 21 ++-- src/ecmult_gen.h | 5 +- src/ecmult_gen_impl.h | 12 +- src/hash.h | 22 ++-- src/hash_impl.h | 114 ++++++++++-------- src/modules/ecdh/main_impl.h | 12 +- src/modules/ecdh/tests_impl.h | 4 +- src/modules/ellswift/main_impl.h | 60 +++++---- src/modules/ellswift/tests_impl.h | 7 +- src/modules/musig/keyagg.h | 2 +- src/modules/musig/keyagg_impl.h | 18 +-- src/modules/musig/session_impl.h | 56 ++++----- src/modules/musig/tests_impl.h | 42 ++++--- src/modules/schnorrsig/main_impl.h | 34 +++--- .../schnorrsig/tests_exhaustive_impl.h | 4 +- src/modules/schnorrsig/tests_impl.h | 9 +- src/secp256k1.c | 27 +++-- src/selftest.h | 11 +- src/testrand_impl.h | 7 +- src/tests.c | 76 ++++++------ 21 files changed, 313 insertions(+), 238 deletions(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index bcf8b431..c7c6aded 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -259,7 +259,7 @@ static void bench_ecmult_multi_teardown(void* arg, int iters) { } } -static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) { +static void generate_scalar(const secp256k1_context *ctx, uint32_t num, secp256k1_scalar* scalar) { secp256k1_sha256 sha256; unsigned char c[10] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0}; unsigned char buf[32]; @@ -269,8 +269,8 @@ static void generate_scalar(uint32_t num, secp256k1_scalar* scalar) { c[8] = num >> 16; c[9] = num >> 24; secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, c, sizeof(c)); - secp256k1_sha256_finalize(&sha256, buf); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha256, c, sizeof(c)); + secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha256, buf); secp256k1_scalar_set_b32(scalar, buf, &overflow); CHECK(!overflow); } @@ -362,7 +362,7 @@ int main(int argc, char **argv) { secp256k1_gej_set_ge(&data.pubkeys_gej[0], &secp256k1_ge_const_g); secp256k1_scalar_set_int(&data.seckeys[0], 1); for (i = 0; i < POINTS; ++i) { - generate_scalar(i, &data.scalars[i]); + generate_scalar(data.ctx, i, &data.scalars[i]); if (i) { secp256k1_gej_double_var(&data.pubkeys_gej[i], &data.pubkeys_gej[i - 1], NULL); secp256k1_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); diff --git a/src/bench_internal.c b/src/bench_internal.c index 001bd25e..44f8d2cb 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -38,6 +38,7 @@ static void help(int default_iters) { } typedef struct { + const secp256k1_context* ctx; secp256k1_scalar scalar[2]; secp256k1_fe fe[4]; secp256k1_ge ge[2]; @@ -82,6 +83,9 @@ static void bench_setup(void* arg) { } }; + /* Customize context if needed */ + data->ctx = secp256k1_context_static; + secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL); secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL); secp256k1_fe_set_b32_limit(&data->fe[0], init[0]); @@ -344,11 +348,12 @@ static void bench_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_sha256 sha; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(data->ctx); for (i = 0; i < iters; i++) { secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data->data, 32); - secp256k1_sha256_finalize(&sha, data->data); + secp256k1_sha256_write(hash_ctx, &sha, data->data, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, data->data); } } @@ -356,11 +361,12 @@ static void bench_hmac_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_hmac_sha256 hmac; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(data->ctx); for (i = 0; i < iters; i++) { - secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); - secp256k1_hmac_sha256_write(&hmac, data->data, 32); - secp256k1_hmac_sha256_finalize(&hmac, data->data); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, data->data, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, data->data, 32); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, data->data); } } @@ -368,10 +374,11 @@ static void bench_rfc6979_hmac_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; secp256k1_rfc6979_hmac_sha256 rng; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(data->ctx); for (i = 0; i < iters; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, data->data, 64); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, data->data, 32); } } diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 43dd10c3..8bc4f14c 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -7,6 +7,7 @@ #ifndef SECP256K1_ECMULT_GEN_H #define SECP256K1_ECMULT_GEN_H +#include "hash.h" #include "scalar.h" #include "group.h" @@ -132,12 +133,12 @@ typedef struct { secp256k1_fe proj_blind; } secp256k1_ecmult_gen_context; -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx); +static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_hash_ctx *hash_ctx); static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); /** Multiply with the generator: R = a*G */ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); +static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32); #endif /* SECP256K1_ECMULT_GEN_H */ diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 2159eed5..5a954977 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -14,8 +14,8 @@ #include "hash_impl.h" #include "precomputed_ecmult_gen.h" -static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx) { - secp256k1_ecmult_gen_blind(ctx, NULL); +static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx) { + secp256k1_ecmult_gen_blind(ctx, hash_ctx, NULL); ctx->built = 1; } @@ -282,7 +282,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 } /* Setup blinding values for secp256k1_ecmult_gen. */ -static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { +static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32) { secp256k1_scalar b; secp256k1_scalar diff; secp256k1_gej gb; @@ -309,17 +309,17 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const */ VERIFY_CHECK(seed32 != NULL); memcpy(keydata + 32, seed32, 32); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, keydata, 64); secp256k1_memclear_explicit(keydata, sizeof(keydata)); /* Compute projective blinding factor (cannot be 0). */ - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32); secp256k1_fe_set_b32_mod(&f, nonce32); secp256k1_fe_cmov(&f, &secp256k1_fe_one, secp256k1_fe_normalizes_to_zero(&f)); ctx->proj_blind = f; /* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */ - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32); secp256k1_scalar_set_b32(&b, nonce32, NULL); /* The blinding value cannot be zero, as that would mean ge_offset = infinity, * which secp256k1_gej_add_ge cannot handle. */ diff --git a/src/hash.h b/src/hash.h index 43cdd60c..35825eae 100644 --- a/src/hash.h +++ b/src/hash.h @@ -10,6 +10,14 @@ #include #include +typedef void (*secp256k1_sha256_compression_function)(uint32_t *state, const unsigned char *blocks64, size_t n_blocks); + +typedef struct { + secp256k1_sha256_compression_function fn_sha256_compression; +} secp256k1_hash_ctx; + +static void secp256k1_hash_ctx_init(secp256k1_hash_ctx *hash_ctx); + typedef struct { uint32_t s[8]; unsigned char buf[64]; @@ -21,17 +29,17 @@ static void secp256k1_sha256_initialize(secp256k1_sha256 *hash); * The byte counter must be a multiple of 64, i.e., there must be no unwritten * bytes in the buffer. */ static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_t bytes, const uint32_t state[8]); -static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t size); -static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32); +static void secp256k1_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, const unsigned char *data, size_t size); +static void secp256k1_sha256_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, unsigned char *out32); static void secp256k1_sha256_clear(secp256k1_sha256 *hash); typedef struct { secp256k1_sha256 inner, outer; } secp256k1_hmac_sha256; -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32); +static void secp256k1_hmac_sha256_initialize(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size); +static void secp256k1_hmac_sha256_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, unsigned char *out32); static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash); typedef struct { @@ -40,8 +48,8 @@ typedef struct { int retry; } secp256k1_rfc6979_hmac_sha256; -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); +static void secp256k1_rfc6979_hmac_sha256_initialize(const secp256k1_hash_ctx *hash_ctx, secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); +static void secp256k1_rfc6979_hmac_sha256_generate(const secp256k1_hash_ctx *hash_ctx, secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng); static void secp256k1_rfc6979_hmac_sha256_clear(secp256k1_rfc6979_hmac_sha256 *rng); diff --git a/src/hash_impl.h b/src/hash_impl.h index da3b4660..d5f16cd1 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -48,7 +48,7 @@ static void secp256k1_sha256_initialize_midstate(secp256k1_sha256 *hash, uint64_ } /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) { +static void secp256k1_sha256_transform_impl(uint32_t* s, const unsigned char* buf) { uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; @@ -130,17 +130,31 @@ static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* buf) { s[7] += h; } -static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { +static void secp256k1_sha256_transform(uint32_t *state, const unsigned char *blocks64, size_t n_blocks) { + while (n_blocks--) { + secp256k1_sha256_transform_impl(state, blocks64); + blocks64 += 64; + } +} + +static void secp256k1_hash_ctx_init(secp256k1_hash_ctx *hash_ctx) { + VERIFY_CHECK(hash_ctx != NULL); + hash_ctx->fn_sha256_compression = secp256k1_sha256_transform; +} + +static void secp256k1_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; VERIFY_CHECK(hash->bytes >= len); + VERIFY_CHECK(hash_ctx != NULL); + VERIFY_CHECK(hash_ctx->fn_sha256_compression != NULL); while (len >= 64 - bufsize) { /* Fill the buffer, and process it. */ size_t chunk_len = 64 - bufsize; memcpy(hash->buf + bufsize, data, chunk_len); data += chunk_len; len -= chunk_len; - secp256k1_sha256_transform(hash->s, hash->buf); + hash_ctx->fn_sha256_compression(hash->s, hash->buf, 1); bufsize = 0; } if (len) { @@ -149,7 +163,7 @@ static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char * } } -static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { +static void secp256k1_sha256_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, unsigned char *out32) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; int i; @@ -157,8 +171,8 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out VERIFY_CHECK(hash->bytes < ((uint64_t)1 << 61)); secp256k1_write_be32(&sizedesc[0], hash->bytes >> 29); secp256k1_write_be32(&sizedesc[4], hash->bytes << 3); - secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); - secp256k1_sha256_write(hash, sizedesc, 8); + secp256k1_sha256_write(hash_ctx, hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); + secp256k1_sha256_write(hash_ctx, hash, sizedesc, 8); for (i = 0; i < 8; i++) { secp256k1_write_be32(&out32[4*i], hash->s[i]); hash->s[i] = 0; @@ -167,22 +181,22 @@ static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out /* Initializes a sha256 struct and writes the 64 byte string * SHA256(tag)||SHA256(tag) into it. */ -static void secp256k1_sha256_initialize_tagged(secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) { +static void secp256k1_sha256_initialize_tagged(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, const unsigned char *tag, size_t taglen) { unsigned char buf[32]; secp256k1_sha256_initialize(hash); - secp256k1_sha256_write(hash, tag, taglen); - secp256k1_sha256_finalize(hash, buf); + secp256k1_sha256_write(hash_ctx, hash, tag, taglen); + secp256k1_sha256_finalize(hash_ctx, hash, buf); secp256k1_sha256_initialize(hash); - secp256k1_sha256_write(hash, buf, 32); - secp256k1_sha256_write(hash, buf, 32); + secp256k1_sha256_write(hash_ctx, hash, buf, 32); + secp256k1_sha256_write(hash_ctx, hash, buf, 32); } static void secp256k1_sha256_clear(secp256k1_sha256 *hash) { secp256k1_memclear_explicit(hash, sizeof(*hash)); } -static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { +static void secp256k1_hmac_sha256_initialize(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { size_t n; unsigned char rkey[64]; if (keylen <= sizeof(rkey)) { @@ -191,8 +205,8 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const } else { secp256k1_sha256 sha256; secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, key, keylen); - secp256k1_sha256_finalize(&sha256, rkey); + secp256k1_sha256_write(hash_ctx, &sha256, key, keylen); + secp256k1_sha256_finalize(hash_ctx, &sha256, rkey); memset(rkey + 32, 0, 32); } @@ -200,33 +214,33 @@ static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c; } - secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); + secp256k1_sha256_write(hash_ctx, &hash->outer, rkey, sizeof(rkey)); secp256k1_sha256_initialize(&hash->inner); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c ^ 0x36; } - secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); + secp256k1_sha256_write(hash_ctx, &hash->inner, rkey, sizeof(rkey)); secp256k1_memclear_explicit(rkey, sizeof(rkey)); } -static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { - secp256k1_sha256_write(&hash->inner, data, size); +static void secp256k1_hmac_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { + secp256k1_sha256_write(hash_ctx, &hash->inner, data, size); } -static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { +static void secp256k1_hmac_sha256_finalize(const secp256k1_hash_ctx *hash_ctx, secp256k1_hmac_sha256 *hash, unsigned char *out32) { unsigned char temp[32]; - secp256k1_sha256_finalize(&hash->inner, temp); - secp256k1_sha256_write(&hash->outer, temp, 32); + secp256k1_sha256_finalize(hash_ctx, &hash->inner, temp); + secp256k1_sha256_write(hash_ctx, &hash->outer, temp, 32); secp256k1_memclear_explicit(temp, sizeof(temp)); - secp256k1_sha256_finalize(&hash->outer, out32); + secp256k1_sha256_finalize(hash_ctx, &hash->outer, out32); } static void secp256k1_hmac_sha256_clear(secp256k1_hmac_sha256 *hash) { secp256k1_memclear_explicit(hash, sizeof(*hash)); } -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { +static void secp256k1_rfc6979_hmac_sha256_initialize(const secp256k1_hash_ctx *hash_ctx, secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { secp256k1_hmac_sha256 hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -235,47 +249,47 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ /* RFC6979 3.2.d. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, zero, 1); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, key, keylen); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->k); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->v); /* RFC6979 3.2.f. */ - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, one, 1); - secp256k1_hmac_sha256_write(&hmac, key, keylen); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, one, 1); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, key, keylen); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->k); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->v); rng->retry = 0; } -static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { +static void secp256k1_rfc6979_hmac_sha256_generate(const secp256k1_hash_ctx *hash_ctx, secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { /* RFC6979 3.2.h. */ static const unsigned char zero[1] = {0x00}; if (rng->retry) { secp256k1_hmac_sha256 hmac; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_write(&hmac, zero, 1); - secp256k1_hmac_sha256_finalize(&hmac, rng->k); - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, zero, 1); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->k); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->v); } while (outlen > 0) { secp256k1_hmac_sha256 hmac; size_t now = outlen; - secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); - secp256k1_hmac_sha256_write(&hmac, rng->v, 32); - secp256k1_hmac_sha256_finalize(&hmac, rng->v); + secp256k1_hmac_sha256_initialize(hash_ctx, &hmac, rng->k, 32); + secp256k1_hmac_sha256_write(hash_ctx, &hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(hash_ctx, &hmac, rng->v); if (now > 32) { now = 32; } diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 9f2dfdd5..3ee3ca7b 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -10,20 +10,24 @@ #include "../../../include/secp256k1_ecdh.h" #include "../../ecmult_const_impl.h" -static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { +static int ecdh_hash_function_sha256_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { unsigned char version = (y32[31] & 0x01) | 0x02; secp256k1_sha256 sha; (void)data; secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, &version, 1); - secp256k1_sha256_write(&sha, x32, 32); - secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_write(hash_ctx, &sha, &version, 1); + secp256k1_sha256_write(hash_ctx, &sha, x32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, output); secp256k1_sha256_clear(&sha); return 1; } +static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { + return ecdh_hash_function_sha256_impl(secp256k1_get_hash_context(secp256k1_context_static), output, x32, y32, data); +} + const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default = ecdh_hash_function_sha256; diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index cb1d953d..e6c1bab9 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -83,8 +83,8 @@ static void test_ecdh_generator_basepoint(void) { /* compute "explicitly" */ CHECK(secp256k1_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, point_ser, point_ser_len); - secp256k1_sha256_finalize(&sha, output_ser); + secp256k1_sha256_write(secp256k1_get_hash_context(CTX), &sha, point_ser, point_ser_len); + secp256k1_sha256_finalize(secp256k1_get_hash_context(CTX), &sha, output_ser); /* compare */ CHECK(secp256k1_memcmp_var(output_ecdh, output_ser, 32) == 0); } diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index f9ef0ac8..29c0a536 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -307,7 +307,7 @@ static int secp256k1_ellswift_xswiftec_inv_var(secp256k1_fe *t, const secp256k1_ * hasher is a SHA256 object to which an incrementing 4-byte counter is written to generate randomness. * Writing 13 bytes (4 bytes for counter, plus 9 bytes for the SHA256 padding) cannot cross a * 64-byte block size boundary (to make sure it only triggers a single SHA256 compression). */ -static void secp256k1_ellswift_prng(unsigned char* out32, const secp256k1_sha256 *hasher, uint32_t cnt) { +static void secp256k1_ellswift_prng(const secp256k1_hash_ctx *hash_ctx, unsigned char* out32, const secp256k1_sha256 *hasher, uint32_t cnt) { secp256k1_sha256 hash = *hasher; unsigned char buf4[4]; #ifdef VERIFY @@ -317,8 +317,8 @@ static void secp256k1_ellswift_prng(unsigned char* out32, const secp256k1_sha256 buf4[1] = cnt >> 8; buf4[2] = cnt >> 16; buf4[3] = cnt >> 24; - secp256k1_sha256_write(&hash, buf4, 4); - secp256k1_sha256_finalize(&hash, out32); + secp256k1_sha256_write(hash_ctx, &hash, buf4, 4); + secp256k1_sha256_finalize(hash_ctx, &hash, out32); /* Writing and finalizing together should trigger exactly one SHA256 compression. */ VERIFY_CHECK(((hash.bytes) >> 6) == (blocks + 1)); @@ -330,7 +330,7 @@ static void secp256k1_ellswift_prng(unsigned char* out32, const secp256k1_sha256 * needs encoding. * * hasher is a hasher in the secp256k1_ellswift_prng sense, with the same restrictions. */ -static void secp256k1_ellswift_xelligatorswift_var(unsigned char *u32, secp256k1_fe *t, const secp256k1_fe *x, const secp256k1_sha256 *hasher) { +static void secp256k1_ellswift_xelligatorswift_var(const secp256k1_context *ctx, unsigned char *u32, secp256k1_fe *t, const secp256k1_fe *x, const secp256k1_sha256 *hasher) { /* Pool of 3-bit branch values. */ unsigned char branch_hash[32]; /* Number of 3-bit values in branch_hash left. */ @@ -346,14 +346,14 @@ static void secp256k1_ellswift_xelligatorswift_var(unsigned char *u32, secp256k1 secp256k1_fe u; /* If the pool of branch values is empty, populate it. */ if (branches_left == 0) { - secp256k1_ellswift_prng(branch_hash, hasher, cnt++); + secp256k1_ellswift_prng(secp256k1_get_hash_context(ctx), branch_hash, hasher, cnt++); branches_left = 64; } /* Take a 3-bit branch value from the branch pool (top bit is discarded). */ --branches_left; branch = (branch_hash[branches_left >> 1] >> ((branches_left & 1) << 2)) & 7; /* Compute a new u value by hashing. */ - secp256k1_ellswift_prng(u32, hasher, cnt++); + secp256k1_ellswift_prng(secp256k1_get_hash_context(ctx), u32, hasher, cnt++); /* overflow is not a problem (we prefer uniform u32 over uniform u). */ secp256k1_fe_set_b32_mod(&u, u32); /* Since u is the output of a hash, it should practically never be 0. We could apply the @@ -372,8 +372,8 @@ static void secp256k1_ellswift_xelligatorswift_var(unsigned char *u32, secp256k1 * as input, and returns an encoding that matches the provided Y coordinate rather than a random * one. */ -static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_fe *t, const secp256k1_ge *p, const secp256k1_sha256 *hasher) { - secp256k1_ellswift_xelligatorswift_var(u32, t, &p->x, hasher); +static void secp256k1_ellswift_elligatorswift_var(const secp256k1_context *ctx, unsigned char *u32, secp256k1_fe *t, const secp256k1_ge *p, const secp256k1_sha256 *hasher) { + secp256k1_ellswift_xelligatorswift_var(ctx, u32, t, &p->x, hasher); secp256k1_fe_normalize_var(t); if (secp256k1_fe_is_odd(t) != secp256k1_fe_is_odd(&p->y)) { secp256k1_fe_negate(t, t, 1); @@ -406,11 +406,11 @@ int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64 * BIP340 tagged hash with tag "secp256k1_ellswift_encode". */ secp256k1_ellswift_sha256_init_encode(&hash); secp256k1_eckey_pubkey_serialize33(&p, p64); - secp256k1_sha256_write(&hash, p64, sizeof(p64)); - secp256k1_sha256_write(&hash, rnd32, 32); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, p64, sizeof(p64)); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, rnd32, 32); /* Compute ElligatorSwift encoding and construct output. */ - secp256k1_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ + secp256k1_ellswift_elligatorswift_var(ctx, ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ secp256k1_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ return 1; } @@ -452,13 +452,13 @@ int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64 /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++), * using BIP340 tagged hash with tag "secp256k1_ellswift_create". */ secp256k1_ellswift_sha256_init_create(&hash); - secp256k1_sha256_write(&hash, seckey32, 32); - secp256k1_sha256_write(&hash, zero32, sizeof(zero32)); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, seckey32, 32); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, zero32, sizeof(zero32)); secp256k1_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */ - if (auxrnd32) secp256k1_sha256_write(&hash, auxrnd32, 32); + if (auxrnd32) secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &hash, auxrnd32, 32); /* Compute ElligatorSwift encoding and construct output. */ - secp256k1_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ + secp256k1_ellswift_elligatorswift_var(ctx, ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ secp256k1_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ secp256k1_memczero(ell64, 64, !ret); @@ -482,20 +482,24 @@ int secp256k1_ellswift_decode(const secp256k1_context *ctx, secp256k1_pubkey *pu return 1; } -static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { +static int ellswift_xdh_hash_function_prefix_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { secp256k1_sha256 sha; secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, data, 64); - secp256k1_sha256_write(&sha, ell_a64, 64); - secp256k1_sha256_write(&sha, ell_b64, 64); - secp256k1_sha256_write(&sha, x32, 32); - secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_write(hash_ctx, &sha, data, 64); + secp256k1_sha256_write(hash_ctx, &sha, ell_a64, 64); + secp256k1_sha256_write(hash_ctx, &sha, ell_b64, 64); + secp256k1_sha256_write(hash_ctx, &sha, x32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, output); secp256k1_sha256_clear(&sha); return 1; } +static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { + return ellswift_xdh_hash_function_prefix_impl(secp256k1_get_hash_context(secp256k1_context_static), output, x32, ell_a64, ell_b64, data); +} + /** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { static const uint32_t midstate[8] = { @@ -505,21 +509,25 @@ static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) { secp256k1_sha256_initialize_midstate(hash, 64, midstate); } -static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { +static int ellswift_xdh_hash_function_bip324_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { secp256k1_sha256 sha; (void)data; secp256k1_ellswift_sha256_init_bip324(&sha); - secp256k1_sha256_write(&sha, ell_a64, 64); - secp256k1_sha256_write(&sha, ell_b64, 64); - secp256k1_sha256_write(&sha, x32, 32); - secp256k1_sha256_finalize(&sha, output); + secp256k1_sha256_write(hash_ctx, &sha, ell_a64, 64); + secp256k1_sha256_write(hash_ctx, &sha, ell_b64, 64); + secp256k1_sha256_write(hash_ctx, &sha, x32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, output); secp256k1_sha256_clear(&sha); return 1; } +static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) { + return ellswift_xdh_hash_function_bip324_impl(secp256k1_get_hash_context(secp256k1_context_static), output, x32, ell_a64, ell_b64, data); +} + const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix; const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324; diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index e3090411..c9a7500f 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -434,6 +434,7 @@ void ellswift_xdh_correctness_tests(void) { /* Test hash initializers */ void ellswift_hash_init_tests(void) { secp256k1_sha256 sha_optimized; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); /* "secp256k1_ellswift_encode" */ static const unsigned char encode_tag[] = {'s', 'e', 'c', 'p', '2', '5', '6', 'k', '1', '_', 'e', 'l', 'l', 's', 'w', 'i', 'f', 't', '_', 'e', 'n', 'c', 'o', 'd', 'e'}; /* "secp256k1_ellswift_create" */ @@ -445,19 +446,19 @@ void ellswift_hash_init_tests(void) { * secp256k1_ellswift_sha256_init_encode has the expected * state. */ secp256k1_ellswift_sha256_init_encode(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, encode_tag, sizeof(encode_tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, encode_tag, sizeof(encode_tag)); /* Check that hash initialized by * secp256k1_ellswift_sha256_init_create has the expected * state. */ secp256k1_ellswift_sha256_init_create(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, create_tag, sizeof(create_tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, create_tag, sizeof(create_tag)); /* Check that hash initialized by * secp256k1_ellswift_sha256_init_bip324 has the expected * state. */ secp256k1_ellswift_sha256_init_bip324(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, bip324_tag, sizeof(bip324_tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, bip324_tag, sizeof(bip324_tag)); } void ellswift_xdh_bad_scalar_tests(void) { diff --git a/src/modules/musig/keyagg.h b/src/modules/musig/keyagg.h index a0b37252..30e77aa9 100644 --- a/src/modules/musig/keyagg.h +++ b/src/modules/musig/keyagg.h @@ -27,6 +27,6 @@ typedef struct { static int secp256k1_keyagg_cache_load(const secp256k1_context* ctx, secp256k1_keyagg_cache_internal *cache_i, const secp256k1_musig_keyagg_cache *cache); -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); +static void secp256k1_musig_keyaggcoef(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk); #endif diff --git a/src/modules/musig/keyagg_impl.h b/src/modules/musig/keyagg_impl.h index 4eb48ddc..f67245d5 100644 --- a/src/modules/musig/keyagg_impl.h +++ b/src/modules/musig/keyagg_impl.h @@ -82,9 +82,9 @@ static int secp256k1_musig_compute_pks_hash(const secp256k1_context *ctx, unsign return 0; } VERIFY_CHECK(ser_len == sizeof(ser)); - secp256k1_sha256_write(&sha, ser, sizeof(ser)); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha, ser, sizeof(ser)); } - secp256k1_sha256_finalize(&sha, pks_hash); + secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha, pks_hash); return 1; } @@ -103,7 +103,7 @@ static void secp256k1_musig_keyaggcoef_sha256(secp256k1_sha256 *sha) { * second_pk is the point at infinity in case there is no second_pk. Assumes * that pk is not the point at infinity and that the Y-coordinates of pk and * second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { +static void secp256k1_musig_keyaggcoef_internal(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *r, const unsigned char *pks_hash, secp256k1_ge *pk, const secp256k1_ge *second_pk) { VERIFY_CHECK(!secp256k1_ge_is_infinity(pk)); if (!secp256k1_ge_is_infinity(second_pk) @@ -113,20 +113,20 @@ static void secp256k1_musig_keyaggcoef_internal(secp256k1_scalar *r, const unsig secp256k1_sha256 sha; unsigned char buf[33]; secp256k1_musig_keyaggcoef_sha256(&sha); - secp256k1_sha256_write(&sha, pks_hash, 32); + secp256k1_sha256_write(hash_ctx, &sha, pks_hash, 32); /* Serialization does not fail since the pk is not the point at infinity * (according to this function's precondition). */ secp256k1_eckey_pubkey_serialize33(pk, buf); - secp256k1_sha256_write(&sha, buf, sizeof(buf)); - secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_write(hash_ctx, &sha, buf, sizeof(buf)); + secp256k1_sha256_finalize(hash_ctx, &sha, buf); secp256k1_scalar_set_b32(r, buf, NULL); } } /* Assumes that pk is not the point at infinity and that the Y-coordinates of pk * and cache_i->second_pk are normalized. */ -static void secp256k1_musig_keyaggcoef(secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { - secp256k1_musig_keyaggcoef_internal(r, cache_i->pks_hash, pk, &cache_i->second_pk); +static void secp256k1_musig_keyaggcoef(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *r, const secp256k1_keyagg_cache_internal *cache_i, secp256k1_ge *pk) { + secp256k1_musig_keyaggcoef_internal(hash_ctx, r, cache_i->pks_hash, pk, &cache_i->second_pk); } typedef struct { @@ -149,7 +149,7 @@ static int secp256k1_musig_pubkey_agg_callback(secp256k1_scalar *sc, secp256k1_g #else (void) ret; #endif - secp256k1_musig_keyaggcoef_internal(sc, ctx->pks_hash, pt, &ctx->second_pk); + secp256k1_musig_keyaggcoef_internal(secp256k1_get_hash_context(ctx->ctx), sc, ctx->pks_hash, pt, &ctx->second_pk); return 1; } diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 42fcd81e..6a37bfdf 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -289,20 +289,20 @@ int secp256k1_musig_partial_sig_serialize(const secp256k1_context* ctx, unsigned } /* Write optional inputs into the hash */ -static void secp256k1_nonce_function_musig_helper(secp256k1_sha256 *sha, unsigned int prefix_size, const unsigned char *data, unsigned char len) { +static void secp256k1_nonce_function_musig_helper(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *sha, unsigned int prefix_size, const unsigned char *data, unsigned char len) { unsigned char zero[7] = { 0 }; /* The spec requires length prefixes to be between 1 and 8 bytes * (inclusive) */ VERIFY_CHECK(prefix_size >= 1 && prefix_size <= 8); /* Since the length of all input data fits in a byte, we can always pad the * length prefix with prefix_size - 1 zero bytes. */ - secp256k1_sha256_write(sha, zero, prefix_size - 1); + secp256k1_sha256_write(hash_ctx, sha, zero, prefix_size - 1); if (data != NULL) { - secp256k1_sha256_write(sha, &len, 1); - secp256k1_sha256_write(sha, data, len); + secp256k1_sha256_write(hash_ctx, sha, &len, 1); + secp256k1_sha256_write(hash_ctx, sha, data, len); } else { len = 0; - secp256k1_sha256_write(sha, &len, 1); + secp256k1_sha256_write(hash_ctx, sha, &len, 1); } } @@ -326,7 +326,7 @@ static void secp256k1_nonce_function_musig_sha256_tagged(secp256k1_sha256 *sha) secp256k1_sha256_initialize_midstate(sha, 64, midstate); } -static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { +static void secp256k1_nonce_function_musig(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *k, const unsigned char *session_secrand, const unsigned char *msg32, const unsigned char *seckey32, const unsigned char *pk33, const unsigned char *agg_pk32, const unsigned char *extra_input32) { secp256k1_sha256 sha; unsigned char rand[32]; unsigned char i; @@ -334,8 +334,8 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c if (seckey32 != NULL) { secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); - secp256k1_sha256_write(&sha, session_secrand, 32); - secp256k1_sha256_finalize(&sha, rand); + secp256k1_sha256_write(hash_ctx, &sha, session_secrand, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, rand); for (i = 0; i < 32; i++) { rand[i] ^= seckey32[i]; } @@ -344,21 +344,21 @@ static void secp256k1_nonce_function_musig(secp256k1_scalar *k, const unsigned c } secp256k1_nonce_function_musig_sha256_tagged(&sha); - secp256k1_sha256_write(&sha, rand, sizeof(rand)); - secp256k1_nonce_function_musig_helper(&sha, 1, pk33, 33); - secp256k1_nonce_function_musig_helper(&sha, 1, agg_pk32, 32); + secp256k1_sha256_write(hash_ctx, &sha, rand, sizeof(rand)); + secp256k1_nonce_function_musig_helper(hash_ctx, &sha, 1, pk33, 33); + secp256k1_nonce_function_musig_helper(hash_ctx, &sha, 1, agg_pk32, 32); msg_present = msg32 != NULL; - secp256k1_sha256_write(&sha, &msg_present, 1); + secp256k1_sha256_write(hash_ctx, &sha, &msg_present, 1); if (msg_present) { - secp256k1_nonce_function_musig_helper(&sha, 8, msg32, 32); + secp256k1_nonce_function_musig_helper(hash_ctx, &sha, 8, msg32, 32); } - secp256k1_nonce_function_musig_helper(&sha, 4, extra_input32, 32); + secp256k1_nonce_function_musig_helper(hash_ctx, &sha, 4, extra_input32, 32); for (i = 0; i < 2; i++) { unsigned char buf[32]; secp256k1_sha256 sha_tmp = sha; - secp256k1_sha256_write(&sha_tmp, &i, 1); - secp256k1_sha256_finalize(&sha_tmp, buf); + secp256k1_sha256_write(hash_ctx, &sha_tmp, &i, 1); + secp256k1_sha256_finalize(hash_ctx, &sha_tmp, buf); secp256k1_scalar_set_b32(&k[i], buf, NULL); /* Attempt to erase secret data */ @@ -407,7 +407,7 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp /* A pubkey cannot be the point at infinity */ secp256k1_eckey_pubkey_serialize33(&pk, pk_ser); - secp256k1_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); + secp256k1_nonce_function_musig(secp256k1_get_hash_context(ctx), k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[0])); VERIFY_CHECK(!secp256k1_scalar_is_zero(&k[1])); secp256k1_musig_secnonce_save(secnonce, k, &pk); @@ -541,7 +541,7 @@ static void secp256k1_musig_compute_noncehash_sha256_tagged(secp256k1_sha256 *sh } /* tagged_hash(aggnonce[0], aggnonce[1], agg_pk, msg) */ -static void secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { +static void secp256k1_musig_compute_noncehash(const secp256k1_hash_ctx *hash_ctx, unsigned char *noncehash, secp256k1_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { unsigned char buf[33]; secp256k1_sha256 sha; int i; @@ -549,11 +549,11 @@ static void secp256k1_musig_compute_noncehash(unsigned char *noncehash, secp256k secp256k1_musig_compute_noncehash_sha256_tagged(&sha); for (i = 0; i < 2; i++) { secp256k1_musig_ge_serialize_ext(buf, &aggnonce[i]); - secp256k1_sha256_write(&sha, buf, sizeof(buf)); + secp256k1_sha256_write(hash_ctx, &sha, buf, sizeof(buf)); } - secp256k1_sha256_write(&sha, agg_pk32, 32); - secp256k1_sha256_write(&sha, msg, 32); - secp256k1_sha256_finalize(&sha, noncehash); + secp256k1_sha256_write(hash_ctx, &sha, agg_pk32, 32); + secp256k1_sha256_write(hash_ctx, &sha, msg, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, noncehash); } /* out_nonce = nonce_pts[0] + b*nonce_pts[1] */ @@ -565,12 +565,12 @@ static void secp256k1_effective_nonce(secp256k1_gej *out_nonce, const secp256k1_ secp256k1_gej_add_ge_var(out_nonce, out_nonce, &nonce_pts[0], NULL); } -static void secp256k1_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { +static void secp256k1_musig_nonce_process_internal(const secp256k1_context *ctx, int *fin_nonce_parity, unsigned char *fin_nonce, secp256k1_scalar *b, secp256k1_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { unsigned char noncehash[32]; secp256k1_ge fin_nonce_pt; secp256k1_gej fin_nonce_ptj; - secp256k1_musig_compute_noncehash(noncehash, aggnonce_pts, agg_pk32, msg); + secp256k1_musig_compute_noncehash(secp256k1_get_hash_context(ctx), noncehash, aggnonce_pts, agg_pk32, msg); secp256k1_scalar_set_b32(b, noncehash, NULL); /* fin_nonce = aggnonce_pts[0] + b*aggnonce_pts[1] */ secp256k1_effective_nonce(&fin_nonce_ptj, aggnonce_pts, b); @@ -607,8 +607,8 @@ int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_ return 0; } - secp256k1_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); - secp256k1_schnorrsig_challenge(&session_i.challenge, fin_nonce, msg32, 32, agg_pk32); + secp256k1_musig_nonce_process_internal(ctx, &session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); + secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &session_i.challenge, fin_nonce, msg32, 32, agg_pk32); /* If there is a tweak then set `challenge` times `tweak` to the `s`-part.*/ secp256k1_scalar_set_int(&session_i.s_part, 0); @@ -678,7 +678,7 @@ int secp256k1_musig_partial_sign(const secp256k1_context* ctx, secp256k1_musig_p } /* Multiply KeyAgg coefficient */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pk); + secp256k1_musig_keyaggcoef(secp256k1_get_hash_context(ctx), &mu, &cache_i, &pk); secp256k1_scalar_mul(&sk, &sk, &mu); if (!secp256k1_musig_session_load(ctx, &session_i, session)) { @@ -738,7 +738,7 @@ int secp256k1_musig_partial_sig_verify(const secp256k1_context* ctx, const secp2 /* Multiplying the challenge by the KeyAgg coefficient is equivalent * to multiplying the signer's public key by the coefficient, except * much easier to do. */ - secp256k1_musig_keyaggcoef(&mu, &cache_i, &pkp); + secp256k1_musig_keyaggcoef(secp256k1_get_hash_context(ctx), &mu, &cache_i, &pkp); secp256k1_scalar_mul(&e, &session_i.challenge, &mu); /* Negate e if secp256k1_fe_is_odd(&cache_i.pk.y)) XOR cache_i.parity_acc. diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index de09c5e2..cbeb1e28 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -505,12 +505,12 @@ static void musig_api_tests(void) { CHECK(secp256k1_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); } -static void musig_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { +static void musig_nonce_bitflip(const secp256k1_hash_ctx *hash_ctx, unsigned char **args, size_t n_flip, size_t n_bytes) { secp256k1_scalar k1[2], k2[2]; - secp256k1_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(hash_ctx, k1, args[0], args[1], args[2], args[3], args[4], args[5]); testrand_flip(args[n_flip], n_bytes); - secp256k1_nonce_function_musig(k2, args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(hash_ctx, k2, args[0], args[1], args[2], args[3], args[4], args[5]); CHECK(secp256k1_scalar_eq(&k1[0], &k2[0]) == 0); CHECK(secp256k1_scalar_eq(&k1[1], &k2[1]) == 0); } @@ -526,6 +526,7 @@ static void musig_nonce_test(void) { int i, j; secp256k1_scalar k[6][2]; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); testrand_bytes_test(session_secrand, sizeof(session_secrand)); testrand_bytes_test(sk, sizeof(sk)); testrand_bytes_test(pk, sizeof(pk)); @@ -541,12 +542,12 @@ static void musig_nonce_test(void) { args[4] = agg_pk; args[5] = extra_input; for (i = 0; i < COUNT; i++) { - musig_nonce_bitflip(args, 0, sizeof(session_secrand)); - musig_nonce_bitflip(args, 1, sizeof(msg)); - musig_nonce_bitflip(args, 2, sizeof(sk)); - musig_nonce_bitflip(args, 3, sizeof(pk)); - musig_nonce_bitflip(args, 4, sizeof(agg_pk)); - musig_nonce_bitflip(args, 5, sizeof(extra_input)); + musig_nonce_bitflip(hash_ctx, args, 0, sizeof(session_secrand)); + musig_nonce_bitflip(hash_ctx, args, 1, sizeof(msg)); + musig_nonce_bitflip(hash_ctx, args, 2, sizeof(sk)); + musig_nonce_bitflip(hash_ctx, args, 3, sizeof(pk)); + musig_nonce_bitflip(hash_ctx, args, 4, sizeof(agg_pk)); + musig_nonce_bitflip(hash_ctx, args, 5, sizeof(extra_input)); } /* Check that if any argument is NULL, a different nonce is produced than if * any other argument is NULL. */ @@ -555,12 +556,12 @@ static void musig_nonce_test(void) { memcpy(pk, session_secrand, sizeof(session_secrand)); memcpy(agg_pk, session_secrand, sizeof(agg_pk)); memcpy(extra_input, session_secrand, sizeof(extra_input)); - secp256k1_nonce_function_musig(k[0], args[0], args[1], args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[1], args[0], NULL, args[2], args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[2], args[0], args[1], NULL, args[3], args[4], args[5]); - secp256k1_nonce_function_musig(k[3], args[0], args[1], args[2], NULL, args[4], args[5]); - secp256k1_nonce_function_musig(k[4], args[0], args[1], args[2], args[3], NULL, args[5]); - secp256k1_nonce_function_musig(k[5], args[0], args[1], args[2], args[3], args[4], NULL); + secp256k1_nonce_function_musig(hash_ctx, k[0], args[0], args[1], args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(hash_ctx, k[1], args[0], NULL, args[2], args[3], args[4], args[5]); + secp256k1_nonce_function_musig(hash_ctx, k[2], args[0], args[1], NULL, args[3], args[4], args[5]); + secp256k1_nonce_function_musig(hash_ctx, k[3], args[0], args[1], args[2], NULL, args[4], args[5]); + secp256k1_nonce_function_musig(hash_ctx, k[4], args[0], args[1], args[2], args[3], NULL, args[5]); + secp256k1_nonce_function_musig(hash_ctx, k[5], args[0], args[1], args[2], args[3], args[4], NULL); for (i = 0; i < 6; i++) { CHECK(!secp256k1_scalar_eq(&k[i][0], &k[i][1])); for (j = i+1; j < 6; j++) { @@ -574,35 +575,36 @@ static void musig_nonce_test(void) { * state. */ static void sha256_tag_test(void) { secp256k1_sha256 sha; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); { /* "KeyAgg list" */ static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'l', 'i', 's', 't'}; secp256k1_musig_keyagglist_sha256(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha, tag, sizeof(tag)); } { /* "KeyAgg coefficient" */ static const unsigned char tag[] = {'K', 'e', 'y', 'A', 'g', 'g', ' ', 'c', 'o', 'e', 'f', 'f', 'i', 'c', 'i', 'e', 'n', 't'}; secp256k1_musig_keyaggcoef_sha256(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha, tag, sizeof(tag)); } { /* "MuSig/aux" */ static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'a', 'u', 'x' }; secp256k1_nonce_function_musig_sha256_tagged_aux(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha, tag, sizeof(tag)); } { /* "MuSig/nonce" */ static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'n', 'o', 'n', 'c', 'e' }; secp256k1_nonce_function_musig_sha256_tagged(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha, tag, sizeof(tag)); } { /* "MuSig/noncecoef" */ static const unsigned char tag[] = { 'M', 'u', 'S', 'i', 'g', '/', 'n', 'o', 'n', 'c', 'e', 'c', 'o', 'e', 'f' }; secp256k1_musig_compute_noncehash_sha256_tagged(&sha); - test_sha256_tag_midstate(&sha, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha, tag, sizeof(tag)); } } diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 21c1f412..3fe645b4 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -37,7 +37,7 @@ static const unsigned char bip340_algo[] = {'B', 'I', 'P', '0', '3', '4', '0', ' static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC; -static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { +static int nonce_function_bip340_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { secp256k1_sha256 sha; unsigned char masked_key[32]; int i; @@ -48,8 +48,8 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms if (data != NULL) { secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha); - secp256k1_sha256_write(&sha, data, 32); - secp256k1_sha256_finalize(&sha, masked_key); + secp256k1_sha256_write(hash_ctx, &sha, data, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, masked_key); for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; } @@ -73,20 +73,24 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms && secp256k1_memcmp_var(algo, bip340_algo, algolen) == 0) { secp256k1_nonce_function_bip340_sha256_tagged(&sha); } else { - secp256k1_sha256_initialize_tagged(&sha, algo, algolen); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, algo, algolen); } /* Hash masked-key||pk||msg using the tagged hash as per the spec */ - secp256k1_sha256_write(&sha, masked_key, 32); - secp256k1_sha256_write(&sha, xonly_pk32, 32); - secp256k1_sha256_write(&sha, msg, msglen); - secp256k1_sha256_finalize(&sha, nonce32); + secp256k1_sha256_write(hash_ctx, &sha, masked_key, 32); + secp256k1_sha256_write(hash_ctx, &sha, xonly_pk32, 32); + secp256k1_sha256_write(hash_ctx, &sha, msg, msglen); + secp256k1_sha256_finalize(hash_ctx, &sha, nonce32); secp256k1_sha256_clear(&sha); secp256k1_memclear_explicit(masked_key, sizeof(masked_key)); return 1; } +static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) { + return nonce_function_bip340_impl(secp256k1_get_hash_context(secp256k1_context_static), nonce32, msg, msglen, key32, xonly_pk32, algo, algolen, data); +} + const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340; /* Initializes SHA256 with fixed midstate. This midstate was computed by applying @@ -99,17 +103,17 @@ static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { secp256k1_sha256_initialize_midstate(sha, 64, midstate); } -static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) +static void secp256k1_schnorrsig_challenge(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) { unsigned char buf[32]; secp256k1_sha256 sha; /* tagged hash(r.x, pk.x, msg) */ secp256k1_schnorrsig_sha256_tagged(&sha); - secp256k1_sha256_write(&sha, r32, 32); - secp256k1_sha256_write(&sha, pubkey32, 32); - secp256k1_sha256_write(&sha, msg, msglen); - secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_write(hash_ctx, &sha, r32, 32); + secp256k1_sha256_write(hash_ctx, &sha, pubkey32, 32); + secp256k1_sha256_write(hash_ctx, &sha, msg, msglen); + secp256k1_sha256_finalize(hash_ctx, &sha, buf); /* Set scalar e to the challenge hash modulo the curve order as per * BIP340. */ secp256k1_scalar_set_b32(e, buf, NULL); @@ -165,7 +169,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_fe_normalize_var(&r.x); secp256k1_fe_get_b32(&sig64[0], &r.x); - secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf); + secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, &sig64[0], msg, msglen, pk_buf); secp256k1_scalar_mul(&e, &e, &sk); secp256k1_scalar_add(&e, &e, &k); secp256k1_scalar_get_b32(&sig64[32], &e); @@ -235,7 +239,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha /* Compute e. */ secp256k1_fe_get_b32(buf, &pk.x); - secp256k1_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf); + secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, &sig64[0], msg, msglen, buf); /* Compute rj = s*G + (-e)*pkj */ secp256k1_scalar_negate(&e, &e); diff --git a/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/modules/schnorrsig/tests_exhaustive_impl.h index 601b5497..a8298f65 100644 --- a/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -105,7 +105,7 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons secp256k1_scalar e; unsigned char msg32[32]; testrand256(msg32); - secp256k1_schnorrsig_challenge(&e, sig64, msg32, sizeof(msg32), pk32); + secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, sig64, msg32, sizeof(msg32), pk32); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { /* Iterate over the possible valid last 32 bytes in the signature. @@ -162,7 +162,7 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; testrand256(msg32); - secp256k1_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); + secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 9a1b15f0..009bb3e1 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -38,18 +38,20 @@ static void run_nonce_function_bip340_tests(void) { unsigned char *args[5]; int i; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); + /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged has the expected * state. */ secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, tag, sizeof(tag)); /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected * state. */ secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, aux_tag, sizeof(aux_tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, aux_tag, sizeof(aux_tag)); testrand256(msg); testrand256(key); @@ -162,8 +164,9 @@ static void test_schnorrsig_sha256_tagged(void) { unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); - secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, (unsigned char *) tag, sizeof(tag)); secp256k1_schnorrsig_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); } diff --git a/src/secp256k1.c b/src/secp256k1.c index 218ceafb..b91b3bc6 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -60,6 +60,7 @@ * context_eq function. */ struct secp256k1_context_struct { secp256k1_ecmult_gen_context ecmult_gen_ctx; + secp256k1_hash_ctx hash_ctx; secp256k1_callback illegal_callback; secp256k1_callback error_callback; int declassify; @@ -67,6 +68,7 @@ struct secp256k1_context_struct { static const secp256k1_context secp256k1_context_static_ = { { 0 }, + { secp256k1_sha256_transform }, { secp256k1_default_illegal_callback_fn, 0 }, { secp256k1_default_error_callback_fn, 0 }, 0 @@ -129,10 +131,11 @@ secp256k1_context* secp256k1_context_preallocated_create(void* prealloc, unsigne ret = (secp256k1_context*)prealloc; ret->illegal_callback = default_illegal_callback; ret->error_callback = default_error_callback; + secp256k1_hash_ctx_init(&ret->hash_ctx); /* Flags have been checked by secp256k1_context_preallocated_size. */ VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT); - secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx); + secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->hash_ctx); ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); return ret; @@ -220,6 +223,10 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } +static SECP256K1_INLINE const secp256k1_hash_ctx* secp256k1_get_hash_context(const secp256k1_context *ctx) { + return &ctx->hash_ctx; +} + static secp256k1_scratch_space* secp256k1_scratch_space_create(const secp256k1_context* ctx, size_t max_size) { VERIFY_CHECK(ctx != NULL); return secp256k1_scratch_create(&ctx->error_callback, max_size); @@ -476,7 +483,7 @@ static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *off *offset += len; } -static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { +static int nonce_function_rfc6979_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { unsigned char keydata[112]; unsigned int offset = 0; secp256k1_rfc6979_hmac_sha256 rng; @@ -501,9 +508,9 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m if (algo16 != NULL) { buffer_append(keydata, &offset, algo16, 16); } - secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, keydata, offset); for (i = 0; i <= counter; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, nonce32, 32); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); @@ -512,6 +519,10 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m return 1; } +static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + return nonce_function_rfc6979_impl(secp256k1_get_hash_context(secp256k1_context_static), nonce32, msg32, key32, algo16, data, counter); +} + const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; @@ -757,7 +768,7 @@ int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *see ARG_CHECK(secp256k1_context_is_proper(ctx)); if (secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { - secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, secp256k1_get_hash_context(ctx), seed32); } return 1; } @@ -795,9 +806,9 @@ int secp256k1_tagged_sha256(const secp256k1_context* ctx, unsigned char *hash32, ARG_CHECK(tag != NULL); ARG_CHECK(msg != NULL); - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); - secp256k1_sha256_write(&sha, msg, msglen); - secp256k1_sha256_finalize(&sha, hash32); + secp256k1_sha256_initialize_tagged(secp256k1_get_hash_context(ctx), &sha, tag, taglen); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha, msg, msglen); + secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha, hash32); secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/selftest.h b/src/selftest.h index d083ac95..de0e0597 100644 --- a/src/selftest.h +++ b/src/selftest.h @@ -11,7 +11,8 @@ #include -static int secp256k1_selftest_sha256(void) { +static int secp256k1_selftest_sha256(secp256k1_sha256_compression_function fn_compression) { + secp256k1_hash_ctx hash_ctx; static const char *input63 = "For this sample, this 63-byte string will be used as input data"; static const unsigned char output32[32] = { 0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, @@ -20,13 +21,15 @@ static int secp256k1_selftest_sha256(void) { unsigned char out[32]; secp256k1_sha256 hasher; secp256k1_sha256_initialize(&hasher); - secp256k1_sha256_write(&hasher, (const unsigned char*)input63, 63); - secp256k1_sha256_finalize(&hasher, out); + hash_ctx.fn_sha256_compression = fn_compression; + secp256k1_sha256_write(&hash_ctx, &hasher, (const unsigned char*)input63, 63); + secp256k1_sha256_finalize(&hash_ctx, &hasher, out); return secp256k1_memcmp_var(out, output32, 32) == 0; } static int secp256k1_selftest_passes(void) { - return secp256k1_selftest_sha256(); + /* Use default sha256 compression */ + return secp256k1_selftest_sha256(secp256k1_sha256_transform); } #endif /* SECP256K1_SELFTEST_H */ diff --git a/src/testrand_impl.h b/src/testrand_impl.h index b84f5730..e1e5d858 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -22,12 +22,13 @@ SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) { unsigned char out32[32]; secp256k1_sha256 hash; int i; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(secp256k1_context_static); /* Use SHA256(PREFIX || seed16) as initial state. */ secp256k1_sha256_initialize(&hash); - secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX)); - secp256k1_sha256_write(&hash, seed16, 16); - secp256k1_sha256_finalize(&hash, out32); + secp256k1_sha256_write(hash_ctx, &hash, PREFIX, sizeof(PREFIX)); + secp256k1_sha256_write(hash_ctx, &hash, seed16, 16); + secp256k1_sha256_finalize(hash_ctx, &hash, out32); for (i = 0; i < 4; ++i) { uint64_t s = 0; int j; diff --git a/src/tests.c b/src/tests.c index fa580cc9..9c2ab89c 100644 --- a/src/tests.c +++ b/src/tests.c @@ -132,6 +132,7 @@ static int ecmult_gen_context_eq(const secp256k1_ecmult_gen_context *a, const se static int context_eq(const secp256k1_context *a, const secp256k1_context *b) { return a->declassify == b->declassify && ecmult_gen_context_eq(&a->ecmult_gen_ctx, &b->ecmult_gen_ctx) + && a->hash_ctx.fn_sha256_compression == b->hash_ctx.fn_sha256_compression && a->illegal_callback.fn == b->illegal_callback.fn && a->illegal_callback.data == b->illegal_callback.data && a->error_callback.fn == b->error_callback.fn @@ -454,6 +455,7 @@ static void run_ctz_tests(void) { /***** HASH TESTS *****/ static void run_sha256_known_output_tests(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); static const char *inputs[] = { "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", @@ -489,10 +491,10 @@ static void run_sha256_known_output_tests(void) { j = repeat[i]; secp256k1_sha256_initialize(&hasher); while (j > 0) { - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + secp256k1_sha256_write(hash_ctx, &hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); j--; } - secp256k1_sha256_finalize(&hasher, out); + secp256k1_sha256_finalize(hash_ctx, &hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); /* 2. Run: split the input bytestrings randomly before writing */ if (strlen(inputs[i]) > 0) { @@ -500,11 +502,11 @@ static void run_sha256_known_output_tests(void) { secp256k1_sha256_initialize(&hasher); j = repeat[i]; while (j > 0) { - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_sha256_write(hash_ctx, &hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_sha256_write(hash_ctx, &hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); j--; } - secp256k1_sha256_finalize(&hasher, out); + secp256k1_sha256_finalize(hash_ctx, &hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); } } @@ -602,12 +604,13 @@ static void run_sha256_counter_tests(void) { {0x2c, 0xf3, 0xa9, 0xf6, 0x15, 0x25, 0x80, 0x70, 0x76, 0x99, 0x7d, 0xf1, 0xc3, 0x2f, 0xa3, 0x31, 0xff, 0x92, 0x35, 0x2e, 0x8d, 0x04, 0x13, 0x33, 0xd8, 0x0d, 0xdb, 0x4a, 0xf6, 0x8c, 0x03, 0x34}, {0xec, 0x12, 0x24, 0x9f, 0x35, 0xa4, 0x29, 0x8b, 0x9e, 0x4a, 0x95, 0xf8, 0x61, 0xaf, 0x61, 0xc5, 0x66, 0x55, 0x3e, 0x3f, 0x2a, 0x98, 0xea, 0x71, 0x16, 0x6b, 0x1c, 0xd9, 0xe4, 0x09, 0xd2, 0x8e}, }; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); unsigned int i; for (i = 0; i < sizeof(midstates)/sizeof(midstates[0]); i++) { unsigned char out[32]; secp256k1_sha256 hasher = midstates[i]; - secp256k1_sha256_write(&hasher, (const unsigned char*)input, strlen(input)); - secp256k1_sha256_finalize(&hasher, out); + secp256k1_sha256_write(hash_ctx, &hasher, (const unsigned char*)input, strlen(input)); + secp256k1_sha256_finalize(hash_ctx, &hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); } } @@ -624,9 +627,9 @@ static void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 } /* Convenience function for using test_sha256_eq to verify the correctness of a * tagged hash midstate. This function is used by some module tests. */ -static void test_sha256_tag_midstate(secp256k1_sha256 *sha_tagged, const unsigned char *tag, size_t taglen) { +static void test_sha256_tag_midstate(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *sha_tagged, const unsigned char *tag, size_t taglen) { secp256k1_sha256 sha; - secp256k1_sha256_initialize_tagged(&sha, tag, taglen); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, tag, taglen); test_sha256_eq(&sha, sha_tagged); } @@ -656,19 +659,20 @@ static void run_hmac_sha256_tests(void) { {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }; int i; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); for (i = 0; i < 6; i++) { secp256k1_hmac_sha256 hasher; unsigned char out[32]; - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - secp256k1_hmac_sha256_finalize(&hasher, out); + secp256k1_hmac_sha256_initialize(hash_ctx, &hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(hash_ctx, &hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + secp256k1_hmac_sha256_finalize(hash_ctx, &hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { int split = testrand_int(strlen(inputs[i])); - secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - secp256k1_hmac_sha256_finalize(&hasher, out); + secp256k1_hmac_sha256_initialize(hash_ctx, &hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(hash_ctx, &hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_hmac_sha256_write(hash_ctx, &hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_hmac_sha256_finalize(hash_ctx, &hasher, out); CHECK(secp256k1_memcmp_var(out, outputs[i], 32) == 0); } } @@ -689,27 +693,28 @@ static void run_rfc6979_hmac_sha256_tests(void) { {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} }; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_rfc6979_hmac_sha256 rng; unsigned char out[32]; int i; - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, key1, 64); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, out, 32); CHECK(secp256k1_memcmp_var(out, out1[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, key1, 65); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, out, 32); CHECK(secp256k1_memcmp_var(out, out1[i], 32) != 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, key2, 64); for (i = 0; i < 3; i++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, out, 32); CHECK(secp256k1_memcmp_var(out, out2[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); @@ -746,10 +751,11 @@ static void run_sha256_initialize_midstate_tests(void) { 0xa9ec59eaul, 0x9b4c2ffful, 0x400821e2ul, 0x0dcf3847ul, 0xbe7ea179ul, 0xa5772bdcul, 0x7d29bfe3ul, 0xa486b855ul }; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_sha256 sha; secp256k1_sha256_initialize_midstate(&sha, 64, midstate); - test_sha256_tag_midstate(&sha, tag, sizeof(tag) - 1); + test_sha256_tag_midstate(hash_ctx, &sha, tag, sizeof(tag) - 1); } /***** MODINV TESTS *****/ @@ -5501,11 +5507,11 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar if (secp256k1_ge_is_infinity(&r)) { /* Store infinity as 0x00 */ const unsigned char zerobyte[1] = {0}; - secp256k1_sha256_write(acc, zerobyte, 1); + secp256k1_sha256_write(secp256k1_get_hash_context(CTX), acc, zerobyte, 1); } else { /* Store other points using their uncompressed serialization. */ secp256k1_eckey_pubkey_serialize65(&r, bytes); - secp256k1_sha256_write(acc, bytes, sizeof(bytes)); + secp256k1_sha256_write(secp256k1_get_hash_context(CTX), acc, bytes, sizeof(bytes)); } } @@ -5547,7 +5553,7 @@ static void test_ecmult_constants_2bit(void) { test_ecmult_accumulate(&acc, &x, scratch); } } - secp256k1_sha256_finalize(&acc, b32); + secp256k1_sha256_finalize(secp256k1_get_hash_context(CTX), &acc, b32); CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0); secp256k1_scratch_space_destroy(CTX, scratch); @@ -5566,6 +5572,7 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign unsigned char b32[32]; unsigned char inp[6]; size_t i; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(CTX, 65536); inp[0] = prefix & 0xFF; @@ -5585,12 +5592,12 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign inp[4] = i & 0xff; inp[5] = (i >> 8) & 0xff; secp256k1_sha256_initialize(&gen); - secp256k1_sha256_write(&gen, inp, sizeof(inp)); - secp256k1_sha256_finalize(&gen, b32); + secp256k1_sha256_write(hash_ctx, &gen, inp, sizeof(inp)); + secp256k1_sha256_finalize(hash_ctx, &gen, b32); secp256k1_scalar_set_b32(&x, b32, NULL); test_ecmult_accumulate(&acc, &x, scratch); } - secp256k1_sha256_finalize(&acc, b32); + secp256k1_sha256_finalize(hash_ctx, &acc, b32); CHECK(secp256k1_memcmp_var(b32, expected32, 32) == 0); secp256k1_scratch_space_destroy(CTX, scratch); @@ -5644,7 +5651,7 @@ static void test_ecmult_gen_blind(void) { testrand256(seed32); b = CTX->ecmult_gen_ctx.scalar_offset; p = CTX->ecmult_gen_ctx.ge_offset; - secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, seed32); + secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), seed32); CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej2, &key); CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); @@ -5657,10 +5664,10 @@ static void test_ecmult_gen_blind_reset(void) { /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ secp256k1_scalar b; secp256k1_ge p1, p2; - secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); + secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), 0); b = CTX->ecmult_gen_ctx.scalar_offset; p1 = CTX->ecmult_gen_ctx.ge_offset; - secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); + secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), 0); CHECK(secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); p2 = CTX->ecmult_gen_ctx.ge_offset; CHECK(secp256k1_ge_eq_var(&p1, &p2)); @@ -7467,6 +7474,7 @@ static void test_ecdsa_wycheproof(void) { #include "wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h" int t; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); for (t = 0; t < SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS; t++) { secp256k1_ecdsa_signature signature; secp256k1_sha256 hasher; @@ -7481,8 +7489,8 @@ static void test_ecdsa_wycheproof(void) { secp256k1_sha256_initialize(&hasher); msg = &wycheproof_ecdsa_messages[testvectors[t].msg_offset]; - secp256k1_sha256_write(&hasher, msg, testvectors[t].msg_len); - secp256k1_sha256_finalize(&hasher, out); + secp256k1_sha256_write(hash_ctx, &hasher, msg, testvectors[t].msg_len); + secp256k1_sha256_finalize(hash_ctx, &hasher, out); sig = &wycheproof_ecdsa_signatures[testvectors[t].sig_offset]; if (secp256k1_ecdsa_signature_parse_der(CTX, &signature, sig, testvectors[t].sig_len) == 1) { From 0753f8b909d8960781ad8bdba74e0045aaf8725c Mon Sep 17 00:00:00 2001 From: furszy Date: Fri, 23 Jan 2026 13:41:55 -0500 Subject: [PATCH 316/383] Add API to override SHA256 compression at runtime This introduces `secp256k1_context_set_sha256_compression()`, which allows users to provide their own SHA256 block-compression function at runtime. This is useful in setups where the fastest implementation can only be determined dynamically based on the available CPU features, and rebuilding the library is not possible. The callback is installed on the `secp256k1_context` and is then used by all operations that compute SHA256 hashes. As part of the setup, the library performs sanity checks to ensure that the supplied function is equivalent to the default transform. Passing NULL to the callback setter restores the built-in implementation. --- include/secp256k1.h | 41 ++++++++++++++++ src/hash.h | 2 - src/modules/ecdh/main_impl.h | 11 +++-- src/modules/ecdh/tests_impl.h | 26 +++++++++++ src/modules/ellswift/main_impl.h | 10 +++- src/modules/ellswift/tests_impl.h | 35 ++++++++++++++ src/modules/schnorrsig/main_impl.h | 14 ++++-- src/modules/schnorrsig/tests_impl.h | 24 ++++++++++ src/secp256k1.c | 24 ++++++++-- src/tests.c | 72 +++++++++++++++++++++++++++-- src/testutil.h | 9 ++++ 11 files changed, 247 insertions(+), 21 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 9de45f1f..b7ec6a22 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -6,6 +6,7 @@ extern "C" { #endif #include +#include /** Unless explicitly stated all pointer arguments must not be NULL. * @@ -404,6 +405,46 @@ SECP256K1_API void secp256k1_context_set_error_callback( const void *data ) SECP256K1_ARG_NONNULL(1); +/** A pointer to a function implementing SHA256's internal compression function. + * + * This function processes one or more contiguous 64-byte message blocks and + * updates the internal SHA256 state accordingly. The function is not responsible + * for counting consumed blocks or bytes, nor for performing padding. + * + * In/Out: state: pointer to eight 32-bit words representing the current internal state; + * the state is updated in place. + * In: blocks64: pointer to concatenation of n_blocks blocks, of 64 bytes each. + * no alignment guarantees are made for this pointer. + * n_blocks: number of contiguous 64-byte blocks to process. + */ +typedef void (*secp256k1_sha256_compression_function)( + uint32_t *state, + const unsigned char *blocks64, + size_t n_blocks +); + +/** + * Set a callback function to override the internal SHA256 compression function. + * + * This installs a function to replace the built-in block-compression + * step used by the library's internal SHA256 implementation. + * The provided callback must exactly implement the effect of n_blocks + * repeated applications of the SHA256 compression function. + * + * This API exists to support environments that wish to route the + * SHA256 compression step through a hardware-accelerated or otherwise + * specialized implementation. It is NOT meant for replacing SHA256 + * with a different hash function. + * + * Args: ctx: pointer to a context object. + * In: fn_compression: pointer to a function implementing the compression function; + * passing NULL restores the default implementation. + */ +SECP256K1_API void secp256k1_context_set_sha256_compression( + secp256k1_context *ctx, + secp256k1_sha256_compression_function fn_compression +) SECP256K1_ARG_NONNULL(1); + /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. diff --git a/src/hash.h b/src/hash.h index 35825eae..79d97671 100644 --- a/src/hash.h +++ b/src/hash.h @@ -10,8 +10,6 @@ #include #include -typedef void (*secp256k1_sha256_compression_function)(uint32_t *state, const unsigned char *blocks64, size_t n_blocks); - typedef struct { secp256k1_sha256_compression_function fn_sha256_compression; } secp256k1_hash_ctx; diff --git a/src/modules/ecdh/main_impl.h b/src/modules/ecdh/main_impl.h index 3ee3ca7b..b0359b2c 100644 --- a/src/modules/ecdh/main_impl.h +++ b/src/modules/ecdh/main_impl.h @@ -45,10 +45,6 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se ARG_CHECK(point != NULL); ARG_CHECK(scalar != NULL); - if (hashfp == NULL) { - hashfp = secp256k1_ecdh_hash_function_default; - } - secp256k1_pubkey_load(ctx, &pt, point); secp256k1_scalar_set_b32(&s, scalar, &overflow); @@ -64,7 +60,12 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se secp256k1_fe_get_b32(x, &pt.x); secp256k1_fe_get_b32(y, &pt.y); - ret = hashfp(output, x, y, data); + if (hashfp == NULL) { + /* Use ctx-aware function by default */ + ret = ecdh_hash_function_sha256_impl(secp256k1_get_hash_context(ctx), output, x, y, data); + } else { + ret = hashfp(output, x, y, data); + } secp256k1_memclear_explicit(x, sizeof(x)); secp256k1_memclear_explicit(y, sizeof(y)); diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index e6c1bab9..c75ce9ff 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -8,6 +8,7 @@ #define SECP256K1_MODULE_ECDH_TESTS_H #include "../../unit_test.h" +#include "../../testutil.h" static int ecdh_hash_function_test_xpassthru(unsigned char *output, const unsigned char *x, const unsigned char *y, void *data) { (void)y; @@ -90,6 +91,30 @@ static void test_ecdh_generator_basepoint(void) { } } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_ecdh) +static void test_ecdh_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char out_default[65], out_custom[65]; + const unsigned char sk[32] = {1}; + secp256k1_pubkey pubkey; + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, sk) == 1); + + /* Default behavior */ + CHECK(secp256k1_ecdh(ctx, out_default, &pubkey, sk, NULL, NULL) == 1); + CHECK(!sha256_ecdh_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_ecdh; + CHECK(secp256k1_ecdh(ctx, out_custom, &pubkey, sk, NULL, NULL) == 1); + + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default, out_custom, 32) != 0); + CHECK(sha256_ecdh_called); + + secp256k1_context_destroy(ctx); +} + static void test_bad_scalar(void) { unsigned char s_zero[32] = { 0 }; unsigned char s_overflow[32] = { 0 }; @@ -187,6 +212,7 @@ static const struct tf_test_entry tests_ecdh[] = { CASE1(test_bad_scalar), CASE1(test_result_basepoint), CASE1(test_ecdh_wycheproof), + CASE1(test_ecdh_ctx_sha256), }; #endif /* SECP256K1_MODULE_ECDH_TESTS_H */ diff --git a/src/modules/ellswift/main_impl.h b/src/modules/ellswift/main_impl.h index 29c0a536..27cb3db6 100644 --- a/src/modules/ellswift/main_impl.h +++ b/src/modules/ellswift/main_impl.h @@ -562,8 +562,14 @@ int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, secp256k1_fe_normalize(&px); secp256k1_fe_get_b32(sx, &px); - /* Invoke hasher */ - ret = hashfp(output, sx, ell_a64, ell_b64, data); + /* Invoke hasher. Use ctx-aware function by default */ + if (hashfp == secp256k1_ellswift_xdh_hash_function_bip324) { + ret = ellswift_xdh_hash_function_bip324_impl(secp256k1_get_hash_context(ctx), output, sx, ell_a64, ell_b64, data); + } else if (hashfp == secp256k1_ellswift_xdh_hash_function_prefix) { + ret = ellswift_xdh_hash_function_prefix_impl(secp256k1_get_hash_context(ctx), output, sx, ell_a64, ell_b64, data); + } else { + ret = hashfp(output, sx, ell_a64, ell_b64, data); + } secp256k1_memclear_explicit(sx, sizeof(sx)); secp256k1_fe_clear(&px); diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index c9a7500f..a849c8e8 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -431,6 +431,40 @@ void ellswift_xdh_correctness_tests(void) { } } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_ellswift_xdh) +void ellswift_xdh_ctx_sha256_tests(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char out_default[65], out_custom[65]; + const unsigned char skA[32] = {1}, skB[32] = {2}; + unsigned char keyA[64], keyB[64], data[64] = {0}; + const secp256k1_ellswift_xdh_hash_function hash_funcs[2] = {secp256k1_ellswift_xdh_hash_function_bip324, secp256k1_ellswift_xdh_hash_function_prefix}; + int i; + + CHECK(secp256k1_ellswift_create(ctx, keyA, skA, NULL)); + CHECK(secp256k1_ellswift_create(ctx, keyB, skB, NULL)); + + for (i = 0; i < 2; i++) { + const secp256k1_ellswift_xdh_hash_function hash_fn = hash_funcs[i]; + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_ellswift_xdh(ctx, out_default, keyA, keyB, skA, 0, hash_fn, data)); + CHECK(!sha256_ellswift_xdh_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_ellswift_xdh; + CHECK(secp256k1_ellswift_xdh(ctx, out_custom, keyA, keyB, skA, 0, hash_fn, data)); + CHECK(sha256_ellswift_xdh_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default, out_custom, 32) != 0); + + /* Restore defaults */ + sha256_ellswift_xdh_called = 0; + secp256k1_context_set_sha256_compression(ctx, NULL); + } + + secp256k1_context_destroy(ctx); +} + /* Test hash initializers */ void ellswift_hash_init_tests(void) { secp256k1_sha256 sha_optimized; @@ -499,6 +533,7 @@ static const struct tf_test_entry tests_ellswift[] = { CASE1(ellswift_xdh_correctness_tests), CASE1(ellswift_hash_init_tests), CASE1(ellswift_xdh_bad_scalar_tests), + CASE1(ellswift_xdh_ctx_sha256_tests), }; #endif diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 3fe645b4..5100557f 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -137,10 +137,6 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi ARG_CHECK(msg != NULL || msglen == 0); ARG_CHECK(keypair != NULL); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_bip340; - } - ret &= secp256k1_keypair_load(ctx, &sk, &pk, keypair); /* Because we are signing for a x-only pubkey, the secret key is negated * before signing if the point corresponding to the secret key does not @@ -151,7 +147,15 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar_get_b32(seckey, &sk); secp256k1_fe_get_b32(pk_buf, &pk.x); - ret &= !!noncefp(nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); + + /* Compute nonce */ + if (noncefp == NULL || noncefp == secp256k1_nonce_function_bip340) { + /* Use context-aware nonce function by default */ + ret &= nonce_function_bip340_impl(secp256k1_get_hash_context(ctx), nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); + } else { + ret &= !!noncefp(nonce32, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); + } + secp256k1_scalar_set_b32(&k, nonce32, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 009bb3e1..56812e7f 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -852,6 +852,29 @@ static void test_schnorrsig_sign_internal(void) { CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0); } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_schnorrsig) +static void test_schnorrsig_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char out_default[64], out_custom[64]; + unsigned char sk[32] = {1}, msg32[32] = {1}; + secp256k1_keypair keypair; + CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); + + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_schnorrsig_sign32(ctx, out_default, msg32, &keypair, NULL)); + CHECK(!sha256_schnorrsig_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_schnorrsig; + CHECK(secp256k1_schnorrsig_sign32(ctx, out_custom, msg32, &keypair, NULL)); + CHECK(sha256_schnorrsig_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default, out_custom, 64) != 0); + + secp256k1_context_destroy(ctx); +} + #define N_SIGS 3 /* Creates N_SIGS valid signatures and verifies them with verify and * verify_batch (TODO). Then flips some bits and checks that verification now @@ -981,6 +1004,7 @@ static const struct tf_test_entry tests_schnorrsig[] = { CASE1(test_schnorrsig_sign), CASE1(test_schnorrsig_sign_verify), CASE1(test_schnorrsig_taproot), + CASE1(test_schnorrsig_ctx_sha256), }; #endif diff --git a/src/secp256k1.c b/src/secp256k1.c index b91b3bc6..e4b80fff 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -223,6 +223,18 @@ void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(co ctx->error_callback.data = data; } +void secp256k1_context_set_sha256_compression(secp256k1_context *ctx, secp256k1_sha256_compression_function fn_compression) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK_VOID(secp256k1_context_is_proper(ctx)); + if (!fn_compression) { /* Reset hash context */ + secp256k1_hash_ctx_init(&ctx->hash_ctx); + return; + } + /* Check and set */ + ARG_CHECK_VOID(secp256k1_selftest_sha256(fn_compression)); + ctx->hash_ctx.fn_sha256_compression = fn_compression; +} + static SECP256K1_INLINE const secp256k1_hash_ctx* secp256k1_get_hash_context(const secp256k1_context *ctx) { return &ctx->hash_ctx; } @@ -538,9 +550,6 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc if (recid) { *recid = 0; } - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } /* Fail if the secret key is invalid. */ is_sec_valid = secp256k1_scalar_set_b32_seckey(&sec, seckey); @@ -548,7 +557,14 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc secp256k1_scalar_set_b32(&msg, msg32, NULL); while (1) { int is_nonce_valid; - ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + + if (noncefp == NULL) { + /* Use ctx-aware function by default */ + ret = nonce_function_rfc6979_impl(secp256k1_get_hash_context(ctx), nonce32, msg32, seckey, NULL, (void*)noncedata, count); + } else { + ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + } + if (!ret) { break; } diff --git a/src/tests.c b/src/tests.c index 9c2ab89c..b85b0652 100644 --- a/src/tests.c +++ b/src/tests.c @@ -433,6 +433,53 @@ static void run_scratch_tests(void) { secp256k1_scratch_space_destroy(CTX, NULL); /* no-op */ } +/* A compression function that does nothing */ +static void invalid_sha256_compression(uint32_t *s, const unsigned char *msg, size_t rounds) { + (void)s; (void)msg; (void)rounds; +} + +static int own_transform_called = 0; +static void good_sha256_compression(uint32_t *s, const unsigned char *msg, size_t rounds) { + own_transform_called = 1; + secp256k1_sha256_transform(s, msg, rounds); +} + +static void run_plug_sha256_compression_tests(void) { + secp256k1_context *ctx, *ctx_cloned; + secp256k1_sha256 sha; + unsigned char sha_out[32]; + /* 1) Verify the context is initialized with the default compression function */ + ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + CHECK(ctx->hash_ctx.fn_sha256_compression == secp256k1_sha256_transform); + + /* 2) Verify providing a bad compression function fails during set */ + CHECK_ILLEGAL_VOID(ctx, secp256k1_context_set_sha256_compression(ctx, invalid_sha256_compression)); + CHECK(ctx->hash_ctx.fn_sha256_compression == secp256k1_sha256_transform); + + /* 3) Provide sha256 to ctx and verify it is called when provided */ + own_transform_called = 0; + secp256k1_context_set_sha256_compression(ctx, good_sha256_compression); + CHECK(own_transform_called); + + /* 4) Verify callback makes it across clone */ + ctx_cloned = secp256k1_context_clone(ctx); + CHECK(ctx_cloned->hash_ctx.fn_sha256_compression == good_sha256_compression); + + /* 5) A hash operation should invoke the installed callback */ + own_transform_called = 0; + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(secp256k1_get_hash_context(ctx), &sha, (const unsigned char*)"a", 1); + secp256k1_sha256_finalize(secp256k1_get_hash_context(ctx), &sha, sha_out); + CHECK(own_transform_called); + + /* 6) Unset sha256 and verify the default one is set again */ + secp256k1_context_set_sha256_compression(ctx, NULL); + CHECK(ctx->hash_ctx.fn_sha256_compression == secp256k1_sha256_transform); + + secp256k1_context_destroy(ctx); + secp256k1_context_destroy(ctx_cloned); +} + static void run_ctz_tests(void) { static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129}; static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef}; @@ -7129,7 +7176,7 @@ static void run_ecdsa_der_parse(void) { } /* Tests several edge cases. */ -static void test_ecdsa_edge_cases(void) { +static void run_ecdsa_edge_cases(void) { int t; secp256k1_ecdsa_signature sig; @@ -7462,8 +7509,25 @@ static void test_ecdsa_edge_cases(void) { } } -static void run_ecdsa_edge_cases(void) { - test_ecdsa_edge_cases(); +DEFINE_SHA256_TRANSFORM_PROBE(sha256_ecdsa) +static void ecdsa_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + secp256k1_ecdsa_signature out_default, out_custom; + unsigned char sk[32] = {1}, msg32[32] = {1}; + + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_ecdsa_sign(ctx, &out_default, msg32, sk, NULL, NULL)); + CHECK(!sha256_ecdsa_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_ecdsa; + CHECK(secp256k1_ecdsa_sign(ctx, &out_custom, msg32, sk, NULL, NULL)); + CHECK(sha256_ecdsa_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default.data, out_custom.data, 64) != 0); + + secp256k1_context_destroy(ctx); } /** Wycheproof tests @@ -7754,6 +7818,7 @@ static const struct tf_test_entry tests_general[] = { CASE(all_static_context_tests), CASE(deprecated_context_flags_test), CASE(scratch_tests), + CASE(plug_sha256_compression_tests), }; static const struct tf_test_entry tests_integer[] = { @@ -7824,6 +7889,7 @@ static const struct tf_test_entry tests_ecdsa[] = { CASE(ecdsa_end_to_end), CASE(ecdsa_edge_cases), CASE(ecdsa_wycheproof), + CASE1(ecdsa_ctx_sha256), }; static const struct tf_test_entry tests_utils[] = { diff --git a/src/testutil.h b/src/testutil.h index 93ee3d58..8fa69a02 100644 --- a/src/testutil.h +++ b/src/testutil.h @@ -11,6 +11,15 @@ #include "testrand.h" #include "util.h" +/* Helper for when we need to check that the ctx-provided sha256 compression was called */ +#define DEFINE_SHA256_TRANSFORM_PROBE(name) \ + static int name##_called = 0; \ + static void name(uint32_t *s, const unsigned char *msg, size_t rounds) { \ + name##_called = 1; \ + secp256k1_sha256_transform(s, msg, rounds); \ + s[0] ^= 0xdeadbeef; /* intentional perturbation for testing */ \ + } + /* group order of the secp256k1 curve in 32-byte big endian representation */ static const unsigned char secp256k1_group_order_bytes[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, From 4d92a083bc267b87db654ae75cbcaf2a87854c09 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 14 Jan 2026 12:16:41 -0500 Subject: [PATCH 317/383] sha256: speed up writes using multi-block compression Multiple 64-byte blocks can now be compressed directly from the input buffer, without copying them into the internal buffer. --- src/hash_impl.h | 20 ++++++++--- src/tests.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/hash_impl.h b/src/hash_impl.h index d5f16cd1..7c40f82e 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -143,22 +143,34 @@ static void secp256k1_hash_ctx_init(secp256k1_hash_ctx *hash_ctx) { } static void secp256k1_sha256_write(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *hash, const unsigned char *data, size_t len) { + size_t chunk_len; size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; VERIFY_CHECK(hash->bytes >= len); VERIFY_CHECK(hash_ctx != NULL); VERIFY_CHECK(hash_ctx->fn_sha256_compression != NULL); - while (len >= 64 - bufsize) { - /* Fill the buffer, and process it. */ - size_t chunk_len = 64 - bufsize; + + /* If we exceed the 64-byte block size with this input, process it and wipe the buffer */ + chunk_len = 64 - bufsize; + if (bufsize && len >= chunk_len) { memcpy(hash->buf + bufsize, data, chunk_len); data += chunk_len; len -= chunk_len; hash_ctx->fn_sha256_compression(hash->s, hash->buf, 1); bufsize = 0; } + + /* If we still have data to process, invoke compression directly on the input */ + if (len >= 64) { + const size_t n_blocks = len / 64; + const size_t advance = n_blocks * 64; + hash_ctx->fn_sha256_compression(hash->s, data, n_blocks); + data += advance; + len -= advance; + } + + /* Fill the buffer with what remains */ if (len) { - /* Fill the buffer with what remains. */ memcpy(hash->buf + bufsize, data, len); } } diff --git a/src/tests.c b/src/tests.c index b85b0652..7c3a96bc 100644 --- a/src/tests.c +++ b/src/tests.c @@ -480,6 +480,99 @@ static void run_plug_sha256_compression_tests(void) { secp256k1_context_destroy(ctx_cloned); } +static void run_sha256_multi_block_compression_tests(void) { + secp256k1_hash_ctx hash_ctx; + secp256k1_sha256 sha256_one; + secp256k1_sha256 sha256_two; + unsigned char out_one[32], out_two[32]; + + hash_ctx.fn_sha256_compression = secp256k1_sha256_transform; + + { /* 1) Writing one 64-byte full block vs two 32-byte blocks */ + const unsigned char data[64] = "totally serious test message to hash, definitely no random data"; + unsigned char data32[32]; + + secp256k1_sha256_initialize(&sha256_one); + secp256k1_sha256_initialize(&sha256_two); + + /* Write the 64-byte block */ + secp256k1_sha256_write(&hash_ctx, &sha256_one, data, 64); + secp256k1_sha256_finalize(&hash_ctx, &sha256_one, out_one); + + /* Write the two 32-byte blocks */ + memcpy(data32, data, 32); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data32, 32); + memcpy(data32, data + 32, 32); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data32, 32); + secp256k1_sha256_finalize(&hash_ctx, &sha256_two, out_two); + + CHECK(secp256k1_memcmp_var(out_one, out_two, 32) == 0); + } + + { /* 2) Writing one 80-byte block vs two 40-byte blocks */ + const unsigned char data[80] = "Genesis: The Times 03/Jan/2009 Chancellor on brink of second bailout for banks "; + unsigned char data40[40]; + + secp256k1_sha256_initialize(&sha256_one); + secp256k1_sha256_initialize(&sha256_two); + + /* Write the 80-byte block */ + secp256k1_sha256_write(&hash_ctx, &sha256_one, data, 80); + secp256k1_sha256_finalize(&hash_ctx, &sha256_one, out_one); + + /* Write the two 40-byte blocks */ + memcpy(data40, data, 40); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data40, 40); + memcpy(data40, data + 40, 40); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data40, 40); + secp256k1_sha256_finalize(&hash_ctx, &sha256_two, out_two); + + CHECK(secp256k1_memcmp_var(out_one, out_two, 32) == 0); + } + + { /* 3) Writing multiple consecutive full blocks in one write (128 bytes) */ + unsigned char data[128]; + unsigned char i; + for (i = 0; i < 128; i++) data[i] = i; + + secp256k1_sha256_initialize(&sha256_one); + secp256k1_sha256_initialize(&sha256_two); + + /* Single write of 128 bytes (two full 64-byte blocks) */ + secp256k1_sha256_write(&hash_ctx, &sha256_one, data, 128); + secp256k1_sha256_finalize(&hash_ctx, &sha256_one, out_one); + + /* Two separate writes of 64 bytes each */ + secp256k1_sha256_write(&hash_ctx, &sha256_two, data, 64); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data + 64, 64); + secp256k1_sha256_finalize(&hash_ctx, &sha256_two, out_two); + + CHECK(secp256k1_memcmp_var(out_one, out_two, 32) == 0); + } + + { /* 4) Mixed small + large writes in sequence */ + unsigned char data[150]; + unsigned char i; + for (i = 0; i < 150; i++) data[i] = i; + + secp256k1_sha256_initialize(&sha256_one); + secp256k1_sha256_initialize(&sha256_two); + + /* Single write of 150 bytes */ + secp256k1_sha256_write(&hash_ctx, &sha256_one, data, 150); + secp256k1_sha256_finalize(&hash_ctx, &sha256_one, out_one); + + /* Split writes: 10, 64, 64, 12 bytes */ + secp256k1_sha256_write(&hash_ctx, &sha256_two, data, 10); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data + 10, 64); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data + 74, 64); + secp256k1_sha256_write(&hash_ctx, &sha256_two, data + 138, 12); + secp256k1_sha256_finalize(&hash_ctx, &sha256_two, out_two); + + CHECK(secp256k1_memcmp_var(out_one, out_two, 32) == 0); + } +} + static void run_ctz_tests(void) { static const uint32_t b32[] = {1, 0xffffffff, 0x5e56968f, 0xe0d63129}; static const uint64_t b64[] = {1, 0xffffffffffffffff, 0xbcd02462139b3fc3, 0x98b5f80c769693ef}; @@ -7819,6 +7912,7 @@ static const struct tf_test_entry tests_general[] = { CASE(deprecated_context_flags_test), CASE(scratch_tests), CASE(plug_sha256_compression_tests), + CASE(sha256_multi_block_compression_tests), }; static const struct tf_test_entry tests_integer[] = { From 48cbd78dfc624afd45febf5cd0f15a7485655716 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Tue, 3 Mar 2026 15:42:49 +0200 Subject: [PATCH 318/383] modules: Port bitcoin-core/secp256k1#1825 to zkp-specific code --- src/modules/bppp/bppp_transcript_impl.h | 16 ++++------- src/modules/ecdsa_adaptor/dleq_impl.h | 16 ++++------- src/modules/ecdsa_adaptor/main_impl.h | 32 +++++++--------------- src/modules/ecdsa_s2c/main_impl.h | 32 +++++++--------------- src/modules/schnorrsig_halfagg/main_impl.h | 16 ++++------- 5 files changed, 35 insertions(+), 77 deletions(-) diff --git a/src/modules/bppp/bppp_transcript_impl.h b/src/modules/bppp/bppp_transcript_impl.h index d53e9023..5e212231 100644 --- a/src/modules/bppp/bppp_transcript_impl.h +++ b/src/modules/bppp/bppp_transcript_impl.h @@ -14,17 +14,11 @@ * SHA256 to SHA256("Bulletproofs_pp/v0/commitment")||SHA256("Bulletproofs_pp/v0/commitment"). */ static void secp256k1_bppp_sha256_tagged_commitment_init(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x52fc8185ul; - sha->s[1] = 0x0e7debf0ul; - sha->s[2] = 0xb0967270ul; - sha->s[3] = 0x6f5abfe1ul; - sha->s[4] = 0x822bdec0ul; - sha->s[5] = 0x36db8beful; - sha->s[6] = 0x03d9e1f1ul; - sha->s[7] = 0x8a5cef6ful; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x52fc8185ul, 0x0e7debf0ul, 0xb0967270ul, 0x6f5abfe1ul, + 0x822bdec0ul, 0x36db8beful, 0x03d9e1f1ul, 0x8a5cef6ful + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Obtain a challenge scalar from the current transcript.*/ diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index 60e63a34..63642dc8 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -4,17 +4,11 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("DLEQ")||SHA256("DLEQ"). */ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x8cc4beacul; - sha->s[1] = 0x2e011f3ful; - sha->s[2] = 0x355c75fbul; - sha->s[3] = 0x3ba6a2c5ul; - sha->s[4] = 0xe96f3aeful; - sha->s[5] = 0x180530fdul; - sha->s[6] = 0x94582499ul; - sha->s[7] = 0x577fd564ul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x8cc4beacul, 0x2e011f3ful, 0x355c75fbul, 0x3ba6a2c5ul, + 0xe96f3aeful, 0x180530fdul, 0x94582499ul, 0x577fd564ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index e43a4222..ea10207f 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -60,33 +60,21 @@ static int secp256k1_ecdsa_adaptor_sig_deserialize(secp256k1_ge *r, secp256k1_sc /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("ECDSAadaptor/non")||SHA256("ECDSAadaptor/non"). */ static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0x791dae43ul; - sha->s[1] = 0xe52d3b44ul; - sha->s[2] = 0x37f9edeaul; - sha->s[3] = 0x9bfd2ab1ul; - sha->s[4] = 0xcfb0f44dul; - sha->s[5] = 0xccf1d880ul; - sha->s[6] = 0xd18f2c13ul; - sha->s[7] = 0xa37b9024ul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0x791dae43ul, 0xe52d3b44ul, 0x37f9edeaul, 0x9bfd2ab1ul, + 0xcfb0f44dul, 0xccf1d880ul, 0xd18f2c13ul, 0xa37b9024ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("ECDSAadaptor/aux")||SHA256("ECDSAadaptor/aux"). */ static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xd14c7bd9ul; - sha->s[1] = 0x095d35e6ul; - sha->s[2] = 0xb8490a88ul; - sha->s[3] = 0xfb00ef74ul; - sha->s[4] = 0x0baa488ful; - sha->s[5] = 0x69366693ul; - sha->s[6] = 0x1c81c5baul; - sha->s[7] = 0xc33b296aul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xd14c7bd9ul, 0x095d35e6ul, 0xb8490a88ul, 0xfb00ef74ul, + 0x0baa488ful, 0x69366693ul, 0x1c81c5baul, 0xc33b296aul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ diff --git a/src/modules/ecdsa_s2c/main_impl.h b/src/modules/ecdsa_s2c/main_impl.h index 59a4cdfa..cdc54737 100644 --- a/src/modules/ecdsa_s2c/main_impl.h +++ b/src/modules/ecdsa_s2c/main_impl.h @@ -36,33 +36,21 @@ int secp256k1_ecdsa_s2c_opening_serialize(const secp256k1_context* ctx, unsigned /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("s2c/ecdsa/point")||SHA256("s2c/ecdsa/point"). */ static void secp256k1_s2c_ecdsa_point_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xa9b21c7bul; - sha->s[1] = 0x358c3e3eul; - sha->s[2] = 0x0b6863d1ul; - sha->s[3] = 0xc62b2035ul; - sha->s[4] = 0xb44b40ceul; - sha->s[5] = 0x254a8912ul; - sha->s[6] = 0x0f85d0d4ul; - sha->s[7] = 0x8a5bf91cul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xa9b21c7bul, 0x358c3e3eul, 0x0b6863d1ul, 0xc62b2035ul, + 0xb44b40ceul, 0x254a8912ul, 0x0f85d0d4ul, 0x8a5bf91cul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("s2c/ecdsa/data")||SHA256("s2c/ecdsa/data"). */ static void secp256k1_s2c_ecdsa_data_sha256_tagged(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xfeefd675ul; - sha->s[1] = 0x73166c99ul; - sha->s[2] = 0xe2309cb8ul; - sha->s[3] = 0x6d458113ul; - sha->s[4] = 0x01d3a512ul; - sha->s[5] = 0x00e18112ul; - sha->s[6] = 0x37ee0874ul; - sha->s[7] = 0x421fc55ful; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xfeefd675ul, 0x73166c99ul, 0xe2309cb8ul, 0x6d458113ul, + 0x01d3a512ul, 0x00e18112ul, 0x37ee0874ul, 0x421fc55ful + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } int secp256k1_ecdsa_s2c_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature* signature, secp256k1_ecdsa_s2c_opening* s2c_opening, const unsigned char diff --git a/src/modules/schnorrsig_halfagg/main_impl.h b/src/modules/schnorrsig_halfagg/main_impl.h index af612195..5d424a38 100644 --- a/src/modules/schnorrsig_halfagg/main_impl.h +++ b/src/modules/schnorrsig_halfagg/main_impl.h @@ -9,17 +9,11 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("HalfAgg/randomizer")||SHA256("HalfAgg/randomizer"). */ static void secp256k1_schnorrsig_sha256_tagged_aggregation(secp256k1_sha256 *sha) { - secp256k1_sha256_initialize(sha); - sha->s[0] = 0xd11f5532ul; - sha->s[1] = 0xfa57f70ful; - sha->s[2] = 0x5db0d728ul; - sha->s[3] = 0xf806ffe1ul; - sha->s[4] = 0x1d4db069ul; - sha->s[5] = 0xb4d587e1ul; - sha->s[6] = 0x50451c2aul; - sha->s[7] = 0x10fb63e9ul; - - sha->bytes = 64; + static const uint32_t midstate[8] = { + 0xd11f5532ul, 0xfa57f70ful, 0x5db0d728ul, 0xf806ffe1ul, + 0x1d4db069ul, 0xb4d587e1ul, 0x50451c2aul, 0x10fb63e9ul + }; + secp256k1_sha256_initialize_midstate(sha, 64, midstate); } int secp256k1_schnorrsig_inc_aggregate(const secp256k1_context *ctx, unsigned char *aggsig, size_t *aggsig_len, const secp256k1_xonly_pubkey *all_pubkeys, const unsigned char *all_msgs32, const unsigned char *new_sigs64, size_t n_before, size_t n_new) { From 799a27c81361221c996d442551191a4aff940f5e Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Tue, 3 Mar 2026 17:33:57 +0200 Subject: [PATCH 319/383] ecdsa_adaptor: Check for infinity in secp256k1_dleq_verify --- src/modules/ecdsa_adaptor/dleq_impl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index 60e63a34..1d1548c4 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -145,6 +145,10 @@ static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scal secp256k1_ecmult(&rj[1], &gen2j, s, &secp256k1_scalar_zero); secp256k1_gej_add_var(&rj[1], &rj[1], &tmpj, NULL); + if (secp256k1_gej_is_infinity(&rj[0]) || secp256k1_gej_is_infinity(&rj[1])) { + return 0; + } + secp256k1_ge_set_all_gej_var(r, rj, 2); secp256k1_dleq_challenge(&e_expected, gen2, &r[0], &r[1], p1, p2); From a4af91d5b9b31b802683ee8432859afd0b52827e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 09:16:36 +0100 Subject: [PATCH 320/383] ecdsa_adaptor: Add test case for R1==infinity in DLEQ proof --- src/modules/ecdsa_adaptor/tests_impl.h | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index 3abc8127..c9bf0dac 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -1114,6 +1114,62 @@ static void multi_hop_lock_tests_internal(void) { CHECK(secp256k1_memcmp_var(buf, pop, 32) == 0); } +static void adaptor_test_issue335(void) { + /* Inputs that will trigger R1==infinity in secp256k1_dleq_verify. */ + unsigned char adaptor_sig[162] = { + 0x03, 0x63, 0x3D, 0x56, 0xAB, 0xEE, 0x6F, 0x36, 0xE6, 0x07, 0xC6, 0x04, + 0x2C, 0x68, 0xB4, 0x09, 0xBE, 0x4F, 0x3D, 0x56, 0x3A, 0x51, 0x7B, 0xCA, + 0x95, 0xE6, 0xD9, 0x48, 0x1E, 0x95, 0xD0, 0xD6, 0xC6, 0x03, 0x91, 0x66, + 0xC2, 0x89, 0xB9, 0xF9, 0x05, 0xE5, 0x5F, 0x9E, 0x3D, 0xF9, 0xF6, 0x9D, + 0x7F, 0x35, 0x6B, 0x4A, 0x22, 0x09, 0x5F, 0x89, 0x4F, 0x47, 0x15, 0x71, + 0x4A, 0xA4, 0xB5, 0x66, 0x06, 0xAF, 0x84, 0x40, 0xB2, 0x83, 0x34, 0xF6, + 0x74, 0x18, 0xD8, 0x3D, 0x5C, 0xDC, 0x14, 0x0A, 0xAB, 0x22, 0x2B, 0x19, + 0x15, 0x13, 0xC3, 0x5D, 0x9C, 0xBC, 0x6D, 0x89, 0x1C, 0xB5, 0x38, 0x74, + 0xB0, 0xCE, 0x5F, 0x34, 0xD7, 0xA0, 0xA9, 0x89, 0x7A, 0x19, 0x45, 0x77, + 0xBD, 0x5F, 0x0F, 0x31, 0xD8, 0x3B, 0x50, 0xC6, 0x2A, 0x4D, 0xCF, 0x4D, + 0xCB, 0x91, 0x71, 0x8C, 0x66, 0xAE, 0xB8, 0xE2, 0x1A, 0x01, 0x65, 0x05, + 0x2D, 0x93, 0x73, 0x97, 0xB7, 0x66, 0xC4, 0xEB, 0x23, 0x8D, 0x3B, 0x55, + 0xA2, 0x3D, 0xF8, 0x8E, 0x56, 0x84, 0x87, 0x10, 0x76, 0x18, 0xC2, 0xE8, + 0x35, 0xF9, 0x4E, 0x2A, 0x29, 0xB2 + }; + unsigned char msg[32] = { + 0x38, 0x9C, 0x43, 0x7B, 0x37, 0xBB, 0x6F, 0x74, 0x09, 0x3D, 0x69, + 0x3E, 0x3D, 0x9B, 0x4F, 0xC7, 0x9D, 0xDF, 0xA9, 0x33, 0x39, 0x8C, + 0x90, 0x03, 0x95, 0x2D, 0x67, 0xCD, 0xD9, 0x99, 0xDC, 0x55 + }; + unsigned char deckey[32] = { + 0x4A, 0x0B, 0x45, 0xA7, 0x4F, 0xBF, 0x49, 0xC3, 0x4B, 0x7C, 0xE0, + 0x8E, 0x34, 0x89, 0xFB, 0xEA, 0xD5, 0x41, 0xA1, 0x2E, 0xBE, 0x13, + 0x3F, 0xD6, 0x8E, 0x24, 0x86, 0x60, 0x1B, 0x19, 0xC1, 0xB5 + }; + unsigned char seckey[32] = { + 0x12, 0xDB, 0x27, 0x33, 0x51, 0x3D, 0xD9, 0xDF, 0x6A, 0x3C, 0x5A, + 0xEC, 0x3C, 0xA9, 0xF5, 0xDA, 0xA7, 0x3E, 0xB4, 0x61, 0xC8, 0xBB, + 0x12, 0xB7, 0xD4, 0xAA, 0xF5, 0x9A, 0xE9, 0xE5, 0x8B, 0xB7 + }; + secp256k1_pubkey pubkey; + secp256k1_pubkey enckey; + + CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, seckey) == 1); + CHECK(secp256k1_ec_pubkey_create(CTX, &enckey, deckey) == 1); + CHECK(secp256k1_ecdsa_adaptor_verify(CTX, adaptor_sig, &pubkey, msg, &enckey) == 0); + + /* This explains how the inputs were obtained. */ + { + unsigned char adaptor_sig_tmp[sizeof(adaptor_sig)]; + /* Since the same nonce function with different algo arguments is used + * both for the adaptor sig secret nonce and the dleq secret nonce, + * but ecdsa_adaptor_nonce_function_overflowing ignores the algo arg + * (in violation of the documented API contract), the resulting secret + * nonces will be the same. */ + CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig_tmp, seckey, &enckey, msg, ecdsa_adaptor_nonce_function_overflowing, NULL) == 1); + CHECK(secp256k1_ecdsa_adaptor_verify(CTX, adaptor_sig_tmp, &pubkey, msg, &enckey) == 1); + /* Increment the last least significant bit of e. */ + adaptor_sig_tmp[129] = 0x01; + CHECK(secp256k1_memcmp_var(adaptor_sig_tmp, adaptor_sig, sizeof(adaptor_sig)) == 0); + } +} + /* --- Test registry --- */ REPEAT_TEST(dleq_tests) REPEAT_TEST(adaptor_tests) @@ -1126,6 +1182,7 @@ static const struct tf_test_entry tests_ecdsa_adaptor[] = { CASE1(dleq_tests), CASE1(adaptor_tests), CASE1(multi_hop_lock_tests), + CASE1(adaptor_test_issue335), }; #endif /* SECP256K1_MODULE_ECDSA_ADAPTOR_TESTS_H */ From dd8db2ea2b37b4b20e2249b1e47dea271146f0c8 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 09:34:07 +0100 Subject: [PATCH 321/383] ecdsa_adaptor: Run tests with default and overflowing nonce function --- src/modules/ecdsa_adaptor/tests_impl.h | 39 +++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index c9bf0dac..6176faec 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -803,6 +803,7 @@ static void test_ecdsa_adaptor_api(void) { unsigned char msg[32]; unsigned char asig[162]; unsigned char deckey[32]; + unsigned char zeros162[162] = { 0 }; /** setup **/ testrand256(sk); @@ -821,6 +822,14 @@ static void test_ecdsa_adaptor_api(void) { CHECK_ILLEGAL(CTX, secp256k1_ecdsa_adaptor_encrypt(CTX, asig, sk, NULL, msg, NULL, NULL)); CHECK_ILLEGAL(CTX, secp256k1_ecdsa_adaptor_encrypt(CTX, asig, sk, &zero_pk, msg, NULL, NULL)); + /* Test bad nonce functions */ + memset(asig, 1, sizeof(asig)); + CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, asig, sk, &enckey, msg, ecdsa_adaptor_nonce_function_failing, NULL) == 0); + CHECK(secp256k1_memcmp_var(asig, zeros162, sizeof(asig)) == 0); + memset(asig, 1, sizeof(asig)); + CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, asig, sk, &enckey, msg, ecdsa_adaptor_nonce_function_0, NULL) == 0); + CHECK(secp256k1_memcmp_var(asig, zeros162, sizeof(asig)) == 0); + CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, asig, sk, &enckey, msg, NULL, NULL) == 1); CHECK(secp256k1_ecdsa_adaptor_verify(CTX, asig, &pubkey, msg, &enckey) == 1); CHECK_ILLEGAL(CTX, secp256k1_ecdsa_adaptor_verify(CTX, NULL, &pubkey, msg, &enckey)); @@ -846,7 +855,7 @@ static void test_ecdsa_adaptor_api(void) { CHECK_ILLEGAL(CTX, secp256k1_ecdsa_adaptor_recover(CTX, deckey, &sig, asig, &zero_pk)); } -static void adaptor_tests_internal(void) { +static void adaptor_tests_internal_impl(secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void* ndata) { unsigned char seckey[32]; secp256k1_pubkey pubkey; unsigned char msg[32]; @@ -864,23 +873,15 @@ static void adaptor_tests_internal(void) { CHECK(secp256k1_ec_pubkey_create(CTX, &pubkey, seckey) == 1); CHECK(secp256k1_ec_pubkey_create(CTX, &enckey, deckey) == 1); - CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig, seckey, &enckey, msg, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig, seckey, &enckey, msg, noncefp, ndata) == 1); { + unsigned char adaptor_sig_tmp[162] = { 0 }; + /* Test overflowing seckey */ memset(big, 0xFF, 32); - CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig, big, &enckey, msg, NULL, NULL) == 0); - CHECK(secp256k1_memcmp_var(adaptor_sig, zeros162, sizeof(adaptor_sig)) == 0); - - /* Test different nonce functions */ - memset(adaptor_sig, 1, sizeof(adaptor_sig)); - CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig, seckey, &enckey, msg, ecdsa_adaptor_nonce_function_failing, NULL) == 0); - CHECK(secp256k1_memcmp_var(adaptor_sig, zeros162, sizeof(adaptor_sig)) == 0); - memset(&adaptor_sig, 1, sizeof(adaptor_sig)); - CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig, seckey, &enckey, msg, ecdsa_adaptor_nonce_function_0, NULL) == 0); - CHECK(secp256k1_memcmp_var(adaptor_sig, zeros162, sizeof(adaptor_sig)) == 0); - CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig, seckey, &enckey, msg, ecdsa_adaptor_nonce_function_overflowing, NULL) == 1); - CHECK(secp256k1_memcmp_var(adaptor_sig, zeros162, sizeof(adaptor_sig)) != 0); + CHECK(secp256k1_ecdsa_adaptor_encrypt(CTX, adaptor_sig_tmp, big, &enckey, msg, NULL, NULL) == 0); + CHECK(secp256k1_memcmp_var(adaptor_sig_tmp, zeros162, sizeof(adaptor_sig)) == 0); } { /* Test adaptor_sig_serialize roundtrip */ @@ -1040,6 +1041,16 @@ static void adaptor_tests_internal(void) { } } +static void adaptor_tests_internal(void) { + adaptor_tests_internal_impl(NULL, NULL); + /* Since the same nonce function with different algo arguments is used + * both for the adaptor sig secret nonce and the dleq secret nonce, + * but ecdsa_adaptor_nonce_function_overflowing ignores the algo arg + * (in violation of the documented API contract), the resulting secret + * nonces will be the same. */ + adaptor_tests_internal_impl(ecdsa_adaptor_nonce_function_overflowing, NULL); +} + static void multi_hop_lock_tests_internal(void) { unsigned char seckey_a[32]; unsigned char seckey_b[32]; From 7f1c5390c2313ca103a6be0dba0e058298dd6022 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 10:09:45 +0100 Subject: [PATCH 322/383] ecdsa_adaptor: Make files more self-contained --- src/modules/ecdsa_adaptor/dleq_impl.h | 10 ++++++++++ src/modules/ecdsa_adaptor/main_impl.h | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index f0f5ea21..a2f1b5ea 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -1,6 +1,16 @@ #ifndef SECP256K1_DLEQ_IMPL_H #define SECP256K1_DLEQ_IMPL_H +#include + +#include "../../../include/secp256k1_ecdsa_adaptor.h" + +#include "../../../src/eckey.h" +#include "../../../src/ecmult_const.h" +#include "../../../src/group.h" +#include "../../../src/hash.h" +#include "../../../src/scalar.h" + /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("DLEQ")||SHA256("DLEQ"). */ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) { diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index ea10207f..2fdd301c 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -7,9 +7,18 @@ #ifndef SECP256K1_MODULE_ECDSA_ADAPTOR_MAIN_H #define SECP256K1_MODULE_ECDSA_ADAPTOR_MAIN_H +#include + #include "../../../include/secp256k1_ecdsa_adaptor.h" #include "dleq_impl.h" +#include "../../../src/eckey.h" +#include "../../../src/ecmult.h" +#include "../../../src/ecmult_const.h" +#include "../../../src/group.h" +#include "../../../src/hash.h" +#include "../../../src/scalar.h" + /* (R, R', s', dleq_proof) */ static void secp256k1_ecdsa_adaptor_sig_serialize(unsigned char *adaptor_sig162, secp256k1_ge *r, secp256k1_ge *rp, const secp256k1_scalar *sp, const secp256k1_scalar *dleq_proof_e, const secp256k1_scalar *dleq_proof_s) { secp256k1_eckey_pubkey_serialize33(r, adaptor_sig162); From c0a26a9c1bd90ae46ededb223bad62d43614efc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:00:11 +0000 Subject: [PATCH 323/383] ci: enable surjectionproof module in CI configs Co-authored-by: real-or-random <1071625+real-or-random@users.noreply.github.com> --- .github/workflows/ci.yml | 43 +++++++++++++++++++++++++--------------- ci/ci.sh | 4 ++-- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c745ea8..d6ff8142 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,7 @@ env: ECDSA_S2C: 'no' GENERATOR: 'no' RANGEPROOF: 'no' + SURJECTIONPROOF: 'no' WHITELIST: 'no' ECDSAADAPTOR: 'no' BPPP: 'no' @@ -103,14 +104,14 @@ jobs: matrix: configuration: - env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' } - - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes'} + - env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes'} - env_vars: { WIDEMUL: 'int128' } - env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' } - env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' } - - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes'} + - env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes'} - env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' } - - env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes'} - - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' } + - env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes'} + - env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' } - env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' } - env_vars: { CPPFLAGS: '-DDETERMINISTIC' } - env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' } @@ -170,6 +171,7 @@ jobs: EXPERIMENTAL: 'yes' ECDSA_S2C: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' GENERATOR: 'yes' ECDSAADAPTOR: 'yes' @@ -206,6 +208,7 @@ jobs: EXPERIMENTAL: 'yes' ECDSA_S2C: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' GENERATOR: 'yes' ECDSAADAPTOR: 'yes' @@ -245,6 +248,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -274,6 +278,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -322,6 +327,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -375,6 +381,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -412,6 +419,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -466,6 +474,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -499,6 +508,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' @@ -535,15 +545,15 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' } - BUILD: 'distcheck' steps: @@ -592,13 +602,13 @@ jobs: fail-fast: false matrix: env_vars: - - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 } - - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - { WIDEMUL: 'int128', RECOVERY: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' } - - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CC: 'gcc' } + - { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', EXPERIMENTAL: 'yes', ECDSA_S2C: 'yes', RANGEPROOF: 'yes', SURJECTIONPROOF: 'yes', WHITELIST: 'yes', GENERATOR: 'yes', ECDSAADAPTOR: 'yes', BPPP: 'yes', SCHNORRSIG_HALFAGG: 'yes', CPPFLAGS: '-DVERIFY' } - BUILD: 'distcheck' steps: @@ -715,6 +725,7 @@ jobs: ECDSA_S2C: 'yes' GENERATOR: 'yes' RANGEPROOF: 'yes' + SURJECTIONPROOF: 'yes' WHITELIST: 'yes' ECDSAADAPTOR: 'yes' BPPP: 'yes' diff --git a/ci/ci.sh b/ci/ci.sh index 15916b79..2185e789 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -14,7 +14,7 @@ print_environment() { for var in WERROR_CFLAGS MAKEFLAGS BUILD \ ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ EXPERIMENTAL ECDH RECOVERY EXTRAKEYS SCHNORRSIG MUSIG SCHNORRSIG_HALFAGG ELLSWIFT \ - ECDSA_S2C GENERATOR RANGEPROOF WHITELIST ECDSAADAPTOR BPPP \ + ECDSA_S2C GENERATOR RANGEPROOF SURJECTIONPROOF WHITELIST ECDSAADAPTOR BPPP \ SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS SYMBOL_CHECK \ EXAMPLES \ HOST WRAPPER_CMD \ @@ -65,7 +65,7 @@ fi --enable-module-extrakeys="$EXTRAKEYS" \ --enable-module-ecdsa-s2c="$ECDSA_S2C" \ --enable-module-bppp="$BPPP" \ - --enable-module-rangeproof="$RANGEPROOF" --enable-module-whitelist="$WHITELIST" --enable-module-generator="$GENERATOR" \ + --enable-module-rangeproof="$RANGEPROOF" --enable-module-surjectionproof="$SURJECTIONPROOF" --enable-module-whitelist="$WHITELIST" --enable-module-generator="$GENERATOR" \ --enable-module-schnorrsig="$SCHNORRSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \ --enable-module-musig="$MUSIG" \ --enable-module-schnorrsig-halfagg="$SCHNORRSIG_HALFAGG" \ From 41a8a2a65b5f11835148e904652eacb014fd27e1 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 10:10:19 +0100 Subject: [PATCH 324/383] ecdsa_adaptor: Clarify identifiers --- src/modules/ecdsa_adaptor/dleq_impl.h | 2 ++ src/modules/ecdsa_adaptor/main_impl.h | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index a2f1b5ea..f183e50a 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -90,6 +90,8 @@ static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_c /* Generates a proof that the discrete logarithm of P1 to the secp256k1 base G is the * same as the discrete logarithm of P2 to the base Y */ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { + /* Note: r[2] and k are local to the DLEQ proof, and they differ from the + * values with the same identifiers in main_impl.h. */ secp256k1_ge r[2]; secp256k1_scalar k = { 0 }; unsigned char sk32[32]; diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index 2fdd301c..b18b86cc 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -139,9 +139,9 @@ const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_e int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char *adaptor_sig162, unsigned char *seckey32, const secp256k1_pubkey *enckey, const unsigned char *msg32, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { secp256k1_scalar k; - secp256k1_ge nonce_pts[2]; - secp256k1_gej nonce_ptj[2]; - secp256k1_ge enckey_ge; + secp256k1_ge r[2]; /* R, R' */ + secp256k1_gej rj[2]; /* R, R' */ + secp256k1_ge enckey_ge; /* Y */ secp256k1_scalar dleq_proof_s; secp256k1_scalar dleq_proof_e; secp256k1_scalar sk; @@ -177,19 +177,19 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); - /* R' := k*G */ - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[0], &k); /* R := k*Y */ - secp256k1_ecmult_const(&nonce_ptj[1], &enckey_ge, &k); + secp256k1_ecmult_const(&rj[0], &enckey_ge, &k); + /* R' := k*G */ + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj[1], &k); - secp256k1_ge_set_all_gej(nonce_pts, nonce_ptj, 2); + secp256k1_ge_set_all_gej(r, rj, 2); /* We declassify the non-secret nonce values to allow using them as branch points. */ - secp256k1_declassify(ctx, &nonce_pts[0], sizeof(nonce_pts[0])); - secp256k1_declassify(ctx, &nonce_pts[1], sizeof(nonce_pts[1])); + secp256k1_declassify(ctx, &r[0], sizeof(r[0])); + secp256k1_declassify(ctx, &r[1], sizeof(r[1])); /* dleq_proof = DLEQ_prove(k, (R', Y, R)) */ - if (!secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &nonce_pts[0], &nonce_pts[1], noncefp, ndata)) { + if (!secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &r[1], &r[0], noncefp, ndata)) { memset(adaptor_sig162, 0, 162); secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&k); @@ -198,8 +198,8 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey32); secp256k1_scalar_cmov(&sk, &secp256k1_scalar_one, !ret); secp256k1_scalar_set_b32(&msg, msg32, NULL); - secp256k1_fe_normalize(&nonce_pts[1].x); - secp256k1_fe_get_b32(buf33, &nonce_pts[1].x); + secp256k1_fe_normalize(&r[0].x); + secp256k1_fe_get_b32(buf33, &r[0].x); secp256k1_scalar_set_b32(&sigr, buf33, NULL); ret &= !secp256k1_scalar_is_zero(&sigr); /* s' = k⁻¹(m + R.x * x) */ @@ -210,7 +210,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= !secp256k1_scalar_is_zero(&sp); /* return (R, R', s', dleq_proof) */ - secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s); + secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &r[0], &r[1], &sp, &dleq_proof_e, &dleq_proof_s); secp256k1_memczero(adaptor_sig162, 162, !ret); secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); From a7d0f246d7ce529508b725421dd0178fdb354bd5 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 10:14:02 +0100 Subject: [PATCH 325/383] ecdsa_adaptor: Simplify code --- src/modules/ecdsa_adaptor/dleq_impl.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index f183e50a..cb097958 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -26,26 +26,23 @@ static const unsigned char dleq_algo[] = {'D','L','E','Q'}; static void secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) { unsigned char buf[33]; - size_t size = 33; secp256k1_eckey_pubkey_serialize33(p, buf); - - secp256k1_sha256_write(sha, buf, size); + secp256k1_sha256_write(sha, buf, 33); } static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, const unsigned char *gen2_33, const unsigned char *p1_33, const unsigned char *p2_33, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { secp256k1_sha256 sha; unsigned char buf[32]; unsigned char nonce[32]; - size_t size = 33; if (noncefp == NULL) { noncefp = secp256k1_nonce_function_ecdsa_adaptor; } secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, p1_33, size); - secp256k1_sha256_write(&sha, p2_33, size); + secp256k1_sha256_write(&sha, p1_33, 33); + secp256k1_sha256_write(&sha, p2_33, 33); secp256k1_sha256_finalize(&sha, buf); secp256k1_sha256_clear(&sha); From ed985641f47caaf3836657b5d45e9ca1a7158b7c Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 13:28:23 +0100 Subject: [PATCH 326/383] ecdsa_adaptor: Make arg order in dleq_{prove,verify} consistent --- src/modules/ecdsa_adaptor/dleq_impl.h | 2 +- src/modules/ecdsa_adaptor/main_impl.h | 2 +- src/modules/ecdsa_adaptor/tests_impl.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index cb097958..a117d69d 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -86,7 +86,7 @@ static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_c /* Generates a proof that the discrete logarithm of P1 to the secp256k1 base G is the * same as the discrete logarithm of P2 to the base Y */ -static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { +static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const secp256k1_scalar *sk, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { /* Note: r[2] and k are local to the DLEQ proof, and they differ from the * values with the same identifiers in main_impl.h. */ secp256k1_ge r[2]; diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index b18b86cc..0d590907 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -189,7 +189,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char secp256k1_declassify(ctx, &r[1], sizeof(r[1])); /* dleq_proof = DLEQ_prove(k, (R', Y, R)) */ - if (!secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &r[1], &r[0], noncefp, ndata)) { + if (!secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &r[1], &enckey_ge, &r[0], noncefp, ndata)) { memset(adaptor_sig162, 0, 162); secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&k); diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index 6176faec..09058997 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -45,7 +45,7 @@ static void dleq_tests_internal(void) { secp256k1_dleq_pair(&CTX->ecmult_gen_ctx, p, &sk, &gen2); p1 = p[0]; p2 = p[1]; - CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p1, &p2, NULL, NULL) == 1); + CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &p1, &gen2, &p2, NULL, NULL) == 1); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p2) == 1); { From 349a94b169357bd79102119d796ea557040b49e8 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 11:02:59 +0100 Subject: [PATCH 327/383] sync-upstream: Remove "select" mode and simplify I believe it was introduced to cherry-pick upstream PRs, but that simply doesn't work. Assume upstream is two PRs A and B ahead, and A has been merged before B. Then trying to cherry-picking B by merging the state of upstream's master after the merge-B commit won't do what we expect. In particular, the merge result will *include A's changes* because A had already been merged in upstream's master when B was merged. (One could think that merging the PR branch of B instead works, but this will yield the same result if B was rebased on master before it was merged.) The proper way to cherry-pick B is to create a PR that cherry-picks all commits that had been included in B. This could be done automatically, but the need to cherry-pick a PR is rare enough that we don't need tool support for it. In fact, because we want to keep cherry-picking at a minimum, there's a good chance that we'd anyway want to pick only a subset of the commits in a upstream PR, and that would need manual work anyway. --- contrib/sync-upstream.sh | 45 ++++++++++++---------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index c1ad8e0a..a0495f60 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -6,14 +6,11 @@ help() { echo "Sync merge commits from bitcoin-core/secp256k1 into secp256k1-zkp." echo echo "Usage:" - echo " $0 [-b ] range [end]" + echo " $0 [-b ] [end]" echo " Merges every merge commit present in upstream/master and missing in " echo " (default: master). If the optional [end] commit is provided, only merges" echo " up to and including [end]." echo - echo " $0 [-b ] select ... " - echo " Merges every selected merge commit into (default: master)." - echo echo "This tool creates a temporary branch and attempts to merge the upstream commits." echo "If there are merge conflicts, resolve them and run tests, then use the generated" echo "script contrib/gh-pr-create.sh to create the PR (requires the gh tool)." @@ -26,7 +23,7 @@ help() { echo "Listing upstream merge commits:" echo " To list merge commits in upstream/master that are missing from (oldest first):" echo " git log --oneline --merges \$(git merge-base upstream/master )..upstream/master | tac" - echo " Use these for [end] in 'range' or as arguments to 'select'." + echo " These are candidates for [end]." exit 1 } @@ -67,14 +64,18 @@ range() { esac } -# Process -b argument -while getopts "b:" opt; do +# Process -b and -h arguments +while getopts "b:h" opt; do case $opt in b) LOCAL_BRANCH=$OPTARG ;; - \?) - echo "Invalid option: -$OPTARG" >&2 + h) + help + ;; + *) + echo + help ;; esac done @@ -82,31 +83,11 @@ done # Shift off the processed options shift $((OPTIND -1)) -if [ "$#" -lt 1 ]; then - help -fi - -case $1 in - range) - shift - setup - range "$@" - REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH range $RANGEEND_COMMIT" - ;; - select) - shift - setup - COMMITS=$* - REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH select $@" - ;; - help) - help - ;; - *) - help -esac +setup +range "$@" TITLE="Upstream PRs" +REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH $RANGEEND_COMMIT" BODY="" for COMMIT in $COMMITS do From 656c7cc70449a2116de4e3475bce21809ee4a3f1 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 12:01:09 +0100 Subject: [PATCH 328/383] sync-upstream: Clarify that we merge a *single* upstream ref Roughly speaking, this changes (assuming 3 upstream PRs) git merge into git merge This is more intuitive. We're merging a single upstream revision, namely . The other two commits are simply parents of that one, i.e., they're included anyway, and git merge ignores them. (In fact, passing multiple refs looks like we're doing an octopus merge. It's just that git recognizes the fact that everything is included in the last ref anyway, and behaves as if only the last one had been passed.) This commit also makes some further clean ups and improvements. --- contrib/sync-upstream.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index a0495f60..1cb285bb 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -22,7 +22,7 @@ help() { echo echo "Listing upstream merge commits:" echo " To list merge commits in upstream/master that are missing from (oldest first):" - echo " git log --oneline --merges \$(git merge-base upstream/master )..upstream/master | tac" + echo " git log --oneline --topo-order --reverse --merges \$(git merge-base upstream/master )..upstream/master" echo " These are candidates for [end]." exit 1 } @@ -53,15 +53,7 @@ range() { if [ "$#" = 1 ]; then RANGEEND_COMMIT=$1 fi - - COMMITS=$(git --no-pager log --oneline --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT") - COMMITS=$(echo "$COMMITS" | tac | awk '{ print $1 }' ORS=' ') - echo "Merging $COMMITS. Continue with y" - read -r yn - case $yn in - [Yy]* ) ;; - * ) exit 1;; - esac + COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT") } # Process -b and -h arguments @@ -94,6 +86,7 @@ do PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\).*'/'\2'/) TITLE="$TITLE $PRNUM," BODY=$(printf "%s\n%s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\)'/'[bitcoin-core\/secp256k1#\2]'/)") + LAST_COMMIT="$COMMIT" done # Remove trailing "," TITLE=${TITLE%?} @@ -109,6 +102,13 @@ Tips: EOF ) +echo "Merging $TITLE. Continue with y" +read -r yn +case $yn in + [Yy]* ) ;; + * ) exit 1;; +esac + echo "-----------------------------------" echo "$TITLE" echo "-----------------------------------" @@ -140,4 +140,4 @@ EOT chmod +x "$FNAME" echo Run "$FNAME" after solving the merge conflicts -git merge --no-edit -m "Merge commits '$COMMITS' into temp-merge-$PRNUM" $COMMITS +git merge --no-edit -m "Merge upstream '${LAST_COMMIT:0:7}' into temp-merge-$PRNUM" "$LAST_COMMIT" From 229e1f127aeb3bf61d5301b1afc54bdb08858cdc Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 10:24:14 +0100 Subject: [PATCH 329/383] surjection: Fix read of uninitialized value in tests --- src/modules/surjection/tests_impl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index 731e2fd4..6083deb8 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -438,6 +438,9 @@ static void test_bad_serialize(void) { size_t serialized_len; proof.n_inputs = 0; + memset(proof.used_inputs, 0, SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS / 8); + memset(proof.data, 0, 32 * (1 + SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS)); + serialized_len = 2 + 31; /* e0 is one byte too short */ CHECK(secp256k1_surjectionproof_serialize(CTX, serialized_proof, &serialized_len, &proof) == 0); From 78999f3a9ae732c7e80a15264160bf1addcdf708 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 21:12:04 +0100 Subject: [PATCH 330/383] surjection: Fix leading whitespace --- src/modules/surjection/main_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index 2bd2c2cd..248efe14 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -25,7 +25,7 @@ static size_t secp256k1_count_bits_set(const unsigned char* data, size_t count) size_t i; for (i = 0; i < count; i++) { #ifdef HAVE_BUILTIN_POPCOUNT - ret += __builtin_popcount(data[i]); + ret += __builtin_popcount(data[i]); #else ret += !!(data[i] & 0x1); ret += !!(data[i] & 0x2); From 4359f050cc64c6e22280b5d8d22abda45f5d7de6 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 5 Mar 2026 21:26:12 +0100 Subject: [PATCH 331/383] surjection: Remove test that reads out of bounds --- src/modules/surjection/tests_impl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index 6083deb8..d81ac624 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -89,7 +89,6 @@ static void test_surjectionproof_api(void) { CHECK_ILLEGAL(CTX, secp256k1_surjectionproof_generate(CTX, NULL, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key)); CHECK_ILLEGAL(CTX, secp256k1_surjectionproof_generate(CTX, &proof, NULL, n_inputs, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key)); - CHECK(secp256k1_surjectionproof_generate(CTX, &proof, ephemeral_input_tags, n_inputs + 1, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(CTX, &proof, ephemeral_input_tags, n_inputs - 1, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK(secp256k1_surjectionproof_generate(CTX, &proof, ephemeral_input_tags, 0, &ephemeral_output_tag, 0, input_blinding_key[0], output_blinding_key) == 0); CHECK_ILLEGAL(CTX, secp256k1_surjectionproof_generate(CTX, &proof, ephemeral_input_tags, n_inputs, NULL, 0, input_blinding_key[0], output_blinding_key)); From 92e61ba95fecac82fd585f05c146788126bc1209 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 6 Mar 2026 12:39:49 +0200 Subject: [PATCH 332/383] build: Add missing schnorrsig_halfagg module configuration --- CMakeLists.txt | 2 ++ configure.ac | 3 +++ src/CMakeLists.txt | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce6a706e..c55cf10f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ option(SECP256K1_ENABLE_MODULE_WHITELIST "Enable key whitelist module." ON) option(SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR "Enable ecdsa adaptor signatures module." ON) option(SECP256K1_ENABLE_MODULE_ECDSA_S2C "Enable ECDSA sign-to-contract module." ON) option(SECP256K1_ENABLE_MODULE_BPPP "Enable Bulletproofs++ module." ON) +option(SECP256K1_ENABLE_MODULE_SCHNORRSIG_HALFAGG "Enable schnorrsig half-aggregation module." ON) option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF) if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS) @@ -302,6 +303,7 @@ message(" whitelist ........................... ${SECP256K1_ENABLE_MODULE_WHITE message(" ecdsa-s2c ........................... ${SECP256K1_ENABLE_MODULE_ECDSA_S2C}") message(" ecdsa-adaptor ....................... ${SECP256K1_ENABLE_MODULE_ECDSA_ADAPTOR}") message(" bppp ................................ ${SECP256K1_ENABLE_MODULE_BPPP}") +message(" schnorrsig-halfagg .................. ${SECP256K1_ENABLE_MODULE_SCHNORRSIG_HALFAGG}") message("Parameters:") message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}") message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB") diff --git a/configure.ac b/configure.ac index 1d961b09..05a8c586 100644 --- a/configure.ac +++ b/configure.ac @@ -455,6 +455,9 @@ SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS" # Processing must be done in a reverse topological sorting of the dependency graph # (dependent module first). if test x"$enable_module_schnorrsig_halfagg" = x"yes"; then + if test x"$enable_module_schnorrsig" = x"no"; then + AC_MSG_ERROR([Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the schnorrsig_halfagg module.]) + fi SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_SCHNORRSIG_HALFAGG=1" enable_module_schnorrsig=yes fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 938d8040..ddd5d314 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,15 @@ set_property(TARGET secp256k1 PROPERTY PUBLIC_HEADER # Processing must be done in a topological sorting of the dependency graph # (dependent module first). +if(SECP256K1_ENABLE_MODULE_SCHNORRSIG_HALFAGG) + if(DEFINED SECP256K1_ENABLE_MODULE_SCHNORRSIG AND NOT SECP256K1_ENABLE_MODULE_SCHNORRSIG) + message(FATAL_ERROR "Module dependency error: You have disabled the schnorrsig module explicitly, but it is required by the schnorrsig_halfagg module.") + endif() + set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON) + add_compile_definitions(ENABLE_MODULE_SCHNORRSIG_HALFAGG=1) + set_property(TARGET secp256k1 APPEND PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig_halfagg.h) +endif() + if(SECP256K1_ENABLE_MODULE_BPPP) if(DEFINED SECP256K1_ENABLE_MODULE_GENERATOR AND NOT SECP256K1_ENABLE_MODULE_GENERATOR) message(FATAL_ERROR "Module dependency error: You have disabled the generator module explicitly, but it is required by the bppp module.") From 7e68c0c88b5300a3c9516722ae23857eac00b756 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 3 Mar 2026 17:26:21 +0100 Subject: [PATCH 333/383] ecmult: Document and test ng=NULL in ecmult --- src/ecmult.h | 5 ++++- src/tests.c | 37 +++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/ecmult.h b/src/ecmult.h index 8d0a9f49..342195d9 100644 --- a/src/ecmult.h +++ b/src/ecmult.h @@ -40,7 +40,10 @@ /** The number of entries a table with precomputed multiples needs to have. */ #define ECMULT_TABLE_SIZE(w) ((size_t)1 << ((w)-2)) -/** Double multiply: R = na*A + ng*G */ +/** Double multiply: R = na*A + ng*G + * + * Passing NULL as ng is equivalent to the zero scalar but a tiny bit faster. + */ static void secp256k1_ecmult(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); typedef int (secp256k1_ecmult_multi_callback)(secp256k1_scalar *sc, secp256k1_ge *pt, size_t idx, void *data); diff --git a/src/tests.c b/src/tests.c index 7265d0df..bf7b432b 100644 --- a/src/tests.c +++ b/src/tests.c @@ -4380,11 +4380,19 @@ static void test_point_times_order(const secp256k1_gej *point) { CHECK(secp256k1_ge_is_valid_var(&res3) == 0); /* check zero/one edge cases */ secp256k1_ecmult(&res1, point, &secp256k1_scalar_zero, &secp256k1_scalar_zero); + secp256k1_ecmult(&res2, point, &secp256k1_scalar_zero, NULL); secp256k1_ge_set_gej(&res3, &res1); + CHECK(secp256k1_gej_is_infinity(&res1)); + CHECK(secp256k1_gej_is_infinity(&res2)); CHECK(secp256k1_ge_is_infinity(&res3)); + secp256k1_ecmult(&res1, point, &secp256k1_scalar_one, &secp256k1_scalar_zero); + secp256k1_ecmult(&res2, point, &secp256k1_scalar_one, NULL); secp256k1_ge_set_gej(&res3, &res1); CHECK(secp256k1_gej_eq_ge_var(point, &res3)); + secp256k1_ge_set_gej(&res3, &res2); + CHECK(secp256k1_gej_eq_ge_var(point, &res3)); + secp256k1_ecmult(&res1, point, &secp256k1_scalar_zero, &secp256k1_scalar_one); secp256k1_ge_set_gej(&res3, &res1); CHECK(secp256k1_ge_eq_var(&secp256k1_ge_const_g, &res3)); @@ -5480,24 +5488,25 @@ static int test_ecmult_accumulate_cb(secp256k1_scalar* sc, secp256k1_ge* pt, siz } static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar* x, secp256k1_scratch* scratch) { - /* Compute x*G in 6 different ways, serialize it uncompressed, and feed it into acc. */ - secp256k1_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj; + /* Compute x*G in many different ways, serialize it uncompressed, and feed it into acc. */ + secp256k1_gej gj, infj; secp256k1_ge r; + secp256k1_gej rj[7]; unsigned char bytes[65]; + size_t i; secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); secp256k1_gej_set_infinity(&infj); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); - secp256k1_ecmult(&rj2, &gj, x, &secp256k1_scalar_zero); - secp256k1_ecmult(&rj3, &infj, &secp256k1_scalar_zero, x); - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj4, x, NULL, NULL, 0)); - CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj5, &secp256k1_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1)); - secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x); - secp256k1_ge_set_gej_var(&r, &rj1); - CHECK(secp256k1_gej_eq_ge_var(&rj2, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj3, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj4, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj5, &r)); - CHECK(secp256k1_gej_eq_ge_var(&rj6, &r)); + secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj[0], x); + secp256k1_ecmult(&rj[1], &gj, x, NULL); + secp256k1_ecmult(&rj[2], &gj, x, &secp256k1_scalar_zero); + secp256k1_ecmult(&rj[3], &infj, &secp256k1_scalar_zero, x); + CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj[4], x, NULL, NULL, 0)); + CHECK(secp256k1_ecmult_multi_var(&CTX->error_callback, scratch, &rj[5], &secp256k1_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1)); + secp256k1_ecmult_const(&rj[6], &secp256k1_ge_const_g, x); + secp256k1_ge_set_gej_var(&r, &rj[0]); + for (i = 0; i < ARRAY_SIZE(rj); i++) { + CHECK(secp256k1_gej_eq_ge_var(&rj[i], &r)); + } if (secp256k1_ge_is_infinity(&r)) { /* Store infinity as 0x00 */ const unsigned char zerobyte[1] = {0}; From 3a403639dc07e39aa6dc48fbcecfe3cb77f09770 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Tue, 3 Mar 2026 17:27:14 +0100 Subject: [PATCH 334/383] eckey: Call ecmult with NULL instead of zero scalar --- src/eckey_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 48745e8f..57024e40 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -86,7 +86,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge *key, const secp256k1_s } secp256k1_gej_set_ge(&pt, key); - secp256k1_ecmult(&pt, &pt, tweak, &secp256k1_scalar_zero); + secp256k1_ecmult(&pt, &pt, tweak, NULL); secp256k1_ge_set_gej(key, &pt); return 1; } From 4681be065b0cd431c22881a964136c366736d3a1 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Thu, 12 Mar 2026 14:12:17 +0200 Subject: [PATCH 335/383] docs: Fix README module descriptions --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f786bbe5..af62b832 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ A fork of [libsecp256k1](https://github.com/bitcoin-core/secp256k1) with support Added features: * Experimental module for ECDSA adaptor signatures. * Experimental module for ECDSA sign-to-contract. -* Experimental module for Confidential Assets (Pedersen commitments, range proofs, and [surjection proofs](src/modules/surjection/surjection.md)). -* Experimental module for Bulletproofs++ range proofs. +* Experimental modules for Confidential Assets (Pedersen commitments, range proofs, and [surjection proofs](src/modules/surjection/surjection.md)). * Experimental module for [address whitelisting](src/modules/whitelist/whitelist.md). +* Experimental module for Schnorr signature half-aggregation. Experimental features are made available for testing and review by the community. The APIs of these features should not be considered stable. From bb736825c1d25384a58401e03d975b616e2b25e7 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 9 Mar 2026 18:36:11 +0200 Subject: [PATCH 336/383] sync-upstream: Add automatic GitHub Actions sync script --- .github/workflows/sync.yml | 98 ++++++++++++++++++++++++++++++++++++++ contrib/sync-upstream.sh | 75 +++++++++-------------------- 2 files changed, 121 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/sync.yml diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml new file mode 100644 index 00000000..ea16d068 --- /dev/null +++ b/.github/workflows/sync.yml @@ -0,0 +1,98 @@ +name: Upstream Sync + +on: + schedule: + - cron: '0 0 1 * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + sync-upstream: + runs-on: ubuntu-latest + env: + UPSTREAM: "https://github.com/bitcoin-core/secp256k1.git" + UPSTREAM_BRANCH: "master" + ORIGIN_BRANCH: "master" + MIN_UPSTREAM_MERGES: 1 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Fetch upstream & generate branch name & check for new commits + id: check_commits + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh repo set-default ${{ github.repository }} # Set the default repo to the origin repository + git remote add upstream ${{ env.UPSTREAM }} + git fetch upstream + + MERGES=$(git rev-list --count --merges HEAD..upstream/${{ env.UPSTREAM_BRANCH }}) + echo "Found $MERGES new merge commits in upstream." + + if [ "$MERGES" -lt ${{ env.MIN_UPSTREAM_MERGES }} ]; then + echo "Exiting." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + # Generate a sync branch name "sync-UPSTREAM_HEAD", where UPSTREAM_HEAD is a commit ID. + UPSTREAM_HEAD=$(git rev-parse --short upstream/${{ env.UPSTREAM_BRANCH }}) + SYNC_BRANCH="sync-$UPSTREAM_HEAD" + echo "Sync branch name: $SYNC_BRANCH" + echo "SYNC_BRANCH=$SYNC_BRANCH" >> "$GITHUB_ENV" + + # Check if the sync branch already exists in the origin repository + if git ls-remote --heads origin "$SYNC_BRANCH" | grep -q "$SYNC_BRANCH"; then + echo "Branch $SYNC_BRANCH already exists. Skipping the sync." + echo "skip=true" >> "$GITHUB_OUTPUT" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Generate PR metadata + id: branch_pr_metadata + if: steps.check_commits.outputs.skip == 'false' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Call the sync script to generate PR title and body + ./contrib/sync-upstream.sh -b ${{ env.ORIGIN_BRANCH }} "$SYNC_BRANCH" + + - name: Push a sync branch + id: push_branch + if: steps.check_commits.outputs.skip == 'false' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "Creating sync branch: $SYNC_BRANCH" + git checkout upstream/${{ env.UPSTREAM_BRANCH }} + git checkout -b "$SYNC_BRANCH" + git push -u origin "$SYNC_BRANCH" + + - name: Create pull request + id: create_pr + if: steps.check_commits.outputs.skip == 'false' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Execute the generated PR creation script + ./contrib/gh-pr-create.sh + + - name: Cleanup sync branch on failure + if: steps.push_branch.outcome == 'success' && steps.create_pr.outcome == 'failure' + run: | + echo "PR creation failed but branch was pushed. Deleting: $SYNC_BRANCH" + git push origin --delete "$SYNC_BRANCH" \ No newline at end of file diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index 1cb285bb..b3274040 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -6,53 +6,35 @@ help() { echo "Sync merge commits from bitcoin-core/secp256k1 into secp256k1-zkp." echo echo "Usage:" - echo " $0 [-b ] [end]" - echo " Merges every merge commit present in upstream/master and missing in " - echo " (default: master). If the optional [end] commit is provided, only merges" - echo " up to and including [end]." + echo " $0 [-b ] " + echo " Find every merge commit present in upstream/master and missing in (default: master)." echo - echo "This tool creates a temporary branch and attempts to merge the upstream commits." - echo "If there are merge conflicts, resolve them and run tests, then use the generated" - echo "script contrib/gh-pr-create.sh to create the PR (requires the gh tool)." + echo "This tool prepares the title and body for a sync PR" + echo "and generates a helper script contrib/gh-pr-create.sh." echo echo "Setup:" echo " Requires a remote named 'upstream' pointing to bitcoin-core/secp256k1." - echo " The script will fetch it automatically, and offer to create it if missing." - echo " To add manually: git remote add upstream git@github.com:bitcoin-core/secp256k1.git" echo echo "Listing upstream merge commits:" echo " To list merge commits in upstream/master that are missing from (oldest first):" echo " git log --oneline --topo-order --reverse --merges \$(git merge-base upstream/master )..upstream/master" - echo " These are candidates for [end]." exit 1 } REMOTE=upstream REMOTE_BRANCH="$REMOTE/master" LOCAL_BRANCH="master" -# Makes sure you have a remote "upstream" that is up-to-date -setup() { - ret=0 - git fetch "$REMOTE" &> /dev/null || ret="$?" - if [ ${ret} == 0 ]; then - return - fi - echo "Adding remote \"$REMOTE\" with URL git@github.com:bitcoin-core/secp256k1.git. Continue with y" - read -r yn - case $yn in - [Yy]* ) ;; - * ) exit 1;; - esac - git remote add "$REMOTE" git@github.com:bitcoin-core/secp256k1.git &> /dev/null - git fetch "$REMOTE" &> /dev/null -} + +if ! git remote get-url "$REMOTE" &> /dev/null; then +echo "Error: Remote '$REMOTE' not found." +echo "Add it with: git remote add upstream git@github.com:bitcoin-core/secp256k1.git" +echo "Then run: git fetch upstream" +exit 1 +fi range() { RANGESTART_COMMIT=$(git merge-base "$REMOTE_BRANCH" "$LOCAL_BRANCH") RANGEEND_COMMIT=$(git rev-parse "$REMOTE_BRANCH") - if [ "$#" = 1 ]; then - RANGEEND_COMMIT=$1 - fi COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT") } @@ -74,12 +56,19 @@ done # Shift off the processed options shift $((OPTIND -1)) +if [ "$#" -lt 1 ]; then + echo "Error: argument is required." >&2 + echo + help + exit 1 +fi -setup -range "$@" +# Extract the PR branch argument +PR_BRANCH=$1 + +range TITLE="Upstream PRs" -REPRODUCE_COMMAND="$0 -b $LOCAL_BRANCH $RANGEEND_COMMIT" BODY="" for COMMIT in $COMMITS do @@ -93,8 +82,6 @@ TITLE=${TITLE%?} BODY+=$(cat <\` to show the conflict resolution in the merge commit. * Use \`git read-tree --reset -u \` to replay these resolutions during the conflict resolution stage when recreating the PR branch locally. @@ -102,22 +89,11 @@ Tips: EOF ) -echo "Merging $TITLE. Continue with y" -read -r yn -case $yn in - [Yy]* ) ;; - * ) exit 1;; -esac - echo "-----------------------------------" echo "$TITLE" echo "-----------------------------------" echo "$BODY" echo "-----------------------------------" -# Create branch from PR commit and create PR -git checkout "$LOCAL_BRANCH" -git pull --autostash -git checkout -b temp-merge-"$PRNUM" # Escape single quote # ' -> '\'' @@ -132,12 +108,7 @@ BASEDIR=$(dirname "$0") FNAME="$BASEDIR/gh-pr-create.sh" cat < "$FNAME" #!/bin/sh -gh pr create -t '$TITLE' -b '$BODY' --web -# Remove temporary branch -git checkout "$LOCAL_BRANCH" -git branch -D temp-merge-"$PRNUM" +gh pr create -t '$TITLE' -b '$BODY' --base '$LOCAL_BRANCH' --head '$PR_BRANCH' EOT chmod +x "$FNAME" -echo Run "$FNAME" after solving the merge conflicts - -git merge --no-edit -m "Merge upstream '${LAST_COMMIT:0:7}' into temp-merge-$PRNUM" "$LAST_COMMIT" +echo "Generated $FNAME for creating a pull request with the above title and body." \ No newline at end of file From 3a18afd5ffe284e919fee74db9e694bc23f93665 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Tue, 17 Mar 2026 13:46:40 +0200 Subject: [PATCH 337/383] sync-upstream: Allow PAT for sync workflow --- .github/workflows/sync.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index ea16d068..04d60172 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -32,7 +32,7 @@ jobs: - name: Fetch upstream & generate branch name & check for new commits id: check_commits env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | gh repo set-default ${{ github.repository }} # Set the default repo to the origin repository git remote add upstream ${{ env.UPSTREAM }} @@ -66,7 +66,7 @@ jobs: id: branch_pr_metadata if: steps.check_commits.outputs.skip == 'false' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | # Call the sync script to generate PR title and body ./contrib/sync-upstream.sh -b ${{ env.ORIGIN_BRANCH }} "$SYNC_BRANCH" @@ -75,7 +75,7 @@ jobs: id: push_branch if: steps.check_commits.outputs.skip == 'false' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | echo "Creating sync branch: $SYNC_BRANCH" git checkout upstream/${{ env.UPSTREAM_BRANCH }} @@ -86,7 +86,7 @@ jobs: id: create_pr if: steps.check_commits.outputs.skip == 'false' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | # Execute the generated PR creation script ./contrib/gh-pr-create.sh From be075fe86cdc2d5d70f0791633d2225da2079ae6 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Tue, 17 Mar 2026 14:12:24 +0200 Subject: [PATCH 338/383] bench: Fix bench_whitelist hang --- src/bench_whitelist.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/bench_whitelist.c b/src/bench_whitelist.c index f02f1e86..46de7d5a 100644 --- a/src/bench_whitelist.c +++ b/src/bench_whitelist.c @@ -14,7 +14,6 @@ #include "hash_impl.h" #include "int128_impl.h" #include "scalar_impl.h" -#include "testrand_impl.h" #define MAX_N_KEYS 30 @@ -50,17 +49,19 @@ static void run_test(bench_data* data, int iters) { run_benchmark(str, bench_whitelist, bench_whitelist_setup, NULL, data, 100, iters); } -static void random_scalar_order(secp256k1_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - testrand256(b32); - secp256k1_scalar_set_b32(num, b32, &overflow); - if (overflow || secp256k1_scalar_is_zero(num)) { - continue; - } - break; - } while(1); +static void generate_scalar(secp256k1_scalar *scalar, unsigned char *seckey, uint32_t num) { + secp256k1_sha256 sha256; + unsigned char c[13] = {'w','h','i','t','e','l','i','s','t', 0, 0, 0, 0}; + int is_valid; + c[9] = num; + c[10] = num >> 8; + c[11] = num >> 16; + c[12] = num >> 24; + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, c, sizeof(c)); + secp256k1_sha256_finalize(&sha256, seckey); + is_valid = secp256k1_scalar_set_b32_seckey(scalar, seckey); + CHECK(is_valid); } int main(void) { @@ -76,22 +77,19 @@ int main(void) { data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); /* Start with subkey */ - random_scalar_order(&ssub); - secp256k1_scalar_get_b32(data.csub, &ssub); + generate_scalar(&ssub, data.csub, 0); CHECK(secp256k1_ec_seckey_verify(data.ctx, data.csub) == 1); CHECK(secp256k1_ec_pubkey_create(data.ctx, &data.sub_pubkey, data.csub) == 1); /* Then offline and online whitelist keys */ for (i = 0; i < n_keys; i++) { secp256k1_scalar son, soff; - /* Create two keys */ - random_scalar_order(&son); - secp256k1_scalar_get_b32(data.online_seckey[i], &son); + /* Create two keys using different counter values to ensure different keys */ + generate_scalar(&son, data.online_seckey[i], i + 1); CHECK(secp256k1_ec_seckey_verify(data.ctx, data.online_seckey[i]) == 1); CHECK(secp256k1_ec_pubkey_create(data.ctx, &data.online_pubkeys[i], data.online_seckey[i]) == 1); - random_scalar_order(&soff); - secp256k1_scalar_get_b32(data.summed_seckey[i], &soff); + generate_scalar(&soff, data.summed_seckey[i], i + 1 + n_keys); CHECK(secp256k1_ec_seckey_verify(data.ctx, data.summed_seckey[i]) == 1); CHECK(secp256k1_ec_pubkey_create(data.ctx, &data.offline_pubkeys[i], data.summed_seckey[i]) == 1); From c9a623c36265da7a0576ec17a3bddfde99316e60 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Thu, 19 Mar 2026 14:31:26 +0200 Subject: [PATCH 339/383] sync-upstream: Pass token via checkout for git push operations --- .github/workflows/sync.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 04d60172..0bfc76df 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -23,6 +23,7 @@ jobs: uses: actions/checkout@v6 with: fetch-depth: 0 + token: ${{ secrets.SYNC_PAT }} - name: Configure Git run: | @@ -65,8 +66,6 @@ jobs: - name: Generate PR metadata id: branch_pr_metadata if: steps.check_commits.outputs.skip == 'false' - env: - GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | # Call the sync script to generate PR title and body ./contrib/sync-upstream.sh -b ${{ env.ORIGIN_BRANCH }} "$SYNC_BRANCH" @@ -74,8 +73,6 @@ jobs: - name: Push a sync branch id: push_branch if: steps.check_commits.outputs.skip == 'false' - env: - GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | echo "Creating sync branch: $SYNC_BRANCH" git checkout upstream/${{ env.UPSTREAM_BRANCH }} From b84635ed3b426899c739ef2f58f98dd90bf0179e Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 20 Mar 2026 16:38:19 +0200 Subject: [PATCH 340/383] tests: Fix C89 function pointer initialization in ellswift tests --- src/modules/ellswift/tests_impl.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/ellswift/tests_impl.h b/src/modules/ellswift/tests_impl.h index 24721571..7da08d50 100644 --- a/src/modules/ellswift/tests_impl.h +++ b/src/modules/ellswift/tests_impl.h @@ -439,14 +439,18 @@ void ellswift_xdh_ctx_sha256_tests(void) { unsigned char out_default[65], out_custom[65]; const unsigned char skA[32] = {1}, skB[32] = {2}; unsigned char keyA[64], keyB[64], data[64] = {0}; - const secp256k1_ellswift_xdh_hash_function hash_funcs[2] = {secp256k1_ellswift_xdh_hash_function_bip324, secp256k1_ellswift_xdh_hash_function_prefix}; + secp256k1_ellswift_xdh_hash_function hash_fn; int i; CHECK(secp256k1_ellswift_create(ctx, keyA, skA, NULL)); CHECK(secp256k1_ellswift_create(ctx, keyB, skB, NULL)); for (i = 0; i < 2; i++) { - const secp256k1_ellswift_xdh_hash_function hash_fn = hash_funcs[i]; + if (i == 0) { + hash_fn = secp256k1_ellswift_xdh_hash_function_bip324; + } else { + hash_fn = secp256k1_ellswift_xdh_hash_function_prefix; + } /* Default behavior. No ctx-provided SHA256 compression */ CHECK(secp256k1_ellswift_xdh(ctx, out_default, keyA, keyB, skA, 0, hash_fn, data)); CHECK(!sha256_ellswift_xdh_called); From efa4e11b65599870022fa97c8c50ed97255f171b Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Fri, 20 Mar 2026 17:09:45 +0200 Subject: [PATCH 341/383] sync-upstream: Use GITHUB_TOKEN for gh commands --- .github/workflows/sync.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 0bfc76df..48184d49 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -6,7 +6,6 @@ on: workflow_dispatch: permissions: - contents: write pull-requests: write jobs: @@ -33,7 +32,7 @@ jobs: - name: Fetch upstream & generate branch name & check for new commits id: check_commits env: - GH_TOKEN: ${{ secrets.SYNC_PAT }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh repo set-default ${{ github.repository }} # Set the default repo to the origin repository git remote add upstream ${{ env.UPSTREAM }} @@ -83,7 +82,7 @@ jobs: id: create_pr if: steps.check_commits.outputs.skip == 'false' env: - GH_TOKEN: ${{ secrets.SYNC_PAT }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # Execute the generated PR creation script ./contrib/gh-pr-create.sh From 43fca0ff5594c1f25ef0ce63556b2ed344282190 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Mon, 23 Mar 2026 16:52:56 +0100 Subject: [PATCH 342/383] ecdsa: VERIFY_CHECK result of _fe_set_b32_limit This also avoids a spurious "-Wmaybe-uninitialized" warning emitted by gcc 16 (snapshot) when compiling with -DDETERMINISTIC. --- src/ecdsa_impl.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index ce36e85e..163539eb 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -196,6 +196,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25 unsigned char c[32]; secp256k1_scalar sn, u1, u2; #if !defined(EXHAUSTIVE_TEST_ORDER) + int range; secp256k1_fe xr; #endif secp256k1_gej pubkeyj; @@ -226,9 +227,16 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25 return secp256k1_scalar_eq(sigr, &computed_r); } #else + + /* Interpret sigr as a field element xr */ secp256k1_scalar_get_b32(c, sigr); - /* we can ignore the fe_set_b32_limit return value, because we know the input is in range */ - (void)secp256k1_fe_set_b32_limit(&xr, c); + range = secp256k1_fe_set_b32_limit(&xr, c); +#ifdef VERIFY + /* We know that c is in range; it comes from a scalar. */ + VERIFY_CHECK(range); +#else + (void)range; +#endif /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), From b96b655a82cd5b79188438de98f3c05792f2b6c3 Mon Sep 17 00:00:00 2001 From: Mykyta Redko Date: Tue, 24 Mar 2026 09:06:33 +0200 Subject: [PATCH 343/383] include: fix a minor grammar mistake in the rangeproof description --- include/secp256k1_rangeproof.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/secp256k1_rangeproof.h b/include/secp256k1_rangeproof.h index 8816bdcf..0224972f 100644 --- a/include/secp256k1_rangeproof.h +++ b/include/secp256k1_rangeproof.h @@ -23,7 +23,7 @@ extern "C" { * an unmodified way. * * Another difference is that the implementation omits the last ring's commitment - * from the proof and recovered by the verifier by subtracting all other digit + * from the proof, which is recovered by the verifier by subtracting all other digit * commitments from the total, reducing proof size by one group element. * * Furthermore, in the implementation every hash calculation includes a message From c5cd9d6d9a83d1cbe33e18acfcc68d563cdbab25 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Wed, 25 Mar 2026 22:30:38 +0100 Subject: [PATCH 344/383] gha: Bump deprecated GHA workflow dependencies Deprecation notice: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/ Changelogs (no entries relevant to us): * https://github.com/docker/setup-buildx-action/releases/tag/v4.0.0 * https://github.com/docker/build-push-action/releases/tag/v7.0.0 * https://github.com/actions/cache#v5 --- .github/actions/install-homebrew-valgrind/action.yml | 2 +- .github/actions/run-in-docker-action/action.yml | 6 +++--- .github/workflows/ci.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/install-homebrew-valgrind/action.yml b/.github/actions/install-homebrew-valgrind/action.yml index ce10eb26..e9aa6150 100644 --- a/.github/actions/install-homebrew-valgrind/action.yml +++ b/.github/actions/install-homebrew-valgrind/action.yml @@ -16,7 +16,7 @@ runs: cat valgrind_fingerprint shell: bash - - uses: actions/cache@v4 + - uses: actions/cache@v5 id: cache with: path: ${{ env.CI_HOMEBREW_CELLAR_VALGRIND }} diff --git a/.github/actions/run-in-docker-action/action.yml b/.github/actions/run-in-docker-action/action.yml index bbbcf324..f0eb9810 100644 --- a/.github/actions/run-in-docker-action/action.yml +++ b/.github/actions/run-in-docker-action/action.yml @@ -13,9 +13,9 @@ inputs: runs: using: "composite" steps: - - uses: docker/setup-buildx-action@v3 + - uses: docker/setup-buildx-action@v4 - - uses: docker/build-push-action@v6 + - uses: docker/build-push-action@v7 id: main_builder continue-on-error: true with: @@ -24,7 +24,7 @@ runs: load: true cache-from: type=gha,scope=${{ inputs.scope }} - - uses: docker/build-push-action@v6 + - uses: docker/build-push-action@v7 id: retry_builder if: steps.main_builder.outcome == 'failure' with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44c2754b..152f9a1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,14 +73,14 @@ jobs: run: echo "period=$((10#$(date +%V) / 4))" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 with: # See: https://github.com/moby/buildkit/issues/3969. driver-opts: | network=host - name: Build container - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: file: ./ci/linux-debian.Dockerfile cache-from: type=gha,scope=${{ runner.arch }}-${{ steps.cache_timestamp.outputs.period }} From e371ab5df0df9c945b8c3dd10294e15a214ebf26 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 23 Mar 2026 17:23:03 +0200 Subject: [PATCH 345/383] sync-upstream: Restore SYNC_PAT for gh commands --- .github/workflows/sync.yml | 7 ++----- contrib/sync-upstream.sh | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index 48184d49..cd534821 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -5,9 +5,6 @@ on: - cron: '0 0 1 * *' workflow_dispatch: -permissions: - pull-requests: write - jobs: sync-upstream: runs-on: ubuntu-latest @@ -32,7 +29,7 @@ jobs: - name: Fetch upstream & generate branch name & check for new commits id: check_commits env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | gh repo set-default ${{ github.repository }} # Set the default repo to the origin repository git remote add upstream ${{ env.UPSTREAM }} @@ -82,7 +79,7 @@ jobs: id: create_pr if: steps.check_commits.outputs.skip == 'false' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.SYNC_PAT }} run: | # Execute the generated PR creation script ./contrib/gh-pr-create.sh diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index b3274040..aaf8cb10 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -69,7 +69,7 @@ PR_BRANCH=$1 range TITLE="Upstream PRs" -BODY="" +BODY="${GITHUB_ACTIONS+This PR has been created by a GitHub Actions workflow without human involvement.}"$'\n' for COMMIT in $COMMITS do PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\).*'/'\2'/) From 0cad3df503b8426a4304f0f433562f201759514e Mon Sep 17 00:00:00 2001 From: "Peter.Dettman" Date: Sun, 12 Apr 2026 17:37:42 +0700 Subject: [PATCH 346/383] Improve checks for scalar _get_bits methods --- src/scalar_4x64_impl.h | 8 +++++--- src/scalar_8x32_impl.h | 3 ++- src/scalar_low_impl.h | 12 ++++++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/scalar_4x64_impl.h b/src/scalar_4x64_impl.h index a5bf18fe..b914136d 100644 --- a/src/scalar_4x64_impl.h +++ b/src/scalar_4x64_impl.h @@ -41,7 +41,8 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); + VERIFY_CHECK(offset <= 256 - count); + VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); return (a->d[offset >> 6] >> (offset & 0x3F)) & (0xFFFFFFFF >> (32 - count)); } @@ -49,12 +50,13 @@ SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK(offset + count <= 256); + VERIFY_CHECK(offset <= 256 - count); if ((offset + count - 1) >> 6 == offset >> 6) { - return secp256k1_scalar_get_bits_limb32(a, offset, count); + return (a->d[offset >> 6] >> (offset & 0x3F)) & (0xFFFFFFFF >> (32 - count)); } else { VERIFY_CHECK((offset >> 6) + 1 < 4); + VERIFY_CHECK((offset & 0x3F) > 0); return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & (0xFFFFFFFF >> (32 - count)); } } diff --git a/src/scalar_8x32_impl.h b/src/scalar_8x32_impl.h index aa87b1d3..055918ca 100644 --- a/src/scalar_8x32_impl.h +++ b/src/scalar_8x32_impl.h @@ -54,6 +54,7 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK(count > 0 && count <= 32); + VERIFY_CHECK(offset <= 256 - count); VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); return (a->d[offset >> 5] >> (offset & 0x1F)) & (0xFFFFFFFF >> (32 - count)); @@ -62,7 +63,7 @@ SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); VERIFY_CHECK(count > 0 && count <= 32); - VERIFY_CHECK(offset + count <= 256); + VERIFY_CHECK(offset <= 256 - count); if ((offset + count - 1) >> 5 == offset >> 5) { return secp256k1_scalar_get_bits_limb32(a, offset, count); diff --git a/src/scalar_low_impl.h b/src/scalar_low_impl.h index 628bfd33..164cda44 100644 --- a/src/scalar_low_impl.h +++ b/src/scalar_low_impl.h @@ -27,8 +27,10 @@ SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsig SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); - VERIFY_CHECK(count > 0 && count <= 32); + VERIFY_CHECK(offset <= 256 - count); + VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); + if (offset < 32) { return (*a >> offset) & (0xFFFFFFFF >> (32 - count)); } else { @@ -38,8 +40,14 @@ SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k SECP256K1_INLINE static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); + VERIFY_CHECK(count > 0 && count <= 32); + VERIFY_CHECK(offset <= 256 - count); - return secp256k1_scalar_get_bits_limb32(a, offset, count); + if (offset < 32) { + return (*a >> offset) & (0xFFFFFFFF >> (32 - count)); + } else { + return 0; + } } SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } From 285cb788e9da2a965178cc8e0769e4821ff0c799 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:54:22 +0100 Subject: [PATCH 347/383] ci: Replace `ilammy/msvc-dev-cmd` with manual MSVC setup The `ilammy/msvc-dev-cmd` repository seems abandoned and should be considered unsafe. This updates the workflow to load the MSVC environment variables directly via `vcvars64.bat`. See https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line. --- .github/workflows/ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 152f9a1f..9b836cd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -604,11 +604,10 @@ jobs: steps: - *CHECKOUT - - name: Add cl.exe to PATH - uses: ilammy/msvc-dev-cmd@v1 - - name: C++ (public headers) + shell: cmd run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" cl.exe -c -WX -TP include/*.h cxx_fpermissive_debian: From baac08d207003151d095423487d3954503a52aeb Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Thu, 2 Apr 2026 18:03:37 +0300 Subject: [PATCH 348/383] modules, tests: Port bitcoin-core/secp256k1#1777 and bitcoin-core/secp256k1#1824 to zkp-specific code --- src/bench_whitelist.c | 6 ++- src/eccommit.h | 2 +- src/eccommit_impl.h | 20 ++++---- src/modules/bppp/bppp_norm_product_impl.h | 10 ++-- src/modules/bppp/bppp_transcript_impl.h | 6 +-- src/modules/bppp/main_impl.h | 5 +- src/modules/bppp/tests_impl.h | 34 +++++++------- src/modules/ecdsa_adaptor/dleq_impl.h | 35 +++++++------- src/modules/ecdsa_adaptor/main_impl.h | 33 +++++++++---- src/modules/ecdsa_adaptor/tests_impl.h | 29 ++++++------ src/modules/ecdsa_s2c/main_impl.h | 13 ++++-- src/modules/ecdsa_s2c/tests_impl.h | 17 +++---- src/modules/generator/main_impl.h | 13 +++--- src/modules/musig/session_impl.h | 12 ----- src/modules/rangeproof/borromean.h | 4 +- src/modules/rangeproof/borromean_impl.h | 38 +++++++-------- src/modules/rangeproof/main_impl.h | 9 ++-- src/modules/rangeproof/rangeproof_impl.h | 52 ++++++++++----------- src/modules/rangeproof/tests_impl.h | 9 ++-- src/modules/schnorrsig_halfagg/main_impl.h | 26 ++++++----- src/modules/schnorrsig_halfagg/tests_impl.h | 3 +- src/modules/surjection/main_impl.h | 21 +++++---- src/modules/surjection/surjection_impl.h | 14 +++--- src/modules/surjection/tests_impl.h | 13 +++--- src/modules/whitelist/main_impl.h | 6 ++- src/modules/whitelist/whitelist_impl.h | 24 +++++----- src/secp256k1.c | 7 +-- src/tests.c | 22 +++++---- 28 files changed, 259 insertions(+), 224 deletions(-) diff --git a/src/bench_whitelist.c b/src/bench_whitelist.c index 46de7d5a..ecaa77b3 100644 --- a/src/bench_whitelist.c +++ b/src/bench_whitelist.c @@ -51,15 +51,17 @@ static void run_test(bench_data* data, int iters) { static void generate_scalar(secp256k1_scalar *scalar, unsigned char *seckey, uint32_t num) { secp256k1_sha256 sha256; + secp256k1_hash_ctx hash_ctx; unsigned char c[13] = {'w','h','i','t','e','l','i','s','t', 0, 0, 0, 0}; int is_valid; + secp256k1_hash_ctx_init(&hash_ctx); c[9] = num; c[10] = num >> 8; c[11] = num >> 16; c[12] = num >> 24; secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, c, sizeof(c)); - secp256k1_sha256_finalize(&sha256, seckey); + secp256k1_sha256_write(&hash_ctx, &sha256, c, sizeof(c)); + secp256k1_sha256_finalize(&hash_ctx, &sha256, seckey); is_valid = secp256k1_scalar_set_b32_seckey(scalar, seckey); CHECK(is_valid); } diff --git a/src/eccommit.h b/src/eccommit.h index 6bb11039..4932ad1c 100644 --- a/src/eccommit.h +++ b/src/eccommit.h @@ -17,7 +17,7 @@ static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* * pubp->infinity before calling this function. */ static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33); /** Compute an ec commitment tweak as hash(pubkey, data). */ -static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); +static int secp256k1_ec_commit_tweak(const secp256k1_hash_ctx *hash_ctx, unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); /** Compute an ec commitment as pubkey + hash(pubkey, data)*G. */ static int secp256k1_ec_commit(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size); /** Compute a secret key commitment as seckey + hash(pubkey, data). */ diff --git a/src/eccommit_impl.h b/src/eccommit_impl.h index 2dc24257..8f273bc5 100644 --- a/src/eccommit_impl.h +++ b/src/eccommit_impl.h @@ -25,42 +25,42 @@ static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsign } /* Compute an ec commitment tweak as hash(pubp, data). */ -static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) +static int secp256k1_ec_commit_tweak(const secp256k1_hash_ctx *hash_ctx, unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { unsigned char rbuf[33]; if (!secp256k1_ec_commit_pubkey_serialize_const(pubp, rbuf)) { return 0; } - secp256k1_sha256_write(sha, rbuf, sizeof(rbuf)); - secp256k1_sha256_write(sha, data, data_size); - secp256k1_sha256_finalize(sha, tweak32); + secp256k1_sha256_write(hash_ctx, sha, rbuf, sizeof(rbuf)); + secp256k1_sha256_write(hash_ctx, sha, data, data_size); + secp256k1_sha256_finalize(hash_ctx, sha, tweak32); return 1; } /* Compute an ec commitment as pubp + hash(pubp, data)*G. */ -static int secp256k1_ec_commit(secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { +static int secp256k1_ec_commit(const secp256k1_hash_ctx *hash_ctx, secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { unsigned char tweak[32]; *commitp = *pubp; - return secp256k1_ec_commit_tweak(tweak, commitp, sha, data, data_size) + return secp256k1_ec_commit_tweak(hash_ctx, tweak, commitp, sha, data, data_size) && secp256k1_ec_pubkey_tweak_add_helper(commitp, tweak); } /* Compute the seckey of an ec commitment from the original secret key of the pubkey as seckey + * hash(pubp, data). */ -static int secp256k1_ec_commit_seckey(secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { +static int secp256k1_ec_commit_seckey(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { unsigned char tweak[32]; - return secp256k1_ec_commit_tweak(tweak, pubp, sha, data, data_size) + return secp256k1_ec_commit_tweak(hash_ctx, tweak, pubp, sha, data, data_size) && secp256k1_ec_seckey_tweak_add_helper(seckey, tweak); } /* Verify an ec commitment as pubp + hash(pubp, data)*G ?= commitment. */ -static int secp256k1_ec_commit_verify(const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { +static int secp256k1_ec_commit_verify(const secp256k1_hash_ctx *hash_ctx, const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) { secp256k1_gej pj; secp256k1_ge p; - if (!secp256k1_ec_commit(&p, pubp, sha, data, data_size)) { + if (!secp256k1_ec_commit(hash_ctx, &p, pubp, sha, data, data_size)) { return 0; } diff --git a/src/modules/bppp/bppp_norm_product_impl.h b/src/modules/bppp/bppp_norm_product_impl.h index daf7b0da..0abd3cd4 100644 --- a/src/modules/bppp/bppp_norm_product_impl.h +++ b/src/modules/bppp/bppp_norm_product_impl.h @@ -236,6 +236,7 @@ static int secp256k1_bppp_rangeproof_norm_product_prove( secp256k1_scalar* c_vec, size_t c_vec_len ) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_scalar mu_f, rho_f = *rho; size_t proof_idx = 0; ecmult_x_cb_data x_cb_data; @@ -316,8 +317,8 @@ static int secp256k1_bppp_rangeproof_norm_product_prove( proof_idx += 65; /* Obtain challenge gamma for the the next round */ - secp256k1_sha256_write(transcript, &proof[proof_idx - 65], 65); - secp256k1_bppp_challenge_scalar(&gamma, transcript, 0); + secp256k1_sha256_write(hash_ctx, transcript, &proof[proof_idx - 65], 65); + secp256k1_bppp_challenge_scalar(hash_ctx, &gamma, transcript, 0); if (g_len > 1) { for (i = 0; i < g_len; i = i + 2) { @@ -434,6 +435,7 @@ static int secp256k1_bppp_rangeproof_norm_product_verify( size_t c_vec_len, const secp256k1_ge* commit ) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_scalar rho_f, mu_f, v, n, l, rho_inv, h_c; secp256k1_scalar *gammas, *s_g, *s_h, *rho_inv_pows; secp256k1_gej res1, res2; @@ -487,8 +489,8 @@ static int secp256k1_bppp_rangeproof_norm_product_verify( for (i = 0; i < n_rounds; i++) { secp256k1_scalar gamma; - secp256k1_sha256_write(transcript, &proof[i * 65], 65); - secp256k1_bppp_challenge_scalar(&gamma, transcript, 0); + secp256k1_sha256_write(hash_ctx, transcript, &proof[i * 65], 65); + secp256k1_bppp_challenge_scalar(hash_ctx, &gamma, transcript, 0); gammas[i] = gamma; } /* s_g[0] = n * \prod_{j=0}^{log_g_len - 1} rho^(2^j) diff --git a/src/modules/bppp/bppp_transcript_impl.h b/src/modules/bppp/bppp_transcript_impl.h index 5e212231..53b86c5d 100644 --- a/src/modules/bppp/bppp_transcript_impl.h +++ b/src/modules/bppp/bppp_transcript_impl.h @@ -22,12 +22,12 @@ static void secp256k1_bppp_sha256_tagged_commitment_init(secp256k1_sha256 *sha) } /* Obtain a challenge scalar from the current transcript.*/ -static void secp256k1_bppp_challenge_scalar(secp256k1_scalar* ch, const secp256k1_sha256 *transcript, uint64_t idx) { +static void secp256k1_bppp_challenge_scalar(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar* ch, const secp256k1_sha256 *transcript, uint64_t idx) { unsigned char buf[32]; secp256k1_sha256 sha = *transcript; secp256k1_bppp_le64(buf, idx); - secp256k1_sha256_write(&sha, buf, 8); - secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_write(hash_ctx, &sha, buf, 8); + secp256k1_sha256_finalize(hash_ctx, &sha, buf); secp256k1_sha256_clear(&sha); secp256k1_scalar_set_b32(ch, buf, NULL); } diff --git a/src/modules/bppp/main_impl.h b/src/modules/bppp/main_impl.h index e8e9e30a..8c4d1eab 100644 --- a/src/modules/bppp/main_impl.h +++ b/src/modules/bppp/main_impl.h @@ -18,6 +18,7 @@ secp256k1_bppp_generators *secp256k1_bppp_generators_create(const secp256k1_context *ctx, size_t n) { secp256k1_bppp_generators *ret; secp256k1_rfc6979_hmac_sha256 rng; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); unsigned char seed[64]; size_t i; @@ -37,11 +38,11 @@ secp256k1_bppp_generators *secp256k1_bppp_generators_create(const secp256k1_cont secp256k1_fe_get_b32(&seed[0], &secp256k1_ge_const_g.x); secp256k1_fe_get_b32(&seed[32], &secp256k1_ge_const_g.y); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, seed, 64); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, seed, 64); for (i = 0; i < n; i++) { secp256k1_generator gen; unsigned char tmp[32] = { 0 }; - secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, tmp, 32); CHECK(secp256k1_generator_generate(ctx, &gen, tmp)); secp256k1_generator_load(&ret->gens[i], &gen); } diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index dda9a8c0..47a00c6d 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -104,6 +104,7 @@ static void test_bppp_generators_fixed(void) { } static void test_bppp_tagged_hash(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); unsigned char tag_data[] = {'B', 'u', 'l', 'l', 'e', 't', 'p', 'r', 'o', 'o', 'f', 's', '_', 'p', 'p', '/', 'v', '0', '/', 'c', 'o', 'm', 'm', 'i', 't', 'm', 'e', 'n', 't'}; secp256k1_sha256 sha; secp256k1_sha256 sha_cached; @@ -111,10 +112,10 @@ static void test_bppp_tagged_hash(void) { unsigned char output_cached[32]; secp256k1_scalar s; - secp256k1_sha256_initialize_tagged(&sha, tag_data, sizeof(tag_data)); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, tag_data, sizeof(tag_data)); secp256k1_bppp_sha256_tagged_commitment_init(&sha_cached); - secp256k1_sha256_finalize(&sha, output); - secp256k1_sha256_finalize(&sha_cached, output_cached); + secp256k1_sha256_finalize(hash_ctx, &sha, output); + secp256k1_sha256_finalize(hash_ctx, &sha_cached, output_cached); CHECK(secp256k1_memcmp_var(output, output_cached, 32) == 0); { @@ -123,7 +124,7 @@ static void test_bppp_tagged_hash(void) { 0x8A, 0x41, 0xC6, 0x85, 0x1A, 0x79, 0x14, 0xFC, 0x48, 0x15, 0xC7, 0x2D, 0xF8, 0x63, 0x8F, 0x1B }; secp256k1_bppp_sha256_tagged_commitment_init(&sha); - secp256k1_bppp_challenge_scalar(&s, &sha, 0); + secp256k1_bppp_challenge_scalar(hash_ctx, &s, &sha, 0); secp256k1_scalar_get_b32(output, &s); CHECK(secp256k1_memcmp_var(output, expected, sizeof(output)) == 0); } @@ -134,8 +135,8 @@ static void test_bppp_tagged_hash(void) { 0x72, 0x7E, 0x3E, 0xB7, 0x10, 0x03, 0xF0, 0xE9, 0x69, 0x4D, 0xAA, 0x96, 0xCE, 0x98, 0xBB, 0x39, 0x1C, 0x2F, 0x7C, 0x2E, 0x1C, 0x17, 0x78, 0x6D }; - secp256k1_sha256_write(&sha, tmp, sizeof(tmp)); - secp256k1_bppp_challenge_scalar(&s, &sha, 0); + secp256k1_sha256_write(hash_ctx, &sha, tmp, sizeof(tmp)); + secp256k1_bppp_challenge_scalar(hash_ctx, &s, &sha, 0); secp256k1_scalar_get_b32(output, &s); CHECK(secp256k1_memcmp_var(output, expected, sizeof(output)) == 0); } @@ -279,6 +280,7 @@ static void secp256k1_norm_arg_commit_initial_data( const secp256k1_ge* commit ) { /* Commit to the initial public values */ + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); unsigned char ser_commit[33], ser_scalar[32], ser_le64[8]; size_t i; secp256k1_ge comm = *commit; @@ -287,24 +289,24 @@ static void secp256k1_norm_arg_commit_initial_data( secp256k1_fe_normalize(&comm.y); CHECK(secp256k1_ge_is_infinity(&comm) == 0); CHECK(secp256k1_bppp_serialize_pt(&ser_commit[0], &comm)); - secp256k1_sha256_write(transcript, ser_commit, 33); + secp256k1_sha256_write(hash_ctx, transcript, ser_commit, 33); secp256k1_scalar_get_b32(ser_scalar, rho); - secp256k1_sha256_write(transcript, ser_scalar, 32); + secp256k1_sha256_write(hash_ctx, transcript, ser_scalar, 32); secp256k1_bppp_le64(ser_le64, g_len); - secp256k1_sha256_write(transcript, ser_le64, 8); + secp256k1_sha256_write(hash_ctx, transcript, ser_le64, 8); secp256k1_bppp_le64(ser_le64, gens_vec->n); - secp256k1_sha256_write(transcript, ser_le64, 8); + secp256k1_sha256_write(hash_ctx, transcript, ser_le64, 8); for (i = 0; i < gens_vec->n; i++) { secp256k1_fe_normalize(&gens_vec->gens[i].x); secp256k1_fe_normalize(&gens_vec->gens[i].y); CHECK(secp256k1_bppp_serialize_pt(&ser_commit[0], &gens_vec->gens[i])); - secp256k1_sha256_write(transcript, ser_commit, 33); + secp256k1_sha256_write(hash_ctx, transcript, ser_commit, 33); } secp256k1_bppp_le64(ser_le64, c_vec_len); - secp256k1_sha256_write(transcript, ser_le64, 8); + secp256k1_sha256_write(hash_ctx, transcript, ser_le64, 8); for (i = 0; i < c_vec_len; i++) { secp256k1_scalar_get_b32(ser_scalar, &c_vec[i]); - secp256k1_sha256_write(transcript, ser_scalar, 32); + secp256k1_sha256_write(hash_ctx, transcript, ser_scalar, 32); } } @@ -561,7 +563,7 @@ int norm_arg_verify_vectors_helper(secp256k1_scratch *scratch, const unsigned ch return ret; } -#define IDX_TO_TEST(i) (norm_arg_verify_vectors_helper(scratch, verify_vector_gens, verify_vector_##i##_proof, sizeof(verify_vector_##i##_proof), verify_vector_##i##_r32, verify_vector_##i##_n_vec_len, verify_vector_##i##_c_vec32, verify_vector_##i##_c_vec, sizeof(verify_vector_##i##_c_vec)/sizeof(secp256k1_scalar), verify_vector_##i##_commit33) == verify_vector_##i##_result) +#define IDX_TO_TEST(i) (norm_arg_verify_vectors_helper(scratch, verify_vector_gens, verify_vector_##i##_proof, sizeof(verify_vector_##i##_proof), verify_vector_##i##_r32, verify_vector_##i##_n_vec_len, verify_vector_##i##_c_vec32, verify_vector_##i##_c_vec, ARRAY_SIZE(verify_vector_##i##_c_vec), verify_vector_##i##_commit33) == verify_vector_##i##_result) static void norm_arg_verify_vectors(void) { secp256k1_scratch *scratch = secp256k1_scratch_space_create(CTX, 1000*1000); /* shouldn't need much */ @@ -629,9 +631,9 @@ static void norm_arg_prove_vectors_helper(secp256k1_scratch *scratch, const unsi #define IDX_TO_TEST(i) (norm_arg_prove_vectors_helper(scratch, prove_vector_gens, prove_vector_##i##_proof, sizeof(prove_vector_##i##_proof), prove_vector_##i##_r32,\ - prove_vector_##i##_n_vec32, prove_vector_##i##_n_vec, sizeof(prove_vector_##i##_n_vec)/sizeof(secp256k1_scalar),\ + prove_vector_##i##_n_vec32, prove_vector_##i##_n_vec, ARRAY_SIZE(prove_vector_##i##_n_vec),\ prove_vector_##i##_l_vec32, prove_vector_##i##_l_vec,\ - prove_vector_##i##_c_vec32, prove_vector_##i##_c_vec, sizeof(prove_vector_##i##_c_vec)/sizeof(secp256k1_scalar), \ + prove_vector_##i##_c_vec32, prove_vector_##i##_c_vec, ARRAY_SIZE(prove_vector_##i##_c_vec), \ prove_vector_##i##_result)) static void norm_arg_prove_vectors(void) { diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index a117d69d..b05c0b18 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -24,14 +24,14 @@ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) { /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ static const unsigned char dleq_algo[] = {'D','L','E','Q'}; -static void secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) { +static void secp256k1_dleq_hash_point(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *sha, secp256k1_ge *p) { unsigned char buf[33]; secp256k1_eckey_pubkey_serialize33(p, buf); - secp256k1_sha256_write(sha, buf, 33); + secp256k1_sha256_write(hash_ctx, sha, buf, 33); } -static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, const unsigned char *gen2_33, const unsigned char *p1_33, const unsigned char *p2_33, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { +static int secp256k1_dleq_nonce(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *k, const unsigned char *sk32, const unsigned char *gen2_33, const unsigned char *p1_33, const unsigned char *p2_33, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { secp256k1_sha256 sha; unsigned char buf[32]; unsigned char nonce[32]; @@ -41,9 +41,9 @@ static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, } secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, p1_33, 33); - secp256k1_sha256_write(&sha, p2_33, 33); - secp256k1_sha256_finalize(&sha, buf); + secp256k1_sha256_write(hash_ctx, &sha, p1_33, 33); + secp256k1_sha256_write(hash_ctx, &sha, p2_33, 33); + secp256k1_sha256_finalize(hash_ctx, &sha, buf); secp256k1_sha256_clear(&sha); if (!noncefp(nonce, buf, sk32, gen2_33, dleq_algo, sizeof(dleq_algo), ndata)) { @@ -59,17 +59,17 @@ static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, /* Generates a challenge as defined in the DLC Specification at * https://github.com/discreetlogcontracts/dlcspecs */ -static void secp256k1_dleq_challenge(secp256k1_scalar *e, secp256k1_ge *gen2, secp256k1_ge *r1, secp256k1_ge *r2, secp256k1_ge *p1, secp256k1_ge *p2) { +static void secp256k1_dleq_challenge(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *e, secp256k1_ge *gen2, secp256k1_ge *r1, secp256k1_ge *r2, secp256k1_ge *p1, secp256k1_ge *p2) { unsigned char buf[32]; secp256k1_sha256 sha; secp256k1_nonce_function_dleq_sha256_tagged(&sha); - secp256k1_dleq_hash_point(&sha, p1); - secp256k1_dleq_hash_point(&sha, gen2); - secp256k1_dleq_hash_point(&sha, p2); - secp256k1_dleq_hash_point(&sha, r1); - secp256k1_dleq_hash_point(&sha, r2); - secp256k1_sha256_finalize(&sha, buf); + secp256k1_dleq_hash_point(hash_ctx, &sha, p1); + secp256k1_dleq_hash_point(hash_ctx, &sha, gen2); + secp256k1_dleq_hash_point(hash_ctx, &sha, p2); + secp256k1_dleq_hash_point(hash_ctx, &sha, r1); + secp256k1_dleq_hash_point(hash_ctx, &sha, r2); + secp256k1_sha256_finalize(hash_ctx, &sha, buf); secp256k1_sha256_clear(&sha); secp256k1_scalar_set_b32(e, buf, NULL); @@ -89,6 +89,7 @@ static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_c static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const secp256k1_scalar *sk, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { /* Note: r[2] and k are local to the DLEQ proof, and they differ from the * values with the same identifiers in main_impl.h. */ + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_ge r[2]; secp256k1_scalar k = { 0 }; unsigned char sk32[32]; @@ -103,7 +104,7 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar * secp256k1_scalar_get_b32(sk32, sk); - ret = secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, noncefp, ndata); + ret = secp256k1_dleq_nonce(hash_ctx, &k, sk32, gen2_33, p1_33, p2_33, noncefp, ndata); secp256k1_declassify(ctx, &ret, sizeof(ret)); if (!ret) { secp256k1_memclear_explicit(sk32, sizeof(sk32)); @@ -118,7 +119,7 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar * /* e = tagged hash(p1, gen2, p2, r[0], r[1]) */ /* s = k + e * sk */ - secp256k1_dleq_challenge(e, gen2, &r[0], &r[1], p1, p2); + secp256k1_dleq_challenge(hash_ctx, e, gen2, &r[0], &r[1], p1, p2); secp256k1_scalar_mul(s, e, sk); secp256k1_scalar_add(s, s, &k); @@ -127,7 +128,7 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar * return 1; } -static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scalar *e, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2) { +static int secp256k1_dleq_verify(const secp256k1_hash_ctx *hash_ctx, const secp256k1_scalar *s, const secp256k1_scalar *e, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2) { secp256k1_scalar e_neg; secp256k1_scalar e_expected; secp256k1_gej gen2j; @@ -154,7 +155,7 @@ static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scal secp256k1_ge_set_all_gej_var(r, rj, 2); - secp256k1_dleq_challenge(&e_expected, gen2, &r[0], &r[1], p1, p2); + secp256k1_dleq_challenge(hash_ctx, &e_expected, gen2, &r[0], &r[1], p1, p2); secp256k1_scalar_add(&e_expected, &e_expected, &e_neg); return secp256k1_scalar_is_zero(&e_expected); diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index 0d590907..19fe1b09 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -90,7 +90,7 @@ static void secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(secp256k1_s static const unsigned char ecdsa_adaptor_algo[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; /* Modified BIP-340 nonce function */ -static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo, size_t algolen, void *data) { +static int nonce_function_ecdsa_adaptor_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo, size_t algolen, void *data) { secp256k1_sha256 sha; unsigned char masked_key[32]; int i; @@ -101,8 +101,8 @@ static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned c if (data != NULL) { secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(&sha); - secp256k1_sha256_write(&sha, data, 32); - secp256k1_sha256_finalize(&sha, masked_key); + secp256k1_sha256_write(hash_ctx, &sha, data, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, masked_key); secp256k1_sha256_clear(&sha); for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; @@ -119,22 +119,34 @@ static int nonce_function_ecdsa_adaptor(unsigned char *nonce32, const unsigned c && secp256k1_memcmp_var(algo, dleq_algo, algolen) == 0) { secp256k1_nonce_function_dleq_sha256_tagged(&sha); } else { - secp256k1_sha256_initialize_tagged(&sha, algo, algolen); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, algo, algolen); } /* Hash (masked-)key||pk||msg using the tagged hash as per BIP-340 */ if (data != NULL) { - secp256k1_sha256_write(&sha, masked_key, 32); + secp256k1_sha256_write(hash_ctx, &sha, masked_key, 32); } else { - secp256k1_sha256_write(&sha, key32, 32); + secp256k1_sha256_write(hash_ctx, &sha, key32, 32); } - secp256k1_sha256_write(&sha, pk33, 33); - secp256k1_sha256_write(&sha, msg32, 32); - secp256k1_sha256_finalize(&sha, nonce32); + secp256k1_sha256_write(hash_ctx, &sha, pk33, 33); + secp256k1_sha256_write(hash_ctx, &sha, msg32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, nonce32); secp256k1_sha256_clear(&sha); return 1; } +static int nonce_function_ecdsa_adaptor( + unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + const unsigned char *pk33, + const unsigned char *algo, + size_t algolen, + void *data) +{ + return nonce_function_ecdsa_adaptor_impl(secp256k1_get_hash_context(secp256k1_context_static),nonce32, msg32, key32, pk33, algo, algolen, data); +} + const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_ecdsa_adaptor = nonce_function_ecdsa_adaptor; int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char *adaptor_sig162, unsigned char *seckey32, const secp256k1_pubkey *enckey, const unsigned char *msg32, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { @@ -232,6 +244,7 @@ int secp256k1_ecdsa_adaptor_verify(const secp256k1_context* ctx, const unsigned secp256k1_gej derived_rp; secp256k1_scalar sn, u1, u2; secp256k1_gej pubkeyj; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); VERIFY_CHECK(ctx != NULL); ARG_CHECK(adaptor_sig162 != NULL); @@ -246,7 +259,7 @@ int secp256k1_ecdsa_adaptor_verify(const secp256k1_context* ctx, const unsigned return 0; } /* DLEQ_verify((R', Y, R), dleq_proof) */ - if(!secp256k1_dleq_verify(&dleq_proof_s, &dleq_proof_e, &rp, &enckey_ge, &r)) { + if(!secp256k1_dleq_verify(hash_ctx, &dleq_proof_s, &dleq_proof_e, &rp, &enckey_ge, &r)) { return 0; } secp256k1_scalar_set_b32(&msg, msg32, NULL); diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index 09058997..693cc7dd 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -20,15 +20,17 @@ static void rand_point(secp256k1_ge *point) { } static void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_scalar k1, k2; - CHECK(secp256k1_dleq_nonce(&k1, args[0], args[1], args[2], args[3], NULL, args[4]) == 1); + CHECK(secp256k1_dleq_nonce(hash_ctx, &k1, args[0], args[1], args[2], args[3], NULL, args[4]) == 1); testrand_flip(args[n_flip], n_bytes); - CHECK(secp256k1_dleq_nonce(&k2, args[0], args[1], args[2], args[3], NULL, args[4]) == 1); + CHECK(secp256k1_dleq_nonce(hash_ctx, &k2, args[0], args[1], args[2], args[3], NULL, args[4]) == 1); CHECK(secp256k1_scalar_eq(&k1, &k2) == 0); } static void dleq_tests_internal(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_scalar s, e, sk, k; secp256k1_ge gen2, p1, p2; secp256k1_ge p[2]; @@ -46,20 +48,20 @@ static void dleq_tests_internal(void) { p1 = p[0]; p2 = p[1]; CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &p1, &gen2, &p2, NULL, NULL) == 1); - CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p2) == 1); + CHECK(secp256k1_dleq_verify(hash_ctx, &s, &e, &p1, &gen2, &p2) == 1); { secp256k1_scalar tmp; secp256k1_scalar_set_int(&tmp, 1); - CHECK(secp256k1_dleq_verify(&tmp, &e, &p1, &gen2, &p2) == 0); - CHECK(secp256k1_dleq_verify(&s, &tmp, &p1, &gen2, &p2) == 0); + CHECK(secp256k1_dleq_verify(hash_ctx, &tmp, &e, &p1, &gen2, &p2) == 0); + CHECK(secp256k1_dleq_verify(hash_ctx, &s, &tmp, &p1, &gen2, &p2) == 0); } { secp256k1_ge p_tmp; rand_point(&p_tmp); - CHECK(secp256k1_dleq_verify(&s, &e, &p_tmp, &gen2, &p2) == 0); - CHECK(secp256k1_dleq_verify(&s, &e, &p1, &p_tmp, &p2) == 0); - CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p_tmp) == 0); + CHECK(secp256k1_dleq_verify(hash_ctx, &s, &e, &p_tmp, &gen2, &p2) == 0); + CHECK(secp256k1_dleq_verify(hash_ctx, &s, &e, &p1, &p_tmp, &p2) == 0); + CHECK(secp256k1_dleq_verify(hash_ctx, &s, &e, &p1, &gen2, &p_tmp) == 0); } /* Nonce tests */ @@ -67,7 +69,7 @@ static void dleq_tests_internal(void) { secp256k1_eckey_pubkey_serialize33(&gen2, gen2_33); secp256k1_eckey_pubkey_serialize33(&p1, p1_33); secp256k1_eckey_pubkey_serialize33(&p2, p2_33); - CHECK(secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1); + CHECK(secp256k1_dleq_nonce(hash_ctx, &k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1); testrand_bytes_test(sk32, sizeof(sk32)); testrand_bytes_test(gen2_33, sizeof(gen2_33)); @@ -93,7 +95,7 @@ static void dleq_tests_internal(void) { } /* NULL aux_rand argument is allowed. */ - CHECK(secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1); + CHECK(secp256k1_dleq_nonce(hash_ctx, &k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1); } static void rand_flip_bit(unsigned char *array, size_t n) { @@ -715,6 +717,7 @@ static void nonce_function_ecdsa_adaptor_bitflip(unsigned char **args, size_t n_ } static void run_nonce_function_ecdsa_adaptor_tests(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); static const unsigned char tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; static const unsigned char aux_tag[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'a', 'u', 'x'}; unsigned char algo[] = {'E', 'C', 'D', 'S', 'A', 'a', 'd', 'a', 'p', 't', 'o', 'r', '/', 'n', 'o', 'n'}; @@ -733,19 +736,19 @@ static void run_nonce_function_ecdsa_adaptor_tests(void) { * secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged has the expected * state. */ secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, tag, sizeof(tag)); /* Check that hash initialized by * secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux has the expected * state. */ secp256k1_nonce_function_ecdsa_adaptor_sha256_tagged_aux(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, aux_tag, sizeof(aux_tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, aux_tag, sizeof(aux_tag)); /* Check that hash initialized by * secp256k1_nonce_function_dleq_sha256_tagged_aux has the expected * state. */ secp256k1_nonce_function_dleq_sha256_tagged(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, dleq_tag, sizeof(dleq_tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, dleq_tag, sizeof(dleq_tag)); testrand_bytes_test(msg, sizeof(msg)); testrand_bytes_test(key, sizeof(key)); diff --git a/src/modules/ecdsa_s2c/main_impl.h b/src/modules/ecdsa_s2c/main_impl.h index cdc54737..d8d85384 100644 --- a/src/modules/ecdsa_s2c/main_impl.h +++ b/src/modules/ecdsa_s2c/main_impl.h @@ -55,6 +55,7 @@ static void secp256k1_s2c_ecdsa_data_sha256_tagged(secp256k1_sha256 *sha) { int secp256k1_ecdsa_s2c_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature* signature, secp256k1_ecdsa_s2c_opening* s2c_opening, const unsigned char *msg32, const unsigned char *seckey, const unsigned char* s2c_data32) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_scalar r, s; int ret; unsigned char ndata[32]; @@ -72,8 +73,8 @@ int secp256k1_ecdsa_s2c_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signa * to derive nonces even if only a SHA256 commitment to the data is * known. This is important in the ECDSA anti-exfil protocol. */ secp256k1_s2c_ecdsa_data_sha256_tagged(&s2c_sha); - secp256k1_sha256_write(&s2c_sha, s2c_data32, 32); - secp256k1_sha256_finalize(&s2c_sha, ndata); + secp256k1_sha256_write(hash_ctx, &s2c_sha, s2c_data32, 32); + secp256k1_sha256_finalize(hash_ctx, &s2c_sha, ndata); secp256k1_sha256_clear(&s2c_sha); secp256k1_s2c_ecdsa_point_sha256_tagged(&s2c_sha); @@ -85,6 +86,7 @@ int secp256k1_ecdsa_s2c_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signa } int secp256k1_ecdsa_s2c_verify_commit(const secp256k1_context* ctx, const secp256k1_ecdsa_signature* sig, const unsigned char* data32, const secp256k1_ecdsa_s2c_opening* opening) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_ge commitment_ge; secp256k1_ge original_pubnonce_ge; unsigned char x_bytes[32]; @@ -100,7 +102,7 @@ int secp256k1_ecdsa_s2c_verify_commit(const secp256k1_context* ctx, const secp25 return 0; } secp256k1_s2c_ecdsa_point_sha256_tagged(&s2c_sha); - if (!secp256k1_ec_commit(&commitment_ge, &original_pubnonce_ge, &s2c_sha, data32, 32)) { + if (!secp256k1_ec_commit(hash_ctx, &commitment_ge, &original_pubnonce_ge, &s2c_sha, data32, 32)) { return 0; } @@ -128,14 +130,15 @@ int secp256k1_ecdsa_s2c_verify_commit(const secp256k1_context* ctx, const secp25 /*** anti-exfil ***/ int secp256k1_ecdsa_anti_exfil_host_commit(const secp256k1_context* ctx, unsigned char* rand_commitment32, const unsigned char* rand32) { secp256k1_sha256 sha; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); VERIFY_CHECK(ctx != NULL); ARG_CHECK(rand_commitment32 != NULL); ARG_CHECK(rand32 != NULL); secp256k1_s2c_ecdsa_data_sha256_tagged(&sha); - secp256k1_sha256_write(&sha, rand32, 32); - secp256k1_sha256_finalize(&sha, rand_commitment32); + secp256k1_sha256_write(hash_ctx, &sha, rand32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, rand_commitment32); secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/modules/ecdsa_s2c/tests_impl.h b/src/modules/ecdsa_s2c/tests_impl.h index d13e5164..ba4f158c 100644 --- a/src/modules/ecdsa_s2c/tests_impl.h +++ b/src/modules/ecdsa_s2c/tests_impl.h @@ -11,6 +11,7 @@ #include "../../unit_test.h" static void test_ecdsa_s2c_tagged_hash(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); unsigned char tag_data[] = {'s', '2', 'c', '/', 'e', 'c', 'd', 's', 'a', '/', 'd', 'a', 't', 'a'}; unsigned char tag_point[] = {'s', '2', 'c', '/', 'e', 'c', 'd', 's', 'a', '/', 'p', 'o', 'i', 'n', 't'}; secp256k1_sha256 sha; @@ -18,16 +19,16 @@ static void test_ecdsa_s2c_tagged_hash(void) { unsigned char output[32]; unsigned char output_optimized[32]; - secp256k1_sha256_initialize_tagged(&sha, tag_data, sizeof(tag_data)); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, tag_data, sizeof(tag_data)); secp256k1_s2c_ecdsa_data_sha256_tagged(&sha_optimized); - secp256k1_sha256_finalize(&sha, output); - secp256k1_sha256_finalize(&sha_optimized, output_optimized); + secp256k1_sha256_finalize(hash_ctx, &sha, output); + secp256k1_sha256_finalize(hash_ctx, &sha_optimized, output_optimized); CHECK(secp256k1_memcmp_var(output, output_optimized, 32) == 0); - secp256k1_sha256_initialize_tagged(&sha, tag_point, sizeof(tag_point)); + secp256k1_sha256_initialize_tagged(hash_ctx, &sha, tag_point, sizeof(tag_point)); secp256k1_s2c_ecdsa_point_sha256_tagged(&sha_optimized); - secp256k1_sha256_finalize(&sha, output); - secp256k1_sha256_finalize(&sha_optimized, output_optimized); + secp256k1_sha256_finalize(hash_ctx, &sha, output); + secp256k1_sha256_finalize(hash_ctx, &sha_optimized, output_optimized); CHECK(secp256k1_memcmp_var(output, output_optimized, 32) == 0); } @@ -171,7 +172,7 @@ static void test_ecdsa_s2c_fixed_vectors(void) { }; size_t i; - for (i = 0; i < sizeof(ecdsa_s2c_tests) / sizeof(ecdsa_s2c_tests[0]); i++) { + for (i = 0; i < ARRAY_SIZE(ecdsa_s2c_tests); i++) { secp256k1_ecdsa_s2c_opening s2c_opening; unsigned char opening_ser[33]; const ecdsa_s2c_test *test = &ecdsa_s2c_tests[i]; @@ -248,7 +249,7 @@ static void test_ecdsa_anti_exfil_signer_commit(void) { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, }; /* Check that original pubnonce is derived from s2c_data */ - for (i = 0; i < sizeof(ecdsa_s2c_tests) / sizeof(ecdsa_s2c_tests[0]); i++) { + for (i = 0; i < ARRAY_SIZE(ecdsa_s2c_tests); i++) { secp256k1_ecdsa_s2c_opening s2c_opening; unsigned char buf[33]; const ecdsa_s2c_test *test = &ecdsa_s2c_tests[i]; diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index c58d66fe..c2a1adff 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -211,6 +211,7 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s secp256k1_sha256 sha256; unsigned char b32[32]; int ret = 1; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); if (blind32) { secp256k1_scalar blind; @@ -220,9 +221,9 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s } secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, prefix1, 16); - secp256k1_sha256_write(&sha256, key32, 32); - secp256k1_sha256_finalize(&sha256, b32); + secp256k1_sha256_write(hash_ctx, &sha256, prefix1, 16); + secp256k1_sha256_write(hash_ctx, &sha256, key32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha256, b32); secp256k1_sha256_clear(&sha256); ret &= secp256k1_fe_set_b32_limit(&t, b32); shallue_van_de_woestijne(&add, &t); @@ -233,9 +234,9 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s } secp256k1_sha256_initialize(&sha256); - secp256k1_sha256_write(&sha256, prefix2, 16); - secp256k1_sha256_write(&sha256, key32, 32); - secp256k1_sha256_finalize(&sha256, b32); + secp256k1_sha256_write(hash_ctx, &sha256, prefix2, 16); + secp256k1_sha256_write(hash_ctx, &sha256, key32, 32); + secp256k1_sha256_finalize(hash_ctx, &sha256, b32); secp256k1_sha256_clear(&sha256); ret &= secp256k1_fe_set_b32_limit(&t, b32); shallue_van_de_woestijne(&add, &t); diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 2c89ba20..7920fbfd 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -619,18 +619,6 @@ int secp256k1_musig_nonce_process(const secp256k1_context* ctx, secp256k1_musig_ secp256k1_ge_set_gej(&aggnonce_pts[0], &tmp); } - /* Add public adaptor to nonce */ - if (adaptor != NULL) { - secp256k1_ge adaptorp; - secp256k1_gej tmp; - if (!secp256k1_pubkey_load(ctx, &adaptorp, adaptor)) { - return 0; - } - secp256k1_gej_set_ge(&tmp, &aggnonce_pts[0]); - secp256k1_gej_add_ge_var(&tmp, &tmp, &adaptorp, NULL); - secp256k1_ge_set_gej(&aggnonce_pts[0], &tmp); - } - secp256k1_musig_nonce_process_internal(ctx, &session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); secp256k1_schnorrsig_challenge(secp256k1_get_hash_context(ctx), &session_i.challenge, fin_nonce, msg32, 32, agg_pk32); diff --git a/src/modules/rangeproof/borromean.h b/src/modules/rangeproof/borromean.h index 5620deac..b4d58d31 100644 --- a/src/modules/rangeproof/borromean.h +++ b/src/modules/rangeproof/borromean.h @@ -14,10 +14,10 @@ #include "../../ecmult.h" #include "../../ecmult_gen.h" -static int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, +static int secp256k1_borromean_verify(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen); -static int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, +static int secp256k1_borromean_sign(const secp256k1_hash_ctx *hash_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen); diff --git a/src/modules/rangeproof/borromean_impl.h b/src/modules/rangeproof/borromean_impl.h index 2fff3c28..cd62abaa 100644 --- a/src/modules/rangeproof/borromean_impl.h +++ b/src/modules/rangeproof/borromean_impl.h @@ -20,7 +20,7 @@ #include #include -SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, +SECP256K1_INLINE static void secp256k1_borromean_hash(const secp256k1_hash_ctx *hash_ctx, unsigned char *hash, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen, size_t ridx, size_t eidx) { unsigned char ring[4]; unsigned char epos[4]; @@ -28,11 +28,11 @@ SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const secp256k1_sha256_initialize(&sha256_en); secp256k1_write_be32(ring, (uint32_t)ridx); secp256k1_write_be32(epos, (uint32_t)eidx); - secp256k1_sha256_write(&sha256_en, e, elen); - secp256k1_sha256_write(&sha256_en, m, mlen); - secp256k1_sha256_write(&sha256_en, ring, 4); - secp256k1_sha256_write(&sha256_en, epos, 4); - secp256k1_sha256_finalize(&sha256_en, hash); + secp256k1_sha256_write(hash_ctx, &sha256_en, e, elen); + secp256k1_sha256_write(hash_ctx, &sha256_en, m, mlen); + secp256k1_sha256_write(hash_ctx, &sha256_en, ring, 4); + secp256k1_sha256_write(hash_ctx, &sha256_en, epos, 4); + secp256k1_sha256_finalize(hash_ctx, &sha256_en, hash); secp256k1_sha256_clear(&sha256_en); } @@ -50,7 +50,7 @@ SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const * | | r_i = r * | return e_0 ==== H(r_{0..i}||m) */ -int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e0, +int secp256k1_borromean_verify(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen) { secp256k1_gej rgej; secp256k1_ge rge; @@ -71,7 +71,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e secp256k1_sha256_initialize(&sha256_e0); for (i = 0; i < nrings; i++) { VERIFY_CHECK(INT_MAX - count > rsizes[i]); - secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0); + secp256k1_borromean_hash(hash_ctx, tmp, m, mlen, e0, 32, i, 0); secp256k1_scalar_set_b32(&ens, tmp, &overflow); for (j = 0; j < rsizes[i]; j++) { if (overflow || secp256k1_scalar_is_zero(&s[count]) || secp256k1_scalar_is_zero(&ens) || secp256k1_gej_is_infinity(&pubs[count])) { @@ -89,21 +89,21 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e secp256k1_ge_set_gej_var(&rge, &rgej); secp256k1_eckey_pubkey_serialize33(&rge, tmp); if (j != rsizes[i] - 1) { - secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1); + secp256k1_borromean_hash(hash_ctx, tmp, m, mlen, tmp, 33, i, j + 1); secp256k1_scalar_set_b32(&ens, tmp, &overflow); } else { - secp256k1_sha256_write(&sha256_e0, tmp, 33); + secp256k1_sha256_write(hash_ctx, &sha256_e0, tmp, 33); } count++; } } - secp256k1_sha256_write(&sha256_e0, m, mlen); - secp256k1_sha256_finalize(&sha256_e0, tmp); + secp256k1_sha256_write(hash_ctx, &sha256_e0, m, mlen); + secp256k1_sha256_finalize(hash_ctx, &sha256_e0, tmp); secp256k1_sha256_clear(&sha256_e0); return secp256k1_memcmp_var(e0, tmp, 32) == 0; } -int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, +int secp256k1_borromean_sign(const secp256k1_hash_ctx *hash_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) { secp256k1_gej rgej; @@ -136,7 +136,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, } secp256k1_eckey_pubkey_serialize33(&rge, tmp); for (j = secidx[i] + 1; j < rsizes[i]; j++) { - secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j); + secp256k1_borromean_hash(hash_ctx, tmp, m, mlen, tmp, 33, i, j); secp256k1_scalar_set_b32(&ens, tmp, &overflow); if (overflow || secp256k1_scalar_is_zero(&ens)) { return 0; @@ -152,16 +152,16 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge_set_gej_var(&rge, &rgej); secp256k1_eckey_pubkey_serialize33(&rge, tmp); } - secp256k1_sha256_write(&sha256_e0, tmp, 33); + secp256k1_sha256_write(hash_ctx, &sha256_e0, tmp, 33); count += rsizes[i]; } - secp256k1_sha256_write(&sha256_e0, m, mlen); - secp256k1_sha256_finalize(&sha256_e0, e0); + secp256k1_sha256_write(hash_ctx, &sha256_e0, m, mlen); + secp256k1_sha256_finalize(hash_ctx, &sha256_e0, e0); secp256k1_sha256_clear(&sha256_e0); count = 0; for (i = 0; i < nrings; i++) { VERIFY_CHECK(INT_MAX - count > rsizes[i]); - secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0); + secp256k1_borromean_hash(hash_ctx, tmp, m, mlen, e0, 32, i, 0); secp256k1_scalar_set_b32(&ens, tmp, &overflow); if (overflow || secp256k1_scalar_is_zero(&ens)) { return 0; @@ -173,7 +173,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, } secp256k1_ge_set_gej_var(&rge, &rgej); secp256k1_eckey_pubkey_serialize33(&rge, tmp); - secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1); + secp256k1_borromean_hash(hash_ctx, tmp, m, mlen, tmp, 33, i, j + 1); secp256k1_scalar_set_b32(&ens, tmp, &overflow); if (overflow || secp256k1_scalar_is_zero(&ens)) { return 0; diff --git a/src/modules/rangeproof/main_impl.h b/src/modules/rangeproof/main_impl.h index 32614caa..420338dd 100644 --- a/src/modules/rangeproof/main_impl.h +++ b/src/modules/rangeproof/main_impl.h @@ -32,6 +32,7 @@ int secp256k1_rangeproof_rewind(const secp256k1_context* ctx, unsigned char *blind_out, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce, uint64_t *min_value, uint64_t *max_value, const secp256k1_pedersen_commitment *commit, const unsigned char *proof, size_t plen, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_generator* gen) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_ge commitp; secp256k1_ge genp; VERIFY_CHECK(ctx != NULL); @@ -46,12 +47,13 @@ int secp256k1_rangeproof_rewind(const secp256k1_context* ctx, ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); secp256k1_pedersen_commitment_load(&commitp, commit); secp256k1_generator_load(&genp, gen); - return secp256k1_rangeproof_verify_impl(&ctx->ecmult_gen_ctx, + return secp256k1_rangeproof_verify_impl(hash_ctx, &ctx->ecmult_gen_ctx, blind_out, value_out, message_out, outlen, nonce, min_value, max_value, &commitp, proof, plen, extra_commit, extra_commit_len, &genp); } int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_value, uint64_t *max_value, const secp256k1_pedersen_commitment *commit, const unsigned char *proof, size_t plen, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_generator* gen) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_ge commitp; secp256k1_ge genp; VERIFY_CHECK(ctx != NULL); @@ -63,13 +65,14 @@ int secp256k1_rangeproof_verify(const secp256k1_context* ctx, uint64_t *min_valu ARG_CHECK(gen != NULL); secp256k1_pedersen_commitment_load(&commitp, commit); secp256k1_generator_load(&genp, gen); - return secp256k1_rangeproof_verify_impl(NULL, + return secp256k1_rangeproof_verify_impl(hash_ctx, NULL, NULL, NULL, NULL, NULL, NULL, min_value, max_value, &commitp, proof, plen, extra_commit, extra_commit_len, &genp); } int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof, size_t *plen, uint64_t min_value, const secp256k1_pedersen_commitment *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value, const unsigned char *message, size_t msg_len, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_generator* gen){ + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_ge commitp; secp256k1_ge genp; VERIFY_CHECK(ctx != NULL); @@ -84,7 +87,7 @@ int secp256k1_rangeproof_sign(const secp256k1_context* ctx, unsigned char *proof ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); secp256k1_pedersen_commitment_load(&commitp, commit); secp256k1_generator_load(&genp, gen); - return secp256k1_rangeproof_sign_impl(&ctx->ecmult_gen_ctx, + return secp256k1_rangeproof_sign_impl(hash_ctx, &ctx->ecmult_gen_ctx, proof, plen, min_value, &commitp, blind, nonce, exp, min_bits, value, message, msg_len, extra_commit, extra_commit_len, &genp); } diff --git a/src/modules/rangeproof/rangeproof_impl.h b/src/modules/rangeproof/rangeproof_impl.h index 476da5eb..50211b07 100644 --- a/src/modules/rangeproof/rangeproof_impl.h +++ b/src/modules/rangeproof/rangeproof_impl.h @@ -58,7 +58,7 @@ SECP256K1_INLINE static void secp256k1_rangeproof_serialize_point(unsigned char* secp256k1_fe_get_b32(data + 1, &pointx); } -SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, secp256k1_scalar *s, unsigned char *message, +SECP256K1_INLINE static int secp256k1_rangeproof_genrand(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *sec, secp256k1_scalar *s, unsigned char *message, size_t *rsizes, size_t rings, const unsigned char *nonce, const secp256k1_ge *commit, const unsigned char *proof, size_t len, const secp256k1_ge* genp) { unsigned char tmp[32]; unsigned char rngseed[32 + 33 + 33 + 10]; @@ -75,15 +75,15 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, secp256k1_rangeproof_serialize_point(rngseed + 32, commit); secp256k1_rangeproof_serialize_point(rngseed + 32 + 33, genp); memcpy(rngseed + 33 + 33 + 32, proof, len); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, rngseed, 32 + 33 + 33 + len); + secp256k1_rfc6979_hmac_sha256_initialize(hash_ctx, &rng, rngseed, 32 + 33 + 33 + len); secp256k1_scalar_set_int(&acc, 0); npub = 0; ret = 1; for (i = 0; i < rings; i++) { if (i < rings - 1) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, tmp, 32); do { - secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, tmp, 32); secp256k1_scalar_set_b32(&sec[i], tmp, &overflow); } while (overflow || secp256k1_scalar_is_zero(&sec[i])); secp256k1_scalar_add(&acc, &acc, &sec[i]); @@ -92,7 +92,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_genrand(secp256k1_scalar *sec, sec[i] = acc; } for (j = 0; j < rsizes[i]; j++) { - secp256k1_rfc6979_hmac_sha256_generate(&rng, tmp, 32); + secp256k1_rfc6979_hmac_sha256_generate(hash_ctx, &rng, tmp, 32); if (message) { for (b = 0; b < 32; b++) { tmp[b] ^= message[(i * 4 + j) * 32 + b]; @@ -189,7 +189,7 @@ SECP256K1_INLINE static int secp256k1_range_proveparams(uint64_t *v, size_t *rin } /* strawman interface, writes proof in proof, a buffer of plen, proves with respect to min_value the range for commit which has the provided blinding factor and value. */ -SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx, +SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_hash_ctx *hash_ctx, const secp256k1_ecmult_gen_context* ecmult_gen_ctx, unsigned char *proof, size_t *plen, uint64_t min_value, const secp256k1_ge *commit, const unsigned char *blind, const unsigned char *nonce, int exp, int min_bits, uint64_t value, const unsigned char *message, size_t msg_len, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp){ @@ -245,10 +245,10 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul } secp256k1_sha256_initialize(&sha256_m); secp256k1_rangeproof_serialize_point(tmp, commit); - secp256k1_sha256_write(&sha256_m, tmp, 33); + secp256k1_sha256_write(hash_ctx, &sha256_m, tmp, 33); secp256k1_rangeproof_serialize_point(tmp, genp); - secp256k1_sha256_write(&sha256_m, tmp, 33); - secp256k1_sha256_write(&sha256_m, proof, len); + secp256k1_sha256_write(hash_ctx, &sha256_m, tmp, 33); + secp256k1_sha256_write(hash_ctx, &sha256_m, proof, len); memset(prep, 0, 4096); if (message != NULL) { @@ -267,7 +267,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul } prep[idx] = 128; } - if (!secp256k1_rangeproof_genrand(sec, s, prep, rsizes, rings, nonce, commit, proof, len, genp)) { + if (!secp256k1_rangeproof_genrand(hash_ctx, sec, s, prep, rsizes, rings, nonce, commit, proof, len, genp)) { return 0; } secp256k1_memclear_explicit(prep, 4096); @@ -309,7 +309,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul secp256k1_ge_set_gej_var(&c, &pubs[npub]); secp256k1_rangeproof_serialize_point(tmpc, &c); quadness = tmpc[0]; - secp256k1_sha256_write(&sha256_m, tmpc, 33); + secp256k1_sha256_write(hash_ctx, &sha256_m, tmpc, 33); signs[i>>3] |= quadness << (i&7); memcpy(&proof[len], tmpc + 1, 32); len += 32; @@ -318,11 +318,11 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul } secp256k1_rangeproof_pub_expand(pubs, exp, rsizes, rings, genp); if (extra_commit != NULL) { - secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len); + secp256k1_sha256_write(hash_ctx, &sha256_m, extra_commit, extra_commit_len); } - secp256k1_sha256_finalize(&sha256_m, tmp); + secp256k1_sha256_finalize(hash_ctx, &sha256_m, tmp); secp256k1_sha256_clear(&sha256_m); - if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { + if (!secp256k1_borromean_sign(hash_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { return 0; } len += 32; @@ -361,7 +361,7 @@ SECP256K1_INLINE static void secp256k1_rangeproof_ch32xor(unsigned char *x, cons } } -SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(secp256k1_scalar *blind, uint64_t *v, +SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *blind, uint64_t *v, unsigned char *m, size_t *mlen, secp256k1_scalar *ev, secp256k1_scalar *s, size_t *rsizes, size_t rings, const unsigned char *nonce, const secp256k1_ge *commit, const unsigned char *proof, size_t len, const secp256k1_ge *genp) { secp256k1_scalar s_orig[128]; @@ -382,7 +382,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_rewind_inner(secp256k1_scalar * VERIFY_CHECK(npub >= 1); memset(prep, 0, 4096); /* Reconstruct the provers random values. */ - secp256k1_rangeproof_genrand(sec, s_orig, prep, rsizes, rings, nonce, commit, proof, len, genp); + secp256k1_rangeproof_genrand(hash_ctx, sec, s_orig, prep, rsizes, rings, nonce, commit, proof, len, genp); *v = UINT64_MAX; secp256k1_scalar_clear(blind); if (rings == 1 && rsizes[0] == 1) { @@ -538,7 +538,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_getheader_impl(size_t *offset, } /* Verifies range proof (len plen) for commit, the min/max values proven are put in the min/max arguments; returns 0 on failure 1 on success.*/ -SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecmult_gen_context* ecmult_gen_ctx, +SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_hash_ctx *hash_ctx, const secp256k1_ecmult_gen_context* ecmult_gen_ctx, unsigned char *blindout, uint64_t *value_out, unsigned char *message_out, size_t *outlen, const unsigned char *nonce, uint64_t *min_value, uint64_t *max_value, const secp256k1_ge *commit, const unsigned char *proof, size_t plen, const unsigned char *extra_commit, size_t extra_commit_len, const secp256k1_ge* genp) { secp256k1_gej accj; @@ -587,10 +587,10 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm } secp256k1_sha256_initialize(&sha256_m); secp256k1_rangeproof_serialize_point(m, commit); - secp256k1_sha256_write(&sha256_m, m, 33); + secp256k1_sha256_write(hash_ctx, &sha256_m, m, 33); secp256k1_rangeproof_serialize_point(m, genp); - secp256k1_sha256_write(&sha256_m, m, 33); - secp256k1_sha256_write(&sha256_m, proof, offset); + secp256k1_sha256_write(hash_ctx, &sha256_m, m, 33); + secp256k1_sha256_write(hash_ctx, &sha256_m, proof, offset); for(i = 0; i < rings - 1; i++) { signs[i] = (proof[offset + ( i>> 3)] & (1 << (i & 7))) != 0; } @@ -617,8 +617,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm } /* Not using secp256k1_rangeproof_serialize_point as we almost have it * serialized form already. */ - secp256k1_sha256_write(&sha256_m, &signs[i], 1); - secp256k1_sha256_write(&sha256_m, &proof[offset], 32); + secp256k1_sha256_write(hash_ctx, &sha256_m, &signs[i], 1); + secp256k1_sha256_write(hash_ctx, &sha256_m, &proof[offset], 32); secp256k1_gej_set_ge(&pubs[npub], &c); secp256k1_gej_add_ge_var(&accj, &accj, &c, NULL); offset += 32; @@ -645,11 +645,11 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm return 0; } if (extra_commit != NULL) { - secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len); + secp256k1_sha256_write(hash_ctx, &sha256_m, extra_commit, extra_commit_len); } - secp256k1_sha256_finalize(&sha256_m, m); + secp256k1_sha256_finalize(hash_ctx, &sha256_m, m); secp256k1_sha256_clear(&sha256_m); - ret = secp256k1_borromean_verify(nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32); + ret = secp256k1_borromean_verify(hash_ctx, nonce ? evalues : NULL, e0, s, pubs, rsizes, rings, m, 32); if (ret && nonce) { /* Given the nonce, try rewinding the witness to recover its initial state. */ secp256k1_scalar blind; @@ -657,7 +657,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_ecm if (!ecmult_gen_ctx) { return 0; } - if (!secp256k1_rangeproof_rewind_inner(&blind, &vv, message_out, outlen, evalues, s, rsizes, rings, nonce, commit, proof, offset_post_header, genp)) { + if (!secp256k1_rangeproof_rewind_inner(hash_ctx, &blind, &vv, message_out, outlen, evalues, s, rsizes, rings, nonce, commit, proof, offset_post_header, genp)) { return 0; } /* Unwind apparently successful, see if the commitment can be reconstructed. */ diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index 7538558e..002c3707 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -123,6 +123,7 @@ static void test_rangeproof_api_internal(void) { } static void test_borromean_internal(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); unsigned char e0[32]; secp256k1_scalar s[64]; secp256k1_gej pubs[64]; @@ -169,11 +170,11 @@ static void test_borromean_internal(void) { } c += rsizes[i]; } - CHECK(secp256k1_borromean_sign(&CTX->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32)); - CHECK(secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32)); + CHECK(secp256k1_borromean_sign(hash_ctx, &CTX->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32)); + CHECK(secp256k1_borromean_verify(hash_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32)); i = testrand32() % c; secp256k1_scalar_negate(&s[i],&s[i]); - CHECK(!secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32)); + CHECK(!secp256k1_borromean_verify(hash_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32)); secp256k1_scalar_negate(&s[i],&s[i]); secp256k1_scalar_set_int(&one, 1); for(j = 0; j < 4; j++) { @@ -183,7 +184,7 @@ static void test_borromean_internal(void) { } else { secp256k1_scalar_add(&s[i],&s[i],&one); } - CHECK(!secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32)); + CHECK(!secp256k1_borromean_verify(hash_ctx, NULL, e0, s, pubs, rsizes, nrings, m, 32)); } } diff --git a/src/modules/schnorrsig_halfagg/main_impl.h b/src/modules/schnorrsig_halfagg/main_impl.h index 5d424a38..466c819b 100644 --- a/src/modules/schnorrsig_halfagg/main_impl.h +++ b/src/modules/schnorrsig_halfagg/main_impl.h @@ -21,6 +21,7 @@ int secp256k1_schnorrsig_inc_aggregate(const secp256k1_context *ctx, unsigned ch size_t n; secp256k1_sha256 hash; secp256k1_scalar s; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); VERIFY_CHECK(ctx != NULL); ARG_CHECK(aggsig != NULL); @@ -47,11 +48,11 @@ int secp256k1_schnorrsig_inc_aggregate(const secp256k1_context *ctx, unsigned ch return 0; } /* write r_i */ - secp256k1_sha256_write(&hash, &aggsig[i*32], 32); + secp256k1_sha256_write(hash_ctx, &hash, &aggsig[i*32], 32); /* write pk_i */ - secp256k1_sha256_write(&hash, pk_ser, 32); + secp256k1_sha256_write(hash_ctx, &hash, pk_ser, 32); /* write m_i*/ - secp256k1_sha256_write(&hash, &all_msgs32[i*32], 32); + secp256k1_sha256_write(hash_ctx, &hash, &all_msgs32[i*32], 32); } /* Compute s = s_old + sum_{i = n_before}^{n} z_i*s_i */ @@ -72,13 +73,13 @@ int secp256k1_schnorrsig_inc_aggregate(const secp256k1_context *ctx, unsigned ch /* Step 1: z_i = TaggedHash(...) */ /* 1.a) Write into hash r_i, pk_i, m_i, r_i */ - secp256k1_sha256_write(&hash, &new_sigs64[(i-n_before)*64], 32); - secp256k1_sha256_write(&hash, pk_ser, 32); - secp256k1_sha256_write(&hash, &all_msgs32[i*32], 32); + secp256k1_sha256_write(hash_ctx, &hash, &new_sigs64[(i-n_before)*64], 32); + secp256k1_sha256_write(hash_ctx, &hash, pk_ser, 32); + secp256k1_sha256_write(hash_ctx, &hash, &all_msgs32[i*32], 32); /* 1.b) Copy the hash */ hashcopy = hash; /* 1.c) Finalize the copy to get zi*/ - secp256k1_sha256_finalize(&hashcopy, hashoutput); + secp256k1_sha256_finalize(hash_ctx, &hashcopy, hashoutput); secp256k1_sha256_clear(&hashcopy); /* Note: No need to check overflow, comes from hash */ secp256k1_scalar_set_b32(&zi, hashoutput, NULL); @@ -105,6 +106,7 @@ int secp256k1_schnorrsig_aggregate(const secp256k1_context *ctx, unsigned char * } int secp256k1_schnorrsig_aggverify(const secp256k1_context *ctx, const secp256k1_xonly_pubkey *pubkeys, const unsigned char *msgs32, size_t n, const unsigned char *aggsig, size_t aggsig_len) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); size_t i; secp256k1_gej lhs, rhs; secp256k1_scalar s; @@ -150,13 +152,13 @@ int secp256k1_schnorrsig_aggverify(const secp256k1_context *ctx, const secp256k1 /* Step 1: z_i = TaggedHash(...) */ /* 1.a) Write into hash r_i, pk_i, m_i, r_i */ - secp256k1_sha256_write(&hash, &aggsig[i*32], 32); - secp256k1_sha256_write(&hash, pk_ser, 32); - secp256k1_sha256_write(&hash, &msgs32[i*32], 32); + secp256k1_sha256_write(hash_ctx, &hash, &aggsig[i*32], 32); + secp256k1_sha256_write(hash_ctx, &hash, pk_ser, 32); + secp256k1_sha256_write(hash_ctx, &hash, &msgs32[i*32], 32); /* 1.b) Copy the hash */ hashcopy = hash; /* 1.c) Finalize the copy to get zi*/ - secp256k1_sha256_finalize(&hashcopy, hashoutput); + secp256k1_sha256_finalize(hash_ctx, &hashcopy, hashoutput); secp256k1_sha256_clear(&hashcopy); secp256k1_scalar_set_b32(&zi, hashoutput, NULL); @@ -170,7 +172,7 @@ int secp256k1_schnorrsig_aggverify(const secp256k1_context *ctx, const secp256k1 } /* 2.b) e_i = int(hash_{BIP0340/challenge}(bytes(r_i) || pk_i || m_i)) mod n */ - secp256k1_schnorrsig_challenge(&ei, &aggsig[i*32], &msgs32[i*32], 32, pk_ser); + secp256k1_schnorrsig_challenge(hash_ctx, &ei, &aggsig[i*32], &msgs32[i*32], 32, pk_ser); secp256k1_gej_set_ge(&ppj, &pp); /* 2.c) T_i = R_i + e_i*P_i */ secp256k1_ecmult(&ti, &ppj, &ei, NULL); diff --git a/src/modules/schnorrsig_halfagg/tests_impl.h b/src/modules/schnorrsig_halfagg/tests_impl.h index 29d39b2c..f4092842 100644 --- a/src/modules/schnorrsig_halfagg/tests_impl.h +++ b/src/modules/schnorrsig_halfagg/tests_impl.h @@ -11,9 +11,10 @@ void test_schnorrsig_sha256_tagged_aggregate(void) { static const unsigned char tag[] = {'H', 'a', 'l', 'f', 'A', 'g', 'g', '/', 'r', 'a', 'n', 'd', 'o', 'm', 'i', 'z', 'e', 'r'}; secp256k1_sha256 sha_optimized; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_schnorrsig_sha256_tagged_aggregation(&sha_optimized); - test_sha256_tag_midstate(&sha_optimized, tag, sizeof(tag)); + test_sha256_tag_midstate(hash_ctx, &sha_optimized, tag, sizeof(tag)); } /* Create n many x-only pubkeys and sigs for random messages */ diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index 248efe14..968cc477 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -138,7 +138,7 @@ static void secp256k1_surjectionproof_csprng_init(secp256k1_surjectionproof_cspr csprng->state_i = 0; } -static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_csprng *csprng, size_t rand_max) { +static size_t secp256k1_surjectionproof_csprng_next(const secp256k1_hash_ctx *hash_ctx, secp256k1_surjectionproof_csprng *csprng, size_t rand_max) { /* The number of random bytes to read for each random sample */ const size_t increment = rand_max > 256 ? 2 : 1; /* The maximum value expressable by the number of random bytes we read */ @@ -151,8 +151,8 @@ static size_t secp256k1_surjectionproof_csprng_next(secp256k1_surjectionproof_cs if (csprng->state_i + increment >= 32) { secp256k1_sha256 sha; secp256k1_sha256_initialize(&sha); - secp256k1_sha256_write(&sha, csprng->state, 32); - secp256k1_sha256_finalize(&sha, csprng->state); + secp256k1_sha256_write(hash_ctx, &sha, csprng->state, 32); + secp256k1_sha256_finalize(hash_ctx, &sha, csprng->state); secp256k1_sha256_clear(&sha); csprng->state_i = 0; } @@ -212,6 +212,7 @@ void secp256k1_surjectionproof_destroy(secp256k1_surjectionproof* proof) { } int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1_surjectionproof* proof, size_t *input_index, const secp256k1_fixed_asset_tag* fixed_input_tags, const size_t n_input_tags, const size_t n_input_tags_to_use, const secp256k1_fixed_asset_tag* fixed_output_tag, const size_t n_max_iterations, const unsigned char *random_seed32) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_surjectionproof_csprng csprng; size_t n_iterations = 0; @@ -239,7 +240,7 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1 for (i = 0; i < n_input_tags_to_use; i++) { while (1) { size_t next_input_index; - next_input_index = secp256k1_surjectionproof_csprng_next(&csprng, n_input_tags); + next_input_index = secp256k1_surjectionproof_csprng_next(hash_ctx, &csprng, n_input_tags); if (secp256k1_memcmp_var(&fixed_input_tags[next_input_index], fixed_output_tag, sizeof(*fixed_output_tag)) == 0) { *input_index = next_input_index; has_output_tag = 1; @@ -270,6 +271,7 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1 } int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_surjectionproof* proof, const secp256k1_generator* ephemeral_input_tags, size_t n_ephemeral_input_tags, const secp256k1_generator* ephemeral_output_tag, size_t input_index, const unsigned char *input_blinding_key, const unsigned char *output_blinding_key) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_scalar blinding_key; secp256k1_scalar tmps; secp256k1_scalar nonce; @@ -334,8 +336,8 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s /* Produce signature */ rsizes[0] = (int) n_used_pubkeys; indices[0] = (int) ring_input_index; - secp256k1_surjection_genmessage(msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag); - if (secp256k1_surjection_genrand(borromean_s, n_used_pubkeys, &blinding_key) == 0) { + secp256k1_surjection_genmessage(hash_ctx, msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag); + if (secp256k1_surjection_genrand(hash_ctx, borromean_s, n_used_pubkeys, &blinding_key) == 0) { return 0; } /* Borromean sign will overwrite one of the s values we just generated, so use @@ -343,7 +345,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s * homage to the rangeproof code which does this very cleverly to encode messages. */ nonce = borromean_s[ring_input_index]; secp256k1_scalar_clear(&borromean_s[ring_input_index]); - if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) { + if (secp256k1_borromean_sign(hash_ctx, &ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) { return 0; } for (i = 0; i < n_used_pubkeys; i++) { @@ -356,6 +358,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s static #endif int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256k1_surjectionproof* proof, const secp256k1_generator* ephemeral_input_tags, size_t n_ephemeral_input_tags, const secp256k1_generator* ephemeral_output_tag) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); size_t rsizes[1]; /* array needed for borromean sig API */ size_t i; size_t n_total_pubkeys; @@ -394,8 +397,8 @@ int secp256k1_surjectionproof_verify(const secp256k1_context* ctx, const secp256 return 0; } } - secp256k1_surjection_genmessage(msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag); - return secp256k1_borromean_verify(NULL, &proof->data[0], borromean_s, ring_pubkeys, rsizes, 1, msg32, 32); + secp256k1_surjection_genmessage(hash_ctx, msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag); + return secp256k1_borromean_verify(hash_ctx, NULL, &proof->data[0], borromean_s, ring_pubkeys, rsizes, 1, msg32, 32); } #endif diff --git a/src/modules/surjection/surjection_impl.h b/src/modules/surjection/surjection_impl.h index 0776e4c8..bccced52 100644 --- a/src/modules/surjection/surjection_impl.h +++ b/src/modules/surjection/surjection_impl.h @@ -15,7 +15,7 @@ #include "../../scalar.h" #include "../../hash.h" -SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg32, const secp256k1_generator *ephemeral_input_tags, size_t n_input_tags, const secp256k1_generator *ephemeral_output_tag) { +SECP256K1_INLINE static void secp256k1_surjection_genmessage(const secp256k1_hash_ctx *hash_ctx, unsigned char *msg32, const secp256k1_generator *ephemeral_input_tags, size_t n_input_tags, const secp256k1_generator *ephemeral_output_tag) { /* compute message */ size_t i; unsigned char pk_ser[33]; @@ -26,16 +26,16 @@ SECP256K1_INLINE static void secp256k1_surjection_genmessage(unsigned char *msg3 for (i = 0; i < n_input_tags; i++) { pk_ser[0] = 2 + (ephemeral_input_tags[i].data[63] & 1); memcpy(&pk_ser[1], &ephemeral_input_tags[i].data[0], 32); - secp256k1_sha256_write(&sha256_en, pk_ser, pk_len); + secp256k1_sha256_write(hash_ctx, &sha256_en, pk_ser, pk_len); } pk_ser[0] = 2 + (ephemeral_output_tag->data[63] & 1); memcpy(&pk_ser[1], &ephemeral_output_tag->data[0], 32); - secp256k1_sha256_write(&sha256_en, pk_ser, pk_len); - secp256k1_sha256_finalize(&sha256_en, msg32); + secp256k1_sha256_write(hash_ctx, &sha256_en, pk_ser, pk_len); + secp256k1_sha256_finalize(hash_ctx, &sha256_en, msg32); secp256k1_sha256_clear(&sha256_en); } -SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) { +SECP256K1_INLINE static int secp256k1_surjection_genrand(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) { size_t i; unsigned char sec_input[36]; secp256k1_sha256 sha256_en; @@ -50,8 +50,8 @@ SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, si sec_input[3] = i >> 24; secp256k1_sha256_initialize(&sha256_en); - secp256k1_sha256_write(&sha256_en, sec_input, 36); - secp256k1_sha256_finalize(&sha256_en, sec_input); + secp256k1_sha256_write(hash_ctx, &sha256_en, sec_input, 36); + secp256k1_sha256_finalize(hash_ctx, &sha256_en, sec_input); secp256k1_sha256_clear(&sha256_en); secp256k1_scalar_set_b32(&s[i], sec_input, &overflow); if (overflow == 1) { diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index d81ac624..7ba328c3 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -26,7 +26,7 @@ static void test_surjectionproof_api(void) { size_t serialized_len; secp256k1_surjectionproof proof; secp256k1_surjectionproof* proof_on_heap; - size_t n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]); + size_t n_inputs = ARRAY_SIZE(fixed_input_tags); size_t input_index; size_t i; @@ -146,7 +146,7 @@ static void test_input_selection(size_t n_inputs) { size_t try_count = n_inputs * 100; secp256k1_surjectionproof proof; secp256k1_fixed_asset_tag fixed_input_tags[1000]; - const size_t max_n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]) - 1; + const size_t max_n_inputs = ARRAY_SIZE(fixed_input_tags) - 1; CHECK(n_inputs < max_n_inputs); testrand256(seed); @@ -313,7 +313,7 @@ static void test_gen_verify(size_t n_inputs, size_t n_used) { secp256k1_fixed_asset_tag fixed_input_tags[1000]; secp256k1_generator ephemeral_input_tags[1000]; unsigned char *input_blinding_key[1000]; - const size_t max_n_inputs = sizeof(fixed_input_tags) / sizeof(fixed_input_tags[0]) - 1; + const size_t max_n_inputs = ARRAY_SIZE(fixed_input_tags) - 1; size_t try_count = n_inputs * 100; size_t key_index; size_t input_index; @@ -395,6 +395,7 @@ static void test_gen_verify(size_t n_inputs, size_t n_used) { /* check that a proof with empty n_used_inputs is invalid */ static void test_no_used_inputs_verify(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_surjectionproof proof; secp256k1_fixed_asset_tag fixed_input_tag; secp256k1_fixed_asset_tag fixed_output_tag; @@ -422,10 +423,10 @@ static void test_no_used_inputs_verify(void) { /* create "borromean signature" which is just a hash of metadata (pubkeys, etc) in this case */ secp256k1_generator_load(&output, &ephemeral_output_tag); - secp256k1_surjection_genmessage(proof.data, ephemeral_input_tags, 1, &ephemeral_output_tag); + secp256k1_surjection_genmessage(hash_ctx, proof.data, ephemeral_input_tags, 1, &ephemeral_output_tag); secp256k1_sha256_initialize(&sha256_e0); - secp256k1_sha256_write(&sha256_e0, proof.data, 32); - secp256k1_sha256_finalize(&sha256_e0, proof.data); + secp256k1_sha256_write(hash_ctx, &sha256_e0, proof.data, 32); + secp256k1_sha256_finalize(hash_ctx, &sha256_e0, proof.data); result = secp256k1_surjectionproof_verify(CTX, &proof, ephemeral_input_tags, n_ephemeral_input_tags, &ephemeral_output_tag); CHECK(result == 0); diff --git a/src/modules/whitelist/main_impl.h b/src/modules/whitelist/main_impl.h index 301d2476..28c563b2 100644 --- a/src/modules/whitelist/main_impl.h +++ b/src/modules/whitelist/main_impl.h @@ -13,6 +13,7 @@ #define MAX_KEYS SECP256K1_WHITELIST_MAX_N_KEYS /* shorter alias */ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_signature *sig, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const size_t n_keys, const secp256k1_pubkey *sub_pubkey, const unsigned char *online_seckey, const unsigned char *summed_seckey, const size_t index) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_gej pubs[MAX_KEYS]; secp256k1_scalar s[MAX_KEYS]; secp256k1_scalar sec, non; @@ -85,7 +86,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s /* Actually sign */ if (ret) { sig->n_keys = n_keys; - ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32); + ret = secp256k1_borromean_sign(hash_ctx, &ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32); /* Signing will change s[index], so update in the sig structure */ secp256k1_scalar_get_b32(&sig->data[32 * (index + 1)], &s[index]); } @@ -96,6 +97,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s } int secp256k1_whitelist_verify(const secp256k1_context* ctx, const secp256k1_whitelist_signature *sig, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const size_t n_keys, const secp256k1_pubkey *sub_pubkey) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); secp256k1_scalar s[MAX_KEYS]; secp256k1_gej pubs[MAX_KEYS]; unsigned char msg32[32]; @@ -123,7 +125,7 @@ int secp256k1_whitelist_verify(const secp256k1_context* ctx, const secp256k1_whi return 0; } /* Do verification */ - return secp256k1_borromean_verify(NULL, &sig->data[0], s, pubs, &sig->n_keys, 1, msg32, 32); + return secp256k1_borromean_verify(hash_ctx, NULL, &sig->data[0], s, pubs, &sig->n_keys, 1, msg32, 32); } size_t secp256k1_whitelist_signature_n_keys(const secp256k1_whitelist_signature *sig) { diff --git a/src/modules/whitelist/whitelist_impl.h b/src/modules/whitelist/whitelist_impl.h index edb90b4f..9a9023fb 100644 --- a/src/modules/whitelist/whitelist_impl.h +++ b/src/modules/whitelist/whitelist_impl.h @@ -7,7 +7,7 @@ #ifndef SECP256K1_WHITELIST_IMPL_H #define SECP256K1_WHITELIST_IMPL_H -static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_gej* pubkey) { +static int secp256k1_whitelist_hash_pubkey(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar* output, secp256k1_gej* pubkey) { unsigned char h[32]; unsigned char c[33]; secp256k1_sha256 sha; @@ -22,8 +22,8 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g return 0; } secp256k1_eckey_pubkey_serialize33(&ge, c); - secp256k1_sha256_write(&sha, c, size); - secp256k1_sha256_finalize(&sha, h); + secp256k1_sha256_write(hash_ctx, &sha, c, size); + secp256k1_sha256_finalize(hash_ctx, &sha, h); secp256k1_sha256_clear(&sha); secp256k1_scalar_set_b32(output, h, &overflow); @@ -35,14 +35,14 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g return 1; } -static int secp256k1_whitelist_tweak_pubkey(secp256k1_gej* pub_tweaked) { +static int secp256k1_whitelist_tweak_pubkey(const secp256k1_hash_ctx *hash_ctx, secp256k1_gej* pub_tweaked) { secp256k1_scalar tweak; secp256k1_scalar zero; int ret; secp256k1_scalar_set_int(&zero, 0); - ret = secp256k1_whitelist_hash_pubkey(&tweak, pub_tweaked); + ret = secp256k1_whitelist_hash_pubkey(hash_ctx, &tweak, pub_tweaked); if (ret) { secp256k1_ecmult(pub_tweaked, pub_tweaked, &tweak, &zero); } @@ -51,6 +51,7 @@ static int secp256k1_whitelist_tweak_pubkey(secp256k1_gej* pub_tweaked) { static int secp256k1_whitelist_compute_tweaked_privkey(const secp256k1_context* ctx, secp256k1_scalar* skey, const unsigned char *online_key, const unsigned char *summed_key) { secp256k1_scalar tweak; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); int ret = 1; int overflow = 0; @@ -61,7 +62,7 @@ static int secp256k1_whitelist_compute_tweaked_privkey(const secp256k1_context* if (ret) { secp256k1_gej pkeyj; secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pkeyj, skey); - ret = secp256k1_whitelist_hash_pubkey(&tweak, &pkeyj); + ret = secp256k1_whitelist_hash_pubkey(hash_ctx, &tweak, &pkeyj); } if (ret) { secp256k1_scalar sonline; @@ -86,6 +87,7 @@ static int secp256k1_whitelist_compute_tweaked_privkey(const secp256k1_context* * for the ring signature; also produce a commitment to every one that will * be our "message". */ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* ctx, unsigned char *msg32, secp256k1_gej *keys, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const int n_keys, const secp256k1_pubkey *sub_pubkey) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); unsigned char c[33]; size_t size = 33; secp256k1_sha256 sha; @@ -97,7 +99,7 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* /* commit to sub-key */ secp256k1_eckey_pubkey_serialize33(&subkey_ge, c); - secp256k1_sha256_write(&sha, c, size); + secp256k1_sha256_write(hash_ctx, &sha, c, size); for (i = 0; i < n_keys; i++) { secp256k1_ge offline_ge; secp256k1_ge online_ge; @@ -106,18 +108,18 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* /* commit to fixed keys */ secp256k1_pubkey_load(ctx, &offline_ge, &offline_pubkeys[i]); secp256k1_eckey_pubkey_serialize33(&offline_ge, c); - secp256k1_sha256_write(&sha, c, size); + secp256k1_sha256_write(hash_ctx, &sha, c, size); secp256k1_pubkey_load(ctx, &online_ge, &online_pubkeys[i]); secp256k1_eckey_pubkey_serialize33(&online_ge, c); - secp256k1_sha256_write(&sha, c, size); + secp256k1_sha256_write(hash_ctx, &sha, c, size); /* compute tweaked keys */ secp256k1_gej_set_ge(&tweaked_gej, &offline_ge); secp256k1_gej_add_ge_var(&tweaked_gej, &tweaked_gej, &subkey_ge, NULL); - secp256k1_whitelist_tweak_pubkey(&tweaked_gej); + secp256k1_whitelist_tweak_pubkey(hash_ctx, &tweaked_gej); secp256k1_gej_add_ge_var(&keys[i], &tweaked_gej, &online_ge, NULL); } - secp256k1_sha256_finalize(&sha, msg32); + secp256k1_sha256_finalize(hash_ctx, &sha, msg32); secp256k1_sha256_clear(&sha); return 1; } diff --git a/src/secp256k1.c b/src/secp256k1.c index 532c9fdf..a3d37bd2 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -561,6 +561,7 @@ const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, secp256k1_sha256* s2c_sha, secp256k1_ecdsa_s2c_opening *s2c_opening, const unsigned char* s2c_data32, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { secp256k1_scalar sec, non, msg; + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(ctx); int ret = 0; int is_sec_valid; unsigned char nonce32[32]; @@ -575,8 +576,8 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc * because we need to ensure that s2c_data is actually hashed into the nonce and * not just ignored. Otherwise an attacker can exfiltrate the secret key by * signing the same message thrice with different commitments. */ - VERIFY_CHECK(s2c_data32 == NULL || noncefp == secp256k1_nonce_function_default); - + VERIFY_CHECK(s2c_data32 == NULL || noncefp == NULL || noncefp == secp256k1_nonce_function_default); + /* Fail if the secret key is invalid. */ is_sec_valid = secp256k1_scalar_set_b32_seckey(&sec, seckey); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, !is_sec_valid); @@ -615,7 +616,7 @@ static int secp256k1_ecdsa_sign_inner(const secp256k1_context* ctx, secp256k1_sc secp256k1_declassify(ctx, &nonce_p.infinity, sizeof(nonce_p.infinity)); /* Tweak nonce with s2c commitment. */ - ret = secp256k1_ec_commit_seckey(&non, &nonce_p, s2c_sha, s2c_data32, 32); + ret = secp256k1_ec_commit_seckey(hash_ctx, &non, &nonce_p, s2c_sha, s2c_data32, 32); secp256k1_declassify(ctx, &ret, sizeof(ret)); /* may be secret that the tweak falied, but happens with negligible probability */ if (!ret) { break; diff --git a/src/tests.c b/src/tests.c index bb0bb190..5d5e833d 100644 --- a/src/tests.c +++ b/src/tests.c @@ -4387,6 +4387,7 @@ static void run_ec_combine(void) { } static void test_ec_commit(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); secp256k1_scalar seckey_s; secp256k1_ge pubkey; secp256k1_gej pubkeyj; @@ -4402,29 +4403,30 @@ static void test_ec_commit(void) { /* Commit to data and verify */ secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 32) == 1); + CHECK(secp256k1_ec_commit(hash_ctx, &commitment, &pubkey, &sha, data, 32) == 1); secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 32) == 1); + CHECK(secp256k1_ec_commit_verify(hash_ctx, &commitment, &pubkey, &sha, data, 32) == 1); secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 1); + CHECK(secp256k1_ec_commit_seckey(hash_ctx, &seckey_s, &pubkey, &sha, data, 32) == 1); secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pubkeyj, &seckey_s); secp256k1_gej_eq_ge_var(&pubkeyj, &commitment); /* Check that verification fails with different data */ secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 31) == 0); + CHECK(secp256k1_ec_commit_verify(hash_ctx, &commitment, &pubkey, &sha, data, 31) == 0); /* Check that commmitting fails when the inner pubkey is the point at * infinity */ secp256k1_sha256_initialize(&sha); secp256k1_ge_set_infinity(&pubkey); - CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 32) == 0); + CHECK(secp256k1_ec_commit(hash_ctx, &commitment, &pubkey, &sha, data, 32) == 0); secp256k1_scalar_set_int(&seckey_s, 0); - CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 0); - CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 32) == 0); + CHECK(secp256k1_ec_commit_seckey(hash_ctx, &seckey_s, &pubkey, &sha, data, 32) == 0); + CHECK(secp256k1_ec_commit_verify(hash_ctx, &commitment, &pubkey, &sha, data, 32) == 0); } static void test_ec_commit_api(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); unsigned char seckey[32]; secp256k1_scalar seckey_s; secp256k1_ge pubkey; @@ -4442,17 +4444,17 @@ static void test_ec_commit_api(void) { secp256k1_ge_set_gej(&pubkey, &pubkeyj); secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 1) == 1); + CHECK(secp256k1_ec_commit(hash_ctx, &commitment, &pubkey, &sha, data, 1) == 1); /* The same pubkey can be both input and output of the function */ { secp256k1_ge pubkey_tmp = pubkey; secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit(&pubkey_tmp, &pubkey_tmp, &sha, data, 1) == 1); + CHECK(secp256k1_ec_commit(hash_ctx, &pubkey_tmp, &pubkey_tmp, &sha, data, 1) == 1); secp256k1_ge_eq_var(&commitment, &pubkey_tmp); } secp256k1_sha256_initialize(&sha); - CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 1) == 1); + CHECK(secp256k1_ec_commit_verify(hash_ctx, &commitment, &pubkey, &sha, data, 1) == 1); } static void run_ec_commit(void) { From 3cca6451a2521e3cfe353b3787ea9f86d6caee2f Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Mon, 27 Apr 2026 06:28:45 +0100 Subject: [PATCH 349/383] ci: Bump GCC snapshot major version to 17 See https://gcc.gnu.org/pipermail/gcc/2026-April/248048.html. --- ci/linux-debian.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/linux-debian.Dockerfile b/ci/linux-debian.Dockerfile index a575d9b1..e743cda8 100644 --- a/ci/linux-debian.Dockerfile +++ b/ci/linux-debian.Dockerfile @@ -40,7 +40,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal apt-get clean && rm -rf /var/lib/apt/lists/* # Build and install gcc snapshot -ARG GCC_SNAPSHOT_MAJOR=16 +ARG GCC_SNAPSHOT_MAJOR=17 RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ wget libgmp-dev libmpfr-dev libmpc-dev flex && \ mkdir gcc && cd gcc && \ From 8479eafa5720421d4b7f4b524a35e0a7edf291c7 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 28 Apr 2026 22:58:11 +0200 Subject: [PATCH 350/383] musig: always clear out secret key in `secp256k1_musig_nonce_gen_counter` Even though `secp256k1_musig_nonce_gen_internal` can currently only fail if the API is misused (invalid `keypair` or `keyagg_cache` parameters), clear out the buffer holding secret key data as well in this case to follow best practices. The issue was found and reported by l0rinc using GPT 5.5 (Thanks!). --- src/modules/musig/session_impl.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 6a37bfdf..510ee89f 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -483,11 +483,9 @@ int secp256k1_musig_nonce_gen_counter(const secp256k1_context* ctx, secp256k1_mu (void) ret; #endif - if (!secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) { - return 0; - } + ret = secp256k1_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32); secp256k1_memclear_explicit(seckey, sizeof(seckey)); - return 1; + return ret; } static int secp256k1_musig_sum_pubnonces(const secp256k1_context* ctx, secp256k1_gej *summed_pubnonces, const secp256k1_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { From 40a0d874a6805e3065341ce5bd96384b7a7caeeb Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Wed, 29 Apr 2026 17:51:24 +0200 Subject: [PATCH 351/383] doc: correct API docs for ECDSA signing out-params (s/array/signature object/) --- include/secp256k1.h | 2 +- include/secp256k1_recovery.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index b7ec6a22..2f3383e1 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -687,7 +687,7 @@ SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default; * Returns: 1: signature created * 0: the nonce generation function failed, or the secret key was invalid. * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: sig: pointer to an array where the signature will be placed. + * Out: sig: pointer to a signature object. * In: msghash32: the 32-byte message hash being signed. * seckey: pointer to a 32-byte secret key. * noncefp: pointer to a nonce generation function. If NULL, diff --git a/include/secp256k1_recovery.h b/include/secp256k1_recovery.h index 2430f993..45f20aba 100644 --- a/include/secp256k1_recovery.h +++ b/include/secp256k1_recovery.h @@ -73,7 +73,7 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( * Returns: 1: signature created * 0: the nonce generation function failed, or the secret key was invalid. * Args: ctx: pointer to a context object (not secp256k1_context_static). - * Out: sig: pointer to an array where the signature will be placed. + * Out: sig: pointer to a signature object. * In: msghash32: the 32-byte message hash being signed. * seckey: pointer to a 32-byte secret key. * noncefp: pointer to a nonce generation function. If NULL, From af1fdd12157c5cd3be1b31410264fe48d59b2d90 Mon Sep 17 00:00:00 2001 From: w0xlt <94266259+w0xlt@users.noreply.github.com> Date: Tue, 12 May 2026 15:26:12 -0700 Subject: [PATCH 352/383] tests: compare full MuSig aggregate nonce --- src/modules/musig/tests_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index cc644916..fb3a10a0 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -862,7 +862,7 @@ static void musig_test_vectors_nonceagg(void) { } CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2)); CHECK(secp256k1_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce)); - CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, 33) == 0); + CHECK(secp256k1_memcmp_var(aggnonce66, c->expected, sizeof(aggnonce66)) == 0); } for (i = 0; i < ARRAY_SIZE(vector->error_case); i++) { const struct musig_nonce_agg_test_case *c = &vector->error_case[i]; From f0ff45f3ab6c6bbdedd69f39431eab132229a9c5 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 24 Apr 2026 11:27:36 +0200 Subject: [PATCH 353/383] sync-upstream: Simplify --- contrib/sync-upstream.sh | 149 +++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 76 deletions(-) diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index aaf8cb10..451456c9 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -3,112 +3,109 @@ set -eou pipefail help() { - echo "Sync merge commits from bitcoin-core/secp256k1 into secp256k1-zkp." - echo - echo "Usage:" - echo " $0 [-b ] " - echo " Find every merge commit present in upstream/master and missing in (default: master)." - echo - echo "This tool prepares the title and body for a sync PR" - echo "and generates a helper script contrib/gh-pr-create.sh." - echo - echo "Setup:" - echo " Requires a remote named 'upstream' pointing to bitcoin-core/secp256k1." - echo - echo "Listing upstream merge commits:" - echo " To list merge commits in upstream/master that are missing from (oldest first):" - echo " git log --oneline --topo-order --reverse --merges \$(git merge-base upstream/master )..upstream/master" - exit 1 +cat < + +This script creates a sync local branch pointing to . Moreover, it +generates a helper script for opening a pull request (PR) merging the created +local branch into . + +The synced upstream PRs are listed in the title and the description of the PR. +(This relies on upstream merging PRs using merge commits with titles of the form +"Merge #: ...".) + +Arguments: + : The branch to sync with upstream + : The upstream ref to merge into + +Usage examples: + $0 master upstream/master + $0 master abc1234 + $0 --switch origin/master upstream/master + +To find candidate merge commits from (oldest first), use: + git log --oneline --topo-order --reverse --merges \$(git merge-base ).. +EOT } -REMOTE=upstream -REMOTE_BRANCH="$REMOTE/master" -LOCAL_BRANCH="master" - -if ! git remote get-url "$REMOTE" &> /dev/null; then -echo "Error: Remote '$REMOTE' not found." -echo "Add it with: git remote add upstream git@github.com:bitcoin-core/secp256k1.git" -echo "Then run: git fetch upstream" -exit 1 -fi - -range() { - RANGESTART_COMMIT=$(git merge-base "$REMOTE_BRANCH" "$LOCAL_BRANCH") - RANGEEND_COMMIT=$(git rev-parse "$REMOTE_BRANCH") - COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT") -} - -# Process -b and -h arguments -while getopts "b:h" opt; do - case $opt in - b) - LOCAL_BRANCH=$OPTARG - ;; - h) - help - ;; - *) - echo - help - ;; - esac -done - -# Shift off the processed options -shift $((OPTIND -1)) -if [ "$#" -lt 1 ]; then - echo "Error: argument is required." >&2 - echo +### Parse arguments +if [ "$#" -ne 2 ]; then help exit 1 fi +BASE_BRANCH="$1" +UPSTREAM_REF="$2" -# Extract the PR branch argument -PR_BRANCH=$1 - -range - +### Create PR metadata TITLE="Upstream PRs" -BODY="${GITHUB_ACTIONS+This PR has been created by a GitHub Actions workflow without human involvement.}"$'\n' -for COMMIT in $COMMITS -do - PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\).*'/'\2'/) +RANGESTART_COMMIT=$(git merge-base "$UPSTREAM_REF" "$BASE_BRANCH") +RANGEEND_COMMIT=$(git rev-parse "$UPSTREAM_REF") +COMMITS=$(git --no-pager log --pretty=format:%H --topo-order --reverse --merges "$RANGESTART_COMMIT".."$RANGEEND_COMMIT") +# If there are no commits, exit successfully +if [ -z "$COMMITS" ]; then + echo "No merge commits in range ${RANGESTART_COMMIT}..${RANGEEND_COMMIT}" >&2 + exit 0 +fi +BODY="${GITHUB_ACTIONS+*Note: This PR has been created by a GitHub Actions workflow without human involvement.* + +}" +BODY+="This PR syncs the following upstream PRs:" +for COMMIT in $COMMITS; do + PRNUM=$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge .*#\([0-9]*\):.*'/'\1'/) TITLE="$TITLE $PRNUM," - BODY=$(printf "%s\n%s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge \(bitcoin-core\/secp256k1\)\?#\([0-9]*\)'/'[bitcoin-core\/secp256k1#\2]'/)") - LAST_COMMIT="$COMMIT" + BODY=$(printf "%s\n * %s" "$BODY" "$(git log -1 "$COMMIT" --pretty=format:%s | sed s/'Merge '//)") done # Remove trailing "," TITLE=${TITLE%?} -BODY+=$(cat <\` to show the conflict resolution in the merge commit. - * Use \`git read-tree --reset -u \` to replay these resolutions during the conflict resolution stage when recreating the PR branch locally. +Usage hints: + * If this PR has merge conflicts, resolve these by switching to the PR branch and merging the base branch into it using `git merge `. + * To show the conflict resolution diff from an existing merge commit, use `git show --remerge-diff `. + * In case you are recreating the PR branch locally, you can (during the conflict resolution state) replay this conflict resolution diff using `git read-tree --reset -u `. Be aware that this may discard your index as well as the uncommitted changes and untracked files in your worktree. EOF ) +### Create a sync branch locally. +SYNC_BRANCH="sync-$(git rev-parse --short "$UPSTREAM_REF")" +# This will error out if the branch already exists, which is what we want. +git branch --no-track "$SYNC_BRANCH" "$UPSTREAM_REF" + +### Print the PR metadata echo "-----------------------------------" echo "$TITLE" echo "-----------------------------------" echo "$BODY" echo "-----------------------------------" -# Escape single quote -# ' -> '\'' +### Generate the helper script for creating the PR +FNAME="gh-pr-create.sh" +# Escape single quote ' -> '\'' quote() { local quoted=${1//\'/\'\\\'\'} printf "%s" "$quoted" } TITLE=$(quote "$TITLE") BODY=$(quote "$BODY") - -BASEDIR=$(dirname "$0") -FNAME="$BASEDIR/gh-pr-create.sh" cat < "$FNAME" #!/bin/sh -gh pr create -t '$TITLE' -b '$BODY' --base '$LOCAL_BRANCH' --head '$PR_BRANCH' +TITLE='$TITLE' +BODY='$BODY' +SYNC_BRANCH='$SYNC_BRANCH' +BASE_BRANCH='$BASE_BRANCH' + +gh pr create --base "\$BASE_BRANCH" --head "\$SYNC_BRANCH" --title "\$TITLE" --body "\$BODY" "\$@" EOT chmod +x "$FNAME" -echo "Generated $FNAME for creating a pull request with the above title and body." \ No newline at end of file + +echo "Successfully created local sync branch $SYNC_BRANCH starting at $UPSTREAM_REF." +echo +echo "You can now:" +echo " 1. Optionally resolve merge conflicts by merging $BASE_BRANCH into $SYNC_BRANCH." +echo " 2. Push $SYNC_BRANCH to some GitHub remote." +echo " 3. Run ./$FNAME to create a pull request. (Tip: Pass --dry-run first.)" From 260fad30aa10613e13a2b27ec3145eb8d9318b1f Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 22 May 2026 15:35:12 +0200 Subject: [PATCH 354/383] sync-upstream: Optionally switch to sync branch --- contrib/sync-upstream.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/contrib/sync-upstream.sh b/contrib/sync-upstream.sh index 451456c9..e4815041 100755 --- a/contrib/sync-upstream.sh +++ b/contrib/sync-upstream.sh @@ -7,7 +7,7 @@ cat < + $0 [--switch] This script creates a sync local branch pointing to . Moreover, it generates a helper script for opening a pull request (PR) merging the created @@ -18,13 +18,13 @@ The synced upstream PRs are listed in the title and the description of the PR. "Merge #: ...".) Arguments: + --switch: Try to switch to the created sync branch : The branch to sync with upstream : The upstream ref to merge into Usage examples: - $0 master upstream/master + $0 --switch master upstream/master $0 master abc1234 - $0 --switch origin/master upstream/master To find candidate merge commits from (oldest first), use: git log --oneline --topo-order --reverse --merges \$(git merge-base ).. @@ -32,6 +32,11 @@ EOT } ### Parse arguments +SWITCH=false +if [ "$#" -ge 1 ] && [ "$1" = "--switch" ]; then + SWITCH=true + shift +fi if [ "$#" -ne 2 ]; then help exit 1 @@ -109,3 +114,10 @@ echo "You can now:" echo " 1. Optionally resolve merge conflicts by merging $BASE_BRANCH into $SYNC_BRANCH." echo " 2. Push $SYNC_BRANCH to some GitHub remote." echo " 3. Run ./$FNAME to create a pull request. (Tip: Pass --dry-run first.)" + +if [ "${SWITCH:-false}" = true ]; then + echo + echo "Trying to switch to the sync branch..." + echo + git switch "$SYNC_BRANCH" +fi From c5be752e2e56d79995598bb77d886756da849892 Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Fri, 22 May 2026 16:00:49 +0200 Subject: [PATCH 355/383] gha: Simplify sync.yml according to sync-upstream.sh changes --- .github/workflows/sync.yml | 92 +++++++++++++------------------------- 1 file changed, 31 insertions(+), 61 deletions(-) diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index cd534821..22e3a6ae 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -9,11 +9,10 @@ jobs: sync-upstream: runs-on: ubuntu-latest env: - UPSTREAM: "https://github.com/bitcoin-core/secp256k1.git" - UPSTREAM_BRANCH: "master" - ORIGIN_BRANCH: "master" - MIN_UPSTREAM_MERGES: 1 - + UPSTREAM: "https://github.com/bitcoin-core/secp256k1.git" + BASE_BRANCH: "master" + UPSTREAM_REF: "upstream/master" + steps: - name: Checkout repository uses: actions/checkout@v6 @@ -26,66 +25,37 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - - name: Fetch upstream & generate branch name & check for new commits - id: check_commits - env: - GH_TOKEN: ${{ secrets.SYNC_PAT }} + - name: Fetch upstream run: | - gh repo set-default ${{ github.repository }} # Set the default repo to the origin repository git remote add upstream ${{ env.UPSTREAM }} git fetch upstream - - MERGES=$(git rev-list --count --merges HEAD..upstream/${{ env.UPSTREAM_BRANCH }}) - echo "Found $MERGES new merge commits in upstream." - - if [ "$MERGES" -lt ${{ env.MIN_UPSTREAM_MERGES }} ]; then - echo "Exiting." - echo "skip=true" >> "$GITHUB_OUTPUT" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - # Generate a sync branch name "sync-UPSTREAM_HEAD", where UPSTREAM_HEAD is a commit ID. - UPSTREAM_HEAD=$(git rev-parse --short upstream/${{ env.UPSTREAM_BRANCH }}) - SYNC_BRANCH="sync-$UPSTREAM_HEAD" - echo "Sync branch name: $SYNC_BRANCH" - echo "SYNC_BRANCH=$SYNC_BRANCH" >> "$GITHUB_ENV" - - # Check if the sync branch already exists in the origin repository - if git ls-remote --heads origin "$SYNC_BRANCH" | grep -q "$SYNC_BRANCH"; then - echo "Branch $SYNC_BRANCH already exists. Skipping the sync." - echo "skip=true" >> "$GITHUB_OUTPUT" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - - name: Generate PR metadata - id: branch_pr_metadata - if: steps.check_commits.outputs.skip == 'false' - run: | - # Call the sync script to generate PR title and body - ./contrib/sync-upstream.sh -b ${{ env.ORIGIN_BRANCH }} "$SYNC_BRANCH" - - - name: Push a sync branch - id: push_branch - if: steps.check_commits.outputs.skip == 'false' - run: | - echo "Creating sync branch: $SYNC_BRANCH" - git checkout upstream/${{ env.UPSTREAM_BRANCH }} - git checkout -b "$SYNC_BRANCH" - git push -u origin "$SYNC_BRANCH" - - - name: Create pull request - id: create_pr - if: steps.check_commits.outputs.skip == 'false' + gh repo set-default ${{ github.repository }} env: GH_TOKEN: ${{ secrets.SYNC_PAT }} - run: | - # Execute the generated PR creation script - ./contrib/gh-pr-create.sh - - name: Cleanup sync branch on failure - if: steps.push_branch.outcome == 'success' && steps.create_pr.outcome == 'failure' + - name: Run sync-upstream.sh + id: sync run: | - echo "PR creation failed but branch was pushed. Deleting: $SYNC_BRANCH" - git push origin --delete "$SYNC_BRANCH" \ No newline at end of file + OUTPUT=$(./contrib/sync-upstream.sh --switch "${{ env.BASE_BRANCH }}" "${{ env.UPSTREAM_REF }}" 2>&1) || { echo "$OUTPUT"; exit 1; } + echo "$OUTPUT" + if echo "$OUTPUT" | grep -qv "^No merge commits"; then + echo "newcommits=true" >> "$GITHUB_OUTPUT" + else + echo "Skipping further workflow steps." + fi + + - name: Push sync branch + id: push + if: steps.sync.outputs.newcommits == 'true' + run: | + if git push -u origin HEAD; then + echo "pushed=true" >> "$GITHUB_OUTPUT" + else + echo "Skipping further workflow steps." + fi + + - name: Create pull request + if: steps.sync.outputs.newcommits == 'true' && steps.push.outputs.pushed == 'true' + env: + GH_TOKEN: ${{ secrets.SYNC_PAT }} + run: ./gh-pr-create.sh From 5698e66c64c6c3b7eef1e17c1fb33b003871eba3 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sat, 2 May 2026 17:53:51 +0200 Subject: [PATCH 356/383] Add exhaustive test for ECDH module --- src/modules/ecdh/Makefile.am.include | 1 + src/modules/ecdh/tests_exhaustive_impl.h | 56 ++++++++++++++++++++++++ src/tests_exhaustive.c | 7 +++ 3 files changed, 64 insertions(+) create mode 100644 src/modules/ecdh/tests_exhaustive_impl.h diff --git a/src/modules/ecdh/Makefile.am.include b/src/modules/ecdh/Makefile.am.include index 18660535..81bc6279 100644 --- a/src/modules/ecdh/Makefile.am.include +++ b/src/modules/ecdh/Makefile.am.include @@ -1,5 +1,6 @@ include_HEADERS += include/secp256k1_ecdh.h noinst_HEADERS += src/modules/ecdh/main_impl.h noinst_HEADERS += src/modules/ecdh/tests_impl.h +noinst_HEADERS += src/modules/ecdh/tests_exhaustive_impl.h noinst_HEADERS += src/modules/ecdh/bench_impl.h noinst_HEADERS += src/wycheproof/ecdh_secp256k1_test.h diff --git a/src/modules/ecdh/tests_exhaustive_impl.h b/src/modules/ecdh/tests_exhaustive_impl.h new file mode 100644 index 00000000..2bcd2434 --- /dev/null +++ b/src/modules/ecdh/tests_exhaustive_impl.h @@ -0,0 +1,56 @@ +/*********************************************************************** + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +#ifndef SECP256K1_MODULE_ECDH_TESTS_EXHAUSTIVE_H +#define SECP256K1_MODULE_ECDH_TESTS_EXHAUSTIVE_H + +#include "../../../include/secp256k1_ecdh.h" +#include "main_impl.h" + +static void test_exhaustive_ecdh(const secp256k1_context *ctx, const secp256k1_ge *group) { + int i, j; + unsigned char seckeys[EXHAUSTIVE_TEST_ORDER - 1][32]; + secp256k1_pubkey pubkeys[EXHAUSTIVE_TEST_ORDER - 1]; + + /* Construct key pairs (32-byte secret key, public key object) for the entire group. */ + for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + secp256k1_scalar scalar; + secp256k1_scalar_set_int(&scalar, i); + secp256k1_scalar_get_b32(seckeys[i - 1], &scalar); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkeys[i - 1], seckeys[i - 1])); + } + + /* Loop over key combinations. */ + for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + for (j = 1; j < EXHAUSTIVE_TEST_ORDER; j++) { + unsigned char ecdh_result_ij[32]; + unsigned char ecdh_result_ji[32]; + + /* Calculate ECDH(i*G, j) and ECDH(j*G, i) using API function and verify that the results match. */ + CHECK(secp256k1_ecdh(ctx, ecdh_result_ij, &pubkeys[i - 1], seckeys[j - 1], NULL, NULL)); + CHECK(secp256k1_ecdh(ctx, ecdh_result_ji, &pubkeys[j - 1], seckeys[i - 1], NULL, NULL)); + CHECK(secp256k1_memcmp_var(ecdh_result_ij, ecdh_result_ji, 32) == 0); + + /* Recalculate the expected ECDH result manually by invoking the default ECDH hash + * function on the precomputed group element (group[i * j]) coordinates, and verify + * that it matches the previously calculated public API results. */ + { + secp256k1_ge ecdh_ge_expected = group[(i * j) % EXHAUSTIVE_TEST_ORDER]; + unsigned char ecdh_result_expected[32]; + unsigned char x[32]; + unsigned char y[32]; + + secp256k1_fe_normalize_var(&ecdh_ge_expected.x); + secp256k1_fe_normalize_var(&ecdh_ge_expected.y); + secp256k1_fe_get_b32(x, &ecdh_ge_expected.x); + secp256k1_fe_get_b32(y, &ecdh_ge_expected.y); + CHECK(secp256k1_ecdh_hash_function_default(ecdh_result_expected, x, y, NULL)); + CHECK(secp256k1_memcmp_var(ecdh_result_ij, ecdh_result_expected, 32) == 0); + } + } + } +} + +#endif diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 68d4bec3..6d128bcc 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -337,6 +337,10 @@ static void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_g */ } +#ifdef ENABLE_MODULE_ECDH +#include "modules/ecdh/tests_exhaustive_impl.h" +#endif + #ifdef ENABLE_MODULE_RECOVERY #include "modules/recovery/tests_exhaustive_impl.h" #endif @@ -437,6 +441,9 @@ int main(int argc, char** argv) { test_exhaustive_sign(ctx, group); test_exhaustive_verify(ctx, group); +#ifdef ENABLE_MODULE_ECDH + test_exhaustive_ecdh(ctx, group); +#endif #ifdef ENABLE_MODULE_RECOVERY test_exhaustive_recovery(ctx, group); #endif From b36c4ab71797907b0f83d1549c25cbca27906e97 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 27 Apr 2026 17:14:49 +0300 Subject: [PATCH 357/383] ecdsa_adaptor: use context hash functions in nonce generation --- src/modules/ecdsa_adaptor/dleq_impl.h | 13 ++++++++----- src/modules/ecdsa_adaptor/main_impl.h | 14 +++++++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index b05c0b18..e38562a5 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -24,6 +24,8 @@ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) { /* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */ static const unsigned char dleq_algo[] = {'D','L','E','Q'}; +static int nonce_function_ecdsa_adaptor_impl(const secp256k1_hash_ctx *hash_ctx, unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, const unsigned char *algo, size_t algolen, void *data); + static void secp256k1_dleq_hash_point(const secp256k1_hash_ctx *hash_ctx, secp256k1_sha256 *sha, secp256k1_ge *p) { unsigned char buf[33]; @@ -36,20 +38,21 @@ static int secp256k1_dleq_nonce(const secp256k1_hash_ctx *hash_ctx, secp256k1_sc unsigned char buf[32]; unsigned char nonce[32]; - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_ecdsa_adaptor; - } - secp256k1_sha256_initialize(&sha); secp256k1_sha256_write(hash_ctx, &sha, p1_33, 33); secp256k1_sha256_write(hash_ctx, &sha, p2_33, 33); secp256k1_sha256_finalize(hash_ctx, &sha, buf); secp256k1_sha256_clear(&sha); - if (!noncefp(nonce, buf, sk32, gen2_33, dleq_algo, sizeof(dleq_algo), ndata)) { + if (noncefp == NULL || noncefp == secp256k1_nonce_function_ecdsa_adaptor) { + if (!nonce_function_ecdsa_adaptor_impl(hash_ctx, nonce, buf, sk32, gen2_33, dleq_algo, sizeof(dleq_algo), ndata)) { + return 0; + } + } else if (!noncefp(nonce, buf, sk32, gen2_33, dleq_algo, sizeof(dleq_algo), ndata)) { return 0; } secp256k1_scalar_set_b32(k, nonce, NULL); + secp256k1_memclear_explicit(nonce, sizeof(nonce)); if (secp256k1_scalar_is_zero(k)) { return 0; } diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index 19fe1b09..ce5611d0 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -150,6 +150,7 @@ static int nonce_function_ecdsa_adaptor( const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_ecdsa_adaptor = nonce_function_ecdsa_adaptor; int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char *adaptor_sig162, unsigned char *seckey32, const secp256k1_pubkey *enckey, const unsigned char *msg32, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { + const secp256k1_hash_ctx *hash_ctx; secp256k1_scalar k; secp256k1_ge r[2]; /* R, R' */ secp256k1_gej rj[2]; /* R, R' */ @@ -175,16 +176,19 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char secp256k1_scalar_clear(&dleq_proof_e); secp256k1_scalar_clear(&dleq_proof_s); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_ecdsa_adaptor; - } - if (!secp256k1_pubkey_load(ctx, &enckey_ge, enckey)) { return 0; } + hash_ctx = secp256k1_get_hash_context(ctx); + secp256k1_eckey_pubkey_serialize33(&enckey_ge, buf33); - ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata); + if (noncefp == NULL || noncefp == secp256k1_nonce_function_ecdsa_adaptor) { + ret &= nonce_function_ecdsa_adaptor_impl(hash_ctx, nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata); + } else { + ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata); + } + secp256k1_scalar_set_b32(&k, nonce32, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); From 240578eef5f9ac92235a3f87095e025d04254e2f Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 15 May 2026 00:03:50 +0200 Subject: [PATCH 358/383] bench: add internal benchmark for `secp256k1_fe_normalize_var` --- src/bench_internal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/bench_internal.c b/src/bench_internal.c index f3c1be98..453f3bb3 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -194,6 +194,17 @@ static void bench_field_normalize(void* arg, int iters) { } } +static void bench_field_normalize_var(void* arg, int iters) { + int i; + bench_inv *data = (bench_inv*)arg; + + /* Note that this benchmark measures the optimistic path. The worst-case path with the final + reduction is very unlikely to be needed, so this is representative of the common case. */ + for (i = 0; i < iters; i++) { + secp256k1_fe_normalize_var(&data->fe[0]); + } +} + static void bench_field_normalize_weak(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; @@ -421,6 +432,7 @@ int main(int argc, char **argv) { if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "half")) run_benchmark("field_half", bench_field_half, bench_setup, NULL, &data, 10, iters*100); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, iters*100); + if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_var", bench_field_normalize_var, bench_setup, NULL, &data, 10, iters*100); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, iters*100); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, iters*10); if (d || have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, iters*10); From a3296d5e23f1475575cb8f0aa8209349cc9a6cfb Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 19 May 2026 16:29:05 +0200 Subject: [PATCH 359/383] refactor: introduce `_ecmult_gen_ge` helper (preventing accidental gej leaks) Scalar multiplication with the generator point frequently involves a conversion to affine coordinates and clearing out the temporary Jacobian group element object after to avoid leaking secret key material, i.e. executing the following three steps: - secp256k1_ecmult_gen(ctx, &rj, ...) - secp256k1_ge_set_gej(&r, &rj) - secp256k1_gej_clear(&rj) This commit introduces a corresponding helper to deduplicate code and mitigate the risk that last step is forgotten (which can easily happen and is not detected by tests). The idea came up during a conversation with furszy, see https://github.com/bitcoin-core/secp256k1/pull/1765#issuecomment-4482838033 --- src/ecdsa_impl.h | 5 +---- src/ecmult_gen.h | 1 + src/ecmult_gen_impl.h | 14 ++++++++++---- src/modules/schnorrsig/main_impl.h | 5 +---- src/secp256k1.c | 5 +---- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index 163539eb..32f1e585 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -273,14 +273,12 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25 static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { unsigned char b[32]; - secp256k1_gej rp; secp256k1_ge r; secp256k1_scalar n; int overflow = 0; int high; - secp256k1_ecmult_gen(ctx, &rp, nonce); - secp256k1_ge_set_gej(&r, &rp); + secp256k1_ecmult_gen_ge(ctx, &r, nonce); secp256k1_fe_normalize(&r.x); secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); @@ -296,7 +294,6 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec secp256k1_scalar_inverse(sigs, nonce); secp256k1_scalar_mul(sigs, sigs, &n); secp256k1_scalar_clear(&n); - secp256k1_gej_clear(&rp); secp256k1_ge_clear(&r); high = secp256k1_scalar_is_high(sigs); secp256k1_scalar_cond_negate(sigs, high); diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index 8bc4f14c..b842e780 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -138,6 +138,7 @@ static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx /** Multiply with the generator: R = a*G */ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); +static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context* ctx, secp256k1_ge *r, const secp256k1_scalar *a); static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32); diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 5a954977..53dc5f3d 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -281,11 +281,19 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 secp256k1_memclear_explicit(&recoded, sizeof(recoded)); } +SECP256K1_INLINE static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context *ctx, secp256k1_ge *r, const secp256k1_scalar *a) { + secp256k1_gej rj; + secp256k1_ecmult_gen(ctx, &rj, a); + secp256k1_ge_set_gej(r, &rj); + /* Jacobian coordinates resulting from our multiplication algorithm could potentially leak + * information about the secret input scalar, so clear the memory out to be on the safe side. */ + secp256k1_gej_clear(&rj); +} + /* Setup blinding values for secp256k1_ecmult_gen. */ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32) { secp256k1_scalar b; secp256k1_scalar diff; - secp256k1_gej gb; secp256k1_fe f; unsigned char nonce32[32]; secp256k1_rfc6979_hmac_sha256 rng; @@ -325,15 +333,13 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const * which secp256k1_gej_add_ge cannot handle. */ secp256k1_scalar_cmov(&b, &secp256k1_scalar_one, secp256k1_scalar_is_zero(&b)); secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_ecmult_gen(ctx, &gb, &b); + secp256k1_ecmult_gen_ge(ctx, &ctx->ge_offset, &b); secp256k1_scalar_negate(&b, &b); secp256k1_scalar_add(&ctx->scalar_offset, &b, &diff); - secp256k1_ge_set_gej(&ctx->ge_offset, &gb); /* Clean up. */ secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&b); - secp256k1_gej_clear(&gb); secp256k1_fe_clear(&f); secp256k1_rfc6979_hmac_sha256_clear(&rng); } diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 5100557f..efc72165 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -123,7 +123,6 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar sk; secp256k1_scalar e; secp256k1_scalar k; - secp256k1_gej rj; secp256k1_ge pk; secp256k1_ge r; unsigned char nonce32[32] = { 0 }; @@ -160,8 +159,7 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); - secp256k1_ge_set_gej(&r, &rj); + secp256k1_ecmult_gen_ge(&ctx->ecmult_gen_ctx, &r, &k); /* We declassify r to allow using it as a branch point. This is fine * because r is not a secret. */ @@ -183,7 +181,6 @@ static int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsi secp256k1_scalar_clear(&sk); secp256k1_memclear_explicit(seckey, sizeof(seckey)); secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); - secp256k1_gej_clear(&rj); return ret; } diff --git a/src/secp256k1.c b/src/secp256k1.c index e4b80fff..b216872e 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -624,15 +624,12 @@ int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char } static int secp256k1_ec_pubkey_create_helper(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_scalar *seckey_scalar, secp256k1_ge *p, const unsigned char *seckey) { - secp256k1_gej pj; int ret; ret = secp256k1_scalar_set_b32_seckey(seckey_scalar, seckey); secp256k1_scalar_cmov(seckey_scalar, &secp256k1_scalar_one, !ret); - secp256k1_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); - secp256k1_ge_set_gej(p, &pj); - secp256k1_gej_clear(&pj); + secp256k1_ecmult_gen_ge(ecmult_gen_ctx, p, seckey_scalar); return ret; } From 9e017e5062bfe306eb5724fe39debe94b6223592 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Thu, 4 Jun 2026 16:35:12 +0200 Subject: [PATCH 360/383] refactor: rename `_ecmult_gen` -> `_ecmult_gen_gej` for consistency Now that we have a function `_ecmult_gen_ge`, it makes sense to rename the existing function `_ecmult_gen` to `_ecmult_gen_gej` for consistency, to signal that the result is a Jacobian group element. This diff was created by applying ``` $ sed -i s/secp256k1_ecmult_gen\(/secp256k1_ecmult_gen_gej\(/g $(git ls-files) ``` --- src/bench_ecmult.c | 4 ++-- src/ecmult_gen.h | 2 +- src/ecmult_gen_impl.h | 4 ++-- src/modules/musig/session_impl.h | 2 +- src/tests.c | 26 +++++++++++++------------- src/tests_exhaustive.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index eb546db4..12d550a6 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -88,7 +88,7 @@ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset secp256k1_scalar_add(&sum_scalars, &sum_scalars, &s); } } - secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars); + secp256k1_ecmult_gen_gej(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars); CHECK(secp256k1_gej_eq_var(&tmp, &sum_output)); } @@ -104,7 +104,7 @@ static void bench_ecmult_gen(void* arg, int iters) { int i; for (i = 0; i < iters; ++i) { - secp256k1_ecmult_gen(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]); + secp256k1_ecmult_gen_gej(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]); } } diff --git a/src/ecmult_gen.h b/src/ecmult_gen.h index b842e780..770b2cb2 100644 --- a/src/ecmult_gen.h +++ b/src/ecmult_gen.h @@ -137,7 +137,7 @@ static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); /** Multiply with the generator: R = a*G */ -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); +static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context* ctx, secp256k1_ge *r, const secp256k1_scalar *a); static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const secp256k1_hash_ctx *hash_ctx, const unsigned char *seed32); diff --git a/src/ecmult_gen_impl.h b/src/ecmult_gen_impl.h index 53dc5f3d..a7a6d34d 100644 --- a/src/ecmult_gen_impl.h +++ b/src/ecmult_gen_impl.h @@ -51,7 +51,7 @@ static void secp256k1_ecmult_gen_scalar_diff(secp256k1_scalar* diff) { secp256k1_scalar_add(diff, diff, &neghalf); } -static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { +static void secp256k1_ecmult_gen_gej(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { uint32_t comb_off; secp256k1_ge add; secp256k1_fe neg; @@ -283,7 +283,7 @@ static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp25 SECP256K1_INLINE static void secp256k1_ecmult_gen_ge(const secp256k1_ecmult_gen_context *ctx, secp256k1_ge *r, const secp256k1_scalar *a) { secp256k1_gej rj; - secp256k1_ecmult_gen(ctx, &rj, a); + secp256k1_ecmult_gen_gej(ctx, &rj, a); secp256k1_ge_set_gej(r, &rj); /* Jacobian coordinates resulting from our multiplication algorithm could potentially leak * information about the secret input scalar, so clear the memory out to be on the safe side. */ diff --git a/src/modules/musig/session_impl.h b/src/modules/musig/session_impl.h index 510ee89f..c05801ee 100644 --- a/src/modules/musig/session_impl.h +++ b/src/modules/musig/session_impl.h @@ -415,7 +415,7 @@ static int secp256k1_musig_nonce_gen_internal(const secp256k1_context* ctx, secp /* Compute pubnonce as two gejs */ for (i = 0; i < 2; i++) { - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]); + secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &nonce_ptj[i], &k[i]); secp256k1_scalar_clear(&k[i]); } diff --git a/src/tests.c b/src/tests.c index 862bef61..9084c1d6 100644 --- a/src/tests.c +++ b/src/tests.c @@ -329,7 +329,7 @@ static void run_proper_context_tests(int use_prealloc) { /*** attempt to use them ***/ testutil_random_scalar_order_test(&msg); testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen(&my_ctx->ecmult_gen_ctx, &pubj, &key); + secp256k1_ecmult_gen_gej(&my_ctx->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); /* obtain a working nonce */ @@ -4311,11 +4311,11 @@ static void test_ec_combine(void) { secp256k1_scalar s; testutil_random_scalar_order_test(&s); secp256k1_scalar_add(&sum, &sum, &s); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &s); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &Qj, &s); secp256k1_ge_set_gej(&Q, &Qj); secp256k1_pubkey_save(&data[i - 1], &Q); d[i - 1] = &data[i - 1]; - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &sum); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &Qj, &sum); secp256k1_ge_set_gej(&Q, &Qj); secp256k1_pubkey_save(&sd, &Q); CHECK(secp256k1_ec_pubkey_combine(CTX, &sd2, d, i) == 1); @@ -4593,9 +4593,9 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) { /* EC multiplications */ if (mode == 0) { - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &p1j, &n1); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &p2j, &n2); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &ptj, target); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &p1j, &n1); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &p2j, &n2); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &ptj, target); } else if (mode == 1) { secp256k1_ecmult(&p1j, &pj, &n1, &secp256k1_scalar_zero); secp256k1_ecmult(&p2j, &pj, &n2, &secp256k1_scalar_zero); @@ -5162,7 +5162,7 @@ static int test_ecmult_multi_random(secp256k1_scratch *scratch) { secp256k1_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar); secp256k1_scalar_inverse_var(&sc_tmp, &sc_tmp); secp256k1_scalar_negate(&sc_tmp, &sc_tmp); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp); ++filled; ++mults; } @@ -5642,7 +5642,7 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar size_t i; secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); secp256k1_gej_set_infinity(&infj); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &rj[0], x); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &rj[0], x); secp256k1_ecmult(&rj[1], &gj, x, NULL); secp256k1_ecmult(&rj[2], &gj, x, &secp256k1_scalar_zero); secp256k1_ecmult(&rj[3], &infj, &secp256k1_scalar_zero, x); @@ -5796,13 +5796,13 @@ static void test_ecmult_gen_blind(void) { secp256k1_ge p; secp256k1_ge pge; testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pgej, &key); testrand256(seed32); b = CTX->ecmult_gen_ctx.scalar_offset; p = CTX->ecmult_gen_ctx.ge_offset; secp256k1_ecmult_gen_blind(&CTX->ecmult_gen_ctx, secp256k1_get_hash_context(CTX), seed32); CHECK(!secp256k1_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej2, &key); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pgej2, &key); CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); CHECK(!secp256k1_ge_eq_var(&p, &CTX->ecmult_gen_ctx.ge_offset)); secp256k1_ge_set_gej(&pge, &pgej); @@ -5832,7 +5832,7 @@ static void test_ecmult_gen_edge_cases(void) { for (i = -1; i < 2; ++i) { /* Run test with gn = i - scalar_offset (so that the ecmult_gen recoded value represents i). */ - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &res1, &gn); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &res1, &gn); secp256k1_ecmult(&res2, NULL, &secp256k1_scalar_zero, &gn); secp256k1_ecmult_const(&res3, &secp256k1_ge_const_g, &gn); CHECK(secp256k1_gej_eq_var(&res1, &res2)); @@ -6524,7 +6524,7 @@ static void test_ecdsa_sign_verify(void) { int recid; testutil_random_scalar_order_test(&msg); testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pubj, &key); secp256k1_ge_set_gej(&pub, &pubj); getrec = testrand_bits(1); /* The specific way in which this conditional is written sidesteps a potential bug in clang. @@ -7292,7 +7292,7 @@ static void run_ecdsa_edge_cases(void) { secp256k1_scalar_negate(&ss, &ss); secp256k1_scalar_inverse(&ss, &ss); secp256k1_scalar_set_int(&sr, 1); - secp256k1_ecmult_gen(&CTX->ecmult_gen_ctx, &keyj, &sr); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &keyj, &sr); secp256k1_ge_set_gej(&key, &keyj); msg = ss; CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 6d128bcc..888b7ac9 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -425,7 +425,7 @@ int main(int argc, char** argv) { secp256k1_ge generated; secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); + secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); secp256k1_ge_set_gej(&generated, &generatedj); CHECK(!secp256k1_ge_is_infinity(&group[i])); From ca68daf8e1caa67c31242bd39704d1967cd35e11 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Mon, 8 Jun 2026 18:33:45 +0200 Subject: [PATCH 361/383] test: refactor: simplify tests by using `_ecmult_gen_ge` helper If the generator point multiplication result in Jacobian coordinates is immediately converted to affine coordinates after and is not needed for anything else, we can deduplicate by using the helper introduced in #1861. Note that in a very strict sense this is not a refactor, as the Jacobian object is now cleared out which was not done on master, but for the logic in the tests this shouldn't matter at all. --- src/tests.c | 19 +++++-------------- src/tests_exhaustive.c | 4 +--- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/tests.c b/src/tests.c index 9084c1d6..95f177ad 100644 --- a/src/tests.c +++ b/src/tests.c @@ -241,7 +241,6 @@ static void run_proper_context_tests(int use_prealloc) { void *my_ctx_prealloc = NULL; unsigned char seed[32] = {0x17}; - secp256k1_gej pubj; secp256k1_ge pub; secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; @@ -329,8 +328,7 @@ static void run_proper_context_tests(int use_prealloc) { /*** attempt to use them ***/ testutil_random_scalar_order_test(&msg); testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen_gej(&my_ctx->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); + secp256k1_ecmult_gen_ge(&my_ctx->ecmult_gen_ctx, &pub, &key); /* obtain a working nonce */ do { @@ -4304,19 +4302,16 @@ static void test_ec_combine(void) { const secp256k1_pubkey* d[6]; secp256k1_pubkey sd; secp256k1_pubkey sd2; - secp256k1_gej Qj; secp256k1_ge Q; int i; for (i = 1; i <= 6; i++) { secp256k1_scalar s; testutil_random_scalar_order_test(&s); secp256k1_scalar_add(&sum, &sum, &s); - secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &Qj, &s); - secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &Q, &s); secp256k1_pubkey_save(&data[i - 1], &Q); d[i - 1] = &data[i - 1]; - secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &Qj, &sum); - secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &Q, &sum); secp256k1_pubkey_save(&sd, &Q); CHECK(secp256k1_ec_pubkey_combine(CTX, &sd2, d, i) == 1); CHECK(secp256k1_memcmp_var(&sd, &sd2, sizeof(sd)) == 0); @@ -6515,7 +6510,6 @@ static void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const se } static void test_ecdsa_sign_verify(void) { - secp256k1_gej pubj; secp256k1_ge pub; secp256k1_scalar one; secp256k1_scalar msg, key; @@ -6524,8 +6518,7 @@ static void test_ecdsa_sign_verify(void) { int recid; testutil_random_scalar_order_test(&msg); testutil_random_scalar_order_test(&key); - secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &pubj, &key); - secp256k1_ge_set_gej(&pub, &pubj); + secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &pub, &key); getrec = testrand_bits(1); /* The specific way in which this conditional is written sidesteps a potential bug in clang. See the commit messages of the commit that introduced this comment for details. */ @@ -7284,7 +7277,6 @@ static void run_ecdsa_edge_cases(void) { /* Test the case where ECDSA recomputes a point that is infinity. */ { - secp256k1_gej keyj; secp256k1_ge key; secp256k1_scalar msg; secp256k1_scalar sr, ss; @@ -7292,8 +7284,7 @@ static void run_ecdsa_edge_cases(void) { secp256k1_scalar_negate(&ss, &ss); secp256k1_scalar_inverse(&ss, &ss); secp256k1_scalar_set_int(&sr, 1); - secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &keyj, &sr); - secp256k1_ge_set_gej(&key, &keyj); + secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &key, &sr); msg = ss; CHECK(secp256k1_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); } diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 888b7ac9..80f71562 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -421,12 +421,10 @@ int main(int argc, char** argv) { /* Verify against ecmult_gen */ { secp256k1_scalar scalar_i; - secp256k1_gej generatedj; secp256k1_ge generated; secp256k1_scalar_set_int(&scalar_i, i); - secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); - secp256k1_ge_set_gej(&generated, &generatedj); + secp256k1_ecmult_gen_ge(&ctx->ecmult_gen_ctx, &generated, &scalar_i); CHECK(!secp256k1_ge_is_infinity(&group[i])); CHECK(secp256k1_ge_eq_var(&group[i], &generated)); From acf2084aa7ea2b946f6f9b0262b588fc7bfec0be Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:22:57 +0100 Subject: [PATCH 362/383] cmake, refactor: Introduce `SetLibtoolAbiVersion` module --- cmake/SetLibtoolAbiVersion.cmake | 28 +++++++++++++++++++++++++++ src/CMakeLists.txt | 33 +++++--------------------------- 2 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 cmake/SetLibtoolAbiVersion.cmake diff --git a/cmake/SetLibtoolAbiVersion.cmake b/cmake/SetLibtoolAbiVersion.cmake new file mode 100644 index 00000000..6ae19d38 --- /dev/null +++ b/cmake/SetLibtoolAbiVersion.cmake @@ -0,0 +1,28 @@ +# This emulates Libtool to make sure Libtool and CMake agree on the ABI version, +# see below "Calculate the version variables" in autotools-aux/ltmain.sh. +function(set_libtool_abi_version target current revision age) + math(EXPR _soversion "${current} - ${age}") + set_target_properties(${target} PROPERTIES + SOVERSION ${_soversion} + ) + if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$") + set_target_properties(${target} PROPERTIES + VERSION ${_soversion}.${age}.${revision} + ) + elseif(APPLE) + math(EXPR _compatibility "${current} + 1") + set_target_properties(${target} PROPERTIES + MACHO_COMPATIBILITY_VERSION ${_compatibility} + MACHO_CURRENT_VERSION ${_compatibility}.${revision} + ) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(_windows_name "secp256k1") + if(MSVC) + set(_windows_name "${PROJECT_NAME}") + endif() + set_target_properties(${target} PROPERTIES + ARCHIVE_OUTPUT_NAME "${_windows_name}" + RUNTIME_OUTPUT_NAME "${_windows_name}-${_soversion}" + ) + endif() +endfunction() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 322f1987..a45eeb93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,35 +94,12 @@ set_target_properties(secp256k1_objs PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "$" ) -# This emulates Libtool to make sure Libtool and CMake agree on the ABI version, -# see below "Calculate the version variables" in autotools-aux/ltmain.sh. -math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}") -set_target_properties(secp256k1 PROPERTIES - SOVERSION ${${PROJECT_NAME}_soversion} +include(SetLibtoolAbiVersion) +set_libtool_abi_version(secp256k1 + ${${PROJECT_NAME}_LIB_VERSION_CURRENT} + ${${PROJECT_NAME}_LIB_VERSION_REVISION} + ${${PROJECT_NAME}_LIB_VERSION_AGE} ) -if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$") - set_target_properties(secp256k1 PROPERTIES - VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION} - ) -elseif(APPLE) - math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1") - set_target_properties(secp256k1 PROPERTIES - MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version} - MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION} - ) - unset(${PROJECT_NAME}_compatibility_version) -elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") - set(${PROJECT_NAME}_windows "secp256k1") - if(MSVC) - set(${PROJECT_NAME}_windows "${PROJECT_NAME}") - endif() - set_target_properties(secp256k1 PROPERTIES - ARCHIVE_OUTPUT_NAME "${${PROJECT_NAME}_windows}" - RUNTIME_OUTPUT_NAME "${${PROJECT_NAME}_windows}-${${PROJECT_NAME}_soversion}" - ) - unset(${PROJECT_NAME}_windows) -endif() -unset(${PROJECT_NAME}_soversion) if(SECP256K1_BUILD_BENCHMARK) add_executable(bench bench.c) From 8a0f4002c7dd0a406c62b8ace455f0c75a4cb620 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:23:08 +0100 Subject: [PATCH 363/383] cmake, refactor: Improve documenting in `SetLibtoolAbiVersion` module --- cmake/SetLibtoolAbiVersion.cmake | 33 ++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/cmake/SetLibtoolAbiVersion.cmake b/cmake/SetLibtoolAbiVersion.cmake index 6ae19d38..8665daa7 100644 --- a/cmake/SetLibtoolAbiVersion.cmake +++ b/cmake/SetLibtoolAbiVersion.cmake @@ -1,28 +1,45 @@ -# This emulates Libtool to make sure Libtool and CMake agree on the ABI version, -# see below "Calculate the version variables" in autotools-aux/ltmain.sh. +#[=[ +This emulates Libtool to make sure Libtool and CMake agree on +the ABI version and file naming for shared libraries. + +The `version_type` variable is set in `libtool.m4` (installed +by autoreconf into autotools-aux/m4/). +For the `major` and `versuffix` variables, see below "Calculate +the version variables" in `ltmain.sh` (installed by autoreconf +into autotools-aux/). +]=] function(set_libtool_abi_version target current revision age) - math(EXPR _soversion "${current} - ${age}") - set_target_properties(${target} PROPERTIES - SOVERSION ${_soversion} - ) if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|FreeBSD)$") + # version_type = linux | freebsd-elf + # major = $current - $age + # versuffix = $major.$age.$revision + math(EXPR _major "${current} - ${age}") set_target_properties(${target} PROPERTIES - VERSION ${_soversion}.${age}.${revision} + SOVERSION ${_major} + VERSION ${_major}.${age}.${revision} ) elseif(APPLE) + # version_type = darwin + # major = $current - $age + math(EXPR _major "${current} - ${age}") math(EXPR _compatibility "${current} + 1") set_target_properties(${target} PROPERTIES + SOVERSION ${_major} MACHO_COMPATIBILITY_VERSION ${_compatibility} MACHO_CURRENT_VERSION ${_compatibility}.${revision} ) elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + # version_type = windows + # major = $current - $age + # versuffix = $major + math(EXPR _major "${current} - ${age}") set(_windows_name "secp256k1") if(MSVC) set(_windows_name "${PROJECT_NAME}") endif() set_target_properties(${target} PROPERTIES ARCHIVE_OUTPUT_NAME "${_windows_name}" - RUNTIME_OUTPUT_NAME "${_windows_name}-${_soversion}" + RUNTIME_OUTPUT_NAME "${_windows_name}-${_major}" ) endif() endfunction() From a401c5145a15b98c60b74abf149a98e3469c90c8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:23:15 +0100 Subject: [PATCH 364/383] cmake: Fix shared library versioning on NetBSD --- cmake/SetLibtoolAbiVersion.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/SetLibtoolAbiVersion.cmake b/cmake/SetLibtoolAbiVersion.cmake index 8665daa7..10ef8e17 100644 --- a/cmake/SetLibtoolAbiVersion.cmake +++ b/cmake/SetLibtoolAbiVersion.cmake @@ -18,6 +18,14 @@ function(set_libtool_abi_version target current revision age) SOVERSION ${_major} VERSION ${_major}.${age}.${revision} ) + elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") + # version_type = sunos + # major = $current + # versuffix = $current.$revision + set_target_properties(${target} PROPERTIES + SOVERSION ${current} + VERSION ${current}.${revision} + ) elseif(APPLE) # version_type = darwin # major = $current - $age From 1eab757207c453db5bb567f2a6e18362eb49ee4c Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:23:25 +0100 Subject: [PATCH 365/383] cmake: Fix shared library versioning on OpenBSD --- cmake/SetLibtoolAbiVersion.cmake | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmake/SetLibtoolAbiVersion.cmake b/cmake/SetLibtoolAbiVersion.cmake index 10ef8e17..0e981053 100644 --- a/cmake/SetLibtoolAbiVersion.cmake +++ b/cmake/SetLibtoolAbiVersion.cmake @@ -26,6 +26,14 @@ function(set_libtool_abi_version target current revision age) SOVERSION ${current} VERSION ${current}.${revision} ) + elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + # version_type = sunos + # major = $current + # versuffix = $current.$revision + set_target_properties(${target} PROPERTIES + # OpenBSD has no `soname_spec` defined in `libtool.m4`. + VERSION ${current}.${revision} + ) elseif(APPLE) # version_type = darwin # major = $current - $age From d7125e517d45507df4a3f19c8ca90393a8290480 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Wed, 10 Jun 2026 00:06:14 +0200 Subject: [PATCH 366/383] test: musig: fix dead "aggnonce encodes two points at infinity" check --- src/modules/musig/tests_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/musig/tests_impl.h b/src/modules/musig/tests_impl.h index fb3a10a0..3a30c233 100644 --- a/src/modules/musig/tests_impl.h +++ b/src/modules/musig/tests_impl.h @@ -374,7 +374,7 @@ static void musig_api_tests(void) { secp256k1_ge aggnonce_pt[2]; secp256k1_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce); for (i = 0; i < 2; i++) { - secp256k1_ge_is_infinity(&aggnonce_pt[i]); + CHECK(secp256k1_ge_is_infinity(&aggnonce_pt[i]) == 1); } } CHECK(secp256k1_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); From 2ee79e77e65bf5f7f747df1d978d04f1ace1e3a0 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Tue, 9 Jun 2026 17:04:53 +0200 Subject: [PATCH 367/383] test: add unit test for `_ecmult_gen_ge` --- src/tests.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/tests.c b/src/tests.c index 95f177ad..5070f590 100644 --- a/src/tests.c +++ b/src/tests.c @@ -5781,6 +5781,25 @@ static void run_ecmult_constants(void) { } } +static void run_ecmult_gen_ge(void) { + /* Test that secp256k1_ecmult_gen_ge result matches secp256k1_ecmult_gen_gej with + * manual Jacobian-to-affine conversion (secp256k1_ge_set_gej) over random scalars */ + int i; + + for (i = 0; i < COUNT; i++) { + secp256k1_scalar scalar; + secp256k1_gej result_gej; + secp256k1_ge result_ge, expected_ge; + + testutil_random_scalar_order_test(&scalar); + secp256k1_ecmult_gen_gej(&CTX->ecmult_gen_ctx, &result_gej, &scalar); + secp256k1_ge_set_gej(&expected_ge, &result_gej); + secp256k1_ecmult_gen_ge(&CTX->ecmult_gen_ctx, &result_ge, &scalar); + + CHECK(secp256k1_ge_eq_var(&result_ge, &expected_ge)); + } +} + static void test_ecmult_gen_blind(void) { /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ secp256k1_scalar key; @@ -7960,6 +7979,7 @@ static const struct tf_test_entry tests_ecmult[] = { CASE(ecmult_near_split_bound), CASE(ecmult_chain), CASE(ecmult_constants), + CASE(ecmult_gen_ge), CASE(ecmult_gen_blind), CASE(ecmult_const_tests), CASE(ecmult_multi_tests), From a77dacad9ad8a2bff51b51c6a000c7dae45dad78 Mon Sep 17 00:00:00 2001 From: kallal79 Date: Fri, 12 Jun 2026 19:10:33 +0530 Subject: [PATCH 368/383] test: enable -Wunused-function in test suite (Fix #1831) --- src/ctime_tests.c | 9 +++++++++ src/tests.c | 9 +++++++++ src/tests_exhaustive.c | 9 +++++++++ src/unit_test.c | 9 +++++++++ 4 files changed, 36 insertions(+) diff --git a/src/ctime_tests.c b/src/ctime_tests.c index f80042a8..8a885ca2 100644 --- a/src/ctime_tests.c +++ b/src/ctime_tests.c @@ -40,6 +40,11 @@ #include "../include/secp256k1_ellswift.h" #endif +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic warning "-Wunused-function" +#endif + static void run_tests(secp256k1_context *ctx, unsigned char *key); int main(void) { @@ -265,3 +270,7 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) { #endif } + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif diff --git a/src/tests.c b/src/tests.c index 5070f590..6c3cd39f 100644 --- a/src/tests.c +++ b/src/tests.c @@ -37,6 +37,11 @@ #include "int128_impl.h" #endif +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic warning "-Wunused-function" +#endif + #define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else static secp256k1_context *CTX = NULL; @@ -8091,3 +8096,7 @@ int main(int argc, char **argv) { if (tf_init(&tf, argc, argv) != 0) return EXIT_FAILURE; return tf_run(&tf); } + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif diff --git a/src/tests_exhaustive.c b/src/tests_exhaustive.c index 80f71562..99d7b244 100644 --- a/src/tests_exhaustive.c +++ b/src/tests_exhaustive.c @@ -31,6 +31,11 @@ #include "testutil.h" #include "util.h" +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic warning "-Wunused-function" +#endif + static int count = 2; static uint32_t num_cores = 1; @@ -467,3 +472,7 @@ int main(int argc, char** argv) { printf("no problems found\n"); return EXIT_SUCCESS; } + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif diff --git a/src/unit_test.c b/src/unit_test.c index a1858a11..2ac709cc 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -17,6 +17,11 @@ #include "testrand.h" #include "tests_common.h" +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic warning "-Wunused-function" +#endif + #define UNUSED(x) (void)(x) /* Number of times certain tests will run */ @@ -477,3 +482,7 @@ static int tf_run(struct tf_framework* tf) { return status; } + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif From 71fcd8410e92adbffe33c6633f60153b4d562f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Fri, 29 May 2026 13:03:42 +0200 Subject: [PATCH 369/383] field: force-inline 5x52 mul and sqr The 5x52 field multiplication and squaring routines are hot in group arithmetic and scalar multiplication. Use the new `SECP256K1_FORCE_INLINE` for the thin wrappers and `int128` inner helpers so compilers can schedule the 64x64->128 arithmetic without a call boundary. Across the measured GCC and MSVC Release builds, this improves ECDSA verification by 0.6% to 9.1%, ECDH by 0.7% to 9.3%, and Schnorr verification by 0.6% to 9.6%. The direct field benchmarks generally show the intended effect on field squaring and multiplication, while Clang results are mostly flat and less consistently positive. This is a code-size tradeoff: the tested static library builds grew by about 4.6% to 4.7%, and the tested Windows Release DLL grew by 14.1%. Co-authored-by: Sebastian Falbesoner Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Co-authored-by: Tim Ruffing --- CMakeLists.txt | 2 ++ src/field_5x52_impl.h | 4 ++-- src/field_5x52_int128_impl.h | 4 ++-- src/util.h | 11 +++++++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ef69c08..a84305c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,8 @@ if(MSVC) string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}") + # Match GCC/Clang's size-optimization macro for the inline guard + add_compile_definitions($<$:__OPTIMIZE_SIZE__=1>) else() string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index 3a976135..0e0e2d65 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -338,11 +338,11 @@ SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp25 r->n[4] += a->n[4]; } -SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { +SECP256K1_FORCE_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { secp256k1_fe_mul_inner(r->n, a->n, b->n); } -SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +SECP256K1_FORCE_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) { secp256k1_fe_sqr_inner(r->n, a->n); } diff --git a/src/field_5x52_int128_impl.h b/src/field_5x52_int128_impl.h index f23f8ee1..8d1977b2 100644 --- a/src/field_5x52_int128_impl.h +++ b/src/field_5x52_int128_impl.h @@ -15,7 +15,7 @@ #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) #define VERIFY_BITS_128(x, n) VERIFY_CHECK(secp256k1_u128_check_bits((x), (n))) -SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { +SECP256K1_FORCE_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { secp256k1_uint128 c, d; uint64_t t3, t4, tx, u0; uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; @@ -151,7 +151,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } -SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { +SECP256K1_FORCE_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { secp256k1_uint128 c, d; uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; uint64_t t3, t4, tx, u0; diff --git a/src/util.h b/src/util.h index 5d03e4c7..492a5929 100644 --- a/src/util.h +++ b/src/util.h @@ -57,6 +57,17 @@ static void print_buf_plain(const unsigned char *buf, size_t len) { # define SECP256K1_INLINE inline # endif +# if !defined(_DEBUG) && !defined(__NO_INLINE__) && !defined(__OPTIMIZE_SIZE__) +# if defined(__OPTIMIZE__) && (SECP256K1_GNUC_PREREQ(3, 0) || defined(__clang__)) +# define SECP256K1_FORCE_INLINE SECP256K1_INLINE __attribute__((always_inline)) +# elif defined(_MSC_VER) +# define SECP256K1_FORCE_INLINE __forceinline +# endif +# endif +# ifndef SECP256K1_FORCE_INLINE +# define SECP256K1_FORCE_INLINE SECP256K1_INLINE +# endif + /** Assert statically that expr is true. * * This is a statement-like macro and can only be used inside functions. From 66260b78a2797fe9f8fa4615623deb0dbe361335 Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 24 Jun 2026 16:55:40 +0100 Subject: [PATCH 370/383] ci: add 'brew trust' invocation to macOS CI Should fix issues like: > Error: Refusing to load formula louisbrunner/valgrind/valgrind from untrusted tap louisbrunner/valgrind. > Run `brew trust --formula louisbrunner/valgrind/valgrind` or `brew trust louisbrunner/valgrind` to trust it. > Error: Process completed with exit code 1. --- .github/actions/install-homebrew-valgrind/action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/install-homebrew-valgrind/action.yml b/.github/actions/install-homebrew-valgrind/action.yml index e9aa6150..c4e0b5d9 100644 --- a/.github/actions/install-homebrew-valgrind/action.yml +++ b/.github/actions/install-homebrew-valgrind/action.yml @@ -5,6 +5,7 @@ runs: steps: - run: | brew tap LouisBrunner/valgrind + brew trust --formula LouisBrunner/valgrind/valgrind brew fetch --HEAD LouisBrunner/valgrind/valgrind echo "CI_HOMEBREW_CELLAR_VALGRIND=$(brew --cellar valgrind)" >> "$GITHUB_ENV" shell: bash From 9d75769dec4fcb40ee7e41f674f22f3f5e5cfc7e Mon Sep 17 00:00:00 2001 From: Tim Ruffing Date: Thu, 25 Jun 2026 11:17:24 +0200 Subject: [PATCH 371/383] tests: Fix GCC 17 snapshot warning Passing a non-malloc pointer to free() would be UB. In this case, the free() line is never actually reached (and GCC 17 fails to prove this) in a correct implementation of secp256k1_scratch_space_destroy(), but the test shouldn't rely on the correctness of the tested function. --- src/tests.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/tests.c b/src/tests.c index 6c3cd39f..b0d94d6a 100644 --- a/src/tests.c +++ b/src/tests.c @@ -372,7 +372,6 @@ static void run_scratch_tests(void) { size_t checkpoint; size_t checkpoint_2; secp256k1_scratch_space *scratch; - secp256k1_scratch_space local_scratch; /* Test public API */ scratch = secp256k1_scratch_space_create(CTX, 1000); @@ -412,16 +411,7 @@ static void run_scratch_tests(void) { CHECK_ERROR_VOID(CTX, secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint_2)); /* checkpoint_2 is after checkpoint */ CHECK_ERROR_VOID(CTX, secp256k1_scratch_apply_checkpoint(&CTX->error_callback, scratch, (size_t) -1)); /* this is just wildly invalid */ - /* try to use badly initialized scratch space */ - secp256k1_scratch_space_destroy(CTX, scratch); - memset(&local_scratch, 0, sizeof(local_scratch)); - scratch = &local_scratch; - CHECK_ERROR(CTX, secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0)); - CHECK_ERROR(CTX, secp256k1_scratch_alloc(&CTX->error_callback, scratch, 500)); - CHECK_ERROR_VOID(CTX, secp256k1_scratch_space_destroy(CTX, scratch)); - /* Test that large integers do not wrap around in a bad way */ - scratch = secp256k1_scratch_space_create(CTX, 1000); /* Try max allocation with a large number of objects. Only makes sense if * ALIGNMENT is greater than 1 because otherwise the objects take no extra * space. */ @@ -436,6 +426,21 @@ static void run_scratch_tests(void) { secp256k1_scratch_space_destroy(CTX, NULL); /* no-op */ } +/* try to use badly initialized scratch space */ +static void run_invalid_scratch_space_tests(void) { + secp256k1_scratch_space* scratch = checked_malloc(&CTX->error_callback, sizeof(*scratch)); + size_t magic_size = sizeof(scratch->magic); + memset(scratch, 0, sizeof(*scratch)); + /* catch accesses beyond the magic */ + SECP256K1_CHECKMEM_UNDEFINE((unsigned char*)scratch + magic_size, sizeof(*scratch) - magic_size); + + CHECK_ERROR(CTX, secp256k1_scratch_max_allocation(&CTX->error_callback, scratch, 0)); + CHECK_ERROR(CTX, secp256k1_scratch_alloc(&CTX->error_callback, scratch, 500)); + CHECK_ERROR_VOID(CTX, secp256k1_scratch_space_destroy(CTX, scratch)); + + free(scratch); +} + /* A compression function that does nothing */ static void invalid_sha256_compression(uint32_t *s, const unsigned char *msg, size_t rounds) { (void)s; (void)msg; (void)rounds; @@ -7935,6 +7940,7 @@ static const struct tf_test_entry tests_general[] = { CASE(all_static_context_tests), CASE(deprecated_context_flags_test), CASE(scratch_tests), + CASE(invalid_scratch_space_tests), CASE(plug_sha256_compression_tests), CASE(sha256_multi_block_compression_tests), }; From 994b35010d1d62383be0ec970582ff4a171f7e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Sun, 21 Jun 2026 13:37:40 +0200 Subject: [PATCH 372/383] field: correct fe_equal's b magnitude bound `secp256k1_fe_equal` negates `a` before adding `b`. That gives the temporary value magnitude 2, and the following field addition requires the input magnitudes to sum to at most 32. So the largest `b` magnitude the implementation can accept is 30, not 31. Lower the documented and checked bound for `b` to 30. Adjust the focused test to use random field elements with randomized magnitudes within the accepted `a <= 1` and `b <= 30` bounds. Co-authored-by: Sebastian Falbesoner Co-authored-by: Tim Ruffing --- src/field.h | 2 +- src/field_impl.h | 2 +- src/tests.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/field.h b/src/field.h index 945029ec..8b25d99b 100644 --- a/src/field.h +++ b/src/field.h @@ -166,7 +166,7 @@ static int secp256k1_fe_is_odd(const secp256k1_fe *a); /** Determine whether two field elements are equal. * * On input, a and b must be valid field elements with magnitudes not exceeding - * 1 and 31, respectively. + * 1 and 30, respectively. * Returns a = b (mod p). */ static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); diff --git a/src/field_impl.h b/src/field_impl.h index 7aa7de43..19af6aa2 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -27,7 +27,7 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp SECP256K1_FE_VERIFY(a); SECP256K1_FE_VERIFY(b); SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); - SECP256K1_FE_VERIFY_MAGNITUDE(b, 31); + SECP256K1_FE_VERIFY_MAGNITUDE(b, 30); secp256k1_fe_negate(&na, a, 1); secp256k1_fe_add(&na, b); diff --git a/src/tests.c b/src/tests.c index b0d94d6a..e821738d 100644 --- a/src/tests.c +++ b/src/tests.c @@ -3064,6 +3064,18 @@ static int fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { return secp256k1_fe_equal(&an, &bn); } +static void run_fe_equal_magnitude_boundaries(void) { + int i; + secp256k1_fe a, b; + for (i = 0; i < 100 * COUNT; ++i) { + testutil_random_fe(&a); + b = a; + testutil_random_fe_magnitude(&a, 1); + testutil_random_fe_magnitude(&b, 30); + CHECK(secp256k1_fe_equal(&a, &b)); + } +} + static void run_field_convert(void) { static const unsigned char b32[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -7970,6 +7982,7 @@ static const struct tf_test_entry tests_scalar[] = { static const struct tf_test_entry tests_field[] = { CASE(field_half), CASE(field_misc), + CASE(fe_equal_magnitude_boundaries), CASE(field_convert), CASE(field_be32_overflow), CASE(fe_mul), From 6a599a44289597c2a3061b5ac6afddbf5c3ff293 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Fri, 26 Jun 2026 03:04:13 +0200 Subject: [PATCH 373/383] scalar: correct `_scalar_get_bits_{limb32,var}` input condition docs --- src/scalar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scalar.h b/src/scalar.h index 40d67191..2a5842b4 100644 --- a/src/scalar.h +++ b/src/scalar.h @@ -22,10 +22,10 @@ /** Clear a scalar to prevent the leak of sensitive data. */ static void secp256k1_scalar_clear(secp256k1_scalar *r); -/** Access bits (1 < count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */ +/** Access bits (1 <= count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */ static uint32_t secp256k1_scalar_get_bits_limb32(const secp256k1_scalar *a, unsigned int offset, unsigned int count); -/** Access bits (1 < count <= 32) from a scalar. offset + count must be < 256. Not constant time in offset and count. */ +/** Access bits (1 <= count <= 32) from a scalar. offset + count must be <= 256. Not constant time in offset and count. */ static uint32_t secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); /** Set a scalar from a big endian byte array. The scalar will be reduced modulo group order `n`. From 21645c03a2ead9c05f2ad6945de311c81cd38885 Mon Sep 17 00:00:00 2001 From: Jonas Nick Date: Mon, 29 Jun 2026 07:06:10 +0000 Subject: [PATCH 374/383] SECURITY.md: remove Jonas Nick from trusted keys --- README.md | 17 +++++++++-------- SECURITY.md | 1 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 90edae1a..daa38d44 100644 --- a/README.md +++ b/README.md @@ -81,20 +81,21 @@ This can be done with the following steps: ``` 4. Check out the latest release tag, e.g. ``` - git checkout v0.6.0 + git checkout v0.7.1 ``` 5. Use git to verify the GPG signature: ``` - % git tag -v v0.6.0 | grep -C 3 'Good signature' + % git tag -v v0.7.1 | grep -C 3 'Good signature' - gpg: Signature made Mon 04 Nov 2024 12:14:44 PM EST - gpg: using RSA key 4BBB845A6F5A65A69DFAEC234861DBF262123605 - gpg: Good signature from "Jonas Nick " [unknown] - gpg: aka "Jonas Nick " [unknown] + gpg: Signature made Mon 26 Jan 2026 07:42:46 PM UTC + gpg: using RSA key 2840EAABF4BC9F0FFD716AFAFBAFCC46DE2D3FE2 + gpg: Good signature from "Pieter Wuille " [unknown] + gpg: aka "Pieter Wuille " [full] + gpg: aka "[jpeg image of size 5996]" [undefined] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. - Primary key fingerprint: 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 - Subkey fingerprint: 4BBB 845A 6F5A 65A6 9DFA EC23 4861 DBF2 6212 3605 + Primary key fingerprint: 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 + Subkey fingerprint: 2840 EAAB F4BC 9F0F FD71 6AFA FBAF CC46 DE2D 3FE2 ``` Building with Autotools diff --git a/SECURITY.md b/SECURITY.md index b515cc1c..4be32e42 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,7 +9,6 @@ The following keys may be used to communicate sensitive information to developer | Name | Fingerprint | |------|-------------| | Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 | -| Jonas Nick | 36C7 1A37 C9D9 88BD E825 08D9 B1A7 0E4F 8DCD 0366 | | Tim Ruffing | 09E0 3F87 1092 E40E 106E 902B 33BC 86AB 80FF 5516 | You can import a key by running the following command with that individual’s fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys ""` Ensure that you put quotes around fingerprints containing spaces. From 217fe59bbf61bc0a4fb737aa81a4bcf448b3a5e3 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 3 Jul 2026 15:17:36 +0300 Subject: [PATCH 375/383] tests: register run_util_tests and run_ec_commit, remove dead print_vector --- src/modules/rangeproof/tests_impl.h | 35 ----------------------------- src/tests.c | 2 ++ 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index 5025c624..85c97c54 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -811,35 +811,6 @@ static void test_rangeproof_fixed_vectors(void) { } } -static void print_vector_helper(unsigned char *buf, size_t buf_len) { - size_t j; - printf(" "); - for (j = 0; j < buf_len; j++) { - printf("0x%02x", buf[j]); - if (j == buf_len-1) { - printf(",\n"); - } else if ((j+1) % 16 != 0) { - printf(", "); - } else { - printf(",\n"); - printf(" "); - } - } - printf("};\n"); -} - -static void print_vector(int i, unsigned char *proof, size_t p_len, secp256k1_pedersen_commitment *commit) { - unsigned char commit_output[33]; - - printf("unsigned char vector_%d[] = {\n", i); - print_vector_helper(proof, p_len); - - CHECK(secp256k1_pedersen_commitment_serialize(CTX, commit_output, commit)); - printf("unsigned char commit_%d[] = {\n", i); - print_vector_helper(commit_output, sizeof(commit_output)); -} - - /* Use same nonce and blinding value for all "reproducible" test vectors */ static unsigned char vector_blind[] = { 0x48, 0x26, 0xad, 0x41, 0x37, 0x4c, 0x25, 0x62, 0x52, 0x14, 0x78, 0x82, 0x89, 0x9c, 0x86, 0x27, @@ -1233,8 +1204,6 @@ static void test_rangeproof_fixed_vectors_reproducible(void) { CHECK(secp256k1_rangeproof_sign(CTX, proof, &p_len, min_value, &pc, vector_blind, vector_nonce, exp, min_bits, value, message, m_len, NULL, 0, secp256k1_generator_h)); CHECK(p_len <= secp256k1_rangeproof_max_size(CTX, value, min_bits)); CHECK(p_len == sizeof(proof)); - /* Uncomment the next line to print the test vector */ - /* print_vector(0, proof, p_len, &pc); */ CHECK(p_len == sizeof(vector_0)); CHECK(secp256k1_memcmp_var(proof, vector_0, p_len) == 0); @@ -1287,8 +1256,6 @@ static void test_rangeproof_fixed_vectors_reproducible(void) { CHECK(secp256k1_rangeproof_sign(CTX, proof, &p_len, min_value, &pc, vector_blind, vector_nonce, exp, min_bits, value, message, m_len, NULL, 0, secp256k1_generator_h)); CHECK(p_len <= secp256k1_rangeproof_max_size(CTX, value, min_bits)); CHECK(p_len == sizeof(proof)); - /* Uncomment the next line to print the test vector */ - /* print_vector(1, proof, p_len, &pc); */ CHECK(p_len == sizeof(vector_1)); CHECK(secp256k1_memcmp_var(proof, vector_1, p_len) == 0); @@ -1333,8 +1300,6 @@ static void test_rangeproof_fixed_vectors_reproducible(void) { CHECK(secp256k1_rangeproof_sign(CTX, proof, &p_len, min_value, &pc, vector_blind, vector_nonce, exp, min_bits, value, message, m_len, NULL, 0, secp256k1_generator_h)); CHECK(p_len <= secp256k1_rangeproof_max_size(CTX, value, min_bits)); CHECK(p_len == sizeof(proof)); - /* Uncomment the next line to print the test vector */ - /* print_vector(2, proof, p_len, &pc); */ CHECK(p_len == sizeof(vector_2)); CHECK(secp256k1_memcmp_var(proof, vector_2, p_len) == 0); diff --git a/src/tests.c b/src/tests.c index 7f8dbe34..ebc49c41 100644 --- a/src/tests.c +++ b/src/tests.c @@ -8208,6 +8208,7 @@ static const struct tf_test_entry tests_ec[] = { CASE(ec_pubkey_parse_test), CASE(eckey_edge_case_test), CASE(eckey_negate_test), + CASE(ec_commit), }; static const struct tf_test_entry tests_ecdsa[] = { @@ -8229,6 +8230,7 @@ static const struct tf_test_entry tests_utils[] = { CASE(secp256k1_is_zero_array_test), CASE(secp256k1_byteorder_tests), CASE(cmov_tests), + CASE(util_tests), }; /* Register test modules */ From 65093e1444e8e90e0cf3166633602bf17d2dd028 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 10 Aug 2026 11:29:49 +0300 Subject: [PATCH 376/383] surjection: prevent s-value reuse for different proof inputs The s-values produced by secp256k1_surjection_genrand previously depended only on their indices and the difference between input_blinding_key and output_blinding_key. Calls with the same difference therefore reused s-values even when their proof inputs differed. For proofs with the same used-input selection and honest input index, the same generated s-value was used as the signing nonce. Reusing this nonce across different proof messages allowed recovery of the blinding-key difference. The remaining repeated s-values also revealed the honest input index. This commit affects proof generation only; verification is unchanged. --- src/modules/surjection/main_impl.h | 15 ++- src/modules/surjection/surjection.h | 2 +- src/modules/surjection/surjection_impl.h | 47 +++++--- src/modules/surjection/tests_impl.h | 143 +++++++++++++++++++++++ 4 files changed, 192 insertions(+), 15 deletions(-) diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index 968cc477..80dbd7f3 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -337,7 +337,20 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s rsizes[0] = (int) n_used_pubkeys; indices[0] = (int) ring_input_index; secp256k1_surjection_genmessage(hash_ctx, msg32, ephemeral_input_tags, n_total_pubkeys, ephemeral_output_tag); - if (secp256k1_surjection_genrand(hash_ctx, borromean_s, n_used_pubkeys, &blinding_key) == 0) { + /* Derive every s-value, including the one used as the signing nonce, from + * every proof-relevant input to + * secp256k1_surjectionproof_generate. Except with negligible hash-collision + * probability, this prevents distinct proof inputs from reusing any + * s-value. + * + * The proof-relevant arguments to secp256k1_surjectionproof_generate + * correspond as follows: proof supplies n_total_pubkeys (proof->n_inputs), + * proof->used_inputs, and n_used_pubkeys, while proof->data is output and + * proof->initialized is VERIFY-only validation state; ephemeral_input_tags + * is committed by msg32; n_ephemeral_input_tags equals n_total_pubkeys as + * checked above; ephemeral_output_tag is committed by msg32; input_index + * and both blinding keys are passed directly. */ + if (secp256k1_surjection_genrand(hash_ctx, borromean_s, n_used_pubkeys, n_total_pubkeys, proof->used_inputs, msg32, input_index, input_blinding_key, output_blinding_key) == 0) { return 0; } /* Borromean sign will overwrite one of the s values we just generated, so use diff --git a/src/modules/surjection/surjection.h b/src/modules/surjection/surjection.h index ac7407d7..70b886ae 100644 --- a/src/modules/surjection/surjection.h +++ b/src/modules/surjection/surjection.h @@ -12,7 +12,7 @@ SECP256K1_INLINE static int secp256k1_surjection_genmessage(unsigned char *msg32, secp256k1_ge *ephemeral_input_tags, size_t n_input_tags, secp256k1_ge *ephemeral_output_tag); -SECP256K1_INLINE static int secp256k1_surjection_genrand(secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key); +SECP256K1_INLINE static int secp256k1_surjection_genrand(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *s, size_t ns, size_t n_inputs, const unsigned char *used_inputs, const unsigned char *msg32, size_t input_index, const unsigned char *input_blinding_key, const unsigned char *output_blinding_key); SECP256K1_INLINE static int secp256k1_surjection_compute_public_keys(secp256k1_gej *pubkeys, size_t n_pubkeys, const secp256k1_ge *input_tags, size_t n_input_tags, const unsigned char *used_tags, const secp256k1_ge *output_tag, size_t input_index, size_t *ring_input_index); diff --git a/src/modules/surjection/surjection_impl.h b/src/modules/surjection/surjection_impl.h index bccced52..cdf7714b 100644 --- a/src/modules/surjection/surjection_impl.h +++ b/src/modules/surjection/surjection_impl.h @@ -35,31 +35,52 @@ SECP256K1_INLINE static void secp256k1_surjection_genmessage(const secp256k1_has secp256k1_sha256_clear(&sha256_en); } -SECP256K1_INLINE static int secp256k1_surjection_genrand(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *s, size_t ns, const secp256k1_scalar *blinding_key) { +/* Derive the ring's s-values, one of which is used as the signing nonce, from a + * seed that hashes the passed-in arguments. See the call site for how these + * correspond to the proof inputs. */ +SECP256K1_INLINE static int secp256k1_surjection_genrand(const secp256k1_hash_ctx *hash_ctx, secp256k1_scalar *s, size_t ns, size_t n_inputs, const unsigned char *used_inputs, const unsigned char *msg32, size_t input_index, const unsigned char *input_blinding_key, const unsigned char *output_blinding_key) { size_t i; - unsigned char sec_input[36]; + size_t used_inputs_len; + unsigned char n_inputs_ser[4]; + unsigned char index_ser[4]; + unsigned char counter[4]; + unsigned char seed[32]; + unsigned char out[32]; secp256k1_sha256 sha256_en; + used_inputs_len = (n_inputs + 7) / 8; + secp256k1_write_be32(n_inputs_ser, (uint32_t)n_inputs); + secp256k1_write_be32(index_ser, (uint32_t)input_index); + + /* Hash the arguments into the seed. */ + secp256k1_sha256_initialize(&sha256_en); + secp256k1_sha256_write(hash_ctx, &sha256_en, n_inputs_ser, 4); + secp256k1_sha256_write(hash_ctx, &sha256_en, used_inputs, used_inputs_len); + secp256k1_sha256_write(hash_ctx, &sha256_en, msg32, 32); + secp256k1_sha256_write(hash_ctx, &sha256_en, index_ser, 4); + secp256k1_sha256_write(hash_ctx, &sha256_en, input_blinding_key, 32); + secp256k1_sha256_write(hash_ctx, &sha256_en, output_blinding_key, 32); + secp256k1_sha256_finalize(hash_ctx, &sha256_en, seed); + secp256k1_sha256_clear(&sha256_en); + /* compute s values */ - secp256k1_scalar_get_b32(&sec_input[4], blinding_key); for (i = 0; i < ns; i++) { int overflow = 0; - sec_input[0] = i; - sec_input[1] = i >> 8; - sec_input[2] = i >> 16; - sec_input[3] = i >> 24; - + secp256k1_write_be32(counter, (uint32_t)i); secp256k1_sha256_initialize(&sha256_en); - secp256k1_sha256_write(hash_ctx, &sha256_en, sec_input, 36); - secp256k1_sha256_finalize(hash_ctx, &sha256_en, sec_input); + secp256k1_sha256_write(hash_ctx, &sha256_en, counter, 4); + secp256k1_sha256_write(hash_ctx, &sha256_en, seed, 32); + secp256k1_sha256_finalize(hash_ctx, &sha256_en, out); secp256k1_sha256_clear(&sha256_en); - secp256k1_scalar_set_b32(&s[i], sec_input, &overflow); + secp256k1_scalar_set_b32(&s[i], out, &overflow); if (overflow == 1) { - secp256k1_memclear_explicit(sec_input, 32); + secp256k1_memclear_explicit(out, sizeof(out)); + secp256k1_memclear_explicit(seed, sizeof(seed)); return 0; } } - secp256k1_memclear_explicit(sec_input, 32); + secp256k1_memclear_explicit(out, sizeof(out)); + secp256k1_memclear_explicit(seed, sizeof(seed)); return 1; } diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index 7ba328c3..0680a2ab 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -643,6 +643,147 @@ static void test_gen_verify_all(void) { test_gen_verify(SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS, SECP256K1_SURJECTIONPROOF_MAX_USED_INPUTS); } +static int surjection_genrand_streams_equal(const secp256k1_scalar *a, const secp256k1_scalar *b, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + if (!secp256k1_scalar_eq(&a[i], &b[i])) { + return 0; + } + } + return 1; +} + +static int surjection_genrand_stream_all_differ(const secp256k1_scalar *a, const secp256k1_scalar *b, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + if (secp256k1_scalar_eq(&a[i], &b[i])) { + return 0; + } + } + return 1; +} + +/* Test that changing any proof-relevant argument to + * secp256k1_surjectionproof_generate changes every s-value produced by + * secp256k1_surjection_genrand. */ +static void test_surjection_genrand(void) { + const secp256k1_hash_ctx *hash_ctx = secp256k1_get_hash_context(CTX); + const size_t ns = 4; + const size_t n_inputs = 5; + unsigned char msg_a[32]; + unsigned char msg_b[32]; + unsigned char ikey_a[32]; + unsigned char ikey_b[32]; + unsigned char okey_a[32]; + unsigned char okey_b[32]; + unsigned char used_a[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS / 8] = { 0 }; + unsigned char used_b[SECP256K1_SURJECTIONPROOF_MAX_N_INPUTS / 8] = { 0 }; + secp256k1_scalar s_base[4]; + secp256k1_scalar s_cmp[4]; + + /* Baseline inputs, plus a one-bit variant of each. */ + testrand256(msg_a); + memcpy(msg_b, msg_a, 32); + msg_b[0] ^= 0x01; + testrand256(ikey_a); + memcpy(ikey_b, ikey_a, 32); + ikey_b[0] ^= 0x01; + testrand256(okey_a); + memcpy(okey_b, okey_a, 32); + okey_b[0] ^= 0x01; + + /* Two used-input bitmaps with the same popcount but a different set. */ + used_a[0] = 0x0f; /* inputs {0,1,2,3} */ + used_b[0] = 0x17; /* inputs {0,1,2,4} */ + + /* Baseline. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_base, ns, n_inputs, used_a, msg_a, 0, ikey_a, okey_a) == 1); + + /* Determinism: identical arguments reproduce the identical stream. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, n_inputs, used_a, msg_a, 0, ikey_a, okey_a) == 1); + CHECK(surjection_genrand_streams_equal(s_base, s_cmp, ns)); + + /* The message is bound. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, n_inputs, used_a, msg_b, 0, ikey_a, okey_a) == 1); + CHECK(surjection_genrand_stream_all_differ(s_base, s_cmp, ns)); + + /* The used-input selection is bound. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, n_inputs, used_b, msg_a, 0, ikey_a, okey_a) == 1); + CHECK(surjection_genrand_stream_all_differ(s_base, s_cmp, ns)); + + /* The total input count is bound even at the same bitmap byte length: + * n_inputs = 8 and n_inputs = 5 both use a one-byte bitmap. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, 8, used_a, msg_a, 0, ikey_a, okey_a) == 1); + CHECK(surjection_genrand_stream_all_differ(s_base, s_cmp, ns)); + + /* The honest input index is bound. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, n_inputs, used_a, msg_a, 1, ikey_a, okey_a) == 1); + CHECK(surjection_genrand_stream_all_differ(s_base, s_cmp, ns)); + + /* The input blinding key is bound. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, n_inputs, used_a, msg_a, 0, ikey_b, okey_a) == 1); + CHECK(surjection_genrand_stream_all_differ(s_base, s_cmp, ns)); + + /* The output blinding key is bound. */ + CHECK(secp256k1_surjection_genrand(hash_ctx, s_cmp, ns, n_inputs, used_a, msg_a, 0, ikey_a, okey_b) == 1); + CHECK(surjection_genrand_stream_all_differ(s_base, s_cmp, ns)); +} + +/* Changing an unused input tag changes the proof message. Check that every + * s-value changes and that both proofs verify. */ +static void test_surjectionproof_generate_changes_s_values(void) { + const size_t n_inputs = 3; + const size_t n_used = 2; + unsigned char seed[32]; + unsigned char input_blinding_key[3][32] = {{ 0 }}; + unsigned char output_blinding_key[32] = { 0 }; + unsigned char reblind[32] = { 0 }; + secp256k1_fixed_asset_tag fixed_input_tags[3]; + secp256k1_generator ephemeral_input_tags[3]; + secp256k1_generator ephemeral_output_tag; + secp256k1_surjectionproof proof_a; + secp256k1_surjectionproof proof_b; + size_t input_index; + size_t unused_index = n_inputs; + size_t i; + + testrand256(seed); + for (i = 0; i < n_inputs; i++) { + testrand256(fixed_input_tags[i].data); + input_blinding_key[i][31] = (unsigned char)i + 1; + CHECK(secp256k1_generator_generate_blinded(CTX, &ephemeral_input_tags[i], fixed_input_tags[i].data, input_blinding_key[i])); + } + output_blinding_key[31] = 4; + reblind[31] = 5; + CHECK(secp256k1_generator_generate_blinded(CTX, &ephemeral_output_tag, fixed_input_tags[1].data, output_blinding_key)); + + CHECK(secp256k1_surjectionproof_initialize(CTX, &proof_a, &input_index, fixed_input_tags, n_inputs, n_used, &fixed_input_tags[1], 100, seed) > 0); + CHECK(input_index == 1); + CHECK(secp256k1_surjectionproof_n_used_inputs(CTX, &proof_a) == n_used); + proof_b = proof_a; + + for (i = 0; i < n_inputs; i++) { + if (!(proof_a.used_inputs[i / 8] & (1 << (i % 8)))) { + unused_index = i; + } + } + CHECK(unused_index < n_inputs); + + CHECK(secp256k1_surjectionproof_generate(CTX, &proof_a, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, input_index, input_blinding_key[input_index], output_blinding_key) == 1); + CHECK(secp256k1_surjectionproof_verify(CTX, &proof_a, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 1); + + /* Regenerate the unused ephemeral input tag with reblind instead of + * input_blinding_key[unused_index]. The modified tag is the only proof input + * that differs between the two secp256k1_surjectionproof_generate calls. */ + CHECK(secp256k1_generator_generate_blinded(CTX, &ephemeral_input_tags[unused_index], fixed_input_tags[unused_index].data, reblind)); + CHECK(secp256k1_surjectionproof_generate(CTX, &proof_b, ephemeral_input_tags, n_inputs, &ephemeral_output_tag, input_index, input_blinding_key[input_index], output_blinding_key) == 1); + CHECK(secp256k1_surjectionproof_verify(CTX, &proof_b, ephemeral_input_tags, n_inputs, &ephemeral_output_tag) == 1); + + for (i = 0; i < n_used; i++) { + CHECK(secp256k1_memcmp_var(&proof_a.data[32 + 32 * i], &proof_b.data[32 + 32 * i], 32) != 0); + } +} + /* --- Test registry --- */ static const struct tf_test_entry tests_surjection[] = { CASE1(test_surjectionproof_api), @@ -651,6 +792,8 @@ static const struct tf_test_entry tests_surjection[] = { CASE1(test_input_selection_all), CASE1(test_input_selection_distribution), CASE1(test_gen_verify_all), + CASE1(test_surjection_genrand), + CASE1(test_surjectionproof_generate_changes_s_values), CASE1(test_no_used_inputs_verify), CASE1(test_bad_serialize), CASE1(test_bad_parse), From cde28971a2274beeeb2e9df27342d956b5664d44 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Mon, 10 Aug 2026 11:50:56 +0300 Subject: [PATCH 377/383] rangeproof: warn that nonce must not be reused across differing arguments --- include/secp256k1_rangeproof.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/secp256k1_rangeproof.h b/include/secp256k1_rangeproof.h index 0224972f..338c7243 100644 --- a/include/secp256k1_rangeproof.h +++ b/include/secp256k1_rangeproof.h @@ -125,7 +125,14 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_rangeproof_rewind( * commit: the commitment being proved. * blind: 32-byte blinding factor used by commit. The blinding factor may be all-zeros as long as min_bits is set to 3 or greater. * This is a side-effect of the underlying crypto, not a deliberate API choice, but it may be useful when balancing CT transactions. - * nonce: 32-byte secret nonce used to initialize the proof (value can be reverse-engineered out of the proof if this secret is known.) + * nonce: 32-byte secret nonce used to initialize the proof. + * + * Each call to this function must have a UNIQUE nonce that + * MUST NOT BE REUSED in subsequent calls. The nonce must be + * KEPT SECRET except from parties authorized to rewind the + * proof. Anyone who knows the nonce can recover `value` and + * `blind` from the proof. Reusing the nonce may expose `blind` + * even to parties that do not know the nonce. * exp: Base-10 exponent. Digits below above will be made public, but the proof will be made smaller. Allowed range is -1 to 18. * (-1 is a special case that makes the value public. 0 is the most private.) * min_bits: Number of bits of the value to keep private. (0 = auto/minimal, - 64). From 1de3864ff9f6d9c7ef0c1e30f0d715f0e6f8cc46 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 10 Aug 2026 14:35:05 +0300 Subject: [PATCH 378/383] bppp: check for overflow in generator allocation --- src/modules/bppp/main_impl.h | 5 +++++ src/modules/bppp/tests_impl.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/modules/bppp/main_impl.h b/src/modules/bppp/main_impl.h index 8c4d1eab..bc7c281b 100644 --- a/src/modules/bppp/main_impl.h +++ b/src/modules/bppp/main_impl.h @@ -28,6 +28,11 @@ secp256k1_bppp_generators *secp256k1_bppp_generators_create(const secp256k1_cont if (ret == NULL) { return NULL; } + /* Ensure that multiplication will not wrap around */ + if (n > SIZE_MAX / sizeof(*ret->gens)) { + free(ret); + return NULL; + } ret->gens = checked_malloc(&ctx->error_callback, n * sizeof(*ret->gens)); if (ret->gens == NULL) { free(ret); diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index 47a00c6d..0c5ed1e9 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -28,6 +28,8 @@ static void test_bppp_generators_api(void) { CHECK(gens != NULL); gens_orig = gens; /* Preserve for round-trip test */ + CHECK(secp256k1_bppp_generators_create(CTX, SIZE_MAX / sizeof(secp256k1_ge) + 1) == NULL); + /* Serialize */ CHECK_ILLEGAL(CTX, secp256k1_bppp_generators_serialize(CTX, NULL, gens_ser, &len)); CHECK_ILLEGAL(CTX, secp256k1_bppp_generators_serialize(CTX, gens, NULL, &len)); From e8c3396597804ea48ab4022829dde0ec6118f511 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 10 Aug 2026 15:01:13 +0300 Subject: [PATCH 379/383] whitelist: honour the documented parse initialization guarantee --- src/modules/whitelist/main_impl.h | 19 ++++++++++++++++--- src/modules/whitelist/tests_impl.h | 7 ++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/modules/whitelist/main_impl.h b/src/modules/whitelist/main_impl.h index 28c563b2..6c66eb2d 100644 --- a/src/modules/whitelist/main_impl.h +++ b/src/modules/whitelist/main_impl.h @@ -133,19 +133,28 @@ size_t secp256k1_whitelist_signature_n_keys(const secp256k1_whitelist_signature } int secp256k1_whitelist_signature_parse(const secp256k1_context* ctx, secp256k1_whitelist_signature *sig, const unsigned char *input, size_t input_len) { + size_t n_keys; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(input != NULL); + /* The header guarantees sig is initialized on every path and that a failed + * parse fails validation for any key set. MAX_KEYS + 1 is that canonical + * invalid state: _verify rejects it on sig->n_keys > MAX_KEYS regardless of + * the count the caller supplies. */ + memset(sig, 0, sizeof(*sig)); + sig->n_keys = MAX_KEYS + 1; + if (input_len == 0) { return 0; } - sig->n_keys = input[0]; - if (sig->n_keys > MAX_KEYS || input_len != 1 + 32 * (sig->n_keys + 1)) { + n_keys = input[0]; + if (n_keys > MAX_KEYS || input_len != 1 + 32 * (n_keys + 1)) { return 0; } - memcpy(&sig->data[0], &input[1], 32 * (sig->n_keys + 1)); + sig->n_keys = n_keys; + memcpy(&sig->data[0], &input[1], 32 * (n_keys + 1)); return 1; } @@ -156,6 +165,10 @@ int secp256k1_whitelist_signature_serialize(const secp256k1_context* ctx, unsign ARG_CHECK(output_len != NULL); ARG_CHECK(sig != NULL); + /* Do not trust n_keys to have come from _parse. */ + if (sig->n_keys > MAX_KEYS) { + return 0; + } if (*output_len < 1 + 32 * (sig->n_keys + 1)) { return 0; } diff --git a/src/modules/whitelist/tests_impl.h b/src/modules/whitelist/tests_impl.h index dad8a479..b7cd1517 100644 --- a/src/modules/whitelist/tests_impl.h +++ b/src/modules/whitelist/tests_impl.h @@ -23,12 +23,17 @@ static void test_whitelist_end_to_end_internal(const unsigned char *summed_secke /* Serialization round trip */ CHECK(secp256k1_whitelist_signature_serialize(CTX, serialized, &slen, &sig) == 1); CHECK(slen == 33 + 32 * n_keys); - CHECK(secp256k1_whitelist_signature_parse(CTX, &sig1, serialized, slen) == 1); /* (Check various bad-length conditions) */ CHECK(secp256k1_whitelist_signature_parse(CTX, &sig1, serialized, slen + 32) == 0); CHECK(secp256k1_whitelist_signature_parse(CTX, &sig1, serialized, slen + 1) == 0); CHECK(secp256k1_whitelist_signature_parse(CTX, &sig1, serialized, slen - 1) == 0); CHECK(secp256k1_whitelist_signature_parse(CTX, &sig1, serialized, 0) == 0); + /* A failed parse must leave a signature that fails validation for any + * key set, as documented on secp256k1_whitelist_signature_parse. */ + CHECK(secp256k1_whitelist_signature_n_keys(&sig1) > SECP256K1_WHITELIST_MAX_N_KEYS); + CHECK(secp256k1_whitelist_verify(CTX, &sig1, online_pubkeys, offline_pubkeys, n_keys, sub_pubkey) == 0); + /* Re-parse to restore a valid state. */ + CHECK(secp256k1_whitelist_signature_parse(CTX, &sig1, serialized, slen) == 1); CHECK(secp256k1_whitelist_verify(CTX, &sig1, online_pubkeys, offline_pubkeys, n_keys, sub_pubkey) == 1); CHECK(secp256k1_whitelist_verify(CTX, &sig1, offline_pubkeys, online_pubkeys, n_keys, sub_pubkey) != 1); From 7ea12c2dca07b82520f396fb10a76b128f232282 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 10 Aug 2026 15:04:25 +0300 Subject: [PATCH 380/383] whitelist: document that the parsed key count is untrusted --- include/secp256k1_whitelist.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/secp256k1_whitelist.h b/include/secp256k1_whitelist.h index 20d495d3..760b719a 100644 --- a/include/secp256k1_whitelist.h +++ b/include/secp256k1_whitelist.h @@ -68,6 +68,10 @@ SECP256K1_API int secp256k1_whitelist_signature_parse( * * Returns: the number of keys for the given signature * In: sig: pointer to a signature object + * + * This count is a property of the signature only. It might not match the + * number of public keys the caller has, and the caller should not truncate + * their key set to match it. */ SECP256K1_API size_t secp256k1_whitelist_signature_n_keys( const secp256k1_whitelist_signature *sig From 598e22dcde2152003c6a60f04196cc5fe2e2a090 Mon Sep 17 00:00:00 2001 From: DarkWindman Date: Mon, 10 Aug 2026 16:55:05 +0300 Subject: [PATCH 381/383] whitelist: document the degenerate W = -P_i destination --- include/secp256k1_whitelist.h | 9 +++++++++ src/modules/whitelist/whitelist_impl.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/include/secp256k1_whitelist.h b/include/secp256k1_whitelist.h index 760b719a..e2f82173 100644 --- a/include/secp256k1_whitelist.h +++ b/include/secp256k1_whitelist.h @@ -113,6 +113,8 @@ SECP256K1_API int secp256k1_whitelist_signature_serialize( * online_i + H(offline_i + whitelist)(offline_i + whitelist) * for each public key pair (offline_i, offline_i). Here H means sha256 of the * compressed serialization of the key. + * + * See secp256k1_whitelist_verify for the rationale on the degenerate destination W = -P_i. */ SECP256K1_API int secp256k1_whitelist_sign( const secp256k1_context *ctx, @@ -135,6 +137,13 @@ SECP256K1_API int secp256k1_whitelist_sign( * offline_pubkeys: list of all offline pubkeys * n_keys: the number of entries in each of the above two arrays * sub_pubkey: the key to be whitelisted + * + * When the destination W equals -P_i for a whitelisted offline key, the tweak + * degenerates and the ring key collapses to K_i = Q_i, so the online key alone + * produces a valid proof for that destination. This is accepted deliberately: + * the output is spendable only by the holder of p_i (the discrete log of -P_i + * is -p_i), i.e. the offline half of the same whitelist entry, so no funds can + * be diverted. */ SECP256K1_API int secp256k1_whitelist_verify( const secp256k1_context *ctx, diff --git a/src/modules/whitelist/whitelist_impl.h b/src/modules/whitelist/whitelist_impl.h index f26c255c..10b6e6d4 100644 --- a/src/modules/whitelist/whitelist_impl.h +++ b/src/modules/whitelist/whitelist_impl.h @@ -117,6 +117,9 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context* /* compute tweaked keys */ secp256k1_gej_set_ge(&tweaked_gej, &offline_ge); secp256k1_gej_add_ge_var(&tweaked_gej, &tweaked_gej, &subkey_ge, NULL); + /* Fails only for the degenerate destination W = -P_i, where the ring + * key intentionally collapses to Q_i. See the rationale on + * secp256k1_whitelist_verify in include/secp256k1_whitelist.h. */ secp256k1_whitelist_tweak_pubkey(hash_ctx, &tweaked_gej); secp256k1_gej_add_ge_var(&keys[i], &tweaked_gej, &online_ge, NULL); } From a69a662d052f2a3839798fdb7d98864d26ccf2cb Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Fri, 10 Jul 2026 19:06:29 +0300 Subject: [PATCH 382/383] Fix missing clears on secret values --- src/modules/ecdsa_s2c/main_impl.h | 1 + src/modules/generator/main_impl.h | 3 +++ src/modules/rangeproof/rangeproof_impl.h | 16 +++++++++++++++- src/modules/surjection/main_impl.h | 13 +++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/modules/ecdsa_s2c/main_impl.h b/src/modules/ecdsa_s2c/main_impl.h index d9957773..c6030245 100644 --- a/src/modules/ecdsa_s2c/main_impl.h +++ b/src/modules/ecdsa_s2c/main_impl.h @@ -171,6 +171,7 @@ int secp256k1_ecdsa_anti_exfil_signer_commit(const secp256k1_context* ctx, secp2 secp256k1_ecmult_gen_ge(&ctx->ecmult_gen_ctx, &r, &k); secp256k1_ecdsa_s2c_opening_save(opening, &r); + secp256k1_scalar_clear(&k); secp256k1_memclear_explicit(nonce32, 32); return 1; } diff --git a/src/modules/generator/main_impl.h b/src/modules/generator/main_impl.h index ec9484a9..b5d68672 100644 --- a/src/modules/generator/main_impl.h +++ b/src/modules/generator/main_impl.h @@ -218,6 +218,7 @@ static int secp256k1_generator_generate_internal(const secp256k1_context* ctx, s secp256k1_scalar_set_b32(&blind, blind32, &overflow); ret = !overflow; secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &accum, &blind); + secp256k1_scalar_clear(&blind); } secp256k1_sha256_initialize(&sha256); @@ -356,6 +357,8 @@ int secp256k1_pedersen_blind_sum(const secp256k1_context* ctx, unsigned char *bl for (i = 0; i < n; i++) { secp256k1_scalar_set_b32(&x, blinds[i], &overflow); if (overflow) { + secp256k1_scalar_clear(&acc); + secp256k1_scalar_clear(&x); return 0; } if (i >= npositive) { diff --git a/src/modules/rangeproof/rangeproof_impl.h b/src/modules/rangeproof/rangeproof_impl.h index 50211b07..8907a0d2 100644 --- a/src/modules/rangeproof/rangeproof_impl.h +++ b/src/modules/rangeproof/rangeproof_impl.h @@ -268,6 +268,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_hash_ prep[idx] = 128; } if (!secp256k1_rangeproof_genrand(hash_ctx, sec, s, prep, rsizes, rings, nonce, commit, proof, len, genp)) { + secp256k1_memclear_explicit(prep, sizeof(prep)); + secp256k1_memclear_explicit(sec, sizeof(sec)); return 0; } secp256k1_memclear_explicit(prep, 4096); @@ -284,7 +286,10 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_hash_ */ secp256k1_scalar_set_b32(&stmp, blind, &overflow); secp256k1_scalar_add(&sec[rings - 1], &sec[rings - 1], &stmp); + secp256k1_scalar_clear(&stmp); if (overflow || secp256k1_scalar_is_zero(&sec[rings - 1])) { + secp256k1_memclear_explicit(sec, sizeof(sec)); + secp256k1_memclear_explicit(k, sizeof(k)); return 0; } signs = &proof[len]; @@ -298,6 +303,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_hash_ /*OPT: Use the precomputed gen2 basis?*/ secp256k1_pedersen_ecmult(ecmult_gen_ctx, &pubs[npub], &sec[i], ((uint64_t)secidx[i] * scale) << (i*2), genp); if (secp256k1_gej_is_infinity(&pubs[npub])) { + secp256k1_memclear_explicit(sec, sizeof(sec)); + secp256k1_memclear_explicit(k, sizeof(k)); return 0; } if (i < rings - 1) { @@ -323,6 +330,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_hash_ secp256k1_sha256_finalize(hash_ctx, &sha256_m, tmp); secp256k1_sha256_clear(&sha256_m); if (!secp256k1_borromean_sign(hash_ctx, ecmult_gen_ctx, &proof[len], s, pubs, k, sec, rsizes, secidx, rings, tmp, 32)) { + secp256k1_memclear_explicit(sec, sizeof(sec)); + secp256k1_memclear_explicit(k, sizeof(k)); return 0; } len += 32; @@ -332,7 +341,8 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_hash_ } VERIFY_CHECK(len <= *plen); *plen = len; - secp256k1_memclear_explicit(prep, 4096); + secp256k1_memclear_explicit(sec, sizeof(sec)); + secp256k1_memclear_explicit(k, sizeof(k)); return 1; } @@ -658,6 +668,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_has return 0; } if (!secp256k1_rangeproof_rewind_inner(hash_ctx, &blind, &vv, message_out, outlen, evalues, s, rsizes, rings, nonce, commit, proof, offset_post_header, genp)) { + secp256k1_scalar_clear(&blind); return 0; } /* Unwind apparently successful, see if the commitment can be reconstructed. */ @@ -665,11 +676,13 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_has vv = (vv * scale) + *min_value; secp256k1_pedersen_ecmult(ecmult_gen_ctx, &accj, &blind, vv, genp); if (secp256k1_gej_is_infinity(&accj)) { + secp256k1_scalar_clear(&blind); return 0; } secp256k1_gej_neg(&accj, &accj); secp256k1_gej_add_ge_var(&accj, &accj, commit, NULL); if (!secp256k1_gej_is_infinity(&accj)) { + secp256k1_scalar_clear(&blind); return 0; } if (blindout) { @@ -678,6 +691,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_verify_impl(const secp256k1_has if (value_out) { *value_out = vv; } + secp256k1_scalar_clear(&blind); } return ret; } diff --git a/src/modules/surjection/main_impl.h b/src/modules/surjection/main_impl.h index 80dbd7f3..8dfe794c 100644 --- a/src/modules/surjection/main_impl.h +++ b/src/modules/surjection/main_impl.h @@ -304,10 +304,13 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s /* Compute secret key */ secp256k1_scalar_set_b32(&tmps, input_blinding_key, &overflow); if (overflow) { + secp256k1_scalar_clear(&tmps); return 0; } secp256k1_scalar_set_b32(&blinding_key, output_blinding_key, &overflow); if (overflow) { + secp256k1_scalar_clear(&tmps); + secp256k1_scalar_clear(&blinding_key); return 0; } /* If any input tag is equal to an output tag, verification will fail, because our ring @@ -316,20 +319,25 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s * this at the same time that we relax the max-256-inputs rule. */ for (i = 0; i < n_ephemeral_input_tags; i++) { if (secp256k1_memcmp_var(ephemeral_input_tags[i].data, ephemeral_output_tag->data, sizeof(ephemeral_output_tag->data)) == 0) { + secp256k1_scalar_clear(&tmps); + secp256k1_scalar_clear(&blinding_key); return 0; } } secp256k1_scalar_negate(&tmps, &tmps); secp256k1_scalar_add(&blinding_key, &blinding_key, &tmps); + secp256k1_scalar_clear(&tmps); /* Compute public keys */ n_total_pubkeys = secp256k1_surjectionproof_n_total_inputs(ctx, proof); if (n_used_pubkeys > n_total_pubkeys || n_total_pubkeys != n_ephemeral_input_tags) { + secp256k1_scalar_clear(&blinding_key); return 0; } if (secp256k1_surjection_compute_public_keys(ring_pubkeys, n_used_pubkeys, ephemeral_input_tags, n_total_pubkeys, proof->used_inputs, ephemeral_output_tag, input_index, &ring_input_index) == 0) { + secp256k1_scalar_clear(&blinding_key); return 0; } @@ -351,6 +359,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s * checked above; ephemeral_output_tag is committed by msg32; input_index * and both blinding keys are passed directly. */ if (secp256k1_surjection_genrand(hash_ctx, borromean_s, n_used_pubkeys, n_total_pubkeys, proof->used_inputs, msg32, input_index, input_blinding_key, output_blinding_key) == 0) { + secp256k1_scalar_clear(&blinding_key); return 0; } /* Borromean sign will overwrite one of the s values we just generated, so use @@ -359,11 +368,15 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s nonce = borromean_s[ring_input_index]; secp256k1_scalar_clear(&borromean_s[ring_input_index]); if (secp256k1_borromean_sign(hash_ctx, &ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) { + secp256k1_scalar_clear(&blinding_key); + secp256k1_scalar_clear(&nonce); return 0; } for (i = 0; i < n_used_pubkeys; i++) { secp256k1_scalar_get_b32(&proof->data[32 + 32 * i], &borromean_s[i]); } + secp256k1_scalar_clear(&blinding_key); + secp256k1_scalar_clear(&nonce); return 1; } From 72867fd682279ff2c79cf13f4f8d8484048d2527 Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 3 Jun 2026 17:38:36 +0300 Subject: [PATCH 383/383] tests: Port hash context tests to zkp modules --- src/modules/bppp/tests_impl.h | 29 ++++++++++++++++ src/modules/ecdsa_adaptor/tests_impl.h | 25 ++++++++++++++ src/modules/ecdsa_s2c/tests_impl.h | 24 ++++++++++++- src/modules/rangeproof/tests_impl.h | 27 +++++++++++++++ src/modules/schnorrsig_halfagg/tests_impl.h | 37 +++++++++++++++++++++ src/modules/surjection/tests_impl.h | 36 ++++++++++++++++++++ 6 files changed, 177 insertions(+), 1 deletion(-) diff --git a/src/modules/bppp/tests_impl.h b/src/modules/bppp/tests_impl.h index 47a00c6d..d7931aa9 100644 --- a/src/modules/bppp/tests_impl.h +++ b/src/modules/bppp/tests_impl.h @@ -662,6 +662,34 @@ static void norm_arg_test_all(void) { norm_arg_test(64, 64); } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_bppp) +static void test_bppp_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char out_default[66], out_custom[66]; + secp256k1_bppp_generators *gens; + size_t len = sizeof(out_default); + + /* Default behavior. No ctx-provided SHA256 compression */ + gens = secp256k1_bppp_generators_create(ctx, 2); + CHECK(gens != NULL); + CHECK(secp256k1_bppp_generators_serialize(ctx, gens, out_default, &len)); + secp256k1_bppp_generators_destroy(ctx, gens); + CHECK(!sha256_bppp_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_bppp; + gens = secp256k1_bppp_generators_create(ctx, 2); + CHECK(gens != NULL); + CHECK(secp256k1_bppp_generators_serialize(ctx, gens, out_custom, &len)); + secp256k1_bppp_generators_destroy(ctx, gens); + CHECK(sha256_bppp_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default, out_custom, 66) != 0); + + secp256k1_context_destroy(ctx); +} + /* --- Test registry --- */ static const struct tf_test_entry tests_bppp[] = { CASE1(test_log_exp), @@ -674,6 +702,7 @@ static const struct tf_test_entry tests_bppp[] = { CASE1(norm_arg_test_all), CASE1(norm_arg_verify_vectors), CASE1(norm_arg_prove_vectors), + CASE1(test_bppp_ctx_sha256), }; #endif diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index 3ed01568..e8122f64 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -1182,6 +1182,30 @@ static void adaptor_test_issue335(void) { } } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_ecdsa_adaptor) +static void test_ecdsa_adaptor_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char out_default[162], out_custom[162]; + unsigned char sk[32] = {1}, msg32[32] = {1}; + unsigned char enckey_sk[32] = {2}; + secp256k1_pubkey enckey; + CHECK(secp256k1_ec_pubkey_create(ctx, &enckey, enckey_sk)); + + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_ecdsa_adaptor_encrypt(ctx, out_default, sk, &enckey, msg32, NULL, NULL)); + CHECK(!sha256_ecdsa_adaptor_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_ecdsa_adaptor; + CHECK(secp256k1_ecdsa_adaptor_encrypt(ctx, out_custom, sk, &enckey, msg32, NULL, NULL)); + CHECK(sha256_ecdsa_adaptor_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default, out_custom, 162) != 0); + + secp256k1_context_destroy(ctx); +} + /* --- Test registry --- */ REPEAT_TEST(dleq_tests) REPEAT_TEST(adaptor_tests) @@ -1195,6 +1219,7 @@ static const struct tf_test_entry tests_ecdsa_adaptor[] = { CASE1(adaptor_tests), CASE1(multi_hop_lock_tests), CASE1(adaptor_test_issue335), + CASE1(test_ecdsa_adaptor_ctx_sha256), }; #endif /* SECP256K1_MODULE_ECDSA_ADAPTOR_TESTS_H */ diff --git a/src/modules/ecdsa_s2c/tests_impl.h b/src/modules/ecdsa_s2c/tests_impl.h index ba4f158c..ea0b650d 100644 --- a/src/modules/ecdsa_s2c/tests_impl.h +++ b/src/modules/ecdsa_s2c/tests_impl.h @@ -325,6 +325,27 @@ static void test_ecdsa_anti_exfil(void) { } } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_ecdsa_s2c) +static void test_ecdsa_s2c_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + secp256k1_ecdsa_signature out_default, out_custom; + unsigned char sk[32] = {1}, msg32[32] = {1}, s2c_data[32] = {1}; + + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_ecdsa_s2c_sign(ctx, &out_default, NULL, msg32, sk, s2c_data)); + CHECK(!sha256_ecdsa_s2c_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_ecdsa_s2c; + CHECK(secp256k1_ecdsa_s2c_sign(ctx, &out_custom, NULL, msg32, sk, s2c_data)); + CHECK(sha256_ecdsa_s2c_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(out_default.data, out_custom.data, 64) != 0); + + secp256k1_context_destroy(ctx); +} + /* --- Test registry --- */ static const struct tf_test_entry tests_ecdsa_s2c[] = { CASE1(run_s2c_opening_test), @@ -333,7 +354,8 @@ static const struct tf_test_entry tests_ecdsa_s2c[] = { CASE1(test_ecdsa_s2c_fixed_vectors), CASE1(test_ecdsa_s2c_sign_verify), CASE1(test_ecdsa_anti_exfil_signer_commit), - CASE1(test_ecdsa_anti_exfil) + CASE1(test_ecdsa_anti_exfil), + CASE1(test_ecdsa_s2c_ctx_sha256), }; #endif /* SECP256K1_MODULE_ECDSA_S2C_TESTS_H */ diff --git a/src/modules/rangeproof/tests_impl.h b/src/modules/rangeproof/tests_impl.h index 85c97c54..19c83ecb 100644 --- a/src/modules/rangeproof/tests_impl.h +++ b/src/modules/rangeproof/tests_impl.h @@ -1319,6 +1319,32 @@ static void test_single_value_proof_all(void) { test_single_value_proof(UINT64_MAX); } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_rangeproof) +static void test_rangeproof_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char proof_default[5134], proof_custom[5134]; + size_t len = sizeof(proof_default); + unsigned char blind[32] = {1}; + secp256k1_pedersen_commitment commit; + + CHECK(secp256k1_pedersen_commit(ctx, &commit, blind, 1, secp256k1_generator_h)); + + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_rangeproof_sign(ctx, proof_default, &len, 0, &commit, blind, commit.data, 0, 0, 1, NULL, 0, NULL, 0, secp256k1_generator_h)); + CHECK(!sha256_rangeproof_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_rangeproof; + len = sizeof(proof_custom); + CHECK(secp256k1_rangeproof_sign(ctx, proof_custom, &len, 0, &commit, blind, commit.data, 0, 0, 1, NULL, 0, NULL, 0, secp256k1_generator_h)); + CHECK(sha256_rangeproof_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(proof_default, proof_custom, len) != 0); + + secp256k1_context_destroy(ctx); +} + /* --- Test registry --- */ REPEAT_TEST(test_rangeproof_api) REPEAT_TEST(test_borromean) @@ -1332,6 +1358,7 @@ static const struct tf_test_entry tests_rangeproof[] = { CASE1(test_rangeproof), CASE1(test_rangeproof_null_blinder), CASE1(test_multiple_generators), + CASE1(test_rangeproof_ctx_sha256), }; #endif diff --git a/src/modules/schnorrsig_halfagg/tests_impl.h b/src/modules/schnorrsig_halfagg/tests_impl.h index f4092842..f7625168 100644 --- a/src/modules/schnorrsig_halfagg/tests_impl.h +++ b/src/modules/schnorrsig_halfagg/tests_impl.h @@ -319,6 +319,42 @@ static void test_schnorrsig_aggregate_overflow_internal(void) { } } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_schnorrsig_halfagg) +static void test_schnorrsig_halfagg_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char aggsig_default[96], aggsig_custom[96]; + unsigned char sk[2][32] = {{1}, {2}}; + unsigned char msgs[2*32]; + secp256k1_keypair keypairs[2]; + secp256k1_xonly_pubkey pks[2]; + unsigned char sigs[2*64]; + size_t aggsig_len; + size_t i; + + memset(msgs, 1, sizeof(msgs)); + for (i = 0; i < 2; i++) { + CHECK(secp256k1_keypair_create(CTX, &keypairs[i], sk[i])); + CHECK(secp256k1_keypair_xonly_pub(CTX, &pks[i], NULL, &keypairs[i])); + CHECK(secp256k1_schnorrsig_sign32(CTX, &sigs[i*64], &msgs[i*32], &keypairs[i], NULL)); + } + + /* Default behavior. No ctx-provided SHA256 compression */ + aggsig_len = sizeof(aggsig_default); + CHECK(secp256k1_schnorrsig_aggregate(ctx, aggsig_default, &aggsig_len, pks, msgs, sigs, 2)); + CHECK(!sha256_schnorrsig_halfagg_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_schnorrsig_halfagg; + aggsig_len = sizeof(aggsig_custom); + CHECK(secp256k1_schnorrsig_aggregate(ctx, aggsig_custom, &aggsig_len, pks, msgs, sigs, 2)); + CHECK(sha256_schnorrsig_halfagg_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(aggsig_default, aggsig_custom, 96) != 0); + + secp256k1_context_destroy(ctx); +} + /* --- Test registry --- */ REPEAT_TEST(test_schnorrsig_aggregate) REPEAT_TEST(test_schnorrsig_aggregate_api) @@ -332,6 +368,7 @@ static const struct tf_test_entry tests_schnorrsig_halfagg[] = { CASE1(test_schnorrsig_aggregate_api), CASE1(test_schnorrsig_aggregate_unforge), CASE1(test_schnorrsig_aggregate_overflow), + CASE1(test_schnorrsig_halfagg_ctx_sha256), }; #undef N_MAX diff --git a/src/modules/surjection/tests_impl.h b/src/modules/surjection/tests_impl.h index 0680a2ab..7153a6f2 100644 --- a/src/modules/surjection/tests_impl.h +++ b/src/modules/surjection/tests_impl.h @@ -784,6 +784,41 @@ static void test_surjectionproof_generate_changes_s_values(void) { } } +DEFINE_SHA256_TRANSFORM_PROBE(sha256_surjection) +static void test_surjectionproof_ctx_sha256(void) { + /* Check ctx-provided SHA256 compression override takes effect */ + secp256k1_context *ctx = secp256k1_context_clone(CTX); + unsigned char serialized_default[SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES(1, 1)]; + unsigned char serialized_custom[SECP256K1_SURJECTIONPROOF_SERIALIZATION_BYTES(1, 1)]; + unsigned char seed[32] = {1}; + unsigned char input_blinding[32] = {1}, output_blinding[32] = {2}; + secp256k1_fixed_asset_tag fixed_tag = {{1}}; + secp256k1_generator input_tag, output_tag; + secp256k1_surjectionproof proof; + size_t input_index; + size_t serialized_len = sizeof(serialized_default); + + CHECK(secp256k1_generator_generate_blinded(CTX, &input_tag, fixed_tag.data, input_blinding)); + CHECK(secp256k1_generator_generate_blinded(CTX, &output_tag, fixed_tag.data, output_blinding)); + + /* Default behavior. No ctx-provided SHA256 compression */ + CHECK(secp256k1_surjectionproof_initialize(ctx, &proof, &input_index, &fixed_tag, 1, 1, &fixed_tag, 100, seed) > 0); + CHECK(secp256k1_surjectionproof_generate(ctx, &proof, &input_tag, 1, &output_tag, 0, input_blinding, output_blinding)); + CHECK(secp256k1_surjectionproof_serialize(ctx, serialized_default, &serialized_len, &proof)); + CHECK(!sha256_surjection_called); + + /* Override SHA256 compression directly, bypassing the ctx setter sanity checks */ + ctx->hash_ctx.fn_sha256_compression = sha256_surjection; + CHECK(secp256k1_surjectionproof_initialize(ctx, &proof, &input_index, &fixed_tag, 1, 1, &fixed_tag, 100, seed) > 0); + CHECK(secp256k1_surjectionproof_generate(ctx, &proof, &input_tag, 1, &output_tag, 0, input_blinding, output_blinding)); + CHECK(secp256k1_surjectionproof_serialize(ctx, serialized_custom, &serialized_len, &proof)); + CHECK(sha256_surjection_called); + /* Outputs must differ if custom compression was used */ + CHECK(secp256k1_memcmp_var(serialized_default, serialized_custom, serialized_len) != 0); + + secp256k1_context_destroy(ctx); +} + /* --- Test registry --- */ static const struct tf_test_entry tests_surjection[] = { CASE1(test_surjectionproof_api), @@ -797,6 +832,7 @@ static const struct tf_test_entry tests_surjection[] = { CASE1(test_no_used_inputs_verify), CASE1(test_bad_serialize), CASE1(test_bad_parse), + CASE1(test_surjectionproof_ctx_sha256), }; #endif