diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index a23367b82..d3fe48f75 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -289,7 +289,7 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.10.0" +version = "0.11.0" dependencies = [ "cc", "libc", diff --git a/Cargo-recent.lock b/Cargo-recent.lock index da1b239aa..71f42992c 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -210,7 +210,7 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.10.0" +version = "0.11.0" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index c2bd1ff4d..639da069c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ global-context = ["std"] global-context-less-secure = ["global-context"] [dependencies] -secp256k1-sys = { version = "0.10.0", default-features = false, path = "./secp256k1-sys" } +secp256k1-sys = { version = "0.11.0", default-features = false, path = "./secp256k1-sys" } hashes = { package = "bitcoin_hashes", version = "0.14", default-features = false, optional = true } rand = { version = "0.8", default-features = false, optional = true } diff --git a/secp256k1-sys/Cargo.toml b/secp256k1-sys/Cargo.toml index 850467496..7a5e98b62 100644 --- a/secp256k1-sys/Cargo.toml +++ b/secp256k1-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "secp256k1-sys" -version = "0.10.0" +version = "0.11.0" authors = [ "Dawid Ciężarkiewicz ", "Andrew Poelstra ", "Steven Roose " ] @@ -12,7 +12,7 @@ description = "FFI for Pieter Wuille's `libsecp256k1` library." keywords = [ "secp256k1", "libsecp256k1", "ffi" ] readme = "README.md" build = "build.rs" -links = "rustsecp256k1_v0_10_0" +links = "rustsecp256k1_v0_11" edition = "2021" rust-version = "1.63.0" diff --git a/secp256k1-sys/depend/scratch.h.patch b/secp256k1-sys/depend/scratch.h.patch new file mode 100644 index 000000000..10e28877f --- /dev/null +++ b/secp256k1-sys/depend/scratch.h.patch @@ -0,0 +1,5 @@ +26,29d25 +< 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/secp256k1-sys/depend/secp256k1-HEAD-revision.txt b/secp256k1-sys/depend/secp256k1-HEAD-revision.txt index 03d4132a9..ecdc0e55f 100644 --- a/secp256k1-sys/depend/secp256k1-HEAD-revision.txt +++ b/secp256k1-sys/depend/secp256k1-HEAD-revision.txt @@ -1,2 +1,2 @@ # This file was automatically created by vendor-libsecp.sh -1ad5185cd42c0636104129fcc9f6a4bf9c67cc40 +0cdc758a56360bf58a851fe91085a327ec97685a diff --git a/secp256k1-sys/depend/secp256k1.c.patch b/secp256k1-sys/depend/secp256k1.c.patch index 3783b1524..c1da0c448 100644 --- a/secp256k1-sys/depend/secp256k1.c.patch +++ b/secp256k1-sys/depend/secp256k1.c.patch @@ -37,14 +37,14 @@ < free(ctx); < } < -220,229d183 +223,232d185 < } < -< 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); diff --git a/secp256k1-sys/depend/secp256k1.h.patch b/secp256k1-sys/depend/secp256k1.h.patch index 193729bda..084cc89f3 100644 --- a/secp256k1-sys/depend/secp256k1.h.patch +++ b/secp256k1-sys/depend/secp256k1.h.patch @@ -18,18 +18,6 @@ < secp256k1_context *ctx < ) SECP256K1_ARG_NONNULL(1); < -402,406d386 -< SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space *secp256k1_scratch_space_create( -< const secp256k1_context *ctx, -< size_t size -< ) SECP256K1_ARG_NONNULL(1); -< -413,417d392 -< SECP256K1_API void secp256k1_scratch_space_destroy( -< const secp256k1_context *ctx, -< secp256k1_scratch_space *scratch -< ) SECP256K1_ARG_NONNULL(1); -< 636d610 < SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; 639d612 diff --git a/secp256k1-sys/depend/secp256k1/.cirrus.yml b/secp256k1-sys/depend/secp256k1/.cirrus.yml index 04aa8f240..81a4f0432 100644 --- a/secp256k1-sys/depend/secp256k1/.cirrus.yml +++ b/secp256k1-sys/depend/secp256k1/.cirrus.yml @@ -10,8 +10,8 @@ env: MAKEFLAGS: -j4 BUILD: check ### secp256k1 config - ECMULTWINDOW: auto - ECMULTGENPRECISION: auto + ECMULTWINDOW: 15 + ECMULTGENKB: 22 ASM: no WIDEMUL: auto WITH_VALGRIND: yes @@ -20,10 +20,12 @@ env: EXPERIMENTAL: no ECDH: no RECOVERY: no + EXTRAKEYS: no SCHNORRSIG: no + MUSIG: no ELLSWIFT: no ### test options - SECP256K1_TEST_ITERS: + SECP256K1_TEST_ITERS: 64 BENCH: yes SECP256K1_BENCH_ITERS: 2 CTIMETESTS: yes @@ -66,7 +68,9 @@ task: 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 @@ -82,7 +86,9 @@ task: env: ECDH: yes RECOVERY: yes + EXTRAKEYS: yes SCHNORRSIG: yes + MUSIG: yes ELLSWIFT: yes WRAPPER_CMD: 'valgrind --error-exitcode=42' SECP256K1_TEST_ITERS: 2 diff --git a/secp256k1-sys/depend/secp256k1/.github/actions/install-homebrew-valgrind/action.yml b/secp256k1-sys/depend/secp256k1/.github/actions/install-homebrew-valgrind/action.yml index 094ff891f..ce10eb268 100644 --- a/secp256k1-sys/depend/secp256k1/.github/actions/install-homebrew-valgrind/action.yml +++ b/secp256k1-sys/depend/secp256k1/.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 }} diff --git a/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml b/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml index dbfaa4fec..74933686a 100644 --- a/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml +++ b/secp256k1-sys/depend/secp256k1/.github/actions/run-in-docker-action/action.yml @@ -36,6 +36,11 @@ runs: load: true 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 + - # Tell Docker to pass environment variables in `env` into the container. run: > docker run \ diff --git a/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml b/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml index 4ad905af5..54b2fab1c 100644 --- a/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml +++ b/secp256k1-sys/depend/secp256k1/.github/workflows/ci.yml @@ -21,8 +21,8 @@ env: MAKEFLAGS: '-j4' BUILD: 'check' ### secp256k1 config - ECMULTWINDOW: 'auto' - ECMULTGENPRECISION: 'auto' + ECMULTWINDOW: 15 + ECMULTGENKB: 86 ASM: 'no' WIDEMUL: 'auto' WITH_VALGRIND: 'yes' @@ -31,10 +31,12 @@ env: EXPERIMENTAL: 'no' ECDH: 'no' RECOVERY: 'no' + EXTRAKEYS: 'no' SCHNORRSIG: 'no' + MUSIG: 'no' ELLSWIFT: 'no' ### test options - SECP256K1_TEST_ITERS: + SECP256K1_TEST_ITERS: 64 BENCH: 'yes' SECP256K1_BENCH_ITERS: 2 CTIMETESTS: 'yes' @@ -71,20 +73,20 @@ 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', MUSIG: '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', 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', 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', SCHNORRSIG: 'yes', ELLSWIFT: 'yes' } - - env_vars: { ECMULTGENPRECISION: 2, ECMULTWINDOW: 2 } - - env_vars: { ECMULTGENPRECISION: 8, ECMULTWINDOW: 4 } + - 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: - 'gcc' - 'clang' @@ -139,7 +141,9 @@ jobs: HOST: 'i686-linux-gnu' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CC: ${{ matrix.cc }} @@ -183,7 +187,9 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -234,7 +240,9 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -279,7 +287,9 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -334,7 +344,9 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -377,8 +389,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, @@ -386,7 +398,9 @@ jobs: WRAPPER_CMD: 'valgrind --error-exitcode=42' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' SECP256K1_TEST_ITERS: 2 @@ -431,13 +445,15 @@ 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' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' CFLAGS: '-fsanitize=undefined,address -g' @@ -485,18 +501,26 @@ jobs: matrix: configuration: - env_vars: + CTIMETESTS: 'yes' CFLAGS: '-fsanitize=memory -fsanitize-recover=memory -g' - env_vars: - ECMULTGENPRECISION: 2 + 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' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' - CTIMETESTS: 'yes' CC: 'clang' SECP256K1_TEST_ITERS: 32 ASM: 'no' @@ -541,7 +565,9 @@ jobs: WITH_VALGRIND: 'no' ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' CTIMETESTS: 'no' @@ -585,10 +611,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' @@ -599,15 +625,15 @@ jobs: 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: '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', MUSIG: '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', 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: @@ -616,7 +642,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 @@ -644,6 +670,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. @@ -679,14 +761,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)" @@ -716,7 +798,9 @@ jobs: WERROR_CFLAGS: ECDH: 'yes' RECOVERY: 'yes' + EXTRAKEYS: 'yes' SCHNORRSIG: 'yes' + MUSIG: 'yes' ELLSWIFT: 'yes' steps: @@ -802,5 +886,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/secp256k1-sys/depend/secp256k1/.gitignore b/secp256k1-sys/depend/secp256k1/.gitignore index 574902b8b..bffba8cb2 100644 --- a/secp256k1-sys/depend/secp256k1/.gitignore +++ b/secp256k1-sys/depend/secp256k1/.gitignore @@ -10,6 +10,8 @@ ctime_tests ecdh_example ecdsa_example schnorr_example +ellswift_example +musig_example *.exe *.so *.a diff --git a/secp256k1-sys/depend/secp256k1/CHANGELOG.md b/secp256k1-sys/depend/secp256k1/CHANGELOG.md index e42420f67..ee447c0c1 100644 --- a/secp256k1-sys/depend/secp256k1/CHANGELOG.md +++ b/secp256k1-sys/depend/secp256k1/CHANGELOG.md @@ -5,6 +5,55 @@ 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). +## [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` 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 + +#### 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. + +#### 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 + +#### 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` (`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 +The ABI is backward compatible with versions 0.4.x and 0.3.x. + ## [0.4.1] - 2023-12-21 #### Changed @@ -113,6 +162,9 @@ 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. +[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 [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/secp256k1-sys/depend/secp256k1/CMakeLists.txt b/secp256k1-sys/depend/secp256k1/CMakeLists.txt index b7aa20c18..041bfa3dc 100644 --- a/secp256k1-sys/depend/secp256k1/CMakeLists.txt +++ b/secp256k1-sys/depend/secp256k1/CMakeLists.txt @@ -1,32 +1,29 @@ -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 / 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 # backwards-compatible and therefore at most increase the minor version. - VERSION 0.4.1 + 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 ) +enable_testing() +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) if(CMAKE_VERSION VERSION_LESS 3.21) - 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.") + # 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 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 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 @@ -34,15 +31,19 @@ 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 1) -set(${PROJECT_NAME}_LIB_VERSION_AGE 1) +set(${PROJECT_NAME}_LIB_VERSION_CURRENT 5) +set(${PROJECT_NAME}_LIB_VERSION_REVISION 0) +set(${PROJECT_NAME}_LIB_VERSION_AGE 0) +#============================= +# 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) @@ -51,29 +52,49 @@ endif() 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. option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON) -if(SECP256K1_ENABLE_MODULE_ECDH) - add_compile_definitions(ENABLE_MODULE_ECDH=1) +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 +# (dependent module first). +if(SECP256K1_ENABLE_MODULE_ELLSWIFT) + add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) endif() -option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF) -if(SECP256K1_ENABLE_MODULE_RECOVERY) - add_compile_definitions(ENABLE_MODULE_RECOVERY=1) +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() -option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON) -option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON) 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() -option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON) -if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - add_compile_definitions(ENABLE_MODULE_ELLSWIFT=1) +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) @@ -81,22 +102,25 @@ 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_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 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) + 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") @@ -172,7 +196,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. @@ -194,23 +218,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() @@ -243,17 +269,41 @@ endif() set(CMAKE_C_VISIBILITY_PRESET hidden) -# 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) -if(SECP256K1_BUILD_BENCHMARK OR SECP256K1_BUILD_TESTS OR SECP256K1_BUILD_EXHAUSTIVE_TESTS OR SECP256K1_BUILD_CTIME_TESTS OR SECP256K1_BUILD_EXAMPLES) - enable_testing() +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() + +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() + +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() +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) @@ -275,10 +325,11 @@ 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}") -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}") @@ -307,7 +358,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}") @@ -330,7 +381,20 @@ else() message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_DEBUG}") message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}") endif() -message("\n") +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( + "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/secp256k1-sys/depend/secp256k1/CONTRIBUTING.md b/secp256k1-sys/depend/secp256k1/CONTRIBUTING.md index 921704ff5..2722c44e1 100644 --- a/secp256k1-sys/depend/secp256k1/CONTRIBUTING.md +++ b/secp256k1-sys/depend/secp256k1/CONTRIBUTING.md @@ -44,11 +44,12 @@ The Contributor Workflow & Peer Review in libsecp256k1 are similar to Bitcoin Co In addition, libsecp256k1 tries to maintain the following coding conventions: -* No runtime heap allocation (e.g., no `malloc`) unless explicitly requested by the caller (via `rustsecp256k1_v0_10_0_context_create` or `rustsecp256k1_v0_10_0_scratch_space_create`, for example). Morever, it should be possible to use the library without any heap allocations. +* No runtime heap allocation (e.g., no `malloc`) unless explicitly requested by the caller (via `rustsecp256k1_v0_11_context_create` or `rustsecp256k1_v0_11_scratch_space_create`, for example). Moreover, it should be possible to use the library without any heap allocations. * The tests should cover all lines and branches of the library (see [Test coverage](#coverage)). * 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 `rustsecp256k1_v0_10_0_memcmp_var` instead of `memcmp` (see [#823](https://github.com/bitcoin-core/secp256k1/issues/823)). +* Use `rustsecp256k1_v0_11_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 @@ -71,7 +72,7 @@ In addition, libsecp256k1 tries to maintain the following coding conventions: * Use `void *ptr` instead of `void* ptr`. * Arguments of the publicly-facing API must have a specific order defined in [include/secp256k1.h](include/secp256k1.h). * User-facing comment lines in headers should be limited to 80 chars if possible. -* All identifiers in file scope should start with `rustsecp256k1_v0_10_0_`. +* All identifiers in file scope should start with `rustsecp256k1_v0_11_`. * Avoid trailing whitespace. ### Tests diff --git a/secp256k1-sys/depend/secp256k1/Makefile.am b/secp256k1-sys/depend/secp256k1/Makefile.am index a26faca78..6b7c64f5f 100644 --- a/secp256k1-sys/depend/secp256k1/Makefile.am +++ b/secp256k1-sys/depend/secp256k1/Makefile.am @@ -6,7 +6,7 @@ AM_CFLAGS = $(SECP_CFLAGS) lib_LTLIBRARIES = libsecp256k1.la include_HEADERS = include/secp256k1.h -include_HEADERS += include/rustsecp256k1_v0_10_0_preallocated.h +include_HEADERS += include/rustsecp256k1_v0_11_preallocated.h noinst_HEADERS = noinst_HEADERS += src/scalar.h noinst_HEADERS += src/scalar_4x64.h @@ -63,22 +63,24 @@ noinst_HEADERS += src/hash_impl.h noinst_HEADERS += src/field.h noinst_HEADERS += src/field_impl.h noinst_HEADERS += src/bench.h -noinst_HEADERS += src/wycheproof/ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.h +noinst_HEADERS += src/wycheproof/ecdsa_rustsecp256k1_v0_11_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 noinst_HEADERS += contrib/lax_der_privatekey_parsing.c noinst_HEADERS += examples/examples_util.h -PRECOMPUTED_LIB = librustsecp256k1_v0_10_0_precomputed.la +PRECOMPUTED_LIB = librustsecp256k1_v0_11_precomputed.la noinst_LTLIBRARIES = $(PRECOMPUTED_LIB) -librustsecp256k1_v0_10_0_precomputed_la_SOURCES = src/precomputed_ecmult.c src/precomputed_ecmult_gen.c -# We need `-I$(top_srcdir)/src` in VPATH builds if librustsecp256k1_v0_10_0_precomputed_la_SOURCES have been recreated in the build tree. +librustsecp256k1_v0_11_precomputed_la_SOURCES = src/precomputed_ecmult.c src/precomputed_ecmult_gen.c +# We need `-I$(top_srcdir)/src` in VPATH builds if librustsecp256k1_v0_11_precomputed_la_SOURCES have been recreated in the build tree. # This helps users and packagers who insist on recreating the precomputed files (e.g., Gentoo). -librustsecp256k1_v0_10_0_precomputed_la_CPPFLAGS = -I$(top_srcdir)/src $(SECP_CONFIG_DEFINES) +librustsecp256k1_v0_11_precomputed_la_CPPFLAGS = -I$(top_srcdir)/src $(SECP_CONFIG_DEFINES) if USE_EXTERNAL_ASM -COMMON_LIB = librustsecp256k1_v0_10_0_common.la +COMMON_LIB = librustsecp256k1_v0_11_common.la else COMMON_LIB = endif @@ -89,14 +91,14 @@ pkgconfig_DATA = libsecp256k1.pc if USE_EXTERNAL_ASM if USE_ASM_ARM -librustsecp256k1_v0_10_0_common_la_SOURCES = src/asm/field_10x26_arm.s +librustsecp256k1_v0_11_common_la_SOURCES = src/asm/field_10x26_arm.s endif endif -librustsecp256k1_v0_10_0_la_SOURCES = src/secp256k1.c -librustsecp256k1_v0_10_0_la_CPPFLAGS = $(SECP_CONFIG_DEFINES) -librustsecp256k1_v0_10_0_la_LIBADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) -librustsecp256k1_v0_10_0_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE) +librustsecp256k1_v0_11_la_SOURCES = src/secp256k1.c +librustsecp256k1_v0_11_la_CPPFLAGS = $(SECP_CONFIG_DEFINES) +librustsecp256k1_v0_11_la_LIBADD = $(COMMON_LIB) $(PRECOMPUTED_LIB) +librustsecp256k1_v0_11_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_CURRENT):$(LIB_VERSION_REVISION):$(LIB_VERSION_AGE) noinst_PROGRAMS = if USE_BENCHMARK @@ -182,6 +184,28 @@ 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 +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 @@ -223,11 +247,11 @@ maintainer-clean-local: clean-precomp ### Pregenerated test vectors ### (see the comments in the previous section for detailed rationale) -TESTVECTORS = src/wycheproof/ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.h +TESTVECTORS = src/wycheproof/ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.h -src/wycheproof/ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.h: +src/wycheproof/ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.h: mkdir -p $(@D) - python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.json > $@ + python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.json > $@ testvectors: $(TESTVECTORS) @@ -241,15 +265,16 @@ 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 EXTRA_DIST += sage/group_prover.sage EXTRA_DIST += sage/prove_group_implementations.sage -EXTRA_DIST += sage/rustsecp256k1_v0_10_0_params.sage +EXTRA_DIST += sage/rustsecp256k1_v0_11_params.sage EXTRA_DIST += sage/weierstrass_prover.sage EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING -EXTRA_DIST += src/wycheproof/ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.json +EXTRA_DIST += src/wycheproof/ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.json EXTRA_DIST += tools/tests_wycheproof_generate.py if ENABLE_MODULE_ECDH @@ -268,6 +293,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/secp256k1-sys/depend/secp256k1/README.md b/secp256k1-sys/depend/secp256k1/README.md index 4013e6a93..222e5fb76 100644 --- a/secp256k1-sys/depend/secp256k1/README.md +++ b/secp256k1-sys/depend/secp256k1/README.md @@ -20,6 +20,8 @@ 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). +* Optional module for MuSig2 Schnorr multi-signatures according to [BIP-327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki). Implementation details ---------------------- @@ -79,9 +81,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 --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. @@ -113,6 +115,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/secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 b/secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 index 11adef4f2..048267fa6 100644 --- a/secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 +++ b/secp256k1-sys/depend/secp256k1/build-aux/m4/bitcoin_secp.m4 @@ -45,6 +45,22 @@ 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) + /* MemorySanitizer is enabled. */ + # elif + # error "MemorySanitizer is disabled." + # endif + #else + # error "__has_feature is not defined." + #endif + ]])], [msan_enabled=yes], [msan_enabled=no]) +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/secp256k1-sys/depend/secp256k1/ci/ci.sh b/secp256k1-sys/depend/secp256k1/ci/ci.sh index 9cc715955..3636deafa 100755 --- a/secp256k1-sys/depend/secp256k1/ci/ci.sh +++ b/secp256k1-sys/depend/secp256k1/ci/ci.sh @@ -12,12 +12,13 @@ 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 \ - EXPERIMENTAL ECDH RECOVERY SCHNORRSIG ELLSWIFT \ + ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \ + EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \ 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 @@ -73,10 +74,12 @@ 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-extrakeys="$EXTRAKEYS" \ --enable-module-schnorrsig="$SCHNORRSIG" \ + --enable-module-musig="$MUSIG" \ --enable-examples="$EXAMPLES" \ --enable-ctime-tests="$CTIMETESTS" \ --with-valgrind="$WITH_VALGRIND" \ diff --git a/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile b/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile index 5ce715b41..241bfa971 100644 --- a/secp256k1-sys/depend/secp256k1/ci/linux-debian.Dockerfile +++ b/secp256k1-sys/depend/secp256k1/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}" && \ diff --git a/secp256k1-sys/depend/secp256k1/cmake/CheckArm32Assembly.cmake b/secp256k1-sys/depend/secp256k1/cmake/CheckArm32Assembly.cmake index 15c44b24b..baeeff029 100644 --- a/secp256k1-sys/depend/secp256k1/cmake/CheckArm32Assembly.cmake +++ b/secp256k1-sys/depend/secp256k1/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() diff --git a/secp256k1-sys/depend/secp256k1/cmake/CheckMemorySanitizer.cmake b/secp256k1-sys/depend/secp256k1/cmake/CheckMemorySanitizer.cmake new file mode 100644 index 000000000..d9ef681e6 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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() diff --git a/secp256k1-sys/depend/secp256k1/cmake/TryAppendCFlags.cmake b/secp256k1-sys/depend/secp256k1/cmake/TryAppendCFlags.cmake index 718eb91a3..251cb61ca 100644 --- a/secp256k1-sys/depend/secp256k1/cmake/TryAppendCFlags.cmake +++ b/secp256k1-sys/depend/secp256k1/cmake/TryAppendCFlags.cmake @@ -1,6 +1,6 @@ include(CheckCCompilerFlag) -function(rustsecp256k1_v0_10_0_check_c_flags_internal flags output) +function(rustsecp256k1_v0_11_check_c_flags_internal flags output) string(MAKE_C_IDENTIFIER "${flags}" result) string(TOUPPER "${result}" result) set(result "C_SUPPORTS_${result}") @@ -17,7 +17,7 @@ endfunction() # Append flags to the COMPILE_OPTIONS directory property if CC accepts them. macro(try_append_c_flags) - rustsecp256k1_v0_10_0_check_c_flags_internal("${ARGV}" result) + rustsecp256k1_v0_11_check_c_flags_internal("${ARGV}" result) if(result) add_compile_options(${ARGV}) endif() diff --git a/secp256k1-sys/depend/secp256k1/configure.ac b/secp256k1-sys/depend/secp256k1/configure.ac index 51ac230cf..f880a3578 100644 --- a/secp256k1-sys/depend/secp256k1/configure.ac +++ b/secp256k1-sys/depend/secp256k1/configure.ac @@ -4,8 +4,8 @@ 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, 1) +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 @@ -13,9 +13,9 @@ define(_PKG_VERSION_IS_RELEASE, true) # 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, 1) -define(_LIB_VERSION_AGE, 1) +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]) @@ -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])]) @@ -203,23 +207,22 @@ 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-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], +[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 86). [default=86]] )], -[req_ecmult_gen_precision=$withval], [req_ecmult_gen_precision=auto]) +[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]] @@ -248,6 +251,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"; 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" @@ -336,14 +353,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 @@ -358,19 +368,18 @@ 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 -else - set_ecmult_gen_precision=$req_ecmult_gen_precision -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 or 86']) ;; esac @@ -387,29 +396,40 @@ SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS" ### Handle module options ### -if test x"$enable_module_ecdh" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ECDH=1" +# Processing must be done in a reverse topological sorting of the dependency graph +# (dependent module first). +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_recovery" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_RECOVERY=1" +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 - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_SCHNORRSIG=1" + 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.]) + fi enable_module_extrakeys=yes + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_SCHNORRSIG=1" fi -if test x"$enable_module_ellswift" = x"yes"; then - SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1" -fi - -# Test if extrakeys is set after the schnorrsig module to allow the schnorrsig -# module to set enable_module_extrakeys=yes if test x"$enable_module_extrakeys" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_EXTRAKEYS=1" fi +if test x"$enable_module_recovery" = x"yes"; then + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_RECOVERY=1" +fi + +if test x"$enable_module_ecdh" = x"yes"; then + SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ECDH=1" +fi + if test x"$enable_external_default_callbacks" = x"yes"; then SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_EXTERNAL_DEFAULT_CALLBACKS=1" fi @@ -418,12 +438,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 @@ -446,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"]) @@ -468,11 +484,12 @@ 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" 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" @@ -484,3 +501,17 @@ 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 + +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 diff --git a/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c index 187234fbc..82b0a3a6e 100644 --- a/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.c @@ -7,10 +7,10 @@ #include #include "lax_der_parsing.h" -extern int rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_signature *sig, const unsigned char *input64); -int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der_lax(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { +extern int rustsecp256k1_v0_11_ecdsa_signature_parse_compact( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *input64); +int rustsecp256k1_v0_11_ecdsa_signature_parse_der_lax(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { size_t rpos, rlen, spos, slen; size_t pos = 0; size_t lenbyte; @@ -18,7 +18,7 @@ int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der_lax(const rustsecp256k1_v0_1 int overflow = 0; /* Hack to initialize sig with a correctly-parsed but invalid signature. */ - rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + rustsecp256k1_v0_11_ecdsa_signature_parse_compact(ctx, sig, tmpsig); /* Sequence tag byte */ if (pos == inputlen || input[pos] != 0x30) { @@ -139,11 +139,11 @@ int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der_lax(const rustsecp256k1_v0_1 } if (!overflow) { - overflow = !rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + overflow = !rustsecp256k1_v0_11_ecdsa_signature_parse_compact(ctx, sig, tmpsig); } if (overflow) { memset(tmpsig, 0, 64); - rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + rustsecp256k1_v0_11_ecdsa_signature_parse_compact(ctx, sig, tmpsig); } return 1; } diff --git a/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h index c1abda485..633d93104 100644 --- a/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_parsing.h @@ -26,8 +26,8 @@ * certain violations are easily supported. You may need to adapt it. * * Do not use this for new systems. Use well-defined DER or compact signatures - * instead if you have the choice (see rustsecp256k1_v0_10_0_ecdsa_signature_parse_der and - * rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact). + * instead if you have the choice (see rustsecp256k1_v0_11_ecdsa_signature_parse_der and + * rustsecp256k1_v0_11_ecdsa_signature_parse_compact). * * The supported violations are: * - All numbers are parsed as nonnegative integers, even though X.609-0207 @@ -67,8 +67,8 @@ extern "C" { * * Returns: 1 when the signature could be parsed, 0 otherwise. * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed + * Out: sig: pointer to a signature object + * In: input: pointer to the signature to be parsed * inputlen: the length of the array pointed to be input * * This function will accept any valid DER encoded signature, even if the @@ -83,9 +83,9 @@ extern "C" { * encoded numbers are out of range, signature validation with it is * guaranteed to fail for every message and public key. */ -int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der_lax( - const rustsecp256k1_v0_10_0_context* ctx, - rustsecp256k1_v0_10_0_ecdsa_signature* sig, +int rustsecp256k1_v0_11_ecdsa_signature_parse_der_lax( + const rustsecp256k1_v0_11_context* ctx, + rustsecp256k1_v0_11_ecdsa_signature* sig, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); diff --git a/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c index f19015b1d..3f0a7553d 100644 --- a/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.c @@ -8,7 +8,7 @@ #include "lax_der_privatekey_parsing.h" -int ec_privkey_import_der(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { +int ec_privkey_import_der(const rustsecp256k1_v0_11_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { const unsigned char *end = privkey + privkeylen; int lenb = 0; int len = 0; @@ -45,17 +45,17 @@ int ec_privkey_import_der(const rustsecp256k1_v0_10_0_context* ctx, unsigned cha return 0; } if (privkey[1]) memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); - if (!rustsecp256k1_v0_10_0_ec_seckey_verify(ctx, out32)) { + if (!rustsecp256k1_v0_11_ec_seckey_verify(ctx, out32)) { memset(out32, 0, 32); return 0; } return 1; } -int ec_privkey_export_der(const rustsecp256k1_v0_10_0_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { - rustsecp256k1_v0_10_0_pubkey pubkey; +int ec_privkey_export_der(const rustsecp256k1_v0_11_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { + rustsecp256k1_v0_11_pubkey pubkey; size_t pubkeylen = 0; - if (!rustsecp256k1_v0_10_0_ec_pubkey_create(ctx, &pubkey, key32)) { + if (!rustsecp256k1_v0_11_ec_pubkey_create(ctx, &pubkey, key32)) { *privkeylen = 0; return 0; } @@ -79,7 +79,7 @@ int ec_privkey_export_der(const rustsecp256k1_v0_10_0_context *ctx, unsigned cha memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); pubkeylen = 33; - rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); + rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; } else { @@ -104,7 +104,7 @@ int ec_privkey_export_der(const rustsecp256k1_v0_10_0_context *ctx, unsigned cha memcpy(ptr, key32, 32); ptr += 32; memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); pubkeylen = 65; - rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); + rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); ptr += pubkeylen; *privkeylen = ptr - privkey; } diff --git a/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h index 69b2555c8..01d2518fc 100644 --- a/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h +++ b/secp256k1-sys/depend/secp256k1/contrib/lax_der_privatekey_parsing.h @@ -43,7 +43,7 @@ extern "C" { /** Export a private key in DER format. * * Returns: 1 if the private key was valid. - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: privkey: pointer to an array for storing the private key in BER. * Should have space for 279 bytes, and cannot be NULL. * privkeylen: Pointer to an int where the length of the private key in @@ -57,10 +57,10 @@ extern "C" { * simple 32-byte private keys are sufficient. * * Note that this function does not guarantee correct DER output. It is - * guaranteed to be parsable by rustsecp256k1_v0_10_0_ec_privkey_import_der + * guaranteed to be parsable by rustsecp256k1_v0_11_ec_privkey_import_der */ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( - const rustsecp256k1_v0_10_0_context* ctx, + const rustsecp256k1_v0_11_context* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, @@ -82,7 +82,7 @@ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( * key. */ SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( - const rustsecp256k1_v0_10_0_context* ctx, + const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *privkey, size_t privkeylen diff --git a/secp256k1-sys/depend/secp256k1/doc/ellswift.md b/secp256k1-sys/depend/secp256k1/doc/ellswift.md index 4c6c0da81..64885a324 100644 --- a/secp256k1-sys/depend/secp256k1/doc/ellswift.md +++ b/secp256k1-sys/depend/secp256k1/doc/ellswift.md @@ -144,8 +144,8 @@ but the approach here is simple enough and gives fairly uniform output even in t **Note**: in the paper these conditions result in $\infty$ as output, due to the use of projective coordinates there. We wish to avoid the need for callers to deal with this special case. -This is implemented in `rustsecp256k1_v0_10_0_ellswift_xswiftec_frac_var` (which decodes to an x-coordinate represented as a fraction), and -in `rustsecp256k1_v0_10_0_ellswift_xswiftec_var` (which outputs the actual x-coordinate). +This is implemented in `rustsecp256k1_v0_11_ellswift_xswiftec_frac_var` (which decodes to an x-coordinate represented as a fraction), and +in `rustsecp256k1_v0_11_ellswift_xswiftec_var` (which outputs the actual x-coordinate). ## 3. The encoding function @@ -247,7 +247,7 @@ the loop can be simplified to only compute one of the inverses instead of all of * Let $t = G_{c,u}(x).$ * If $t \neq \bot$, return $(u, t)$; restart loop otherwise. -This is implemented in `rustsecp256k1_v0_10_0_ellswift_xelligatorswift_var`. +This is implemented in `rustsecp256k1_v0_11_ellswift_xelligatorswift_var`. ### 3.3 Finding the inverse @@ -388,7 +388,7 @@ Specialized for odd-ordered $a=0$ curves: * If $c \in \\{4, 6\\}:$ return $w(\frac{-\sqrt{-3}+1}{2}u + v).$ * If $c \in \\{5, 7\\}:$ return $w(\frac{-\sqrt{-3}-1}{2}u - v).$ -This is implemented in `rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var`. +This is implemented in `rustsecp256k1_v0_11_ellswift_xswiftec_inv_var`. And the x-only ElligatorSwift encoding algorithm is still: @@ -471,11 +471,11 @@ as decoder: * Let $y = \sqrt{g(x)}.$ * Return $(x, y)$ if $sign(y) = sign(t)$; $(x, -y)$ otherwise. -This is implemented in `rustsecp256k1_v0_10_0_ellswift_swiftec_var`. The used $sign(x)$ function is the parity of $x$ when represented as in integer in $[0,q).$ +This is implemented in `rustsecp256k1_v0_11_ellswift_swiftec_var`. The used $sign(x)$ function is the parity of $x$ when represented as in integer in $[0,q).$ The corresponding encoder would invoke the x-only one, but negating the output $t$ if $sign(t) \neq sign(y).$ -This is implemented in `rustsecp256k1_v0_10_0_ellswift_elligatorswift_var`. +This is implemented in `rustsecp256k1_v0_11_ellswift_elligatorswift_var`. Note that this is only intended for encoding points where both the x-coordinate and y-coordinate are unpredictable. When encoding x-only points where the y-coordinate is implicitly even (or implicitly square, or implicitly in $[0,q/2]$), the encoder in diff --git a/secp256k1-sys/depend/secp256k1/doc/musig.md b/secp256k1-sys/depend/secp256k1/doc/musig.md new file mode 100644 index 000000000..de61c0f91 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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/rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_musig_nonce_gen`. + See the corresponding comment in `include/rustsecp256k1_v0_11_musig.h` for how to ensure that. +2. The `rustsecp256k1_v0_11_musig_secnonce` structure is never copied or serialized. + See also the comment on `rustsecp256k1_v0_11_musig_secnonce` in `include/rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_musig_pubkey_agg`. +A plain tweak can be added to the resulting public key with `rustsecp256k1_v0_11_ec_pubkey_tweak_add` by setting the `tweak32` argument to the hash defined in BIP 32. Similarly, a Taproot tweak can be added with `rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_keypair_create` and obtain the public key with `rustsecp256k1_v0_11_keypair_pub`. +2. Call `rustsecp256k1_v0_11_musig_pubkey_agg` with the pubkeys of all participants. +3. Optionally add a (Taproot) tweak with `rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add` and a plain tweak with `rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add`. +4. Generate a pair of secret and public nonce with `rustsecp256k1_v0_11_musig_nonce_gen` and send the public nonce to the other signers. +5. Someone (not necessarily the signer) aggregates the public nonces with `rustsecp256k1_v0_11_musig_nonce_agg` and sends it to the signers. +6. Process the aggregate nonce with `rustsecp256k1_v0_11_musig_nonce_process`. +7. Create a partial signature with `rustsecp256k1_v0_11_musig_partial_sign`. +8. Verify the partial signatures (optional in some scenarios) with `rustsecp256k1_v0_11_musig_partial_sig_verify`. +9. Someone (not necessarily the signer) obtains all partial signatures and aggregates them into the final Schnorr signature using `rustsecp256k1_v0_11_musig_partial_sig_agg`. + +The aggregate signature can be verified with `rustsecp256k1_v0_11_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/secp256k1-sys/depend/secp256k1/doc/release-process.md b/secp256k1-sys/depend/secp256k1/doc/release-process.md index 51e337a5a..a64bae0f0 100644 --- a/secp256k1-sys/depend/secp256k1/doc/release-process.md +++ b/secp256k1-sys/depend/secp256k1/doc/release-process.md @@ -1,4 +1,4 @@ -# Release Process +# Release process This document outlines the process for releasing versions of the form `$MAJOR.$MINOR.$PATCH`. @@ -14,60 +14,62 @@ This process also assumes that there will be no minor releases for old major rel We aim to cut a regular release every 3-4 months, approximately twice as frequent as major Bitcoin Core releases. Every second release should be published one month before the feature freeze of the next major Bitcoin Core release, allowing sufficient time to update the library in Core. -## Sanity Checks -Perform these checks before creating a release: +## Sanity checks +Perform these checks when reviewing the release PR (see below): 1. Ensure `make distcheck` doesn't fail. -```shell -./autogen.sh && ./configure --enable-dev-mode && make distcheck -``` + ```shell + ./autogen.sh && ./configure --enable-dev-mode && make distcheck + ``` 2. Check installation with autotools: -```shell -dir=$(mktemp -d) -./autogen.sh && ./configure --prefix=$dir && make clean && make install && ls -RlAh $dir -gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=$dir/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"$dir/lib" && ./ecdsa -``` + ```shell + dir=$(mktemp -d) + ./autogen.sh && ./configure --prefix=$dir && make clean && make install && ls -RlAh $dir + gcc -o ecdsa examples/ecdsa.c $(PKG_CONFIG_PATH=$dir/lib/pkgconfig pkg-config --cflags --libs libsecp256k1) -Wl,-rpath,"$dir/lib" && ./ecdsa + ``` 3. Check installation with CMake: -```shell -dir=$(mktemp -d) -build=$(mktemp -d) -cmake -B $build -DCMAKE_INSTALL_PREFIX=$dir && cmake --build $build --target install && 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 ensure there are no unexpected ABI incompatibilities and that the version number and release notes accurately reflect all potential ABI changes. To run this tool, the `abi-dumper` and `abi-compliance-checker` packages are required. - -```shell -tools/check-abi.sh -``` + ```shell + dir=$(mktemp -d) + build=$(mktemp -d) + 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. + ```shell + tools/check-abi.sh + ``` ## Regular release 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 - * updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac` and + * sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and, + * if this is not a patch release, + * updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac`, and * updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`. -2. After the PR is merged, tag the commit and push it: +2. Perform the [sanity checks](#sanity-checks) on the PR branch. +3. After the PR is merged, tag the commit, and push the tag: ``` RELEASE_COMMIT= git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" $RELEASE_COMMIT git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH ``` -3. Open a PR to the master branch with a commit (using message `"release cleanup: bump version after $MAJOR.$MINOR.$PATCH"`, for example) that +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). If other maintainers are not present to approve the PR, it can be merged without ACKs. -4. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). +5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). +6. Send an announcement email to the bitcoin-dev mailing list. ## Maintenance release -Note that bugfixes only need to be backported to releases for which no compatible release without the bug exists. +Note that bug fixes need to be backported only to releases for which no compatible release without the bug exists. 1. If there's no maintenance branch `$MAJOR.$MINOR`, create one: ``` @@ -75,19 +77,18 @@ Note that bugfixes only need to be backported to releases for which no compatibl git push git@github.com:bitcoin-core/secp256k1.git $MAJOR.$MINOR ``` 2. Open a pull request to the `$MAJOR.$MINOR` branch that - * includes the bugfixes, + * includes the bug fixes, * finalizes the release notes similar to a regular release, * increments `_PKG_VERSION_PATCH` and `_LIB_VERSION_REVISION` in `configure.ac` and the `$PATCH` component of `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_REVISION` in `CMakeLists.txt` (with commit message `"release: bump versions for $MAJOR.$MINOR.$PATCH"`, for example). -3. After the PRs are merged, update the release branch and tag the commit: +3. Perform the [sanity checks](#sanity-checks) on the PR branch. +4. After the PRs are merged, update the release branch, tag the commit, and push the tag: ``` git checkout $MAJOR.$MINOR && git pull git tag -s v$MAJOR.$MINOR.$PATCH -m "libsecp256k1 $MAJOR.$MINOR.$PATCH" - ``` -4. Push tag: - ``` git push git@github.com:bitcoin-core/secp256k1.git v$MAJOR.$MINOR.$PATCH ``` -5. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). -6. Open PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md). +6. Create a new GitHub release with a link to the corresponding entry in [CHANGELOG.md](../CHANGELOG.md). +7. Send an announcement email to the bitcoin-dev mailing list. +8. Open PR to the master branch that includes a commit (with commit message `"release notes: add $MAJOR.$MINOR.$PATCH"`, for example) that adds release notes to [CHANGELOG.md](../CHANGELOG.md). diff --git a/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt b/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt index 607bb6777..565116d6c 100644 --- a/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt +++ b/secp256k1-sys/depend/secp256k1/examples/CMakeLists.txt @@ -9,14 +9,7 @@ function(add_example name) $<$:bcrypt> ) 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() + add_test(NAME rustsecp256k1_v0_11_${test_name} COMMAND ${target_name}) endfunction() add_example(ecdsa) @@ -28,3 +21,11 @@ endif() if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) add_example(schnorr) endif() + +if(SECP256K1_ENABLE_MODULE_ELLSWIFT) + add_example(ellswift) +endif() + +if(SECP256K1_ENABLE_MODULE_MUSIG) + add_example(musig) +endif() diff --git a/secp256k1-sys/depend/secp256k1/examples/ecdh.c b/secp256k1-sys/depend/secp256k1/examples/ecdh.c index 2f47a5d7f..1c9d87d9d 100644 --- a/secp256k1-sys/depend/secp256k1/examples/ecdh.c +++ b/secp256k1-sys/depend/secp256k1/examples/ecdh.c @@ -26,52 +26,50 @@ int main(void) { unsigned char randomize[32]; int return_val; size_t len; - rustsecp256k1_v0_10_0_pubkey pubkey1; - rustsecp256k1_v0_10_0_pubkey pubkey2; + rustsecp256k1_v0_11_pubkey pubkey1; + rustsecp256k1_v0_11_pubkey pubkey2; /* Before we can call actual API functions, we need to create a "context". */ - rustsecp256k1_v0_10_0_context* ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + rustsecp256k1_v0_11_context* ctx = rustsecp256k1_v0_11_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 `rustsecp256k1_v0_10_0_context_randomize` in secp256k1.h for more + * leakage See `rustsecp256k1_v0_11_context_randomize` in secp256k1.h for more * information about it. This should never fail. */ - return_val = rustsecp256k1_v0_10_0_context_randomize(ctx, randomize); + return_val = rustsecp256k1_v0_11_context_randomize(ctx, randomize); 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 (rustsecp256k1_v0_10_0_ec_seckey_verify(ctx, seckey1) && rustsecp256k1_v0_10_0_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 (!rustsecp256k1_v0_11_ec_seckey_verify(ctx, seckey1) || !rustsecp256k1_v0_11_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 */ - return_val = rustsecp256k1_v0_10_0_ec_pubkey_create(ctx, &pubkey1, seckey1); + return_val = rustsecp256k1_v0_11_ec_pubkey_create(ctx, &pubkey1, seckey1); assert(return_val); - return_val = rustsecp256k1_v0_10_0_ec_pubkey_create(ctx, &pubkey2, seckey2); + return_val = rustsecp256k1_v0_11_ec_pubkey_create(ctx, &pubkey2, seckey2); assert(return_val); /* Serialize pubkey1 in a compressed form (33 bytes), should always return 1 */ len = sizeof(compressed_pubkey1); - return_val = rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, compressed_pubkey1, &len, &pubkey1, SECP256K1_EC_COMPRESSED); + return_val = rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, compressed_pubkey1, &len, &pubkey1, SECP256K1_EC_COMPRESSED); assert(return_val); /* Should be the same size as the size of the output, because we passed a 33 byte array. */ assert(len == sizeof(compressed_pubkey1)); /* Serialize pubkey2 in a compressed form (33 bytes) */ len = sizeof(compressed_pubkey2); - return_val = rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, compressed_pubkey2, &len, &pubkey2, SECP256K1_EC_COMPRESSED); + return_val = rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, compressed_pubkey2, &len, &pubkey2, SECP256K1_EC_COMPRESSED); assert(return_val); /* Should be the same size as the size of the output, because we passed a 33 byte array. */ assert(len == sizeof(compressed_pubkey2)); @@ -80,12 +78,12 @@ int main(void) { /* Perform ECDH with seckey1 and pubkey2. Should never fail with a verified * seckey and valid pubkey */ - return_val = rustsecp256k1_v0_10_0_ecdh(ctx, shared_secret1, &pubkey2, seckey1, NULL, NULL); + return_val = rustsecp256k1_v0_11_ecdh(ctx, shared_secret1, &pubkey2, seckey1, NULL, NULL); assert(return_val); /* Perform ECDH with seckey2 and pubkey1. Should never fail with a verified * seckey and valid pubkey */ - return_val = rustsecp256k1_v0_10_0_ecdh(ctx, shared_secret2, &pubkey1, seckey2, NULL, NULL); + return_val = rustsecp256k1_v0_11_ecdh(ctx, shared_secret2, &pubkey1, seckey2, NULL, NULL); assert(return_val); /* Both parties should end up with the same shared secret */ @@ -104,11 +102,11 @@ int main(void) { print_hex(shared_secret1, sizeof(shared_secret1)); /* This will clear everything from the context and free the memory */ - rustsecp256k1_v0_10_0_context_destroy(ctx); + rustsecp256k1_v0_11_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 + * 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/secp256k1-sys/depend/secp256k1/examples/ecdsa.c b/secp256k1-sys/depend/secp256k1/examples/ecdsa.c index ea08558a5..fcc9797f8 100644 --- a/secp256k1-sys/depend/secp256k1/examples/ecdsa.c +++ b/secp256k1-sys/depend/secp256k1/examples/ecdsa.c @@ -34,42 +34,40 @@ int main(void) { size_t len; int is_signature_valid, is_signature_valid2; int return_val; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_ecdsa_signature sig; /* Before we can call actual API functions, we need to create a "context". */ - rustsecp256k1_v0_10_0_context* ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + rustsecp256k1_v0_11_context* ctx = rustsecp256k1_v0_11_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 `rustsecp256k1_v0_10_0_context_randomize` in secp256k1.h for more + * leakage See `rustsecp256k1_v0_11_context_randomize` in secp256k1.h for more * information about it. This should never fail. */ - return_val = rustsecp256k1_v0_10_0_context_randomize(ctx, randomize); + return_val = rustsecp256k1_v0_11_context_randomize(ctx, randomize); 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 (rustsecp256k1_v0_10_0_ec_seckey_verify(ctx, seckey)) { - break; - } + 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 (!rustsecp256k1_v0_11_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 */ - return_val = rustsecp256k1_v0_10_0_ec_pubkey_create(ctx, &pubkey, seckey); + return_val = rustsecp256k1_v0_11_ec_pubkey_create(ctx, &pubkey, seckey); assert(return_val); /* Serialize the pubkey in a compressed form(33 bytes). Should always return 1. */ len = sizeof(compressed_pubkey); - return_val = rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, compressed_pubkey, &len, &pubkey, SECP256K1_EC_COMPRESSED); + return_val = rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, compressed_pubkey, &len, &pubkey, SECP256K1_EC_COMPRESSED); assert(return_val); /* Should be the same size as the size of the output, because we passed a 33 byte array. */ assert(len == sizeof(compressed_pubkey)); @@ -80,31 +78,31 @@ int main(void) { * custom nonce function, passing `NULL` will use the RFC-6979 safe default. * Signing with a valid context, verified secret key * and the default nonce function should never fail. */ - return_val = rustsecp256k1_v0_10_0_ecdsa_sign(ctx, &sig, msg_hash, seckey, NULL, NULL); + return_val = rustsecp256k1_v0_11_ecdsa_sign(ctx, &sig, msg_hash, seckey, NULL, NULL); assert(return_val); /* Serialize the signature in a compact form. Should always return 1 * according to the documentation in secp256k1.h. */ - return_val = rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(ctx, serialized_signature, &sig); + return_val = rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(ctx, serialized_signature, &sig); assert(return_val); /*** Verification ***/ /* Deserialize the signature. This will return 0 if the signature can't be parsed correctly. */ - if (!rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) { + if (!rustsecp256k1_v0_11_ecdsa_signature_parse_compact(ctx, &sig, serialized_signature)) { printf("Failed parsing the signature\n"); return 1; } /* Deserialize the public key. This will return 0 if the public key can't be parsed correctly. */ - if (!rustsecp256k1_v0_10_0_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) { + if (!rustsecp256k1_v0_11_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, sizeof(compressed_pubkey))) { printf("Failed parsing the public key\n"); return 1; } /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ - is_signature_valid = rustsecp256k1_v0_10_0_ecdsa_verify(ctx, &sig, msg_hash, &pubkey); + is_signature_valid = rustsecp256k1_v0_11_ecdsa_verify(ctx, &sig, msg_hash, &pubkey); printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false"); printf("Secret Key: "); @@ -115,20 +113,20 @@ int main(void) { print_hex(serialized_signature, sizeof(serialized_signature)); /* This will clear everything from the context and free the memory */ - rustsecp256k1_v0_10_0_context_destroy(ctx); + rustsecp256k1_v0_11_context_destroy(ctx); /* Bonus example: if all we need is signature verification (and no key generation or signing), we don't need to use a context created via - rustsecp256k1_v0_10_0_context_create(). We can simply use the static (i.e., global) - context rustsecp256k1_v0_10_0_context_static. See its description in + rustsecp256k1_v0_11_context_create(). We can simply use the static (i.e., global) + context rustsecp256k1_v0_11_context_static. See its description in include/secp256k1.h for details. */ - is_signature_valid2 = rustsecp256k1_v0_10_0_ecdsa_verify(rustsecp256k1_v0_10_0_context_static, + is_signature_valid2 = rustsecp256k1_v0_11_ecdsa_verify(rustsecp256k1_v0_11_context_static, &sig, msg_hash, &pubkey); assert(is_signature_valid2 == is_signature_valid); /* 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/secp256k1-sys/depend/secp256k1/examples/ellswift.c b/secp256k1-sys/depend/secp256k1/examples/ellswift.c new file mode 100644 index 000000000..c50529745 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/examples/ellswift.c @@ -0,0 +1,121 @@ +/************************************************************************* + * 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/rustsecp256k1_v0_11_ellswift.h and doc/ellswift.md. + */ + +#include +#include +#include + +#include +#include + +#include "examples_util.h" + +int main(void) { + rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_context_randomize` in secp256k1.h for more + * information about it. This should never fail. */ + return_val = rustsecp256k1_v0_11_context_randomize(ctx, randomize); + assert(return_val); + + /*** Generate secret keys ***/ + 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 (!rustsecp256k1_v0_11_ec_seckey_verify(ctx, seckey1) || !rustsecp256k1_v0_11_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 + 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 = rustsecp256k1_v0_11_ellswift_create(ctx, ellswift_pubkey1, seckey1, auxrand1); + assert(return_val); + return_val = rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_ellswift_xdh(ctx, shared_secret1, ellswift_pubkey1, ellswift_pubkey2, + seckey1, 0, rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_ellswift_xdh(ctx, shared_secret2, ellswift_pubkey1, ellswift_pubkey2, + seckey2, 1, rustsecp256k1_v0_11_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 */ + rustsecp256k1_v0_11_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; +} diff --git a/secp256k1-sys/depend/secp256k1/examples/musig.c b/secp256k1-sys/depend/secp256k1/examples/musig.c new file mode 100644 index 000000000..a9ead9716 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/examples/musig.c @@ -0,0 +1,260 @@ +/************************************************************************* + * 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/rustsecp256k1_v0_11_musig.h and doc/musig.md. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "examples_util.h" + +struct signer_secrets { + rustsecp256k1_v0_11_keypair keypair; + rustsecp256k1_v0_11_musig_secnonce secnonce; +}; + +struct signer { + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_musig_pubnonce pubnonce; + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer) { + unsigned char seckey[32]; + + 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 (!rustsecp256k1_v0_11_keypair_create(ctx, &signer_secrets->keypair, seckey)) { + return 0; + } + if (!rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_xonly_pubkey *agg_pk, rustsecp256k1_v0_11_musig_keyagg_cache *cache) { + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_musig_pubkey_get` right after key aggregation to get + * the full pubkey and then call `rustsecp256k1_v0_11_ec_pubkey_tweak_add`. */ + + /* Xonly tweaking which, for example, allows creating Taproot commitments */ + if (!rustsecp256k1_v0_11_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 + * `rustsecp256k1_v0_11_xonly_pubkey_tweak_add` (after converting it to an xonly pubkey + * if necessary with `rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_context* ctx, struct signer_secrets *signer_secrets, struct signer *signer, const rustsecp256k1_v0_11_musig_keyagg_cache *cache, const unsigned char *msg32, unsigned char *sig64) { + int i; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonces[N_SIGNERS]; + const rustsecp256k1_v0_11_musig_partial_sig *partial_sigs[N_SIGNERS]; + /* The same for all signers */ + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_nonce_agg and sends + * agg_pubnonce to each signer */ + if (!rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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 + * rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_musig_partial_sig_verify(ctx, &signer[i].partial_sig, &signer[i].pubnonce, &signer[i].pubkey, cache, &session)) { + return 0; + } + } + return rustsecp256k1_v0_11_musig_partial_sig_agg(ctx, sig64, &session, partial_sigs, N_SIGNERS); +} + +int main(void) { + rustsecp256k1_v0_11_context* ctx; + int i; + struct signer_secrets signer_secrets[N_SIGNERS]; + struct signer signers[N_SIGNERS]; + const rustsecp256k1_v0_11_pubkey *pubkeys_ptr[N_SIGNERS]; + rustsecp256k1_v0_11_xonly_pubkey agg_pk; + rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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 + * rustsecp256k1_v0_11_ec_pubkey_sort to ensure that the aggregate public key is + * independent of the order of signers. */ + printf("Sorting public keys....."); + fflush(stdout); + if (!rustsecp256k1_v0_11_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 + * rustsecp256k1_v0_11_musig_pubkey_agg with the keyagg_cache argument set to NULL + * while providing a non-NULL agg_pk argument. */ + if (!rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_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])); + } + rustsecp256k1_v0_11_context_destroy(ctx); + return 0; +} diff --git a/secp256k1-sys/depend/secp256k1/examples/schnorr.c b/secp256k1-sys/depend/secp256k1/examples/schnorr.c index 851dabe10..e41be3ee1 100644 --- a/secp256k1-sys/depend/secp256k1/examples/schnorr.c +++ b/secp256k1-sys/depend/secp256k1/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]; @@ -28,47 +28,44 @@ int main(void) { unsigned char signature[64]; int is_signature_valid, is_signature_valid2; int return_val; - rustsecp256k1_v0_10_0_xonly_pubkey pubkey; - rustsecp256k1_v0_10_0_keypair keypair; + rustsecp256k1_v0_11_xonly_pubkey pubkey; + rustsecp256k1_v0_11_keypair keypair; /* Before we can call actual API functions, we need to create a "context". */ - rustsecp256k1_v0_10_0_context* ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + rustsecp256k1_v0_11_context* ctx = rustsecp256k1_v0_11_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 `rustsecp256k1_v0_10_0_context_randomize` in secp256k1.h for more + * leakage See `rustsecp256k1_v0_11_context_randomize` in secp256k1.h for more * information about it. This should never fail. */ - return_val = rustsecp256k1_v0_10_0_context_randomize(ctx, randomize); + return_val = rustsecp256k1_v0_11_context_randomize(ctx, randomize); 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 (rustsecp256k1_v0_10_0_keypair_create(ctx, &keypair, seckey)) { - break; - } + if (!fill_random(seckey, sizeof(seckey))) { + printf("Failed to generate randomness\n"); + return 1; + } + /* 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 (!rustsecp256k1_v0_11_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 * `pk_parity` as the parity isn't needed for signing or verification. - * `rustsecp256k1_v0_10_0_keypair_xonly_pub` supports returning the parity for + * `rustsecp256k1_v0_11_keypair_xonly_pub` supports returning the parity for * other use cases such as tests or verifying Taproot tweaks. * This should never fail with a valid context and public key. */ - return_val = rustsecp256k1_v0_10_0_keypair_xonly_pub(ctx, &pubkey, NULL, &keypair); + return_val = rustsecp256k1_v0_11_keypair_xonly_pub(ctx, &pubkey, NULL, &keypair); assert(return_val); /* Serialize the public key. Should always return 1 for a valid public key. */ - return_val = rustsecp256k1_v0_10_0_xonly_pubkey_serialize(ctx, serialized_pubkey, &pubkey); + return_val = rustsecp256k1_v0_11_xonly_pubkey_serialize(ctx, serialized_pubkey, &pubkey); assert(return_val); /*** Signing ***/ @@ -76,7 +73,7 @@ int main(void) { /* Instead of signing (possibly very long) messages directly, we sign a * 32-byte hash of the message in this example. * - * We use rustsecp256k1_v0_10_0_tagged_sha256 to create this hash. This function expects + * We use rustsecp256k1_v0_11_tagged_sha256 to create this hash. This function expects * a context-specific "tag", which restricts the context in which the signed * messages should be considered valid. For example, if protocol A mandates * to use the tag "my_fancy_protocol" and protocol B mandates to use the tag @@ -87,7 +84,7 @@ int main(void) { * message that has intended consequences in the intended context (e.g., * protocol A) but would have unintended consequences if it were valid in * some other context (e.g., protocol B). */ - return_val = rustsecp256k1_v0_10_0_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg)); + return_val = rustsecp256k1_v0_11_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg)); assert(return_val); /* Generate 32 bytes of randomness to use with BIP-340 schnorr signing. */ @@ -98,30 +95,30 @@ int main(void) { /* Generate a Schnorr signature. * - * We use the rustsecp256k1_v0_10_0_schnorrsig_sign32 function that provides a simple + * We use the rustsecp256k1_v0_11_schnorrsig_sign32 function that provides a simple * interface for signing 32-byte messages (which in our case is a hash of * the actual message). BIP-340 recommends passing 32 bytes of randomness * to the signing function to improve security against side-channel attacks. * Signing with a valid context, a 32-byte message, a verified keypair, and * any 32 bytes of auxiliary random data should never fail. */ - return_val = rustsecp256k1_v0_10_0_schnorrsig_sign32(ctx, signature, msg_hash, &keypair, auxiliary_rand); + return_val = rustsecp256k1_v0_11_schnorrsig_sign32(ctx, signature, msg_hash, &keypair, auxiliary_rand); assert(return_val); /*** Verification ***/ /* Deserialize the public key. This will return 0 if the public key can't * be parsed correctly */ - if (!rustsecp256k1_v0_10_0_xonly_pubkey_parse(ctx, &pubkey, serialized_pubkey)) { + if (!rustsecp256k1_v0_11_xonly_pubkey_parse(ctx, &pubkey, serialized_pubkey)) { printf("Failed parsing the public key\n"); return 1; } /* Compute the tagged hash on the received messages using the same tag as the signer. */ - return_val = rustsecp256k1_v0_10_0_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg)); + return_val = rustsecp256k1_v0_11_tagged_sha256(ctx, msg_hash, tag, sizeof(tag), msg, sizeof(msg)); assert(return_val); /* Verify a signature. This will return 1 if it's valid and 0 if it's not. */ - is_signature_valid = rustsecp256k1_v0_10_0_schnorrsig_verify(ctx, signature, msg_hash, 32, &pubkey); + is_signature_valid = rustsecp256k1_v0_11_schnorrsig_verify(ctx, signature, msg_hash, 32, &pubkey); printf("Is the signature valid? %s\n", is_signature_valid ? "true" : "false"); @@ -133,20 +130,20 @@ int main(void) { print_hex(signature, sizeof(signature)); /* This will clear everything from the context and free the memory */ - rustsecp256k1_v0_10_0_context_destroy(ctx); + rustsecp256k1_v0_11_context_destroy(ctx); /* Bonus example: if all we need is signature verification (and no key generation or signing), we don't need to use a context created via - rustsecp256k1_v0_10_0_context_create(). We can simply use the static (i.e., global) - context rustsecp256k1_v0_10_0_context_static. See its description in + rustsecp256k1_v0_11_context_create(). We can simply use the static (i.e., global) + context rustsecp256k1_v0_11_context_static. See its description in include/secp256k1.h for details. */ - is_signature_valid2 = rustsecp256k1_v0_10_0_schnorrsig_verify(rustsecp256k1_v0_10_0_context_static, + is_signature_valid2 = rustsecp256k1_v0_11_schnorrsig_verify(rustsecp256k1_v0_11_context_static, signature, msg_hash, 32, &pubkey); assert(is_signature_valid2 == is_signature_valid); /* 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/secp256k1-sys/depend/secp256k1/include/secp256k1.h b/secp256k1-sys/depend/secp256k1/include/secp256k1.h index 4120257f9..300b6c912 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1.h @@ -29,38 +29,25 @@ extern "C" { * The primary purpose of context objects is to store randomization data for * enhanced protection against side-channel leakage. This protection is only * effective if the context is randomized after its creation. See - * rustsecp256k1_v0_10_0_context_create for creation of contexts and - * rustsecp256k1_v0_10_0_context_randomize for randomization. + * rustsecp256k1_v0_11_context_create for creation of contexts and + * rustsecp256k1_v0_11_context_randomize for randomization. * * A secondary purpose of context objects is to store pointers to callback * functions that the library will call when certain error states arise. See - * rustsecp256k1_v0_10_0_context_set_error_callback as well as - * rustsecp256k1_v0_10_0_context_set_illegal_callback for details. Future library versions + * rustsecp256k1_v0_11_context_set_error_callback as well as + * rustsecp256k1_v0_11_context_set_illegal_callback for details. Future library versions * may use context objects for additional purposes. * * A constructed context can safely be used from multiple threads * simultaneously, but API calls that take a non-const pointer to a context * need exclusive access to it. In particular this is the case for - * rustsecp256k1_v0_10_0_context_destroy, rustsecp256k1_v0_10_0_context_preallocated_destroy, - * and rustsecp256k1_v0_10_0_context_randomize. + * rustsecp256k1_v0_11_context_destroy, rustsecp256k1_v0_11_context_preallocated_destroy, + * and rustsecp256k1_v0_11_context_randomize. * * Regarding randomization, either do it once at creation time (in which case * you do not need any locking for the other calls), or use a read-write lock. */ -typedef struct rustsecp256k1_v0_10_0_context_struct rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_scratch_space_struct rustsecp256k1_v0_10_0_scratch_space; +typedef struct rustsecp256k1_v0_11_context_struct rustsecp256k1_v0_11_context; /** Opaque data structure that holds a parsed and valid public key. * @@ -68,25 +55,25 @@ typedef struct rustsecp256k1_v0_10_0_scratch_space_struct rustsecp256k1_v0_10_0_ * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 64 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage or transmission, - * use rustsecp256k1_v0_10_0_ec_pubkey_serialize and rustsecp256k1_v0_10_0_ec_pubkey_parse. To - * compare keys, use rustsecp256k1_v0_10_0_ec_pubkey_cmp. + * use rustsecp256k1_v0_11_ec_pubkey_serialize and rustsecp256k1_v0_11_ec_pubkey_parse. To + * compare keys, use rustsecp256k1_v0_11_ec_pubkey_cmp. */ -typedef struct { +typedef struct rustsecp256k1_v0_11_pubkey { unsigned char data[64]; -} rustsecp256k1_v0_10_0_pubkey; +} rustsecp256k1_v0_11_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 * however guaranteed to be 64 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage, transmission, or - * comparison, use the rustsecp256k1_v0_10_0_ecdsa_signature_serialize_* and - * rustsecp256k1_v0_10_0_ecdsa_signature_parse_* functions. + * comparison, use the rustsecp256k1_v0_11_ecdsa_signature_serialize_* and + * rustsecp256k1_v0_11_ecdsa_signature_parse_* functions. */ -typedef struct { +typedef struct rustsecp256k1_v0_11_ecdsa_signature { unsigned char data[64]; -} rustsecp256k1_v0_10_0_ecdsa_signature; +} rustsecp256k1_v0_11_ecdsa_signature; /** A pointer to a function to deterministically generate a nonce. * @@ -104,7 +91,7 @@ typedef struct { * Except for test cases, this function should compute some cryptographic hash of * the message, the algorithm, the key and the attempt. */ -typedef int (*rustsecp256k1_v0_10_0_nonce_function)( +typedef int (*rustsecp256k1_v0_11_nonce_function)( unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, @@ -147,6 +134,15 @@ typedef int (*rustsecp256k1_v0_10_0_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 +152,12 @@ typedef int (*rustsecp256k1_v0_10_0_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 @@ -200,8 +197,8 @@ typedef int (*rustsecp256k1_v0_10_0_nonce_function)( #define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) #define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) -/** Context flags to pass to rustsecp256k1_v0_10_0_context_create, rustsecp256k1_v0_10_0_context_preallocated_size, and - * rustsecp256k1_v0_10_0_context_preallocated_create. */ +/** Context flags to pass to rustsecp256k1_v0_11_context_create, rustsecp256k1_v0_11_context_preallocated_size, and + * rustsecp256k1_v0_11_context_preallocated_create. */ #define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) /** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */ @@ -211,7 +208,7 @@ typedef int (*rustsecp256k1_v0_10_0_nonce_function)( /* Testing flag. Do not use. */ #define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY) -/** Flag to pass to rustsecp256k1_v0_10_0_ec_pubkey_serialize. */ +/** Flag to pass to rustsecp256k1_v0_11_ec_pubkey_serialize. */ #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) #define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) @@ -223,20 +220,20 @@ typedef int (*rustsecp256k1_v0_10_0_nonce_function)( #define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 /** A built-in constant secp256k1 context object with static storage duration, to be - * used in conjunction with rustsecp256k1_v0_10_0_selftest. + * used in conjunction with rustsecp256k1_v0_11_selftest. * * This context object offers *only limited functionality* , i.e., it cannot be used * for API functions that perform computations involving secret keys, e.g., signing * and public key generation. If this restriction applies to a specific API function, - * it is mentioned in its documentation. See rustsecp256k1_v0_10_0_context_create if you need a + * it is mentioned in its documentation. See rustsecp256k1_v0_11_context_create if you need a * full context object that supports all functionality offered by the library. * - * It is highly recommended to call rustsecp256k1_v0_10_0_selftest before using this context. + * It is highly recommended to call rustsecp256k1_v0_11_selftest before using this context. */ -/** Deprecated alias for rustsecp256k1_v0_10_0_context_static. */ +/** Deprecated alias for rustsecp256k1_v0_11_context_static. */ -/** Perform basic self tests (to be used in conjunction with rustsecp256k1_v0_10_0_context_static) +/** Perform basic self tests (to be used in conjunction with rustsecp256k1_v0_11_context_static) * * This function performs self tests that detect some serious usage errors and * similar conditions, e.g., when the library is compiled for the wrong endianness. @@ -244,25 +241,25 @@ typedef int (*rustsecp256k1_v0_10_0_nonce_function)( * very rudimentary and are not intended as a replacement for running the test * binaries. * - * It is highly recommended to call this before using rustsecp256k1_v0_10_0_context_static. + * It is highly recommended to call this before using rustsecp256k1_v0_11_context_static. * It is not necessary to call this function before using a context created with - * rustsecp256k1_v0_10_0_context_create (or rustsecp256k1_v0_10_0_context_preallocated_create), which will + * rustsecp256k1_v0_11_context_create (or rustsecp256k1_v0_11_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 - * program (see rustsecp256k1_v0_10_0_context_set_error_callback). + * program (see rustsecp256k1_v0_11_context_set_error_callback). */ -SECP256K1_API void rustsecp256k1_v0_10_0_selftest(void); +SECP256K1_API void rustsecp256k1_v0_11_selftest(void); /** Create a secp256k1 context object (in dynamically allocated memory). * * This function uses malloc to allocate memory. It is guaranteed that malloc is * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see rustsecp256k1_v0_10_0_context_static and the functions in - * rustsecp256k1_v0_10_0_preallocated.h. + * memory allocation entirely, see rustsecp256k1_v0_11_context_static and the functions in + * rustsecp256k1_v0_11_preallocated.h. * - * Returns: a newly created context object. + * Returns: pointer to a newly created context object. * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). * * The only valid non-deprecated flag in recent library versions is @@ -273,9 +270,9 @@ SECP256K1_API void rustsecp256k1_v0_10_0_selftest(void); * * If the context is intended to be used for API functions that perform computations * involving secret keys, e.g., signing and public key generation, then it is highly - * recommended to call rustsecp256k1_v0_10_0_context_randomize on the context before calling + * recommended to call rustsecp256k1_v0_11_context_randomize on the context before calling * those API functions. This will provide enhanced protection against side-channel - * leakage, see rustsecp256k1_v0_10_0_context_randomize for details. + * leakage, see rustsecp256k1_v0_11_context_randomize for details. * * Do not create a new context object for each operation, as construction and * randomization can take non-negligible time. @@ -284,27 +281,27 @@ SECP256K1_API void rustsecp256k1_v0_10_0_selftest(void); * * This function uses malloc to allocate memory. It is guaranteed that malloc is * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see the functions in rustsecp256k1_v0_10_0_preallocated.h. + * memory allocation entirely, see the functions in rustsecp256k1_v0_11_preallocated.h. * - * Cloning rustsecp256k1_v0_10_0_context_static is not possible, and should not be emulated by + * Cloning rustsecp256k1_v0_11_context_static is not possible, and should not be emulated by * the caller (e.g., using memcpy). Create a new context instead. * - * Returns: a newly created context object. - * Args: ctx: an existing context to copy (not rustsecp256k1_v0_10_0_context_static) + * Returns: pointer to a newly created context object. + * Args: ctx: pointer to a context to copy (not rustsecp256k1_v0_11_context_static). */ /** Destroy a secp256k1 context object (created in dynamically allocated memory). * * The context pointer may not be used afterwards. * - * The context to destroy must have been created using rustsecp256k1_v0_10_0_context_create - * or rustsecp256k1_v0_10_0_context_clone. If the context has instead been created using - * rustsecp256k1_v0_10_0_context_preallocated_create or rustsecp256k1_v0_10_0_context_preallocated_clone, the - * behaviour is undefined. In that case, rustsecp256k1_v0_10_0_context_preallocated_destroy must + * The context to destroy must have been created using rustsecp256k1_v0_11_context_create + * or rustsecp256k1_v0_11_context_clone. If the context has instead been created using + * rustsecp256k1_v0_11_context_preallocated_create or rustsecp256k1_v0_11_context_preallocated_clone, the + * behaviour is undefined. In that case, rustsecp256k1_v0_11_context_preallocated_destroy must * be used instead. * - * Args: ctx: an existing context to destroy, constructed using - * rustsecp256k1_v0_10_0_context_create or rustsecp256k1_v0_10_0_context_clone - * (i.e., not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context to destroy, constructed using + * rustsecp256k1_v0_11_context_create or rustsecp256k1_v0_11_context_clone + * (i.e., not rustsecp256k1_v0_11_context_static). */ /** Set a callback function to be called when an illegal argument is passed to * an API call. It will only trigger for violations that are mentioned @@ -327,24 +324,24 @@ SECP256K1_API void rustsecp256k1_v0_10_0_selftest(void); * 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 rustsecp256k1_v0_10_0_default_illegal_callback_fn(const char *message, void *data); - * - void rustsecp256k1_v0_10_0_default_error_callback_fn(const char *message, void *data); + * - void rustsecp256k1_v0_11_default_illegal_callback_fn(const char *message, void *data); + * - void rustsecp256k1_v0_11_default_error_callback_fn(const char *message, void *data); * The library can call these default handlers even before a proper callback data - * pointer could have been set using rustsecp256k1_v0_10_0_context_set_illegal_callback or - * rustsecp256k1_v0_10_0_context_set_error_callback, e.g., when the creation of a context + * pointer could have been set using rustsecp256k1_v0_11_context_set_illegal_callback or + * rustsecp256k1_v0_11_context_set_error_callback, e.g., when the creation of a context * fails. In this case, the corresponding default handler will be called with * the data pointer argument set to NULL. * - * Args: ctx: an existing context object. - * In: fun: a pointer to a function to call when an illegal argument is + * 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. * - * See also rustsecp256k1_v0_10_0_context_set_error_callback. + * See also rustsecp256k1_v0_11_context_set_error_callback. */ -SECP256K1_API void rustsecp256k1_v0_10_0_context_set_illegal_callback( - rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API void rustsecp256k1_v0_11_context_set_illegal_callback( + rustsecp256k1_v0_11_context *ctx, void (*fun)(const char *message, void *data), const void *data ) SECP256K1_ARG_NONNULL(1); @@ -358,43 +355,30 @@ SECP256K1_API void rustsecp256k1_v0_10_0_context_set_illegal_callback( * 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 - * incorrect usage of the API (see rustsecp256k1_v0_10_0_context_set_illegal_callback + * incorrect usage of the API (see rustsecp256k1_v0_11_context_set_illegal_callback * for that). After this callback returns, anything may happen, including * crashing. * - * Args: ctx: an existing context object. - * In: fun: a pointer to a function to call when an internal error occurs, + * 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 rustsecp256k1_v0_10_0_context_set_illegal_callback + * default handler, see rustsecp256k1_v0_11_context_set_illegal_callback * for details). * data: the opaque pointer to pass to fun above, must be NULL for the default handler. * - * See also rustsecp256k1_v0_10_0_context_set_illegal_callback. + * See also rustsecp256k1_v0_11_context_set_illegal_callback. */ -SECP256K1_API void rustsecp256k1_v0_10_0_context_set_error_callback( - rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API void rustsecp256k1_v0_11_context_set_error_callback( + rustsecp256k1_v0_11_context *ctx, void (*fun)(const char *message, void *data), const void *data ) SECP256K1_ARG_NONNULL(1); -/** Create a secp256k1 scratch space object. - * - * Returns: a newly created scratch space. - * Args: ctx: an existing context object. - * In: size: amount of memory to be available as scratch space. Some extra - * (<100 bytes) will be allocated for extra accounting. - */ -/** Destroy a secp256k1 scratch space. - * - * The pointer may not be used afterwards. - * Args: ctx: a secp256k1 context object. - * scratch: space to destroy - */ /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. * 0 if the public key could not be parsed or is invalid. - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object. * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a * parsed version of input. If not, its value is undefined. * In: input: pointer to a serialized public key @@ -404,9 +388,9 @@ SECP256K1_API void rustsecp256k1_v0_10_0_context_set_error_callback( * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header * byte 0x06 or 0x07) format public keys. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_parse( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_parse( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -414,23 +398,23 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_p /** Serialize a pubkey object into a serialized byte sequence. * * Returns: 1 always. - * Args: ctx: a secp256k1 context object. - * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if + * Args: ctx: pointer to a context object. + * Out: output: pointer to a 65-byte (if compressed==0) or 33-byte (if * compressed==1) byte array to place the serialized key * in. - * In/Out: outputlen: a pointer to an integer which is initially set to the + * In/Out: outputlen: pointer to an integer which is initially set to the * size of output, and is overwritten with the written * size. - * In: pubkey: a pointer to a rustsecp256k1_v0_10_0_pubkey containing an + * In: pubkey: pointer to a rustsecp256k1_v0_11_pubkey containing an * initialized public key. * flags: SECP256K1_EC_COMPRESSED if serialization should be in * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ec_pubkey_serialize( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_ec_pubkey_serialize( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output, size_t *outputlen, - const rustsecp256k1_v0_10_0_pubkey *pubkey, + const rustsecp256k1_v0_11_pubkey *pubkey, unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -439,22 +423,36 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ec_pubkey_serialize( * Returns: <0 if the first public key is less than the second * >0 if the first public key is greater than the second * 0 if the two public keys are equal - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object * In: pubkey1: first public key to compare * pubkey2: second public key to compare */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_cmp( - const rustsecp256k1_v0_10_0_context *ctx, - const rustsecp256k1_v0_10_0_pubkey *pubkey1, - const rustsecp256k1_v0_10_0_pubkey *pubkey2 +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_cmp( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_pubkey *pubkey1, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_ec_pubkey_sort( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_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. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to the 64-byte array to parse + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input64: pointer to the 64-byte array to parse * * The signature must consist of a 32-byte big endian R value, followed by a * 32-byte big endian S value. If R or S fall outside of [0..order-1], the @@ -464,18 +462,18 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_c * S are zero, the resulting sig value is guaranteed to fail verification for * any message and public key. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_signature *sig, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_parse_compact( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *input64 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Parse a DER ECDSA signature. * * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input: pointer to the signature to be parsed * inputlen: the length of the array pointed to be input * * This function will accept any valid DER encoded signature, even if the @@ -485,9 +483,9 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact( * encoded numbers are out of range, signature verification with it is * guaranteed to fail for every message and public key. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_signature *sig, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_parse_der( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -495,41 +493,41 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der( /** Serialize an ECDSA signature in DER format. * * Returns: 1 if enough space was available to serialize, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: output: a pointer to an array to store the DER serialization - * In/Out: outputlen: a pointer to a length integer. Initially, this integer + * Args: ctx: pointer to a context object + * Out: output: pointer to an array to store the DER serialization + * In/Out: outputlen: pointer to a length integer. Initially, this integer * should be set to the length of output. After the call * it will be set to the length of the serialization (even * if 0 was returned). - * In: sig: a pointer to an initialized signature object + * In: sig: pointer to an initialized signature object */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_serialize_der( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output, size_t *outputlen, - const rustsecp256k1_v0_10_0_ecdsa_signature *sig + const rustsecp256k1_v0_11_ecdsa_signature *sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Serialize an ECDSA signature in compact (64 byte) format. * * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array to store the compact serialization - * In: sig: a pointer to an initialized signature object + * Args: ctx: pointer to a context object + * Out: output64: pointer to a 64-byte array to store the compact serialization + * In: sig: pointer to an initialized signature object * - * See rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact for details about the encoding. + * See rustsecp256k1_v0_11_ecdsa_signature_parse_compact for details about the encoding. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_serialize_compact( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output64, - const rustsecp256k1_v0_10_0_ecdsa_signature *sig + const rustsecp256k1_v0_11_ecdsa_signature *sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Verify an ECDSA signature. * * Returns: 1: correct signature * 0: incorrect or unparseable signature - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object * In: sig: the signature being verified. * msghash32: the 32-byte message hash being verified. * The verifier must make sure to apply a cryptographic @@ -545,27 +543,27 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact( * form are accepted. * * If you need to accept ECDSA signatures from sources that do not obey this - * rule, apply rustsecp256k1_v0_10_0_ecdsa_signature_normalize to the signature prior to + * rule, apply rustsecp256k1_v0_11_ecdsa_signature_normalize to the signature prior to * verification, but be aware that doing so results in malleable signatures. * * For details, see the comments for that function. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ecdsa_verify( - const rustsecp256k1_v0_10_0_context *ctx, - const rustsecp256k1_v0_10_0_ecdsa_signature *sig, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ecdsa_verify( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *msghash32, - const rustsecp256k1_v0_10_0_pubkey *pubkey + const rustsecp256k1_v0_11_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Convert a signature to a normalized lower-S form. * * Returns: 1 if sigin was not normalized, 0 if it already was. - * Args: ctx: a secp256k1 context object - * Out: sigout: a pointer to a signature to fill with the normalized form, + * Args: ctx: pointer to a context object + * Out: sigout: pointer to a signature to fill with the normalized form, * or copy if the input was already normalized. (can be NULL if * you're only interested in whether the input was already * normalized). - * In: sigin: a pointer to a signature to check/normalize (can be identical to sigout) + * In: sigin: pointer to a signature to check/normalize (can be identical to sigout) * * With ECDSA a third-party can forge a second distinct signature of the same * message, given a single initial signature, but without knowing the key. This @@ -593,15 +591,15 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ecdsa_verif * accept various non-unique encodings, so care should be taken when this * property is required for an application. * - * The rustsecp256k1_v0_10_0_ecdsa_sign function will by default create signatures in the - * lower-S form, and rustsecp256k1_v0_10_0_ecdsa_verify will not accept others. In case + * The rustsecp256k1_v0_11_ecdsa_sign function will by default create signatures in the + * lower-S form, and rustsecp256k1_v0_11_ecdsa_verify will not accept others. In case * signatures come from a system that cannot enforce this property, - * rustsecp256k1_v0_10_0_ecdsa_signature_normalize must be called before verification. + * rustsecp256k1_v0_11_ecdsa_signature_normalize must be called before verification. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_normalize( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_signature *sigout, - const rustsecp256k1_v0_10_0_ecdsa_signature *sigin +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_normalize( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sigout, + const rustsecp256k1_v0_11_ecdsa_signature *sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); /** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. @@ -609,49 +607,51 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_signature_normalize( * extra entropy. */ -/** A default safe nonce generation function (currently equal to rustsecp256k1_v0_10_0_nonce_function_rfc6979). */ +/** A default safe nonce generation function (currently equal to rustsecp256k1_v0_11_nonce_function_rfc6979). */ /** Create an ECDSA signature. * * Returns: 1: signature created * 0: the nonce generation function failed, or the secret key was invalid. - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: sig: pointer to an array where the signature will be placed. * 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, - * rustsecp256k1_v0_10_0_nonce_function_default is used. + * rustsecp256k1_v0_11_nonce_function_default is used. * ndata: pointer to arbitrary data used by the nonce generation function * (can be NULL). If it is non-NULL and - * rustsecp256k1_v0_10_0_nonce_function_default is used, then ndata must be a + * rustsecp256k1_v0_11_nonce_function_default is used, then ndata must be a * pointer to 32-bytes of additional data. * * The created signature is always in lower-S form. See - * rustsecp256k1_v0_10_0_ecdsa_signature_normalize for more details. + * rustsecp256k1_v0_11_ecdsa_signature_normalize for more details. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_sign( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_signature *sig, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_sign( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *msghash32, const unsigned char *seckey, - rustsecp256k1_v0_10_0_nonce_function noncefp, + rustsecp256k1_v0_11_nonce_function noncefp, 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 * Args: ctx: pointer to a context object. * In: seckey: pointer to a 32-byte secret key. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_seckey_verify( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_verify( + const rustsecp256k1_v0_11_context *ctx, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); @@ -659,38 +659,38 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_seckey_v * * Returns: 1: secret was valid, public key stores. * 0: secret was invalid, try again. - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: pubkey: pointer to the created public key. * In: seckey: pointer to a 32-byte secret key. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_create( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_create( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Negates a secret key in place. * * Returns: 0 if the given secret key is invalid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify. 1 otherwise + * rustsecp256k1_v0_11_ec_seckey_verify. 1 otherwise * Args: ctx: pointer to a context object * In/Out: seckey: pointer to the 32-byte secret key to be negated. If the * secret key is invalid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify, this function returns 0 and + * rustsecp256k1_v0_11_ec_seckey_verify, this function returns 0 and * seckey will be set to some unspecified value. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_seckey_negate( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_negate( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); -/** Same as rustsecp256k1_v0_10_0_ec_seckey_negate, but DEPRECATED. Will be removed in +/** Same as rustsecp256k1_v0_11_ec_seckey_negate, but DEPRECATED. Will be removed in * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_privkey_negate( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_privkey_negate( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) - SECP256K1_DEPRECATED("Use rustsecp256k1_v0_10_0_ec_seckey_negate instead"); + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_ec_seckey_negate instead"); /** Negates a public key in place. * @@ -698,9 +698,9 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_privkey_ * 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 rustsecp256k1_v0_10_0_ec_pubkey_negate( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_negate( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); /** Tweak a secret key by adding tweak to it. @@ -710,28 +710,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_n * otherwise. * Args: ctx: pointer to a context object. * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is - * invalid according to rustsecp256k1_v0_10_0_ec_seckey_verify, this + * invalid according to rustsecp256k1_v0_11_ec_seckey_verify, this * function returns 0. seckey will be set to some unspecified * value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak, which must be valid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify or 32 zero bytes. For uniformly + * rustsecp256k1_v0_11_ec_seckey_verify or 32 zero bytes. For uniformly * random 32-byte tweaks, the chance of being invalid is * negligible (around 1 in 2^128). */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_seckey_tweak_add( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Same as rustsecp256k1_v0_10_0_ec_seckey_tweak_add, but DEPRECATED. Will be removed in +/** Same as rustsecp256k1_v0_11_ec_seckey_tweak_add, but DEPRECATED. Will be removed in * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_privkey_tweak_add( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_privkey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) - SECP256K1_DEPRECATED("Use rustsecp256k1_v0_10_0_ec_seckey_tweak_add instead"); + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_ec_seckey_tweak_add instead"); /** Tweak a public key by adding tweak times the generator to it. * @@ -742,13 +742,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_privkey_ * In/Out: pubkey: pointer to a public key object. pubkey will be set to an * invalid value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak, which must be valid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify or 32 zero bytes. For uniformly + * rustsecp256k1_v0_11_ec_seckey_verify or 32 zero bytes. For uniformly * random 32-byte tweaks, the chance of being invalid is * negligible (around 1 in 2^128). */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_tweak_add( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -757,28 +757,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_t * Returns: 0 if the arguments are invalid. 1 otherwise. * Args: ctx: pointer to a context object. * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is - * invalid according to rustsecp256k1_v0_10_0_ec_seckey_verify, this + * invalid according to rustsecp256k1_v0_11_ec_seckey_verify, this * function returns 0. seckey will be set to some unspecified * value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify, this function returns 0. For + * rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_ec_seckey_tweak_mul( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_tweak_mul( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Same as rustsecp256k1_v0_10_0_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in +/** Same as rustsecp256k1_v0_11_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in * future versions. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_privkey_tweak_mul( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_privkey_tweak_mul( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) - SECP256K1_DEPRECATED("Use rustsecp256k1_v0_10_0_ec_seckey_tweak_mul instead"); + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_ec_seckey_tweak_mul instead"); /** Tweak a public key by multiplying it by a tweak value. * @@ -787,13 +787,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_privkey_ * In/Out: pubkey: pointer to a public key object. pubkey will be set to an * invalid value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify, this function returns 0. For + * rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_tweak_mul( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -801,7 +801,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_t * * Returns: 1: randomization successful * 0: error - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state). * * While secp256k1 code is written and tested to be constant-time no matter what @@ -812,25 +812,25 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_t * certain computations which involve secret keys. * * It is highly recommended to call this function on contexts returned from - * rustsecp256k1_v0_10_0_context_create or rustsecp256k1_v0_10_0_context_clone (or from the corresponding - * functions in rustsecp256k1_v0_10_0_preallocated.h) before using these contexts to call API + * rustsecp256k1_v0_11_context_create or rustsecp256k1_v0_11_context_clone (or from the corresponding + * functions in rustsecp256k1_v0_11_preallocated.h) before using these contexts to call API * functions that perform computations involving secret keys, e.g., signing and * public key generation. It is possible to call this function more than once on * the same context, and doing so before every few computations involving secret * keys is recommended as a defense-in-depth measure. Randomization of the static - * context rustsecp256k1_v0_10_0_context_static is not supported. + * context rustsecp256k1_v0_11_context_static is not supported. * * Currently, the random seed is mainly used for blinding multiplications of a * secret scalar with the elliptic curve base point. Multiplications of this * kind are performed by exactly those API functions which are documented to - * require a context that is not rustsecp256k1_v0_10_0_context_static. As a rule of thumb, + * require a context that is not rustsecp256k1_v0_11_context_static. As a rule of thumb, * these are all functions which take a secret key (or a keypair) as an input. * A notable exception to that rule is the ECDH module, which relies on a different * kind of elliptic curve point multiplication and thus does not benefit from * enhanced protection against side-channel leakage currently. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_context_randomize( - rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_context_randomize( + rustsecp256k1_v0_11_context *ctx, const unsigned char *seed32 ) SECP256K1_ARG_NONNULL(1); @@ -843,10 +843,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_context_ran * In: ins: pointer to array of pointers to public keys. * n: the number of public keys to add together (must be at least 1). */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_combine( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *out, - const rustsecp256k1_v0_10_0_pubkey * const *ins, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_combine( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *out, + const rustsecp256k1_v0_11_pubkey * const *ins, size_t n ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -866,8 +866,8 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ec_pubkey_c * msg: pointer to an array containing the message * msglen: length of the message array */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_tagged_sha256( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_tagged_sha256( + const rustsecp256k1_v0_11_context *ctx, unsigned char *hash32, const unsigned char *tag, size_t taglen, diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1.h.orig b/secp256k1-sys/depend/secp256k1/include/secp256k1.h.orig new file mode 100644 index 000000000..f7f11d6ef --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1.h.orig @@ -0,0 +1,899 @@ +#ifndef SECP256K1_H +#define SECP256K1_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** Unless explicitly stated all pointer arguments must not be NULL. + * + * The following rules specify the order of arguments in API calls: + * + * 1. Context pointers go first, followed by output arguments, combined + * output/input arguments, and finally input-only arguments. + * 2. Array lengths always immediately follow the argument whose length + * they describe, even if this violates rule 1. + * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated + * later go first. This means: signatures, public nonces, secret nonces, + * messages, public keys, secret keys, tweaks. + * 4. Arguments that are not data pointers go last, from more complex to less + * complex: function pointers, algorithm names, messages, void pointers, + * counts, flags, booleans. + * 5. Opaque data pointers follow the function pointer they are to be passed to. + */ + +/** Opaque data structure that holds context information + * + * The primary purpose of context objects is to store randomization data for + * enhanced protection against side-channel leakage. This protection is only + * effective if the context is randomized after its creation. See + * rustsecp256k1_v0_11_context_create for creation of contexts and + * rustsecp256k1_v0_11_context_randomize for randomization. + * + * A secondary purpose of context objects is to store pointers to callback + * functions that the library will call when certain error states arise. See + * rustsecp256k1_v0_11_context_set_error_callback as well as + * rustsecp256k1_v0_11_context_set_illegal_callback for details. Future library versions + * may use context objects for additional purposes. + * + * A constructed context can safely be used from multiple threads + * simultaneously, but API calls that take a non-const pointer to a context + * need exclusive access to it. In particular this is the case for + * rustsecp256k1_v0_11_context_destroy, rustsecp256k1_v0_11_context_preallocated_destroy, + * and rustsecp256k1_v0_11_context_randomize. + * + * Regarding randomization, either do it once at creation time (in which case + * you do not need any locking for the other calls), or use a read-write lock. + */ +typedef struct rustsecp256k1_v0_11_context_struct rustsecp256k1_v0_11_context; + +/** Opaque data structure that holds a parsed and valid public key. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage or transmission, + * use rustsecp256k1_v0_11_ec_pubkey_serialize and rustsecp256k1_v0_11_ec_pubkey_parse. To + * compare keys, use rustsecp256k1_v0_11_ec_pubkey_cmp. + */ +typedef struct rustsecp256k1_v0_11_pubkey { + unsigned char data[64]; +} rustsecp256k1_v0_11_pubkey; + +/** 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 + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use the rustsecp256k1_v0_11_ecdsa_signature_serialize_* and + * rustsecp256k1_v0_11_ecdsa_signature_parse_* functions. + */ +typedef struct rustsecp256k1_v0_11_ecdsa_signature { + unsigned char data[64]; +} rustsecp256k1_v0_11_ecdsa_signature; + +/** A pointer to a function to deterministically generate a nonce. + * + * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. + * Out: nonce32: pointer to a 32-byte array to be filled by the function. + * In: msg32: the 32-byte message hash being verified (will not be NULL) + * key32: pointer to a 32-byte secret key (will not be NULL) + * algo16: pointer to a 16-byte array describing the signature + * algorithm (will be NULL for ECDSA for compatibility). + * data: Arbitrary data pointer that is passed through. + * attempt: how many iterations we have tried to find a nonce. + * This will almost always be 0, but different attempt values + * are required to result in a different nonce. + * + * Except for test cases, this function should compute some cryptographic hash of + * the message, the algorithm, the key and the attempt. + */ +typedef int (*rustsecp256k1_v0_11_nonce_function)( + unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + const unsigned char *algo16, + void *data, + unsigned int attempt +); + +# if !defined(SECP256K1_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define SECP256K1_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +/* When this header is used at build-time the SECP256K1_BUILD define needs to be set + * to correctly setup export attributes and nullness checks. This is normally done + * by secp256k1.c but to guard against this header being included before secp256k1.c + * has had a chance to set the define (e.g. via test harnesses that just includes + * secp256k1.c) we set SECP256K1_NO_BUILD when this header is processed without the + * BUILD define so this condition can be caught. + */ +#ifndef SECP256K1_BUILD +# define SECP256K1_NO_BUILD +#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 +#endif + +/* Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ +# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +# else +# define SECP256K1_WARN_UNUSED_RESULT +# endif +# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +# else +# define SECP256K1_ARG_NONNULL(_x) +# endif + +/* Attribute for marking functions, types, and variables as deprecated */ +#if !defined(SECP256K1_BUILD) && defined(__has_attribute) +# if __has_attribute(__deprecated__) +# define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg))) +# else +# define SECP256K1_DEPRECATED(_msg) +# endif +#else +# define SECP256K1_DEPRECATED(_msg) +#endif + +/* All flags' lower 8 bits indicate what they're for. Do not use directly. */ +#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) +#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) +#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) +/* The higher bits contain the actual data. Do not use directly. */ +#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) +#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) +#define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) +#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) + +/** Context flags to pass to rustsecp256k1_v0_11_context_create, rustsecp256k1_v0_11_context_preallocated_size, and + * rustsecp256k1_v0_11_context_preallocated_create. */ +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */ +#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) +#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) + +/* Testing flag. Do not use. */ +#define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY) + +/** Flag to pass to rustsecp256k1_v0_11_ec_pubkey_serialize. */ +#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) +#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) + +/** Prefix byte used to tag various encoded curvepoints for specific purposes */ +#define SECP256K1_TAG_PUBKEY_EVEN 0x02 +#define SECP256K1_TAG_PUBKEY_ODD 0x03 +#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04 +#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 +#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 + +/** A built-in constant secp256k1 context object with static storage duration, to be + * used in conjunction with rustsecp256k1_v0_11_selftest. + * + * This context object offers *only limited functionality* , i.e., it cannot be used + * for API functions that perform computations involving secret keys, e.g., signing + * and public key generation. If this restriction applies to a specific API function, + * it is mentioned in its documentation. See rustsecp256k1_v0_11_context_create if you need a + * full context object that supports all functionality offered by the library. + * + * It is highly recommended to call rustsecp256k1_v0_11_selftest before using this context. + */ +SECP256K1_API const rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_static; + +/** Deprecated alias for rustsecp256k1_v0_11_context_static. */ +SECP256K1_API const rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_no_precomp +SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_context_static instead"); + +/** Perform basic self tests (to be used in conjunction with rustsecp256k1_v0_11_context_static) + * + * This function performs self tests that detect some serious usage errors and + * similar conditions, e.g., when the library is compiled for the wrong endianness. + * This is a last resort measure to be used in production. The performed tests are + * very rudimentary and are not intended as a replacement for running the test + * binaries. + * + * It is highly recommended to call this before using rustsecp256k1_v0_11_context_static. + * It is not necessary to call this function before using a context created with + * rustsecp256k1_v0_11_context_create (or rustsecp256k1_v0_11_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 + * program (see rustsecp256k1_v0_11_context_set_error_callback). + */ +SECP256K1_API void rustsecp256k1_v0_11_selftest(void); + + +/** Create a secp256k1 context object (in dynamically allocated memory). + * + * This function uses malloc to allocate memory. It is guaranteed that malloc is + * called at most once for every call of this function. If you need to avoid dynamic + * memory allocation entirely, see rustsecp256k1_v0_11_context_static and the functions in + * rustsecp256k1_v0_11_preallocated.h. + * + * Returns: pointer to a newly created context object. + * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). + * + * The only valid non-deprecated flag in recent library versions is + * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality + * offered by the library. All other (deprecated) flags will be treated as equivalent + * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for + * historical reasons, future versions of the library may introduce new flags. + * + * If the context is intended to be used for API functions that perform computations + * involving secret keys, e.g., signing and public key generation, then it is highly + * recommended to call rustsecp256k1_v0_11_context_randomize on the context before calling + * those API functions. This will provide enhanced protection against side-channel + * leakage, see rustsecp256k1_v0_11_context_randomize for details. + * + * Do not create a new context object for each operation, as construction and + * randomization can take non-negligible time. + */ +SECP256K1_API rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_create( + unsigned int flags +) SECP256K1_WARN_UNUSED_RESULT; + +/** Copy a secp256k1 context object (into dynamically allocated memory). + * + * This function uses malloc to allocate memory. It is guaranteed that malloc is + * called at most once for every call of this function. If you need to avoid dynamic + * memory allocation entirely, see the functions in rustsecp256k1_v0_11_preallocated.h. + * + * Cloning rustsecp256k1_v0_11_context_static is not possible, and should not be emulated by + * the caller (e.g., using memcpy). Create a new context instead. + * + * Returns: pointer to a newly created context object. + * Args: ctx: pointer to a context to copy (not rustsecp256k1_v0_11_context_static). + */ +SECP256K1_API rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_clone( + const rustsecp256k1_v0_11_context *ctx +) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; + +/** Destroy a secp256k1 context object (created in dynamically allocated memory). + * + * The context pointer may not be used afterwards. + * + * The context to destroy must have been created using rustsecp256k1_v0_11_context_create + * or rustsecp256k1_v0_11_context_clone. If the context has instead been created using + * rustsecp256k1_v0_11_context_preallocated_create or rustsecp256k1_v0_11_context_preallocated_clone, the + * behaviour is undefined. In that case, rustsecp256k1_v0_11_context_preallocated_destroy must + * be used instead. + * + * Args: ctx: pointer to a context to destroy, constructed using + * rustsecp256k1_v0_11_context_create or rustsecp256k1_v0_11_context_clone + * (i.e., not rustsecp256k1_v0_11_context_static). + */ +SECP256K1_API void rustsecp256k1_v0_11_context_destroy( + rustsecp256k1_v0_11_context *ctx +) SECP256K1_ARG_NONNULL(1); + +/** Set a callback function to be called when an illegal argument is passed to + * 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. + * + * 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. + * + * 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 + * 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 rustsecp256k1_v0_11_default_illegal_callback_fn(const char *message, void *data); + * - void rustsecp256k1_v0_11_default_error_callback_fn(const char *message, void *data); + * The library can call these default handlers even before a proper callback data + * pointer could have been set using rustsecp256k1_v0_11_context_set_illegal_callback or + * rustsecp256k1_v0_11_context_set_error_callback, e.g., when the creation of a context + * fails. In this case, the corresponding default handler 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. + * + * See also rustsecp256k1_v0_11_context_set_error_callback. + */ +SECP256K1_API void rustsecp256k1_v0_11_context_set_illegal_callback( + rustsecp256k1_v0_11_context *ctx, + void (*fun)(const char *message, void *data), + const void *data +) SECP256K1_ARG_NONNULL(1); + +/** Set a callback function to be called when an internal consistency check + * fails. + * + * The default callback writes an error message to stderr and calls abort + * 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 + * incorrect usage of the API (see rustsecp256k1_v0_11_context_set_illegal_callback + * for that). After this callback returns, anything may happen, including + * crashing. + * + * 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 rustsecp256k1_v0_11_context_set_illegal_callback + * for details). + * data: the opaque pointer to pass to fun above, must be NULL for the default handler. + * + * See also rustsecp256k1_v0_11_context_set_illegal_callback. + */ +SECP256K1_API void rustsecp256k1_v0_11_context_set_error_callback( + rustsecp256k1_v0_11_context *ctx, + void (*fun)(const char *message, void *data), + const void *data +) SECP256K1_ARG_NONNULL(1); + +/** Parse a variable-length public key into the pubkey object. + * + * Returns: 1 if the public key was fully valid. + * 0 if the public key could not be parsed or is invalid. + * Args: ctx: pointer to a context object. + * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a + * parsed version of input. If not, its value is undefined. + * In: input: pointer to a serialized public key + * inputlen: length of the array pointed to by input + * + * This function supports parsing compressed (33 bytes, header byte 0x02 or + * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header + * byte 0x06 or 0x07) format public keys. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_parse( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a pubkey object into a serialized byte sequence. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object. + * Out: output: pointer to a 65-byte (if compressed==0) or 33-byte (if + * compressed==1) byte array to place the serialized key + * in. + * In/Out: outputlen: pointer to an integer which is initially set to the + * size of output, and is overwritten with the written + * size. + * In: pubkey: pointer to a rustsecp256k1_v0_11_pubkey containing an + * initialized public key. + * flags: SECP256K1_EC_COMPRESSED if serialization should be in + * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. + */ +SECP256K1_API int rustsecp256k1_v0_11_ec_pubkey_serialize( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *output, + size_t *outputlen, + const rustsecp256k1_v0_11_pubkey *pubkey, + unsigned int flags +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Compare two public keys using lexicographic (of compressed serialization) order + * + * Returns: <0 if the first public key is less than the second + * >0 if the first public key is greater than the second + * 0 if the two public keys are equal + * Args: ctx: pointer to a context object + * In: pubkey1: first public key to compare + * pubkey2: second public key to compare + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_cmp( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_pubkey *pubkey1, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_ec_pubkey_sort( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_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. + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input64: pointer to the 64-byte array to parse + * + * The signature must consist of a 32-byte big endian R value, followed by a + * 32-byte big endian S value. If R or S fall outside of [0..order-1], the + * encoding is invalid. R and S with value 0 are allowed in the encoding. + * + * After the call, sig will always be initialized. If parsing failed or R or + * S are zero, the resulting sig value is guaranteed to fail verification for + * any message and public key. + */ +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_parse_compact( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, + const unsigned char *input64 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a DER ECDSA 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: input: pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * + * This function will accept any valid DER encoded signature, even if the + * encoded numbers are out of range. + * + * 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 rustsecp256k1_v0_11_ecdsa_signature_parse_der( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in DER format. + * + * Returns: 1 if enough space was available to serialize, 0 otherwise + * Args: ctx: pointer to a context object + * Out: output: pointer to an array to store the DER serialization + * In/Out: outputlen: pointer to a length integer. Initially, this integer + * should be set to the length of output. After the call + * it will be set to the length of the serialization (even + * if 0 was returned). + * In: sig: pointer to an initialized signature object + */ +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_serialize_der( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *output, + size_t *outputlen, + const rustsecp256k1_v0_11_ecdsa_signature *sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Serialize an ECDSA signature in compact (64 byte) format. + * + * Returns: 1 + * Args: ctx: pointer to a context object + * Out: output64: pointer to a 64-byte array to store the compact serialization + * In: sig: pointer to an initialized signature object + * + * See rustsecp256k1_v0_11_ecdsa_signature_parse_compact for details about the encoding. + */ +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_serialize_compact( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *output64, + const rustsecp256k1_v0_11_ecdsa_signature *sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Verify an ECDSA signature. + * + * Returns: 1: correct signature + * 0: incorrect or unparseable signature + * Args: ctx: pointer to a context object + * In: sig: the signature being verified. + * msghash32: the 32-byte message hash being verified. + * The verifier must make sure to apply a cryptographic + * hash function to the message by itself and not accept an + * msghash32 value directly. Otherwise, it would be easy to + * create a "valid" signature without knowledge of the + * secret key. See also + * https://bitcoin.stackexchange.com/a/81116/35586 for more + * background on this topic. + * pubkey: pointer to an initialized public key to verify with. + * + * To avoid accepting malleable signatures, only ECDSA signatures in lower-S + * form are accepted. + * + * If you need to accept ECDSA signatures from sources that do not obey this + * rule, apply rustsecp256k1_v0_11_ecdsa_signature_normalize to the signature prior to + * verification, but be aware that doing so results in malleable signatures. + * + * For details, see the comments for that function. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ecdsa_verify( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_ecdsa_signature *sig, + const unsigned char *msghash32, + const rustsecp256k1_v0_11_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Convert a signature to a normalized lower-S form. + * + * Returns: 1 if sigin was not normalized, 0 if it already was. + * Args: ctx: pointer to a context object + * Out: sigout: pointer to a signature to fill with the normalized form, + * or copy if the input was already normalized. (can be NULL if + * you're only interested in whether the input was already + * normalized). + * In: sigin: pointer to a signature to check/normalize (can be identical to sigout) + * + * With ECDSA a third-party can forge a second distinct signature of the same + * message, given a single initial signature, but without knowing the key. This + * is done by negating the S value modulo the order of the curve, 'flipping' + * the sign of the random point R which is not included in the signature. + * + * Forgery of the same message isn't universally problematic, but in systems + * where message malleability or uniqueness of signatures is important this can + * cause issues. This forgery can be blocked by all verifiers forcing signers + * to use a normalized form. + * + * The lower-S form reduces the size of signatures slightly on average when + * variable length encodings (such as DER) are used and is cheap to verify, + * making it a good choice. Security of always using lower-S is assured because + * anyone can trivially modify a signature after the fact to enforce this + * property anyway. + * + * The lower S value is always between 0x1 and + * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, + * inclusive. + * + * No other forms of ECDSA malleability are known and none seem likely, but + * there is no formal proof that ECDSA, even with this additional restriction, + * is free of other malleability. Commonly used serialization schemes will also + * accept various non-unique encodings, so care should be taken when this + * property is required for an application. + * + * The rustsecp256k1_v0_11_ecdsa_sign function will by default create signatures in the + * lower-S form, and rustsecp256k1_v0_11_ecdsa_verify will not accept others. In case + * signatures come from a system that cannot enforce this property, + * rustsecp256k1_v0_11_ecdsa_signature_normalize must be called before verification. + */ +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_signature_normalize( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sigout, + const rustsecp256k1_v0_11_ecdsa_signature *sigin +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); + +/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. + * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of + * extra entropy. + */ +SECP256K1_API const rustsecp256k1_v0_11_nonce_function rustsecp256k1_v0_11_nonce_function_rfc6979; + +/** A default safe nonce generation function (currently equal to rustsecp256k1_v0_11_nonce_function_rfc6979). */ +SECP256K1_API const rustsecp256k1_v0_11_nonce_function rustsecp256k1_v0_11_nonce_function_default; + +/** Create an ECDSA signature. + * + * Returns: 1: signature created + * 0: the nonce generation function failed, or the secret key was invalid. + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). + * Out: sig: pointer to an array where the signature will be placed. + * 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, + * rustsecp256k1_v0_11_nonce_function_default is used. + * ndata: pointer to arbitrary data used by the nonce generation function + * (can be NULL). If it is non-NULL and + * rustsecp256k1_v0_11_nonce_function_default is used, then ndata must be a + * pointer to 32-bytes of additional data. + * + * The created signature is always in lower-S form. See + * rustsecp256k1_v0_11_ecdsa_signature_normalize for more details. + */ +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_sign( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, + const unsigned char *msghash32, + const unsigned char *seckey, + rustsecp256k1_v0_11_nonce_function noncefp, + const void *ndata +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** 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. 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 + * Args: ctx: pointer to a context object. + * In: seckey: pointer to a 32-byte secret key. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_verify( + const rustsecp256k1_v0_11_context *ctx, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Compute the public key for a secret key. + * + * Returns: 1: secret was valid, public key stores. + * 0: secret was invalid, try again. + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). + * Out: pubkey: pointer to the created public key. + * In: seckey: pointer to a 32-byte secret key. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_create( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Negates a secret key in place. + * + * Returns: 0 if the given secret key is invalid according to + * rustsecp256k1_v0_11_ec_seckey_verify. 1 otherwise + * Args: ctx: pointer to a context object + * In/Out: seckey: pointer to the 32-byte secret key to be negated. If the + * secret key is invalid according to + * rustsecp256k1_v0_11_ec_seckey_verify, this function returns 0 and + * seckey will be set to some unspecified value. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_negate( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Same as rustsecp256k1_v0_11_ec_seckey_negate, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_privkey_negate( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_ec_seckey_negate instead"); + +/** Negates a public key in place. + * + * Returns: 1 always + * 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 rustsecp256k1_v0_11_ec_pubkey_negate( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Tweak a secret key by adding tweak to it. + * + * Returns: 0 if the arguments are invalid or the resulting secret key would be + * invalid (only when the tweak is the negation of the secret key). 1 + * otherwise. + * Args: ctx: pointer to a context object. + * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is + * invalid according to rustsecp256k1_v0_11_ec_seckey_verify, this + * function returns 0. seckey will be set to some unspecified + * value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak, which must be valid according to + * rustsecp256k1_v0_11_ec_seckey_verify or 32 zero bytes. For uniformly + * random 32-byte tweaks, the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_seckey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Same as rustsecp256k1_v0_11_ec_seckey_tweak_add, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_privkey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_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 + * invalid (only when the tweak is the negation of the corresponding + * secret key). 1 otherwise. + * Args: ctx: pointer to a context object. + * In/Out: pubkey: pointer to a public key object. pubkey will be set to an + * invalid value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak, which must be valid according to + * rustsecp256k1_v0_11_ec_seckey_verify or 32 zero bytes. For uniformly + * random 32-byte tweaks, the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a secret key by multiplying it by a tweak. + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * Args: ctx: pointer to a context object. + * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is + * invalid according to rustsecp256k1_v0_11_ec_seckey_verify, this + * function returns 0. seckey will be set to some unspecified + * value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to + * rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_ec_seckey_tweak_mul( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Same as rustsecp256k1_v0_11_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_privkey_tweak_mul( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_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. + * Args: ctx: pointer to a context object. + * In/Out: pubkey: pointer to a public key object. pubkey will be set to an + * invalid value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to + * rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_ec_pubkey_tweak_mul( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Randomizes the context to provide enhanced protection against side-channel leakage. + * + * Returns: 1: randomization successful + * 0: error + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). + * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state). + * + * While secp256k1 code is written and tested to be constant-time no matter what + * secret values are, it is possible that a compiler may output code which is not, + * and also that the CPU may not emit the same radio frequencies or draw the same + * amount of power for all values. Randomization of the context shields against + * side-channel observations which aim to exploit secret-dependent behaviour in + * certain computations which involve secret keys. + * + * It is highly recommended to call this function on contexts returned from + * rustsecp256k1_v0_11_context_create or rustsecp256k1_v0_11_context_clone (or from the corresponding + * functions in rustsecp256k1_v0_11_preallocated.h) before using these contexts to call API + * functions that perform computations involving secret keys, e.g., signing and + * public key generation. It is possible to call this function more than once on + * the same context, and doing so before every few computations involving secret + * keys is recommended as a defense-in-depth measure. Randomization of the static + * context rustsecp256k1_v0_11_context_static is not supported. + * + * Currently, the random seed is mainly used for blinding multiplications of a + * secret scalar with the elliptic curve base point. Multiplications of this + * kind are performed by exactly those API functions which are documented to + * require a context that is not rustsecp256k1_v0_11_context_static. As a rule of thumb, + * these are all functions which take a secret key (or a keypair) as an input. + * A notable exception to that rule is the ECDH module, which relies on a different + * kind of elliptic curve point multiplication and thus does not benefit from + * enhanced protection against side-channel leakage currently. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_context_randomize( + rustsecp256k1_v0_11_context *ctx, + const unsigned char *seed32 +) SECP256K1_ARG_NONNULL(1); + +/** Add a number of public keys together. + * + * Returns: 1: the sum of the public keys is valid. + * 0: the sum of the public keys is not valid. + * Args: ctx: pointer to a context object. + * Out: out: pointer to a public key object for placing the resulting public key. + * In: ins: pointer to array of pointers to public keys. + * n: the number of public keys to add together (must be at least 1). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ec_pubkey_combine( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *out, + const rustsecp256k1_v0_11_pubkey * const *ins, + size_t n +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Compute a tagged hash as defined in BIP-340. + * + * This is useful for creating a message hash and achieving domain separation + * through an application-specific tag. This function returns + * SHA256(SHA256(tag)||SHA256(tag)||msg). Therefore, tagged hash + * implementations optimized for a specific tag can precompute the SHA256 state + * after hashing the tag hashes. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object + * Out: hash32: pointer to a 32-byte array to store the resulting hash + * In: tag: pointer to an array containing the tag + * taglen: length of the tag array + * msg: pointer to an array containing the message + * msglen: length of the message array + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_tagged_sha256( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *hash32, + const unsigned char *tag, + size_t taglen, + const unsigned char *msg, + size_t msglen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_H */ diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h index 99a53cf56..edf23a549 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_ecdh.h @@ -10,15 +10,15 @@ extern "C" { /** A pointer to a function that hashes an EC point to obtain an ECDH secret * * Returns: 1 if the point was successfully hashed. - * 0 will cause rustsecp256k1_v0_10_0_ecdh to fail and return 0. + * 0 will cause rustsecp256k1_v0_11_ecdh to fail and return 0. * Other return values are not allowed, and the behaviour of - * rustsecp256k1_v0_10_0_ecdh is undefined for other return values. + * rustsecp256k1_v0_11_ecdh is undefined for other return values. * Out: output: pointer to an array to be filled by the function * In: x32: pointer to a 32-byte x coordinate * y32: pointer to a 32-byte y coordinate * data: arbitrary data pointer that is passed through */ -typedef int (*rustsecp256k1_v0_10_0_ecdh_hash_function)( +typedef int (*rustsecp256k1_v0_11_ecdh_hash_function)( unsigned char *output, const unsigned char *x32, const unsigned char *y32, @@ -27,11 +27,11 @@ typedef int (*rustsecp256k1_v0_10_0_ecdh_hash_function)( /** An implementation of SHA256 hash function that applies to compressed public key. * Populates the output parameter with 32 bytes. */ -SECP256K1_API const rustsecp256k1_v0_10_0_ecdh_hash_function rustsecp256k1_v0_10_0_ecdh_hash_function_sha256; +SECP256K1_API const rustsecp256k1_v0_11_ecdh_hash_function rustsecp256k1_v0_11_ecdh_hash_function_sha256; -/** A default ECDH hash function (currently equal to rustsecp256k1_v0_10_0_ecdh_hash_function_sha256). +/** A default ECDH hash function (currently equal to rustsecp256k1_v0_11_ecdh_hash_function_sha256). * Populates the output parameter with 32 bytes. */ -SECP256K1_API const rustsecp256k1_v0_10_0_ecdh_hash_function rustsecp256k1_v0_10_0_ecdh_hash_function_default; +SECP256K1_API const rustsecp256k1_v0_11_ecdh_hash_function rustsecp256k1_v0_11_ecdh_hash_function_default; /** Compute an EC Diffie-Hellman secret in constant time * @@ -39,20 +39,20 @@ SECP256K1_API const rustsecp256k1_v0_10_0_ecdh_hash_function rustsecp256k1_v0_10 * 0: scalar was invalid (zero or overflow) or hashfp returned 0 * Args: ctx: pointer to a context object. * Out: output: pointer to an array to be filled by hashfp. - * In: pubkey: a pointer to a rustsecp256k1_v0_10_0_pubkey containing an initialized public key. + * In: pubkey: pointer to a rustsecp256k1_v0_11_pubkey containing an initialized public key. * seckey: a 32-byte scalar with which to multiply the point. * hashfp: pointer to a hash function. If NULL, - * rustsecp256k1_v0_10_0_ecdh_hash_function_sha256 is used + * rustsecp256k1_v0_11_ecdh_hash_function_sha256 is used * (in which case, 32 bytes will be written to output). * data: arbitrary data pointer that is passed through to hashfp - * (can be NULL for rustsecp256k1_v0_10_0_ecdh_hash_function_sha256). + * (can be NULL for rustsecp256k1_v0_11_ecdh_hash_function_sha256). */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ecdh( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ecdh( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output, - const rustsecp256k1_v0_10_0_pubkey *pubkey, + const rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *seckey, - rustsecp256k1_v0_10_0_ecdh_hash_function hashfp, + rustsecp256k1_v0_11_ecdh_hash_function hashfp, void *data ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_ellswift.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_ellswift.h index 5d4b9ac7b..e7b9d4c40 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_ellswift.h +++ b/secp256k1-sys/depend/secp256k1/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 @@ -45,13 +45,13 @@ extern "C" { * For mathematical background about the scheme, see the doc/ellswift.md file. */ -/** A pointer to a function used by rustsecp256k1_v0_10_0_ellswift_xdh to hash the shared X +/** A pointer to a function used by rustsecp256k1_v0_11_ellswift_xdh to hash the shared X * coordinate along with the encoded public keys to a uniform shared secret. * * Returns: 1 if a shared secret was successfully computed. - * 0 will cause rustsecp256k1_v0_10_0_ellswift_xdh to fail and return 0. + * 0 will cause rustsecp256k1_v0_11_ellswift_xdh to fail and return 0. * Other return values are not allowed, and the behaviour of - * rustsecp256k1_v0_10_0_ellswift_xdh is undefined for other return values. + * rustsecp256k1_v0_11_ellswift_xdh is undefined for other return values. * Out: output: pointer to an array to be filled by the function * In: x32: pointer to the 32-byte serialized X coordinate * of the resulting shared point (will not be NULL) @@ -61,7 +61,7 @@ extern "C" { * (will not be NULL) * data: arbitrary data pointer that is passed through */ -typedef int (*rustsecp256k1_v0_10_0_ellswift_xdh_hash_function)( +typedef int (*rustsecp256k1_v0_11_ellswift_xdh_hash_function)( unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, @@ -69,25 +69,25 @@ typedef int (*rustsecp256k1_v0_10_0_ellswift_xdh_hash_function)( void *data ); -/** An implementation of an rustsecp256k1_v0_10_0_ellswift_xdh_hash_function which uses +/** An implementation of an rustsecp256k1_v0_11_ellswift_xdh_hash_function which uses * SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte * array pointed to by data. */ -SECP256K1_API const rustsecp256k1_v0_10_0_ellswift_xdh_hash_function rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_prefix; +SECP256K1_API const rustsecp256k1_v0_11_ellswift_xdh_hash_function rustsecp256k1_v0_11_ellswift_xdh_hash_function_prefix; -/** An implementation of an rustsecp256k1_v0_10_0_ellswift_xdh_hash_function compatible with +/** An implementation of an rustsecp256k1_v0_11_ellswift_xdh_hash_function compatible with * BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the * BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent - * to rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_prefix with prefix64 set to + * to rustsecp256k1_v0_11_ellswift_xdh_hash_function_prefix with prefix64 set to * SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh"). * The data argument is ignored. */ -SECP256K1_API const rustsecp256k1_v0_10_0_ellswift_xdh_hash_function rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324; +SECP256K1_API const rustsecp256k1_v0_11_ellswift_xdh_hash_function rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324; /** Construct a 64-byte ElligatorSwift encoding of a given pubkey. * * Returns: 1 always. * Args: ctx: pointer to a context object * Out: ell64: pointer to a 64-byte array to be filled - * In: pubkey: a pointer to a rustsecp256k1_v0_10_0_pubkey containing an + * In: pubkey: pointer to a rustsecp256k1_v0_11_pubkey containing an * initialized public key * rnd32: pointer to 32 bytes of randomness * @@ -104,10 +104,10 @@ SECP256K1_API const rustsecp256k1_v0_10_0_ellswift_xdh_hash_function rustsecp256 * * This function runs in variable time. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ellswift_encode( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_ellswift_encode( + const rustsecp256k1_v0_11_context *ctx, unsigned char *ell64, - const rustsecp256k1_v0_10_0_pubkey *pubkey, + const rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *rnd32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -115,14 +115,14 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ellswift_encode( * * Returns: always 1 * Args: ctx: pointer to a context object - * Out: pubkey: pointer to a rustsecp256k1_v0_10_0_pubkey that will be filled + * Out: pubkey: pointer to a rustsecp256k1_v0_11_pubkey that will be filled * In: ell64: pointer to a 64-byte array to decode * * This function runs in variable time. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ellswift_decode( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, +SECP256K1_API int rustsecp256k1_v0_11_ellswift_decode( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *ell64 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -141,18 +141,18 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ellswift_decode( * It is recommended that auxrnd32 contains 32 uniformly random bytes, though * it is optional (and does result in encodings that are indistinguishable from * uniform even without any auxrnd32). It differs from the (mandatory) rnd32 - * argument to rustsecp256k1_v0_10_0_ellswift_encode in this regard. + * argument to rustsecp256k1_v0_11_ellswift_encode in this regard. * - * This function can be used instead of calling rustsecp256k1_v0_10_0_ec_pubkey_create - * followed by rustsecp256k1_v0_10_0_ellswift_encode. It is safer, as it uses the secret + * This function can be used instead of calling rustsecp256k1_v0_11_ec_pubkey_create + * followed by rustsecp256k1_v0_11_ellswift_encode. It is safer, as it uses the secret * key as entropy for the encoding (supplemented with auxrnd32, if provided). * - * Like rustsecp256k1_v0_10_0_ellswift_encode, this function does not guarantee that the + * Like rustsecp256k1_v0_11_ellswift_encode, this function does not guarantee that the * computed encoding is stable across versions of the library, even if all * arguments (including auxrnd32) are the same. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ellswift_create( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ellswift_create( + const rustsecp256k1_v0_11_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32 @@ -169,7 +169,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ellswift_cr * (will not be NULL) * ell_b64: pointer to the 64-byte encoded public key of party B * (will not be NULL) - * seckey32: a pointer to our 32-byte secret key + * seckey32: pointer to our 32-byte secret key * party: boolean indicating which party we are: zero if we are * party A, non-zero if we are party B. seckey32 must be * the private key corresponding to that party's ell_?64. @@ -182,14 +182,14 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ellswift_cr * This function is more efficient than decoding the public keys, and performing * ECDH on them. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ellswift_xdh( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ellswift_xdh( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, - rustsecp256k1_v0_10_0_ellswift_xdh_hash_function hashfp, + rustsecp256k1_v0_11_ellswift_xdh_hash_function hashfp, void *data ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7); diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h index 033fbb6f6..ddcf821a2 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_extrakeys.h @@ -16,12 +16,12 @@ extern "C" { * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 64 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage, transmission, use - * use rustsecp256k1_v0_10_0_xonly_pubkey_serialize and rustsecp256k1_v0_10_0_xonly_pubkey_parse. To - * compare keys, use rustsecp256k1_v0_10_0_xonly_pubkey_cmp. + * use rustsecp256k1_v0_11_xonly_pubkey_serialize and rustsecp256k1_v0_11_xonly_pubkey_parse. To + * compare keys, use rustsecp256k1_v0_11_xonly_pubkey_cmp. */ -typedef struct { +typedef struct rustsecp256k1_v0_11_xonly_pubkey { unsigned char data[64]; -} rustsecp256k1_v0_10_0_xonly_pubkey; +} rustsecp256k1_v0_11_xonly_pubkey; /** Opaque data structure that holds a keypair consisting of a secret and a * public key. @@ -30,23 +30,23 @@ 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 rustsecp256k1_v0_11_keypair { unsigned char data[96]; -} rustsecp256k1_v0_10_0_keypair; +} rustsecp256k1_v0_11_keypair; /** Parse a 32-byte sequence into a xonly_pubkey object. * * Returns: 1 if the public key was fully valid. * 0 if the public key could not be parsed or is invalid. * - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object. * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a * parsed version of input. If not, it's set to an invalid value. * In: input32: pointer to a serialized xonly_pubkey. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubkey_parse( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_xonly_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_xonly_pubkey_parse( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_xonly_pubkey *pubkey, const unsigned char *input32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -54,14 +54,14 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubke * * Returns: 1 always. * - * Args: ctx: a secp256k1 context object. - * Out: output32: a pointer to a 32-byte array to place the serialized key in. - * In: pubkey: a pointer to a rustsecp256k1_v0_10_0_xonly_pubkey containing an initialized public key. + * Args: ctx: pointer to a context object. + * Out: output32: pointer to a 32-byte array to place the serialized key in. + * In: pubkey: pointer to a rustsecp256k1_v0_11_xonly_pubkey containing an initialized public key. */ -SECP256K1_API int rustsecp256k1_v0_10_0_xonly_pubkey_serialize( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_xonly_pubkey_serialize( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output32, - const rustsecp256k1_v0_10_0_xonly_pubkey *pubkey + const rustsecp256k1_v0_11_xonly_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Compare two x-only public keys using lexicographic order @@ -69,17 +69,17 @@ SECP256K1_API int rustsecp256k1_v0_10_0_xonly_pubkey_serialize( * Returns: <0 if the first public key is less than the second * >0 if the first public key is greater than the second * 0 if the two public keys are equal - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object. * In: pubkey1: first public key to compare * pubkey2: second public key to compare */ -SECP256K1_API int rustsecp256k1_v0_10_0_xonly_pubkey_cmp( - const rustsecp256k1_v0_10_0_context *ctx, - const rustsecp256k1_v0_10_0_xonly_pubkey *pk1, - const rustsecp256k1_v0_10_0_xonly_pubkey *pk2 +SECP256K1_API int rustsecp256k1_v0_11_xonly_pubkey_cmp( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_xonly_pubkey *pk1, + const rustsecp256k1_v0_11_xonly_pubkey *pk2 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Converts a rustsecp256k1_v0_10_0_pubkey into a rustsecp256k1_v0_10_0_xonly_pubkey. +/** Converts a rustsecp256k1_v0_11_pubkey into a rustsecp256k1_v0_11_xonly_pubkey. * * Returns: 1 always. * @@ -90,11 +90,11 @@ SECP256K1_API int rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_xonly_pubkey *xonly_pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_xonly_pubkey_from_pubkey( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_xonly_pubkey *xonly_pubkey, int *pk_parity, - const rustsecp256k1_v0_10_0_pubkey *pubkey + const rustsecp256k1_v0_11_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); /** Tweak an x-only public key by adding the generator multiplied with tweak32 @@ -102,7 +102,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubke * * Note that the resulting point can not in general be represented by an x-only * pubkey because it may have an odd Y coordinate. Instead, the output_pubkey - * is a normal rustsecp256k1_v0_10_0_pubkey. + * is a normal rustsecp256k1_v0_11_pubkey. * * 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 @@ -113,23 +113,23 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubke * to an invalid value if this function returns 0. * In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to. * tweak32: pointer to a 32-byte tweak, which must be valid - * according to rustsecp256k1_v0_10_0_ec_seckey_verify or 32 zero + * according to rustsecp256k1_v0_11_ec_seckey_verify or 32 zero * bytes. For uniformly random 32-byte tweaks, the chance of * being invalid is negligible (around 1 in 2^128). */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *output_pubkey, - const rustsecp256k1_v0_10_0_xonly_pubkey *internal_pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_xonly_pubkey_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *output_pubkey, + const rustsecp256k1_v0_11_xonly_pubkey *internal_pubkey, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Checks that a tweaked pubkey is the result of calling - * rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add with internal_pubkey and tweak32. + * rustsecp256k1_v0_11_xonly_pubkey_tweak_add with internal_pubkey and tweak32. * * The tweaked pubkey is represented by its 32-byte x-only serialization and * its pk_parity, which can both be obtained by converting the result of - * tweak_add to a rustsecp256k1_v0_10_0_xonly_pubkey. + * tweak_add to a rustsecp256k1_v0_11_xonly_pubkey. * * Note that this alone does _not_ verify that the tweaked pubkey is a * commitment. If the tweak is not chosen in a specific way, the tweaked pubkey @@ -142,30 +142,33 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubke * tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization * is passed in as tweaked_pubkey32). This must match the * pk_parity value that is returned when calling - * rustsecp256k1_v0_10_0_xonly_pubkey with the tweaked pubkey, or + * rustsecp256k1_v0_11_xonly_pubkey with the tweaked pubkey, or * this function will fail. * internal_pubkey: pointer to an x-only public key object to apply the tweak to. * tweak32: pointer to a 32-byte tweak. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check( + const rustsecp256k1_v0_11_context *ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, - const rustsecp256k1_v0_10_0_xonly_pubkey *internal_pubkey, + const rustsecp256k1_v0_11_xonly_pubkey *internal_pubkey, 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. + * + * See the documentation of `rustsecp256k1_v0_11_ec_seckey_verify` for more information + * about the validity of secret keys. * - * Returns: 1: secret was valid, keypair is ready to use - * 0: secret was invalid, try again with a different secret - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Returns: 1: secret key is valid + * 0: secret key is invalid + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: keypair: pointer to the created keypair. * In: seckey: pointer to a 32-byte secret key. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_keypair_create( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_keypair *keypair, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_keypair_create( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_keypair *keypair, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -176,10 +179,10 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_keypair_cre * 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 rustsecp256k1_v0_10_0_keypair_sec( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_keypair_sec( + const rustsecp256k1_v0_11_context *ctx, unsigned char *seckey, - const rustsecp256k1_v0_10_0_keypair *keypair + const rustsecp256k1_v0_11_keypair *keypair ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Get the public key from a keypair. @@ -189,38 +192,38 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_keypair_pub( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, - const rustsecp256k1_v0_10_0_keypair *keypair +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_keypair_pub( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, + const rustsecp256k1_v0_11_keypair *keypair ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Get the x-only public key from a keypair. * - * This is the same as calling rustsecp256k1_v0_10_0_keypair_pub and then - * rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey. + * This is the same as calling rustsecp256k1_v0_11_keypair_pub and then + * rustsecp256k1_v0_11_xonly_pubkey_from_pubkey. * * Returns: 1 always. * Args: ctx: pointer to a context object. * Out: pubkey: pointer to an xonly_pubkey object, set to the keypair * public key after converting it to an xonly_pubkey. * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the - * pk_parity argument of rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey. + * pk_parity argument of rustsecp256k1_v0_11_xonly_pubkey_from_pubkey. * In: keypair: pointer to a keypair. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_keypair_xonly_pub( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_xonly_pubkey *pubkey, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_keypair_xonly_pub( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_xonly_pubkey *pubkey, int *pk_parity, - const rustsecp256k1_v0_10_0_keypair *keypair + const rustsecp256k1_v0_11_keypair *keypair ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); /** Tweak a keypair by adding tweak32 to the secret key and updating the public * key accordingly. * - * Calling this function and then rustsecp256k1_v0_10_0_keypair_pub results in the same - * public key as calling rustsecp256k1_v0_10_0_keypair_xonly_pub and then - * rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add. + * Calling this function and then rustsecp256k1_v0_11_keypair_pub results in the same + * public key as calling rustsecp256k1_v0_11_keypair_xonly_pub and then + * rustsecp256k1_v0_11_xonly_pubkey_tweak_add. * * Returns: 0 if the arguments are invalid or the resulting keypair would be * invalid (only when the tweak is the negation of the keypair's @@ -230,13 +233,13 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_keypair_xon * In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to * an invalid value if this function returns 0. * In: tweak32: pointer to a 32-byte tweak, which must be valid according to - * rustsecp256k1_v0_10_0_ec_seckey_verify or 32 zero bytes. For uniformly + * rustsecp256k1_v0_11_ec_seckey_verify or 32 zero bytes. For uniformly * random 32-byte tweaks, the chance of being invalid is * negligible (around 1 in 2^128). */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_keypair_xonly_tweak_add( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_keypair *keypair, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_keypair_xonly_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_keypair *keypair, const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_musig.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_musig.h new file mode 100644 index 000000000..ec1e49bde --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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 `rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_keyagg_cache { + unsigned char data[197]; +} rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_secnonce { + unsigned char data[132]; +} rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubnonce { + unsigned char data[132]; +} rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_aggnonce { + unsigned char data[132]; +} rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_session { + unsigned char data[133]; +} rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_partial_sig { + unsigned char data[36]; +} rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubnonce_parse( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubnonce_serialize( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *out66, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_aggnonce_parse( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_aggnonce_serialize( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *out66, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_partial_sig_parse( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_partial_sig_serialize( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *out32, + const rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubkey_agg( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_xonly_pubkey *agg_pk, + rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubkey_get( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *agg_pk, + const rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_ec_pubkey_tweak_add`. So after + * the following pseudocode buf and buf2 have identical contents (absent + * earlier failures). + * + * rustsecp256k1_v0_11_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...) + * rustsecp256k1_v0_11_musig_pubkey_get(..., agg_pk, keyagg_cache) + * rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache) + * rustsecp256k1_v0_11_ec_pubkey_serialize(..., buf, ..., output_pk, ...) + * rustsecp256k1_v0_11_ec_pubkey_tweak_add(..., agg_pk, tweak32) + * rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 + * `rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *output_pubkey, + rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_xonly_pubkey_tweak_add`. So in + * the following pseudocode xonly_pubkey_tweak_add_check (absent earlier + * failures) returns 1. + * + * rustsecp256k1_v0_11_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...) + * rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add(..., output_pk, keyagg_cache, tweak32) + * rustsecp256k1_v0_11_xonly_pubkey_serialize(..., buf, output_pk) + * rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 + * `rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *output_pubkey, + rustsecp256k1_v0_11_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 + * rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_nonce_gen( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_musig_secnonce *secnonce, + rustsecp256k1_v0_11_musig_pubnonce *pubnonce, + unsigned char *session_secrand32, + const unsigned char *seckey, + const rustsecp256k1_v0_11_pubkey *pubkey, + const unsigned char *msg32, + const rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_musig_nonce_gen_counter` + * (through the keypair argument), as opposed to `rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_nonce_gen_counter( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_musig_secnonce *secnonce, + rustsecp256k1_v0_11_musig_pubnonce *pubnonce, + uint64_t nonrepeating_cnt, + const rustsecp256k1_v0_11_keypair *keypair, + const unsigned char *msg32, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_nonce_agg( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_musig_aggnonce *aggnonce, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_nonce_process( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_musig_session *session, + const rustsecp256k1_v0_11_musig_aggnonce *aggnonce, + const unsigned char *msg32, + const rustsecp256k1_v0_11_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 `rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_partial_sign( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_musig_partial_sig *partial_sig, + rustsecp256k1_v0_11_musig_secnonce *secnonce, + const rustsecp256k1_v0_11_keypair *keypair, + const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_partial_sig_verify( + const rustsecp256k1_v0_11_context *ctx, + const rustsecp256k1_v0_11_musig_partial_sig *partial_sig, + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce, + const rustsecp256k1_v0_11_pubkey *pubkey, + const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, + const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_partial_sig_agg( + const rustsecp256k1_v0_11_context *ctx, + unsigned char *sig64, + const rustsecp256k1_v0_11_musig_session *session, + const rustsecp256k1_v0_11_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/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h index 46bc0da82..7ec542ec3 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_preallocated.h @@ -16,8 +16,8 @@ extern "C" { * objects created by functions in secp256k1.h, i.e., they can be passed to any * API function that expects a context object (see secp256k1.h for details). The * only exception is that context objects created by functions in this module - * must be destroyed using rustsecp256k1_v0_10_0_context_preallocated_destroy (in this - * module) instead of rustsecp256k1_v0_10_0_context_destroy (in secp256k1.h). + * must be destroyed using rustsecp256k1_v0_11_context_preallocated_destroy (in this + * module) instead of rustsecp256k1_v0_11_context_destroy (in secp256k1.h). * * It is guaranteed that functions in this module will not call malloc or its * friends realloc, calloc, and free. @@ -27,24 +27,24 @@ extern "C" { * caller-provided memory. * * The purpose of this function is to determine how much memory must be provided - * to rustsecp256k1_v0_10_0_context_preallocated_create. + * to rustsecp256k1_v0_11_context_preallocated_create. * * Returns: the required size of the caller-provided memory block * In: flags: which parts of the context to initialize. */ -SECP256K1_API size_t rustsecp256k1_v0_10_0_context_preallocated_size( +SECP256K1_API size_t rustsecp256k1_v0_11_context_preallocated_size( unsigned int flags ) SECP256K1_WARN_UNUSED_RESULT; /** Create a secp256k1 context object in caller-provided memory. * * The caller must provide a pointer to a rewritable contiguous block of memory - * of size at least rustsecp256k1_v0_10_0_context_preallocated_size(flags) bytes, suitably + * of size at least rustsecp256k1_v0_11_context_preallocated_size(flags) bytes, suitably * aligned to hold an object of any type. * * The block of memory is exclusively owned by the created context object during * the lifetime of this context object, which begins with the call to this - * function and ends when a call to rustsecp256k1_v0_10_0_context_preallocated_destroy + * function and ends when a call to rustsecp256k1_v0_11_context_preallocated_destroy * (which destroys the context object again) returns. During the lifetime of the * context object, the caller is obligated not to access this block of memory, * i.e., the caller may not read or write the memory, e.g., by copying the memory @@ -52,18 +52,18 @@ SECP256K1_API size_t rustsecp256k1_v0_10_0_context_preallocated_size( * in the memory. In simpler words, the prealloc pointer (or any pointer derived * from it) should not be used during the lifetime of the context object. * - * Returns: a newly created context object. - * In: prealloc: a pointer to a rewritable contiguous block of memory of - * size at least rustsecp256k1_v0_10_0_context_preallocated_size(flags) + * Returns: pointer to newly created context object. + * In: prealloc: pointer to a rewritable contiguous block of memory of + * size at least rustsecp256k1_v0_11_context_preallocated_size(flags) * bytes, as detailed above. * flags: which parts of the context to initialize. * - * See rustsecp256k1_v0_10_0_context_create (in secp256k1.h) for further details. + * See rustsecp256k1_v0_11_context_create (in secp256k1.h) for further details. * - * See also rustsecp256k1_v0_10_0_context_randomize (in secp256k1.h) - * and rustsecp256k1_v0_10_0_context_preallocated_destroy. + * See also rustsecp256k1_v0_11_context_randomize (in secp256k1.h) + * and rustsecp256k1_v0_11_context_preallocated_destroy. */ -SECP256K1_API rustsecp256k1_v0_10_0_context *rustsecp256k1_v0_10_0_context_preallocated_create( +SECP256K1_API rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_preallocated_create( void *prealloc, unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; @@ -72,33 +72,33 @@ SECP256K1_API rustsecp256k1_v0_10_0_context *rustsecp256k1_v0_10_0_context_preal * caller-provided memory. * * Returns: the required size of the caller-provided memory block. - * In: ctx: an existing context to copy. + * In: ctx: pointer to a context to copy. */ -SECP256K1_API size_t rustsecp256k1_v0_10_0_context_preallocated_clone_size( - const rustsecp256k1_v0_10_0_context *ctx +SECP256K1_API size_t rustsecp256k1_v0_11_context_preallocated_clone_size( + const rustsecp256k1_v0_11_context *ctx ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; /** Copy a secp256k1 context object into caller-provided memory. * * The caller must provide a pointer to a rewritable contiguous block of memory - * of size at least rustsecp256k1_v0_10_0_context_preallocated_size(flags) bytes, suitably + * of size at least rustsecp256k1_v0_11_context_preallocated_size(flags) bytes, suitably * aligned to hold an object of any type. * * The block of memory is exclusively owned by the created context object during * the lifetime of this context object, see the description of - * rustsecp256k1_v0_10_0_context_preallocated_create for details. + * rustsecp256k1_v0_11_context_preallocated_create for details. * - * Cloning rustsecp256k1_v0_10_0_context_static is not possible, and should not be emulated by + * Cloning rustsecp256k1_v0_11_context_static is not possible, and should not be emulated by * the caller (e.g., using memcpy). Create a new context instead. * - * Returns: a newly created context object. - * Args: ctx: an existing context to copy (not rustsecp256k1_v0_10_0_context_static). - * In: prealloc: a pointer to a rewritable contiguous block of memory of - * size at least rustsecp256k1_v0_10_0_context_preallocated_size(flags) + * Returns: pointer to a newly created context object. + * Args: ctx: pointer to a context to copy (not rustsecp256k1_v0_11_context_static). + * In: prealloc: pointer to a rewritable contiguous block of memory of + * size at least rustsecp256k1_v0_11_context_preallocated_size(flags) * bytes, as detailed above. */ -SECP256K1_API rustsecp256k1_v0_10_0_context *rustsecp256k1_v0_10_0_context_preallocated_clone( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_preallocated_clone( + const rustsecp256k1_v0_11_context *ctx, void *prealloc ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_WARN_UNUSED_RESULT; @@ -108,23 +108,23 @@ SECP256K1_API rustsecp256k1_v0_10_0_context *rustsecp256k1_v0_10_0_context_preal * The context pointer may not be used afterwards. * * The context to destroy must have been created using - * rustsecp256k1_v0_10_0_context_preallocated_create or rustsecp256k1_v0_10_0_context_preallocated_clone. - * If the context has instead been created using rustsecp256k1_v0_10_0_context_create or - * rustsecp256k1_v0_10_0_context_clone, the behaviour is undefined. In that case, - * rustsecp256k1_v0_10_0_context_destroy must be used instead. + * rustsecp256k1_v0_11_context_preallocated_create or rustsecp256k1_v0_11_context_preallocated_clone. + * If the context has instead been created using rustsecp256k1_v0_11_context_create or + * rustsecp256k1_v0_11_context_clone, the behaviour is undefined. In that case, + * rustsecp256k1_v0_11_context_destroy must be used instead. * * If required, it is the responsibility of the caller to deallocate the block * of memory properly after this function returns, e.g., by calling free on the - * preallocated pointer given to rustsecp256k1_v0_10_0_context_preallocated_create or - * rustsecp256k1_v0_10_0_context_preallocated_clone. + * preallocated pointer given to rustsecp256k1_v0_11_context_preallocated_create or + * rustsecp256k1_v0_11_context_preallocated_clone. * - * Args: ctx: an existing context to destroy, constructed using - * rustsecp256k1_v0_10_0_context_preallocated_create or - * rustsecp256k1_v0_10_0_context_preallocated_clone - * (i.e., not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context to destroy, constructed using + * rustsecp256k1_v0_11_context_preallocated_create or + * rustsecp256k1_v0_11_context_preallocated_clone + * (i.e., not rustsecp256k1_v0_11_context_static). */ -SECP256K1_API void rustsecp256k1_v0_10_0_context_preallocated_destroy( - rustsecp256k1_v0_10_0_context *ctx +SECP256K1_API void rustsecp256k1_v0_11_context_preallocated_destroy( + rustsecp256k1_v0_11_context *ctx ) SECP256K1_ARG_NONNULL(1); #ifdef __cplusplus diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h index 64acee9b4..d6b0d602b 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_recovery.h @@ -7,35 +7,35 @@ 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 * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 65 bytes in size, and can be safely copied/moved. * If you need to convert to a format suitable for storage or transmission, use - * the rustsecp256k1_v0_10_0_ecdsa_signature_serialize_* and - * rustsecp256k1_v0_10_0_ecdsa_signature_parse_* functions. + * the rustsecp256k1_v0_11_ecdsa_signature_serialize_* and + * rustsecp256k1_v0_11_ecdsa_signature_parse_* functions. * * Furthermore, it is guaranteed that identical signatures (including their * recoverability) will have identical representation, so they can be * memcmp'ed. */ -typedef struct { +typedef struct rustsecp256k1_v0_11_ecdsa_recoverable_signature { unsigned char data[65]; -} rustsecp256k1_v0_10_0_ecdsa_recoverable_signature; +} rustsecp256k1_v0_11_ecdsa_recoverable_signature; /** Parse a compact ECDSA signature (64 bytes + recovery id). * * Returns: 1 when the signature could be parsed, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to a 64-byte compact signature + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input64: pointer to a 64-byte compact signature * recid: the recovery id (0, 1, 2 or 3) */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *sig, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -43,50 +43,50 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compac /** Convert a recoverable signature into a normal signature. * * Returns: 1 - * Args: ctx: a secp256k1 context object. - * Out: sig: a pointer to a normal signature. - * In: sigin: a pointer to a recoverable signature. + * Args: ctx: pointer to a context object. + * Out: sig: pointer to a normal signature. + * In: sigin: pointer to a recoverable signature. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_signature *sig, - const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *sigin +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_signature *sig, + const rustsecp256k1_v0_11_ecdsa_recoverable_signature *sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Serialize an ECDSA signature in compact format (64 bytes + recovery id). * * Returns: 1 - * Args: ctx: a secp256k1 context object. - * Out: output64: a pointer to a 64-byte array of the compact signature. - * recid: a pointer to an integer to hold the recovery id. - * In: sig: a pointer to an initialized signature object. + * Args: ctx: pointer to a context object. + * Out: output64: pointer to a 64-byte array of the compact signature. + * recid: pointer to an integer to hold the recovery id. + * In: sig: pointer to an initialized signature object. */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact( + const rustsecp256k1_v0_11_context *ctx, unsigned char *output64, int *recid, - const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *sig + const rustsecp256k1_v0_11_ecdsa_recoverable_signature *sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Create a recoverable ECDSA signature. * * Returns: 1: signature created * 0: the nonce generation function failed, or the secret key was invalid. - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: sig: pointer to an array where the signature will be placed. * 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, - * rustsecp256k1_v0_10_0_nonce_function_default is used. + * rustsecp256k1_v0_11_nonce_function_default is used. * ndata: pointer to arbitrary data used by the nonce generation function - * (can be NULL for rustsecp256k1_v0_10_0_nonce_function_default). + * (can be NULL for rustsecp256k1_v0_11_nonce_function_default). */ -SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_sign_recoverable( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *sig, +SECP256K1_API int rustsecp256k1_v0_11_ecdsa_sign_recoverable( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_ecdsa_recoverable_signature *sig, const unsigned char *msghash32, const unsigned char *seckey, - rustsecp256k1_v0_10_0_nonce_function noncefp, + rustsecp256k1_v0_11_nonce_function noncefp, const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); @@ -99,10 +99,10 @@ SECP256K1_API int rustsecp256k1_v0_10_0_ecdsa_sign_recoverable( * In: sig: pointer to initialized signature that supports pubkey recovery. * msghash32: the 32-byte message hash assumed to be signed. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_ecdsa_recover( - const rustsecp256k1_v0_10_0_context *ctx, - rustsecp256k1_v0_10_0_pubkey *pubkey, - const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *sig, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_ecdsa_recover( + const rustsecp256k1_v0_11_context *ctx, + rustsecp256k1_v0_11_pubkey *pubkey, + const rustsecp256k1_v0_11_ecdsa_recoverable_signature *sig, const unsigned char *msghash32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); diff --git a/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h b/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h index 6912558ea..3efe3815f 100644 --- a/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h +++ b/secp256k1-sys/depend/secp256k1/include/secp256k1_schnorrsig.h @@ -15,7 +15,7 @@ extern "C" { /** A pointer to a function to deterministically generate a nonce. * - * Same as rustsecp256k1_v0_10_0_nonce function with the exception of accepting an + * Same as rustsecp256k1_v0_11_nonce function with the exception of accepting an * additional pubkey argument and not requiring an attempt argument. The pubkey * argument can protect signature schemes with key-prefixed challenge hash * inputs against reusing the nonce when signing with the wrong precomputed @@ -38,7 +38,7 @@ extern "C" { * Except for test cases, this function should compute some cryptographic hash of * the message, the key, the pubkey, the algorithm description, and data. */ -typedef int (*rustsecp256k1_v0_10_0_nonce_function_hardened)( +typedef int (*rustsecp256k1_v0_11_nonce_function_hardened)( unsigned char *nonce32, const unsigned char *msg, size_t msglen, @@ -61,7 +61,7 @@ typedef int (*rustsecp256k1_v0_10_0_nonce_function_hardened)( * Therefore, to create BIP-340 compliant signatures, algo must be set to * "BIP0340/nonce" and algolen to 13. */ -SECP256K1_API const rustsecp256k1_v0_10_0_nonce_function_hardened rustsecp256k1_v0_10_0_nonce_function_bip340; +SECP256K1_API const rustsecp256k1_v0_11_nonce_function_hardened rustsecp256k1_v0_11_nonce_function_bip340; /** Data structure that contains additional arguments for schnorrsig_sign_custom. * @@ -73,17 +73,17 @@ SECP256K1_API const rustsecp256k1_v0_10_0_nonce_function_hardened rustsecp256k1_ * and has no other function than making sure the object is * initialized. * noncefp: pointer to a nonce generation function. If NULL, - * rustsecp256k1_v0_10_0_nonce_function_bip340 is used + * rustsecp256k1_v0_11_nonce_function_bip340 is used * ndata: pointer to arbitrary data used by the nonce generation function * (can be NULL). If it is non-NULL and - * rustsecp256k1_v0_10_0_nonce_function_bip340 is used, then ndata must be a + * rustsecp256k1_v0_11_nonce_function_bip340 is used, then ndata must be a * pointer to 32-byte auxiliary randomness as per BIP-340. */ -typedef struct { +typedef struct rustsecp256k1_v0_11_schnorrsig_extraparams { unsigned char magic[4]; - rustsecp256k1_v0_10_0_nonce_function_hardened noncefp; + rustsecp256k1_v0_11_nonce_function_hardened noncefp; void *ndata; -} rustsecp256k1_v0_10_0_schnorrsig_extraparams; +} rustsecp256k1_v0_11_schnorrsig_extraparams; #define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC { 0xda, 0x6f, 0xb3, 0x8c } #define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\ @@ -95,18 +95,18 @@ typedef struct { /** Create a Schnorr signature. * * Does _not_ strictly follow BIP-340 because it does not verify the resulting - * signature. Instead, you can manually use rustsecp256k1_v0_10_0_schnorrsig_verify and + * signature. Instead, you can manually use rustsecp256k1_v0_11_schnorrsig_verify and * abort if it fails. * * This function only signs 32-byte messages. If you have messages of a * different size (or the same size but without a context-specific tag * prefix), it is recommended to create a 32-byte message hash with - * rustsecp256k1_v0_10_0_tagged_sha256 and then sign the hash. Tagged hashing allows + * rustsecp256k1_v0_11_tagged_sha256 and then sign the hash. Tagged hashing allows * providing an context-specific tag for domain separation. This prevents * signatures from being valid in multiple contexts by accident. * * Returns 1 on success, 0 on failure. - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: sig64: pointer to a 64-byte array to store the serialized signature. * In: msg32: the 32-byte message being signed. * keypair: pointer to an initialized keypair. @@ -116,71 +116,71 @@ typedef struct { * BIP-340 "Default Signing" for a full explanation of this * argument and for guidance if randomness is expensive. */ -SECP256K1_API int rustsecp256k1_v0_10_0_schnorrsig_sign32( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_schnorrsig_sign32( + const rustsecp256k1_v0_11_context *ctx, unsigned char *sig64, const unsigned char *msg32, - const rustsecp256k1_v0_10_0_keypair *keypair, + const rustsecp256k1_v0_11_keypair *keypair, const unsigned char *aux_rand32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -/** Same as rustsecp256k1_v0_10_0_schnorrsig_sign32, but DEPRECATED. Will be removed in +/** Same as rustsecp256k1_v0_11_schnorrsig_sign32, but DEPRECATED. Will be removed in * future versions. */ -SECP256K1_API int rustsecp256k1_v0_10_0_schnorrsig_sign( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_schnorrsig_sign( + const rustsecp256k1_v0_11_context *ctx, unsigned char *sig64, const unsigned char *msg32, - const rustsecp256k1_v0_10_0_keypair *keypair, + const rustsecp256k1_v0_11_keypair *keypair, const unsigned char *aux_rand32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) - SECP256K1_DEPRECATED("Use rustsecp256k1_v0_10_0_schnorrsig_sign32 instead"); + SECP256K1_DEPRECATED("Use rustsecp256k1_v0_11_schnorrsig_sign32 instead"); /** Create a Schnorr signature with a more flexible API. * - * Same arguments as rustsecp256k1_v0_10_0_schnorrsig_sign except that it allows signing + * Same arguments as rustsecp256k1_v0_11_schnorrsig_sign except that it allows signing * variable length messages and accepts a pointer to an extraparams object that * allows customizing signing by passing additional arguments. * - * Equivalent to rustsecp256k1_v0_10_0_schnorrsig_sign32(..., aux_rand32) if msglen is 32 + * Equivalent to rustsecp256k1_v0_11_schnorrsig_sign32(..., aux_rand32) if msglen is 32 * and extraparams is initialized as follows: * ``` - * rustsecp256k1_v0_10_0_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; + * rustsecp256k1_v0_11_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; * extraparams.ndata = (unsigned char*)aux_rand32; * ``` * * Returns 1 on success, 0 on failure. - * Args: ctx: pointer to a context object (not rustsecp256k1_v0_10_0_context_static). + * Args: ctx: pointer to a context object (not rustsecp256k1_v0_11_context_static). * Out: sig64: pointer to a 64-byte array to store the serialized signature. * In: msg: the message being signed. Can only be NULL if msglen is 0. * msglen: length of the message. * keypair: pointer to an initialized keypair. * extraparams: pointer to an extraparams object (can be NULL). */ -SECP256K1_API int rustsecp256k1_v0_10_0_schnorrsig_sign_custom( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API int rustsecp256k1_v0_11_schnorrsig_sign_custom( + const rustsecp256k1_v0_11_context *ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, - const rustsecp256k1_v0_10_0_keypair *keypair, - rustsecp256k1_v0_10_0_schnorrsig_extraparams *extraparams + const rustsecp256k1_v0_11_keypair *keypair, + rustsecp256k1_v0_11_schnorrsig_extraparams *extraparams ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); /** Verify a Schnorr signature. * * Returns: 1: correct signature * 0: incorrect signature - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object. * In: sig64: pointer to the 64-byte signature to verify. * msg: the message being verified. Can only be NULL if msglen is 0. * msglen: length of the message - * pubkey: pointer to an x-only public key to verify with (cannot be NULL) + * pubkey: pointer to an x-only public key to verify with */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_10_0_schnorrsig_verify( - const rustsecp256k1_v0_10_0_context *ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int rustsecp256k1_v0_11_schnorrsig_verify( + const rustsecp256k1_v0_11_context *ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, - const rustsecp256k1_v0_10_0_xonly_pubkey *pubkey + const rustsecp256k1_v0_11_xonly_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); #ifdef __cplusplus diff --git a/secp256k1-sys/depend/secp256k1/sage/gen_exhaustive_groups.sage b/secp256k1-sys/depend/secp256k1/sage/gen_exhaustive_groups.sage index 1fc57f4b0..141041116 100644 --- a/secp256k1-sys/depend/secp256k1/sage/gen_exhaustive_groups.sage +++ b/secp256k1-sys/depend/secp256k1/sage/gen_exhaustive_groups.sage @@ -1,4 +1,4 @@ -load("rustsecp256k1_v0_10_0_params.sage") +load("rustsecp256k1_v0_11_params.sage") MAX_ORDER = 1000 @@ -124,7 +124,7 @@ for f in sorted(solutions.keys()): print(f"# {'if' if first else 'elif'} EXHAUSTIVE_TEST_ORDER == {f}") first = False print() - print(f"static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256K1_G_ORDER_{f};") + print(f"static const rustsecp256k1_v0_11_ge rustsecp256k1_v0_11_ge_const_g = SECP256K1_G_ORDER_{f};") output_b(b) print() print("# else") @@ -132,7 +132,7 @@ print("# error No known generator for the specified exhaustive test group ord print("# endif") print("#else") print() -print("static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256K1_G;") +print("static const rustsecp256k1_v0_11_ge rustsecp256k1_v0_11_ge_const_g = SECP256K1_G;") output_b(7) print() print("#endif") diff --git a/secp256k1-sys/depend/secp256k1/sage/gen_split_lambda_constants.sage b/secp256k1-sys/depend/secp256k1/sage/gen_split_lambda_constants.sage index 5fa589efe..65cb87414 100644 --- a/secp256k1-sys/depend/secp256k1/sage/gen_split_lambda_constants.sage +++ b/secp256k1-sys/depend/secp256k1/sage/gen_split_lambda_constants.sage @@ -1,9 +1,9 @@ -""" Generates the constants used in rustsecp256k1_v0_10_0_scalar_split_lambda. +""" Generates the constants used in rustsecp256k1_v0_11_scalar_split_lambda. -See the comments for rustsecp256k1_v0_10_0_scalar_split_lambda in src/scalar_impl.h for detailed explanations. +See the comments for rustsecp256k1_v0_11_scalar_split_lambda in src/scalar_impl.h for detailed explanations. """ -load("rustsecp256k1_v0_10_0_params.sage") +load("rustsecp256k1_v0_11_params.sage") def inf_norm(v): """Returns the infinity norm of a vector.""" @@ -24,17 +24,17 @@ def gauss_reduction(i1, i2): v2[1] -= m*v1[1] def find_split_constants_gauss(): - """Find constants for rustsecp256k1_v0_10_0_scalar_split_lamdba using gauss reduction.""" + """Find constants for rustsecp256k1_v0_11_scalar_split_lamdba using gauss reduction.""" (v11, v12), (v21, v22) = gauss_reduction([0, N], [1, int(LAMBDA)]) - # We use related vectors in rustsecp256k1_v0_10_0_scalar_split_lambda. + # We use related vectors in rustsecp256k1_v0_11_scalar_split_lambda. A1, B1 = -v21, -v11 A2, B2 = v22, -v21 return A1, B1, A2, B2 def find_split_constants_explicit_tof(): - """Find constants for rustsecp256k1_v0_10_0_scalar_split_lamdba using the trace of Frobenius. + """Find constants for rustsecp256k1_v0_11_scalar_split_lamdba using the trace of Frobenius. See Benjamin Smith: "Easy scalar decompositions for efficient scalar multiplication on elliptic curves and genus 2 Jacobians" (https://eprint.iacr.org/2013/672), Example 2 @@ -51,7 +51,7 @@ def find_split_constants_explicit_tof(): A2 = Integer((t + c)/2 - 1) B2 = Integer(1 - (t - c)/2) - # We use a negated b values in rustsecp256k1_v0_10_0_scalar_split_lambda. + # We use a negated b values in rustsecp256k1_v0_11_scalar_split_lambda. B1, B2 = -B1, -B2 return A1, B1, A2, B2 @@ -90,7 +90,7 @@ def rnddiv2(v): return v >> 1 def scalar_lambda_split(k): - """Equivalent to rustsecp256k1_v0_10_0_scalar_lambda_split().""" + """Equivalent to rustsecp256k1_v0_11_scalar_lambda_split().""" c1 = rnddiv2((k * G1) >> 383) c2 = rnddiv2((k * G2) >> 383) c1 = (c1 * -B1) % N diff --git a/secp256k1-sys/depend/secp256k1/sage/prove_group_implementations.sage b/secp256k1-sys/depend/secp256k1/sage/prove_group_implementations.sage index 015905215..ff2275e1f 100644 --- a/secp256k1-sys/depend/secp256k1/sage/prove_group_implementations.sage +++ b/secp256k1-sys/depend/secp256k1/sage/prove_group_implementations.sage @@ -5,8 +5,8 @@ import sys load("group_prover.sage") load("weierstrass_prover.sage") -def formula_rustsecp256k1_v0_10_0_gej_double_var(a): - """libsecp256k1's rustsecp256k1_v0_10_0_gej_double_var, used by various addition functions""" +def formula_rustsecp256k1_v0_11_gej_double_var(a): + """libsecp256k1's rustsecp256k1_v0_11_gej_double_var, used by various addition functions""" rz = a.Z * a.Y s = a.Y^2 l = a.X^2 @@ -24,8 +24,8 @@ def formula_rustsecp256k1_v0_10_0_gej_double_var(a): ry = -ry return jacobianpoint(rx, ry, rz) -def formula_rustsecp256k1_v0_10_0_gej_add_var(branch, a, b): - """libsecp256k1's rustsecp256k1_v0_10_0_gej_add_var""" +def formula_rustsecp256k1_v0_11_gej_add_var(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_11_gej_add_var""" if branch == 0: return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) if branch == 1: @@ -43,7 +43,7 @@ def formula_rustsecp256k1_v0_10_0_gej_add_var(branch, a, b): i = -s2 i = i + s1 if branch == 2: - r = formula_rustsecp256k1_v0_10_0_gej_double_var(a) + r = formula_rustsecp256k1_v0_11_gej_double_var(a) return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) if branch == 3: return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) @@ -63,8 +63,8 @@ def formula_rustsecp256k1_v0_10_0_gej_add_var(branch, a, b): ry = ry + h3 return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) -def formula_rustsecp256k1_v0_10_0_gej_add_ge_var(branch, a, b): - """libsecp256k1's rustsecp256k1_v0_10_0_gej_add_ge_var, which assume bz==1""" +def formula_rustsecp256k1_v0_11_gej_add_ge_var(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_11_gej_add_ge_var, which assume bz==1""" if branch == 0: return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) if branch == 1: @@ -80,7 +80,7 @@ def formula_rustsecp256k1_v0_10_0_gej_add_ge_var(branch, a, b): i = -s2 i = i + s1 if (branch == 2): - r = formula_rustsecp256k1_v0_10_0_gej_double_var(a) + r = formula_rustsecp256k1_v0_11_gej_double_var(a) return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) if (branch == 3): return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) @@ -99,8 +99,8 @@ def formula_rustsecp256k1_v0_10_0_gej_add_ge_var(branch, a, b): ry = ry + h3 return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) -def formula_rustsecp256k1_v0_10_0_gej_add_zinv_var(branch, a, b): - """libsecp256k1's rustsecp256k1_v0_10_0_gej_add_zinv_var""" +def formula_rustsecp256k1_v0_11_gej_add_zinv_var(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_11_gej_add_zinv_var""" bzinv = b.Z^(-1) if branch == 0: rinf = b.Infinity @@ -124,7 +124,7 @@ def formula_rustsecp256k1_v0_10_0_gej_add_zinv_var(branch, a, b): i = -s2 i = i + s1 if branch == 2: - r = formula_rustsecp256k1_v0_10_0_gej_double_var(a) + r = formula_rustsecp256k1_v0_11_gej_double_var(a) return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) if branch == 3: return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) @@ -143,8 +143,8 @@ def formula_rustsecp256k1_v0_10_0_gej_add_zinv_var(branch, a, b): ry = ry + h3 return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) -def formula_rustsecp256k1_v0_10_0_gej_add_ge(branch, a, b): - """libsecp256k1's rustsecp256k1_v0_10_0_gej_add_ge""" +def formula_rustsecp256k1_v0_11_gej_add_ge(branch, a, b): + """libsecp256k1's rustsecp256k1_v0_11_gej_add_ge""" zeroes = {} nonzeroes = {} a_infinity = False @@ -205,8 +205,8 @@ def formula_rustsecp256k1_v0_10_0_gej_add_ge(branch, a, b): nonzeroes.update({rz : 'r.z != 0'}) return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) -def formula_rustsecp256k1_v0_10_0_gej_add_ge_old(branch, a, b): - """libsecp256k1's old rustsecp256k1_v0_10_0_gej_add_ge, which fails when ay+by=0 but ax!=bx""" +def formula_rustsecp256k1_v0_11_gej_add_ge_old(branch, a, b): + """libsecp256k1's old rustsecp256k1_v0_11_gej_add_ge, which fails when ay+by=0 but ax!=bx""" a_infinity = (branch & 1) != 0 zero = {} nonzero = {} @@ -269,17 +269,17 @@ def formula_rustsecp256k1_v0_10_0_gej_add_ge_old(branch, a, b): if __name__ == "__main__": success = True - success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_var", 0, 7, 5, formula_rustsecp256k1_v0_10_0_gej_add_var) - success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_ge_var", 0, 7, 5, formula_rustsecp256k1_v0_10_0_gej_add_ge_var) - success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_zinv_var", 0, 7, 5, formula_rustsecp256k1_v0_10_0_gej_add_zinv_var) - success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_ge", 0, 7, 8, formula_rustsecp256k1_v0_10_0_gej_add_ge) - success = success & (not check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_ge_old [should fail]", 0, 7, 4, formula_rustsecp256k1_v0_10_0_gej_add_ge_old)) + success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_var", 0, 7, 5, formula_rustsecp256k1_v0_11_gej_add_var) + success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_ge_var", 0, 7, 5, formula_rustsecp256k1_v0_11_gej_add_ge_var) + success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_zinv_var", 0, 7, 5, formula_rustsecp256k1_v0_11_gej_add_zinv_var) + success = success & check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_ge", 0, 7, 8, formula_rustsecp256k1_v0_11_gej_add_ge) + success = success & (not check_symbolic_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_ge_old [should fail]", 0, 7, 4, formula_rustsecp256k1_v0_11_gej_add_ge_old)) if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": - success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_var", 0, 7, 5, formula_rustsecp256k1_v0_10_0_gej_add_var, 43) - success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_ge_var", 0, 7, 5, formula_rustsecp256k1_v0_10_0_gej_add_ge_var, 43) - success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_zinv_var", 0, 7, 5, formula_rustsecp256k1_v0_10_0_gej_add_zinv_var, 43) - success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_ge", 0, 7, 8, formula_rustsecp256k1_v0_10_0_gej_add_ge, 43) - success = success & (not check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_10_0_gej_add_ge_old [should fail]", 0, 7, 4, formula_rustsecp256k1_v0_10_0_gej_add_ge_old, 43)) + success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_var", 0, 7, 5, formula_rustsecp256k1_v0_11_gej_add_var, 43) + success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_ge_var", 0, 7, 5, formula_rustsecp256k1_v0_11_gej_add_ge_var, 43) + success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_zinv_var", 0, 7, 5, formula_rustsecp256k1_v0_11_gej_add_zinv_var, 43) + success = success & check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_ge", 0, 7, 8, formula_rustsecp256k1_v0_11_gej_add_ge, 43) + success = success & (not check_exhaustive_jacobian_weierstrass("rustsecp256k1_v0_11_gej_add_ge_old [should fail]", 0, 7, 4, formula_rustsecp256k1_v0_11_gej_add_ge_old, 43)) sys.exit(int(not success)) diff --git a/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt b/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt index caac60526..bc2e04ba5 100644 --- a/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt +++ b/secp256k1-sys/depend/secp256k1/src/CMakeLists.txt @@ -1,23 +1,23 @@ # Must be included before CMAKE_INSTALL_INCLUDEDIR is used. include(GNUInstallDirs) -add_library(rustsecp256k1_v0_10_0_precomputed OBJECT EXCLUDE_FROM_ALL +add_library(rustsecp256k1_v0_11_precomputed OBJECT EXCLUDE_FROM_ALL precomputed_ecmult.c precomputed_ecmult_gen.c ) # Add objects explicitly rather than linking to the object libs to keep them # from being exported. -add_library(secp256k1 secp256k1.c $) +add_library(secp256k1 secp256k1.c $) -add_library(rustsecp256k1_v0_10_0_asm INTERFACE) +add_library(rustsecp256k1_v0_11_asm INTERFACE) if(SECP256K1_ASM STREQUAL "arm32") - add_library(rustsecp256k1_v0_10_0_asm_arm OBJECT EXCLUDE_FROM_ALL) - target_sources(rustsecp256k1_v0_10_0_asm_arm PUBLIC + add_library(rustsecp256k1_v0_11_asm_arm OBJECT EXCLUDE_FROM_ALL) + target_sources(rustsecp256k1_v0_11_asm_arm PUBLIC asm/field_10x26_arm.s ) - target_sources(secp256k1 PRIVATE $) - target_link_libraries(rustsecp256k1_v0_10_0_asm INTERFACE rustsecp256k1_v0_10_0_asm_arm) + target_sources(secp256k1 PRIVATE $) + target_link_libraries(rustsecp256k1_v0_11_asm INTERFACE rustsecp256k1_v0_11_asm_arm) endif() if(WIN32) @@ -29,7 +29,7 @@ endif() # Object libs don't know if they're being built for a shared or static lib. # Grab the PIC property from secp256k1 which knows. get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE) -set_target_properties(rustsecp256k1_v0_10_0_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic}) +set_target_properties(rustsecp256k1_v0_11_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic}) target_include_directories(secp256k1 INTERFACE # Add the include path for parent projects so that they don't have to manually add it. @@ -79,29 +79,29 @@ if(SECP256K1_BUILD_BENCHMARK) add_executable(bench bench.c) target_link_libraries(bench secp256k1) add_executable(bench_internal bench_internal.c) - target_link_libraries(bench_internal rustsecp256k1_v0_10_0_precomputed rustsecp256k1_v0_10_0_asm) + target_link_libraries(bench_internal rustsecp256k1_v0_11_precomputed rustsecp256k1_v0_11_asm) add_executable(bench_ecmult bench_ecmult.c) - target_link_libraries(bench_ecmult rustsecp256k1_v0_10_0_precomputed rustsecp256k1_v0_10_0_asm) + target_link_libraries(bench_ecmult rustsecp256k1_v0_11_precomputed rustsecp256k1_v0_11_asm) endif() if(SECP256K1_BUILD_TESTS) add_executable(noverify_tests tests.c) - target_link_libraries(noverify_tests rustsecp256k1_v0_10_0_precomputed rustsecp256k1_v0_10_0_asm) - add_test(NAME noverify_tests COMMAND noverify_tests) + target_link_libraries(noverify_tests rustsecp256k1_v0_11_precomputed rustsecp256k1_v0_11_asm) + add_test(NAME rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_precomputed rustsecp256k1_v0_10_0_asm) - add_test(NAME tests COMMAND tests) + target_link_libraries(tests rustsecp256k1_v0_11_precomputed rustsecp256k1_v0_11_asm) + add_test(NAME rustsecp256k1_v0_11_tests COMMAND tests) endif() endif() if(SECP256K1_BUILD_EXHAUSTIVE_TESTS) - # Note: do not include rustsecp256k1_v0_10_0_precomputed in exhaustive_tests (it uses runtime-generated tables). + # Note: do not include rustsecp256k1_v0_11_precomputed in exhaustive_tests (it uses runtime-generated tables). add_executable(exhaustive_tests tests_exhaustive.c) - target_link_libraries(exhaustive_tests rustsecp256k1_v0_10_0_asm) + target_link_libraries(exhaustive_tests rustsecp256k1_v0_11_asm) target_compile_definitions(exhaustive_tests PRIVATE $<$>:VERIFY>) - add_test(NAME exhaustive_tests COMMAND exhaustive_tests) + add_test(NAME rustsecp256k1_v0_11_exhaustive_tests COMMAND exhaustive_tests) endif() if(SECP256K1_BUILD_CTIME_TESTS) @@ -118,22 +118,25 @@ if(SECP256K1_INSTALL) ) set(${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1.h" - "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_10_0_preallocated.h" + "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_preallocated.h" ) if(SECP256K1_ENABLE_MODULE_ECDH) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_10_0_ecdh.h") + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_ecdh.h") endif() if(SECP256K1_ENABLE_MODULE_RECOVERY) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_10_0_recovery.h") + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_recovery.h") endif() if(SECP256K1_ENABLE_MODULE_EXTRAKEYS) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_10_0_extrakeys.h") + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_extrakeys.h") endif() if(SECP256K1_ENABLE_MODULE_SCHNORRSIG) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_10_0_schnorrsig.h") + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_schnorrsig.h") + endif() + if(SECP256K1_ENABLE_MODULE_MUSIG) + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_musig.h") endif() if(SECP256K1_ENABLE_MODULE_ELLSWIFT) - list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_10_0_ellswift.h") + list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/rustsecp256k1_v0_11_ellswift.h") endif() install(FILES ${${PROJECT_NAME}_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} diff --git a/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s b/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s index 7b90c1a8b..fb79bf90c 100644 --- a/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s +++ b/secp256k1-sys/depend/secp256k1/src/asm/field_10x26_arm.s @@ -27,9 +27,9 @@ Note: .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff .align 2 - .global rustsecp256k1_v0_10_0_fe_mul_inner - .type rustsecp256k1_v0_10_0_fe_mul_inner, %function - .hidden rustsecp256k1_v0_10_0_fe_mul_inner + .global rustsecp256k1_v0_11_fe_mul_inner + .type rustsecp256k1_v0_11_fe_mul_inner, %function + .hidden rustsecp256k1_v0_11_fe_mul_inner @ Arguments: @ r0 r Restrict: can overlap with a, not with b @ r1 a @@ -37,7 +37,7 @@ Note: @ Stack (total 4+10*4 = 44) @ sp + #0 saved 'r' pointer @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -rustsecp256k1_v0_10_0_fe_mul_inner: +rustsecp256k1_v0_11_fe_mul_inner: stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} sub sp, sp, #48 @ frame=44 + alignment str r0, [sp, #0] @ save result address, we need it only at the end @@ -512,19 +512,19 @@ rustsecp256k1_v0_10_0_fe_mul_inner: add sp, sp, #48 ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size rustsecp256k1_v0_10_0_fe_mul_inner, .-rustsecp256k1_v0_10_0_fe_mul_inner + .size rustsecp256k1_v0_11_fe_mul_inner, .-rustsecp256k1_v0_11_fe_mul_inner .align 2 - .global rustsecp256k1_v0_10_0_fe_sqr_inner - .type rustsecp256k1_v0_10_0_fe_sqr_inner, %function - .hidden rustsecp256k1_v0_10_0_fe_sqr_inner + .global rustsecp256k1_v0_11_fe_sqr_inner + .type rustsecp256k1_v0_11_fe_sqr_inner, %function + .hidden rustsecp256k1_v0_11_fe_sqr_inner @ Arguments: @ r0 r Can overlap with a @ r1 a @ Stack (total 4+10*4 = 44) @ sp + #0 saved 'r' pointer @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 -rustsecp256k1_v0_10_0_fe_sqr_inner: +rustsecp256k1_v0_11_fe_sqr_inner: stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} sub sp, sp, #48 @ frame=44 + alignment str r0, [sp, #0] @ save result address, we need it only at the end @@ -911,6 +911,6 @@ rustsecp256k1_v0_10_0_fe_sqr_inner: add sp, sp, #48 ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} - .size rustsecp256k1_v0_10_0_fe_sqr_inner, .-rustsecp256k1_v0_10_0_fe_sqr_inner + .size rustsecp256k1_v0_11_fe_sqr_inner, .-rustsecp256k1_v0_11_fe_sqr_inner .section .note.GNU-stack,"",%progbits diff --git a/secp256k1-sys/depend/secp256k1/src/assumptions.h b/secp256k1-sys/depend/secp256k1/src/assumptions.h index d7d69404a..e29b7d555 100644 --- a/secp256k1-sys/depend/secp256k1/src/assumptions.h +++ b/secp256k1-sys/depend/secp256k1/src/assumptions.h @@ -19,65 +19,69 @@ reduce the odds of experiencing an unwelcome surprise. */ -struct rustsecp256k1_v0_10_0_assumption_checker { - /* This uses a trick to implement a static assertion in C89: a type with an array of negative size is not - allowed. */ - int dummy_array[( - /* Bytes are 8 bits. */ - (CHAR_BIT == 8) && +#if defined(__has_attribute) +# if __has_attribute(__unavailable__) +__attribute__((__unavailable__("Don't call this function. It only exists because STATIC_ASSERT cannot be used outside a function."))) +# endif +#endif +static void rustsecp256k1_v0_11_assumption_checker(void) { + /* Bytes are 8 bits. */ + STATIC_ASSERT(CHAR_BIT == 8); - /* No integer promotion for uint32_t. This ensures that we can multiply uintXX_t values where XX >= 32 - without signed overflow, which would be undefined behaviour. */ - (UINT_MAX <= UINT32_MAX) && + /* No integer promotion for uint32_t. This ensures that we can multiply uintXX_t values where XX >= 32 + without signed overflow, which would be undefined behaviour. */ + STATIC_ASSERT(UINT_MAX <= UINT32_MAX); - /* Conversions from unsigned to signed outside of the bounds of the signed type are - implementation-defined. Verify that they function as reinterpreting the lower - bits of the input in two's complement notation. Do this for conversions: - - from uint(N)_t to int(N)_t with negative result - - from uint(2N)_t to int(N)_t with negative result - - from int(2N)_t to int(N)_t with negative result - - from int(2N)_t to int(N)_t with positive result */ + /* Conversions from unsigned to signed outside of the bounds of the signed type are + implementation-defined. Verify that they function as reinterpreting the lower + bits of the input in two's complement notation. Do this for conversions: + - from uint(N)_t to int(N)_t with negative result + - from uint(2N)_t to int(N)_t with negative result + - from int(2N)_t to int(N)_t with negative result + - from int(2N)_t to int(N)_t with positive result */ - /* To int8_t. */ - ((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55) && - ((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33) && - ((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF) && - ((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34) && + /* To int8_t. */ + STATIC_ASSERT(((int8_t)(uint8_t)0xAB == (int8_t)-(int8_t)0x55)); + STATIC_ASSERT((int8_t)(uint16_t)0xABCD == (int8_t)-(int8_t)0x33); + STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0xCDEF == (int8_t)(uint8_t)0xEF); + STATIC_ASSERT((int8_t)(int16_t)(uint16_t)0x9234 == (int8_t)(uint8_t)0x34); - /* To int16_t. */ - ((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322) && - ((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C) && - ((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4) && - ((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678) && + /* To int16_t. */ + STATIC_ASSERT((int16_t)(uint16_t)0xBCDE == (int16_t)-(int16_t)0x4322); + STATIC_ASSERT((int16_t)(uint32_t)0xA1B2C3D4 == (int16_t)-(int16_t)0x3C2C); + STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0xC1D2E3F4 == (int16_t)(uint16_t)0xE3F4); + STATIC_ASSERT((int16_t)(int32_t)(uint32_t)0x92345678 == (int16_t)(uint16_t)0x5678); - /* To int32_t. */ - ((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B) && - ((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE) && - ((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8) && - ((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789) && + /* To int32_t. */ + STATIC_ASSERT((int32_t)(uint32_t)0xB2C3D4E5 == (int32_t)-(int32_t)0x4D3C2B1B); + STATIC_ASSERT((int32_t)(uint64_t)0xA123B456C789D012ULL == (int32_t)-(int32_t)0x38762FEE); + STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xC1D2E3F4A5B6C7D8ULL == (int32_t)(uint32_t)0xA5B6C7D8); + STATIC_ASSERT((int32_t)(int64_t)(uint64_t)0xABCDEF0123456789ULL == (int32_t)(uint32_t)0x23456789); - /* To int64_t. */ - ((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL) && + /* To int64_t. */ + STATIC_ASSERT((int64_t)(uint64_t)0xB123C456D789E012ULL == (int64_t)-(int64_t)0x4EDC3BA928761FEEULL); #if defined(SECP256K1_INT128_NATIVE) - ((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL) && - (((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL) && - (((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL) && + STATIC_ASSERT((int64_t)(((uint128_t)0xA1234567B8901234ULL << 64) + 0xC5678901D2345678ULL) == (int64_t)-(int64_t)0x3A9876FE2DCBA988ULL); + STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xB1C2D3E4F5A6B7C8ULL << 64) + 0xD9E0F1A2B3C4D5E6ULL)) == (int64_t)(uint64_t)0xD9E0F1A2B3C4D5E6ULL); + STATIC_ASSERT(((int64_t)(int128_t)(((uint128_t)0xABCDEF0123456789ULL << 64) + 0x0123456789ABCDEFULL)) == (int64_t)(uint64_t)0x0123456789ABCDEFULL); - /* To int128_t. */ - ((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)) && + /* To int128_t. */ + STATIC_ASSERT((int128_t)(((uint128_t)0xB1234567C8901234ULL << 64) + 0xD5678901E2345678ULL) == (int128_t)(-(int128_t)0x8E1648B3F50E80DCULL * 0x8E1648B3F50E80DDULL + 0x5EA688D5482F9464ULL)); #endif - /* Right shift on negative signed values is implementation defined. Verify that it - acts as a right shift in two's complement with sign extension (i.e duplicating - the top bit into newly added bits). */ - ((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA) && - ((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A) && - ((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48) && - ((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL) && + /* Right shift on negative signed values is implementation defined. Verify that it + acts as a right shift in two's complement with sign extension (i.e duplicating + the top bit into newly added bits). */ + STATIC_ASSERT((((int8_t)0xE8) >> 2) == (int8_t)(uint8_t)0xFA); + STATIC_ASSERT((((int16_t)0xE9AC) >> 4) == (int16_t)(uint16_t)0xFE9A); + STATIC_ASSERT((((int32_t)0x937C918A) >> 9) == (int32_t)(uint32_t)0xFFC9BE48); + STATIC_ASSERT((((int64_t)0xA8B72231DF9CF4B9ULL) >> 19) == (int64_t)(uint64_t)0xFFFFF516E4463BF3ULL); #if defined(SECP256K1_INT128_NATIVE) - ((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)) && + STATIC_ASSERT((((int128_t)(((uint128_t)0xCD833A65684A0DBCULL << 64) + 0xB349312F71EA7637ULL)) >> 39) == (int128_t)(((uint128_t)0xFFFFFFFFFF9B0674ULL << 64) + 0xCAD0941B79669262ULL)); #endif - 1) * 2 - 1]; -}; + + /* This function is not supposed to be called. */ + VERIFY_CHECK(0); +} #endif /* SECP256K1_ASSUMPTIONS_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/bench.c b/secp256k1-sys/depend/secp256k1/src/bench.c index 902d7facc..0b2c6bb12 100644 --- a/secp256k1-sys/depend/secp256k1/src/bench.c +++ b/secp256k1-sys/depend/secp256k1/src/bench.c @@ -67,7 +67,7 @@ static void help(int default_iters) { } typedef struct { - rustsecp256k1_v0_10_0_context *ctx; + rustsecp256k1_v0_11_context *ctx; unsigned char msg[32]; unsigned char key[32]; unsigned char sig[72]; @@ -81,14 +81,14 @@ static void bench_verify(void* arg, int iters) { bench_data* data = (bench_data*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_ecdsa_signature sig; data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); data->sig[data->siglen - 1] ^= (i & 0xFF); data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); @@ -115,9 +115,9 @@ static void bench_sign_run(void* arg, int iters) { for (i = 0; i < iters; i++) { size_t siglen = 74; int j; - rustsecp256k1_v0_10_0_ecdsa_signature signature; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); + rustsecp256k1_v0_11_ecdsa_signature signature; + CHECK(rustsecp256k1_v0_11_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); for (j = 0; j < 32; j++) { data->msg[j] = sig[j]; data->key[j] = sig[j + 32]; @@ -141,9 +141,9 @@ static void bench_keygen_run(void *arg, int iters) { for (i = 0; i < iters; i++) { unsigned char pub33[33]; size_t len = 33; - rustsecp256k1_v0_10_0_pubkey pubkey; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(data->ctx, &pubkey, data->key)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(data->ctx, pub33, &len, &pubkey, SECP256K1_EC_COMPRESSED)); + rustsecp256k1_v0_11_pubkey pubkey; + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(data->ctx, &pubkey, data->key)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(data->ctx, pub33, &len, &pubkey, SECP256K1_EC_COMPRESSED)); memcpy(data->key, pub33 + 1, 32); } } @@ -167,8 +167,8 @@ static void bench_keygen_run(void *arg, int iters) { int main(int argc, char** argv) { int i; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_ecdsa_signature sig; bench_data data; int d = argc == 1; @@ -232,7 +232,7 @@ int main(int argc, char** argv) { #endif /* ECDSA benchmark */ - data.ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + data.ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); for (i = 0; i < 32; i++) { data.msg[i] = 1 + i; @@ -241,11 +241,11 @@ int main(int argc, char** argv) { data.key[i] = 33 + i; } data.siglen = 72; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(data.ctx, &pubkey, data.key)); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(data.ctx, &pubkey, data.key)); data.pubkeylen = 33; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); print_output_table_header_row(); if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "verify") || have_flag(argc, argv, "ecdsa_verify")) run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters); @@ -253,7 +253,7 @@ int main(int argc, char** argv) { if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "ecdsa_sign")) run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "ec") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ec_keygen")) run_benchmark("ec_keygen", bench_keygen_run, bench_keygen_setup, NULL, &data, 10, iters); - rustsecp256k1_v0_10_0_context_destroy(data.ctx); + rustsecp256k1_v0_11_context_destroy(data.ctx); #ifdef ENABLE_MODULE_ECDH /* ECDH benchmarks */ diff --git a/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c b/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c index 676c1f0ef..d42dc4166 100644 --- a/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_ecmult.c @@ -35,14 +35,14 @@ static void help(char **argv) { typedef struct { /* Setup once in advance */ - rustsecp256k1_v0_10_0_context* ctx; - rustsecp256k1_v0_10_0_scratch_space* scratch; - rustsecp256k1_v0_10_0_scalar* scalars; - rustsecp256k1_v0_10_0_ge* pubkeys; - rustsecp256k1_v0_10_0_gej* pubkeys_gej; - rustsecp256k1_v0_10_0_scalar* seckeys; - rustsecp256k1_v0_10_0_gej* expected_output; - rustsecp256k1_v0_10_0_ecmult_multi_func ecmult_multi; + rustsecp256k1_v0_11_context* ctx; + rustsecp256k1_v0_11_scratch_space* scratch; + rustsecp256k1_v0_11_scalar* scalars; + rustsecp256k1_v0_11_ge* pubkeys; + rustsecp256k1_v0_11_gej* pubkeys_gej; + rustsecp256k1_v0_11_scalar* seckeys; + rustsecp256k1_v0_11_gej* expected_output; + rustsecp256k1_v0_11_ecmult_multi_func ecmult_multi; /* Changes per benchmark */ size_t count; @@ -54,7 +54,7 @@ typedef struct { size_t offset2; /* Benchmark output. */ - rustsecp256k1_v0_10_0_gej* output; + rustsecp256k1_v0_11_gej* output; } bench_data; /* Hashes x into [0, POINTS) twice and store the result in offset1 and offset2. */ @@ -67,24 +67,24 @@ static void hash_into_offset(bench_data* data, size_t x) { * sum(outputs) ?= (sum(scalars_gen) + sum(seckeys)*sum(scalars))*G */ static void bench_ecmult_teardown_helper(bench_data* data, size_t* seckey_offset, size_t* scalar_offset, size_t* scalar_gen_offset, int iters) { int i; - rustsecp256k1_v0_10_0_gej sum_output, tmp; - rustsecp256k1_v0_10_0_scalar sum_scalars; + rustsecp256k1_v0_11_gej sum_output, tmp; + rustsecp256k1_v0_11_scalar sum_scalars; - rustsecp256k1_v0_10_0_gej_set_infinity(&sum_output); - rustsecp256k1_v0_10_0_scalar_clear(&sum_scalars); + rustsecp256k1_v0_11_gej_set_infinity(&sum_output); + rustsecp256k1_v0_11_scalar_set_int(&sum_scalars, 0); for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_10_0_gej_add_var(&sum_output, &sum_output, &data->output[i], NULL); + rustsecp256k1_v0_11_gej_add_var(&sum_output, &sum_output, &data->output[i], NULL); if (scalar_gen_offset != NULL) { - rustsecp256k1_v0_10_0_scalar_add(&sum_scalars, &sum_scalars, &data->scalars[(*scalar_gen_offset+i) % POINTS]); + rustsecp256k1_v0_11_scalar_add(&sum_scalars, &sum_scalars, &data->scalars[(*scalar_gen_offset+i) % POINTS]); } if (seckey_offset != NULL) { - rustsecp256k1_v0_10_0_scalar s = data->seckeys[(*seckey_offset+i) % POINTS]; - rustsecp256k1_v0_10_0_scalar_mul(&s, &s, &data->scalars[(*scalar_offset+i) % POINTS]); - rustsecp256k1_v0_10_0_scalar_add(&sum_scalars, &sum_scalars, &s); + rustsecp256k1_v0_11_scalar s = data->seckeys[(*seckey_offset+i) % POINTS]; + rustsecp256k1_v0_11_scalar_mul(&s, &s, &data->scalars[(*scalar_offset+i) % POINTS]); + rustsecp256k1_v0_11_scalar_add(&sum_scalars, &sum_scalars, &s); } } - rustsecp256k1_v0_10_0_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&tmp, &sum_output)); + rustsecp256k1_v0_11_ecmult_gen(&data->ctx->ecmult_gen_ctx, &tmp, &sum_scalars); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&tmp, &sum_output)); } static void bench_ecmult_setup(void* arg) { @@ -99,7 +99,7 @@ static void bench_ecmult_gen(void* arg, int iters) { int i; for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_10_0_ecmult_gen(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]); + rustsecp256k1_v0_11_ecmult_gen(&data->ctx->ecmult_gen_ctx, &data->output[i], &data->scalars[(data->offset1+i) % POINTS]); } } @@ -113,7 +113,7 @@ static void bench_ecmult_const(void* arg, int iters) { int i; for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_10_0_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS]); + rustsecp256k1_v0_11_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS]); } } @@ -127,7 +127,7 @@ static void bench_ecmult_1p(void* arg, int iters) { int i; for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_10_0_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL); + rustsecp256k1_v0_11_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], NULL); } } @@ -141,7 +141,7 @@ static void bench_ecmult_0p_g(void* arg, int iters) { int i; for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_10_0_ecmult(&data->output[i], NULL, &rustsecp256k1_v0_10_0_scalar_zero, &data->scalars[(data->offset1+i) % POINTS]); + rustsecp256k1_v0_11_ecmult(&data->output[i], NULL, &rustsecp256k1_v0_11_scalar_zero, &data->scalars[(data->offset1+i) % POINTS]); } } @@ -155,7 +155,7 @@ static void bench_ecmult_1p_g(void* arg, int iters) { int i; for (i = 0; i < iters/2; ++i) { - rustsecp256k1_v0_10_0_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]); + rustsecp256k1_v0_11_ecmult(&data->output[i], &data->pubkeys_gej[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], &data->scalars[(data->offset1+i) % POINTS]); } } @@ -181,12 +181,12 @@ static void run_ecmult_bench(bench_data* data, int iters) { run_benchmark(str, bench_ecmult_1p_g, bench_ecmult_setup, bench_ecmult_1p_g_teardown, data, 10, 2*iters); } -static int bench_ecmult_multi_callback(rustsecp256k1_v0_10_0_scalar* sc, rustsecp256k1_v0_10_0_ge* ge, size_t idx, void* arg) { +static int bench_ecmult_multi_callback(rustsecp256k1_v0_11_scalar* sc, rustsecp256k1_v0_11_ge* ge, size_t idx, void* arg) { bench_data* data = (bench_data*)arg; if (data->includes_g) ++idx; if (idx == 0) { *sc = data->scalars[data->offset1]; - *ge = rustsecp256k1_v0_10_0_ge_const_g; + *ge = rustsecp256k1_v0_11_ge_const_g; } else { *sc = data->scalars[(data->offset1 + idx) % POINTS]; *ge = data->pubkeys[(data->offset2 + idx - 1) % POINTS]; @@ -220,14 +220,14 @@ static void bench_ecmult_multi_teardown(void* arg, int iters) { iters = iters / data->count; /* Verify the results in teardown, to avoid doing comparisons while benchmarking. */ for (iter = 0; iter < iters; ++iter) { - rustsecp256k1_v0_10_0_gej tmp; - rustsecp256k1_v0_10_0_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&tmp)); + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_gej_add_var(&tmp, &data->output[iter], &data->expected_output[iter], NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&tmp)); } } -static void generate_scalar(uint32_t num, rustsecp256k1_v0_10_0_scalar* scalar) { - rustsecp256k1_v0_10_0_sha256 sha256; +static void generate_scalar(uint32_t num, rustsecp256k1_v0_11_scalar* scalar) { + rustsecp256k1_v0_11_sha256 sha256; unsigned char c[10] = {'e', 'c', 'm', 'u', 'l', 't', 0, 0, 0, 0}; unsigned char buf[32]; int overflow = 0; @@ -235,10 +235,10 @@ static void generate_scalar(uint32_t num, rustsecp256k1_v0_10_0_scalar* scalar) c[7] = num >> 8; c[8] = num >> 16; c[9] = num >> 24; - rustsecp256k1_v0_10_0_sha256_initialize(&sha256); - rustsecp256k1_v0_10_0_sha256_write(&sha256, c, sizeof(c)); - rustsecp256k1_v0_10_0_sha256_finalize(&sha256, buf); - rustsecp256k1_v0_10_0_scalar_set_b32(scalar, buf, &overflow); + rustsecp256k1_v0_11_sha256_initialize(&sha256); + rustsecp256k1_v0_11_sha256_write(&sha256, c, sizeof(c)); + rustsecp256k1_v0_11_sha256_finalize(&sha256, buf); + rustsecp256k1_v0_11_scalar_set_b32(scalar, buf, &overflow); CHECK(!overflow); } @@ -253,15 +253,15 @@ static void run_ecmult_multi_bench(bench_data* data, size_t count, int includes_ /* Compute (the negation of) the expected results directly. */ hash_into_offset(data, data->count); for (iter = 0; iter < iters; ++iter) { - rustsecp256k1_v0_10_0_scalar tmp; - rustsecp256k1_v0_10_0_scalar total = data->scalars[(data->offset1++) % POINTS]; + rustsecp256k1_v0_11_scalar tmp; + rustsecp256k1_v0_11_scalar total = data->scalars[(data->offset1++) % POINTS]; size_t i = 0; for (i = 0; i + 1 < count; ++i) { - rustsecp256k1_v0_10_0_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]); - rustsecp256k1_v0_10_0_scalar_add(&total, &total, &tmp); + rustsecp256k1_v0_11_scalar_mul(&tmp, &data->seckeys[(data->offset2++) % POINTS], &data->scalars[(data->offset1++) % POINTS]); + rustsecp256k1_v0_11_scalar_add(&total, &total, &tmp); } - rustsecp256k1_v0_10_0_scalar_negate(&total, &total); - rustsecp256k1_v0_10_0_ecmult(&data->expected_output[iter], NULL, &rustsecp256k1_v0_10_0_scalar_zero, &total); + rustsecp256k1_v0_11_scalar_negate(&total, &total); + rustsecp256k1_v0_11_ecmult(&data->expected_output[iter], NULL, &rustsecp256k1_v0_11_scalar_zero, &total); } /* Run the benchmark. */ @@ -280,7 +280,7 @@ int main(int argc, char **argv) { int iters = get_iters(10000); - data.ecmult_multi = rustsecp256k1_v0_10_0_ecmult_multi_var; + data.ecmult_multi = rustsecp256k1_v0_11_ecmult_multi_var; if (argc > 1) { if(have_flag(argc, argv, "-h") @@ -290,10 +290,10 @@ int main(int argc, char **argv) { return 0; } else if(have_flag(argc, argv, "pippenger_wnaf")) { printf("Using pippenger_wnaf:\n"); - data.ecmult_multi = rustsecp256k1_v0_10_0_ecmult_pippenger_batch_single; + data.ecmult_multi = rustsecp256k1_v0_11_ecmult_pippenger_batch_single; } else if(have_flag(argc, argv, "strauss_wnaf")) { printf("Using strauss_wnaf:\n"); - data.ecmult_multi = rustsecp256k1_v0_10_0_ecmult_strauss_batch_single; + data.ecmult_multi = rustsecp256k1_v0_11_ecmult_strauss_batch_single; } else if(have_flag(argc, argv, "simple")) { printf("Using simple algorithm:\n"); } else { @@ -303,33 +303,33 @@ int main(int argc, char **argv) { } } - data.ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); - scratch_size = rustsecp256k1_v0_10_0_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; + data.ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); + scratch_size = rustsecp256k1_v0_11_strauss_scratch_size(POINTS) + STRAUSS_SCRATCH_OBJECTS*16; if (!have_flag(argc, argv, "simple")) { - data.scratch = rustsecp256k1_v0_10_0_scratch_space_create(data.ctx, scratch_size); + data.scratch = rustsecp256k1_v0_11_scratch_space_create(data.ctx, scratch_size); } else { data.scratch = NULL; } /* Allocate stuff */ - data.scalars = malloc(sizeof(rustsecp256k1_v0_10_0_scalar) * POINTS); - data.seckeys = malloc(sizeof(rustsecp256k1_v0_10_0_scalar) * POINTS); - data.pubkeys = malloc(sizeof(rustsecp256k1_v0_10_0_ge) * POINTS); - data.pubkeys_gej = malloc(sizeof(rustsecp256k1_v0_10_0_gej) * POINTS); - data.expected_output = malloc(sizeof(rustsecp256k1_v0_10_0_gej) * (iters + 1)); - data.output = malloc(sizeof(rustsecp256k1_v0_10_0_gej) * (iters + 1)); + data.scalars = malloc(sizeof(rustsecp256k1_v0_11_scalar) * POINTS); + data.seckeys = malloc(sizeof(rustsecp256k1_v0_11_scalar) * POINTS); + data.pubkeys = malloc(sizeof(rustsecp256k1_v0_11_ge) * POINTS); + data.pubkeys_gej = malloc(sizeof(rustsecp256k1_v0_11_gej) * POINTS); + data.expected_output = malloc(sizeof(rustsecp256k1_v0_11_gej) * (iters + 1)); + data.output = malloc(sizeof(rustsecp256k1_v0_11_gej) * (iters + 1)); /* Generate a set of scalars, and private/public keypairs. */ - rustsecp256k1_v0_10_0_gej_set_ge(&data.pubkeys_gej[0], &rustsecp256k1_v0_10_0_ge_const_g); - rustsecp256k1_v0_10_0_scalar_set_int(&data.seckeys[0], 1); + rustsecp256k1_v0_11_gej_set_ge(&data.pubkeys_gej[0], &rustsecp256k1_v0_11_ge_const_g); + rustsecp256k1_v0_11_scalar_set_int(&data.seckeys[0], 1); for (i = 0; i < POINTS; ++i) { generate_scalar(i, &data.scalars[i]); if (i) { - rustsecp256k1_v0_10_0_gej_double_var(&data.pubkeys_gej[i], &data.pubkeys_gej[i - 1], NULL); - rustsecp256k1_v0_10_0_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); + rustsecp256k1_v0_11_gej_double_var(&data.pubkeys_gej[i], &data.pubkeys_gej[i - 1], NULL); + rustsecp256k1_v0_11_scalar_add(&data.seckeys[i], &data.seckeys[i - 1], &data.seckeys[i - 1]); } } - rustsecp256k1_v0_10_0_ge_set_all_gej_var(data.pubkeys, data.pubkeys_gej, POINTS); + rustsecp256k1_v0_11_ge_set_all_gej_var(data.pubkeys, data.pubkeys_gej, POINTS); print_output_table_header_row(); @@ -353,9 +353,9 @@ int main(int argc, char **argv) { } if (data.scratch != NULL) { - rustsecp256k1_v0_10_0_scratch_space_destroy(data.ctx, data.scratch); + rustsecp256k1_v0_11_scratch_space_destroy(data.ctx, data.scratch); } - rustsecp256k1_v0_10_0_context_destroy(data.ctx); + rustsecp256k1_v0_11_context_destroy(data.ctx); free(data.scalars); free(data.pubkeys); free(data.pubkeys_gej); diff --git a/secp256k1-sys/depend/secp256k1/src/bench_internal.c b/secp256k1-sys/depend/secp256k1/src/bench_internal.c index 913bb9c0b..e9a301b83 100644 --- a/secp256k1-sys/depend/secp256k1/src/bench_internal.c +++ b/secp256k1-sys/depend/secp256k1/src/bench_internal.c @@ -37,10 +37,10 @@ static void help(int default_iters) { } typedef struct { - rustsecp256k1_v0_10_0_scalar scalar[2]; - rustsecp256k1_v0_10_0_fe fe[4]; - rustsecp256k1_v0_10_0_ge ge[2]; - rustsecp256k1_v0_10_0_gej gej[2]; + rustsecp256k1_v0_11_scalar scalar[2]; + rustsecp256k1_v0_11_fe fe[4]; + rustsecp256k1_v0_11_ge ge[2]; + rustsecp256k1_v0_11_gej gej[2]; unsigned char data[64]; int wnaf[256]; } bench_inv; @@ -81,18 +81,18 @@ static void bench_setup(void* arg) { } }; - rustsecp256k1_v0_10_0_scalar_set_b32(&data->scalar[0], init[0], NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(&data->scalar[1], init[1], NULL); - rustsecp256k1_v0_10_0_fe_set_b32_limit(&data->fe[0], init[0]); - rustsecp256k1_v0_10_0_fe_set_b32_limit(&data->fe[1], init[1]); - rustsecp256k1_v0_10_0_fe_set_b32_limit(&data->fe[2], init[2]); - rustsecp256k1_v0_10_0_fe_set_b32_limit(&data->fe[3], init[3]); - CHECK(rustsecp256k1_v0_10_0_ge_set_xo_var(&data->ge[0], &data->fe[0], 0)); - CHECK(rustsecp256k1_v0_10_0_ge_set_xo_var(&data->ge[1], &data->fe[1], 1)); - rustsecp256k1_v0_10_0_gej_set_ge(&data->gej[0], &data->ge[0]); - rustsecp256k1_v0_10_0_gej_rescale(&data->gej[0], &data->fe[2]); - rustsecp256k1_v0_10_0_gej_set_ge(&data->gej[1], &data->ge[1]); - rustsecp256k1_v0_10_0_gej_rescale(&data->gej[1], &data->fe[3]); + rustsecp256k1_v0_11_scalar_set_b32(&data->scalar[0], init[0], NULL); + rustsecp256k1_v0_11_scalar_set_b32(&data->scalar[1], init[1], NULL); + rustsecp256k1_v0_11_fe_set_b32_limit(&data->fe[0], init[0]); + rustsecp256k1_v0_11_fe_set_b32_limit(&data->fe[1], init[1]); + rustsecp256k1_v0_11_fe_set_b32_limit(&data->fe[2], init[2]); + rustsecp256k1_v0_11_fe_set_b32_limit(&data->fe[3], init[3]); + CHECK(rustsecp256k1_v0_11_ge_set_xo_var(&data->ge[0], &data->fe[0], 0)); + CHECK(rustsecp256k1_v0_11_ge_set_xo_var(&data->ge[1], &data->fe[1], 1)); + rustsecp256k1_v0_11_gej_set_ge(&data->gej[0], &data->ge[0]); + rustsecp256k1_v0_11_gej_rescale(&data->gej[0], &data->fe[2]); + rustsecp256k1_v0_11_gej_set_ge(&data->gej[1], &data->ge[1]); + rustsecp256k1_v0_11_gej_rescale(&data->gej[1], &data->fe[3]); memcpy(data->data, init[0], 32); memcpy(data->data + 32, init[1], 32); } @@ -102,7 +102,7 @@ static void bench_scalar_add(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - j += rustsecp256k1_v0_10_0_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); + j += rustsecp256k1_v0_11_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } @@ -112,17 +112,17 @@ static void bench_scalar_negate(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_scalar_negate(&data->scalar[0], &data->scalar[0]); + rustsecp256k1_v0_11_scalar_negate(&data->scalar[0], &data->scalar[0]); } } static void bench_scalar_half(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_scalar s = data->scalar[0]; + rustsecp256k1_v0_11_scalar s = data->scalar[0]; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_scalar_half(&s, &s); + rustsecp256k1_v0_11_scalar_half(&s, &s); } data->scalar[0] = s; @@ -133,18 +133,18 @@ static void bench_scalar_mul(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_scalar_mul(&data->scalar[0], &data->scalar[0], &data->scalar[1]); + rustsecp256k1_v0_11_scalar_mul(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } } static void bench_scalar_split(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_scalar tmp; + rustsecp256k1_v0_11_scalar tmp; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_scalar_split_lambda(&tmp, &data->scalar[1], &data->scalar[0]); - j += rustsecp256k1_v0_10_0_scalar_add(&data->scalar[0], &tmp, &data->scalar[1]); + rustsecp256k1_v0_11_scalar_split_lambda(&tmp, &data->scalar[1], &data->scalar[0]); + j += rustsecp256k1_v0_11_scalar_add(&data->scalar[0], &tmp, &data->scalar[1]); } CHECK(j <= iters); } @@ -154,8 +154,8 @@ static void bench_scalar_inverse(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_scalar_inverse(&data->scalar[0], &data->scalar[0]); - j += rustsecp256k1_v0_10_0_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); + rustsecp256k1_v0_11_scalar_inverse(&data->scalar[0], &data->scalar[0]); + j += rustsecp256k1_v0_11_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } @@ -165,8 +165,8 @@ static void bench_scalar_inverse_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_scalar_inverse_var(&data->scalar[0], &data->scalar[0]); - j += rustsecp256k1_v0_10_0_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); + rustsecp256k1_v0_11_scalar_inverse_var(&data->scalar[0], &data->scalar[0]); + j += rustsecp256k1_v0_11_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(j <= iters); } @@ -176,7 +176,7 @@ static void bench_field_half(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_half(&data->fe[0]); + rustsecp256k1_v0_11_fe_half(&data->fe[0]); } } @@ -185,7 +185,7 @@ static void bench_field_normalize(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_normalize(&data->fe[0]); + rustsecp256k1_v0_11_fe_normalize(&data->fe[0]); } } @@ -194,7 +194,7 @@ static void bench_field_normalize_weak(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_normalize_weak(&data->fe[0]); + rustsecp256k1_v0_11_fe_normalize_weak(&data->fe[0]); } } @@ -203,7 +203,7 @@ static void bench_field_mul(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_mul(&data->fe[0], &data->fe[0], &data->fe[1]); + rustsecp256k1_v0_11_fe_mul(&data->fe[0], &data->fe[0], &data->fe[1]); } } @@ -212,7 +212,7 @@ static void bench_field_sqr(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_sqr(&data->fe[0], &data->fe[0]); + rustsecp256k1_v0_11_fe_sqr(&data->fe[0], &data->fe[0]); } } @@ -221,8 +221,8 @@ static void bench_field_inverse(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_inv(&data->fe[0], &data->fe[0]); - rustsecp256k1_v0_10_0_fe_add(&data->fe[0], &data->fe[1]); + rustsecp256k1_v0_11_fe_inv(&data->fe[0], &data->fe[0]); + rustsecp256k1_v0_11_fe_add(&data->fe[0], &data->fe[1]); } } @@ -231,20 +231,20 @@ static void bench_field_inverse_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_fe_inv_var(&data->fe[0], &data->fe[0]); - rustsecp256k1_v0_10_0_fe_add(&data->fe[0], &data->fe[1]); + rustsecp256k1_v0_11_fe_inv_var(&data->fe[0], &data->fe[0]); + rustsecp256k1_v0_11_fe_add(&data->fe[0], &data->fe[1]); } } static void bench_field_sqrt(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_fe t; + rustsecp256k1_v0_11_fe t; for (i = 0; i < iters; i++) { t = data->fe[0]; - j += rustsecp256k1_v0_10_0_fe_sqrt(&data->fe[0], &t); - rustsecp256k1_v0_10_0_fe_add(&data->fe[0], &data->fe[1]); + j += rustsecp256k1_v0_11_fe_sqrt(&data->fe[0], &t); + rustsecp256k1_v0_11_fe_add(&data->fe[0], &data->fe[1]); } CHECK(j <= iters); } @@ -252,12 +252,12 @@ static void bench_field_sqrt(void* arg, int iters) { static void bench_field_is_square_var(void* arg, int iters) { int i, j = 0; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_fe t = data->fe[0]; + rustsecp256k1_v0_11_fe t = data->fe[0]; for (i = 0; i < iters; i++) { - j += rustsecp256k1_v0_10_0_fe_is_square_var(&t); - rustsecp256k1_v0_10_0_fe_add(&t, &data->fe[1]); - rustsecp256k1_v0_10_0_fe_normalize_var(&t); + j += rustsecp256k1_v0_11_fe_is_square_var(&t); + rustsecp256k1_v0_11_fe_add(&t, &data->fe[1]); + rustsecp256k1_v0_11_fe_normalize_var(&t); } CHECK(j <= iters); } @@ -267,7 +267,7 @@ static void bench_group_double_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_gej_double_var(&data->gej[0], &data->gej[0], NULL); + rustsecp256k1_v0_11_gej_double_var(&data->gej[0], &data->gej[0], NULL); } } @@ -276,7 +276,7 @@ static void bench_group_add_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_gej_add_var(&data->gej[0], &data->gej[0], &data->gej[1], NULL); + rustsecp256k1_v0_11_gej_add_var(&data->gej[0], &data->gej[0], &data->gej[1], NULL); } } @@ -285,7 +285,7 @@ static void bench_group_add_affine(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_gej_add_ge(&data->gej[0], &data->gej[0], &data->ge[1]); + rustsecp256k1_v0_11_gej_add_ge(&data->gej[0], &data->gej[0], &data->ge[1]); } } @@ -294,7 +294,7 @@ static void bench_group_add_affine_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_gej_add_ge_var(&data->gej[0], &data->gej[0], &data->ge[1], NULL); + rustsecp256k1_v0_11_gej_add_ge_var(&data->gej[0], &data->gej[0], &data->ge[1], NULL); } } @@ -303,7 +303,7 @@ static void bench_group_add_zinv_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_gej_add_zinv_var(&data->gej[0], &data->gej[0], &data->ge[1], &data->gej[0].y); + rustsecp256k1_v0_11_gej_add_zinv_var(&data->gej[0], &data->gej[0], &data->ge[1], &data->gej[0].y); } } @@ -312,18 +312,18 @@ static void bench_group_to_affine_var(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; ++i) { - rustsecp256k1_v0_10_0_ge_set_gej_var(&data->ge[1], &data->gej[0]); + rustsecp256k1_v0_11_ge_set_gej_var(&data->ge[1], &data->gej[0]); /* Use the output affine X/Y coordinates to vary the input X/Y/Z coordinates. Note that the resulting coordinates will generally not correspond to a point on the curve, but this is not a problem for the code being benchmarked here. Adding and normalizing have less overhead than EC operations (which could guarantee the point remains on the curve). */ - rustsecp256k1_v0_10_0_fe_add(&data->gej[0].x, &data->ge[1].y); - rustsecp256k1_v0_10_0_fe_add(&data->gej[0].y, &data->fe[2]); - rustsecp256k1_v0_10_0_fe_add(&data->gej[0].z, &data->ge[1].x); - rustsecp256k1_v0_10_0_fe_normalize_var(&data->gej[0].x); - rustsecp256k1_v0_10_0_fe_normalize_var(&data->gej[0].y); - rustsecp256k1_v0_10_0_fe_normalize_var(&data->gej[0].z); + rustsecp256k1_v0_11_fe_add(&data->gej[0].x, &data->ge[1].y); + rustsecp256k1_v0_11_fe_add(&data->gej[0].y, &data->fe[2]); + rustsecp256k1_v0_11_fe_add(&data->gej[0].z, &data->ge[1].x); + rustsecp256k1_v0_11_fe_normalize_var(&data->gej[0].x); + rustsecp256k1_v0_11_fe_normalize_var(&data->gej[0].y); + rustsecp256k1_v0_11_fe_normalize_var(&data->gej[0].z); } } @@ -332,8 +332,8 @@ static void bench_ecmult_wnaf(void* arg, int iters) { bench_inv *data = (bench_inv*)arg; for (i = 0; i < iters; i++) { - bits += rustsecp256k1_v0_10_0_ecmult_wnaf(data->wnaf, 256, &data->scalar[0], WINDOW_A); - overflow += rustsecp256k1_v0_10_0_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); + bits += rustsecp256k1_v0_11_ecmult_wnaf(data->wnaf, 256, &data->scalar[0], WINDOW_A); + overflow += rustsecp256k1_v0_11_scalar_add(&data->scalar[0], &data->scalar[0], &data->scalar[1]); } CHECK(overflow >= 0); CHECK(bits <= 256*iters); @@ -342,35 +342,35 @@ static void bench_ecmult_wnaf(void* arg, int iters) { static void bench_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_sha256_initialize(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, data->data, 32); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, data->data); + rustsecp256k1_v0_11_sha256_initialize(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, data->data, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, data->data); } } static void bench_hmac_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_hmac_sha256 hmac; + rustsecp256k1_v0_11_hmac_sha256 hmac; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, data->data, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, data->data, 32); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, data->data); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, data->data, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, data->data, 32); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, data->data); } } static void bench_rfc6979_hmac_sha256(void* arg, int iters) { int i; bench_inv *data = (bench_inv*)arg; - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 rng; + rustsecp256k1_v0_11_rfc6979_hmac_sha256 rng; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, data->data, 32); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, data->data, 32); } } @@ -378,7 +378,7 @@ static void bench_context(void* arg, int iters) { int i; (void)arg; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_context_destroy(rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE)); + rustsecp256k1_v0_11_context_destroy(rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE)); } } diff --git a/secp256k1-sys/depend/secp256k1/src/checkmem.h b/secp256k1-sys/depend/secp256k1/src/checkmem.h index f2169decf..7e333ce5f 100644 --- a/secp256k1-sys/depend/secp256k1/src/checkmem.h +++ b/secp256k1-sys/depend/secp256k1/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 diff --git a/secp256k1-sys/depend/secp256k1/src/ctime_tests.c b/secp256k1-sys/depend/secp256k1/src/ctime_tests.c index 4149e0ef1..19c0abe3e 100644 --- a/secp256k1-sys/depend/secp256k1/src/ctime_tests.c +++ b/secp256k1-sys/depend/secp256k1/src/ctime_tests.c @@ -5,6 +5,7 @@ ***********************************************************************/ #include +#include #include "../include/secp256k1.h" #include "assumptions.h" @@ -15,29 +16,33 @@ #endif #ifdef ENABLE_MODULE_ECDH -# include "../include/rustsecp256k1_v0_10_0_ecdh.h" +# include "../include/rustsecp256k1_v0_11_ecdh.h" #endif #ifdef ENABLE_MODULE_RECOVERY -# include "../include/rustsecp256k1_v0_10_0_recovery.h" +# include "../include/rustsecp256k1_v0_11_recovery.h" #endif #ifdef ENABLE_MODULE_EXTRAKEYS -# include "../include/rustsecp256k1_v0_10_0_extrakeys.h" +# include "../include/rustsecp256k1_v0_11_extrakeys.h" #endif #ifdef ENABLE_MODULE_SCHNORRSIG #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 -static void run_tests(rustsecp256k1_v0_10_0_context *ctx, unsigned char *key); +static void run_tests(rustsecp256k1_v0_11_context *ctx, unsigned char *key); int main(void) { - rustsecp256k1_v0_10_0_context* ctx; + rustsecp256k1_v0_11_context* ctx; unsigned char key[32]; int ret, i; @@ -46,7 +51,7 @@ int main(void) { fprintf(stderr, "Usage: libtool --mode=execute valgrind ./ctime_tests\n"); return 1; } - ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_DECLASSIFY); + ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_DECLASSIFY); /** In theory, testing with a single secret input should be sufficient: * If control flow depended on secrets the tool would generate an error. */ @@ -59,17 +64,17 @@ int main(void) { /* Test context randomisation. Do this last because it leaves the context * tainted. */ SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_context_randomize(ctx, key); + ret = rustsecp256k1_v0_11_context_randomize(ctx, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret); - rustsecp256k1_v0_10_0_context_destroy(ctx); + rustsecp256k1_v0_11_context_destroy(ctx); return 0; } -static void run_tests(rustsecp256k1_v0_10_0_context *ctx, unsigned char *key) { - rustsecp256k1_v0_10_0_ecdsa_signature signature; - rustsecp256k1_v0_10_0_pubkey pubkey; +static void run_tests(rustsecp256k1_v0_11_context *ctx, unsigned char *key) { + rustsecp256k1_v0_11_ecdsa_signature signature; + rustsecp256k1_v0_11_pubkey pubkey; size_t siglen = 74; size_t outputlen = 33; int i; @@ -78,11 +83,11 @@ static void run_tests(rustsecp256k1_v0_10_0_context *ctx, unsigned char *key) { unsigned char sig[74]; unsigned char spubkey[33]; #ifdef ENABLE_MODULE_RECOVERY - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature recoverable_signature; + rustsecp256k1_v0_11_ecdsa_recoverable_signature recoverable_signature; int recid; #endif #ifdef ENABLE_MODULE_EXTRAKEYS - rustsecp256k1_v0_10_0_keypair keypair; + rustsecp256k1_v0_11_keypair keypair; #endif #ifdef ENABLE_MODULE_ELLSWIFT unsigned char ellswift[64]; @@ -95,24 +100,24 @@ static void run_tests(rustsecp256k1_v0_10_0_context *ctx, unsigned char *key) { /* Test keygen. */ SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ec_pubkey_create(ctx, &pubkey, key); - SECP256K1_CHECKMEM_DEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); + ret = rustsecp256k1_v0_11_ec_pubkey_create(ctx, &pubkey, key); + SECP256K1_CHECKMEM_DEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, spubkey, &outputlen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); /* Test signing. */ SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL); - SECP256K1_CHECKMEM_DEFINE(&signature, sizeof(rustsecp256k1_v0_10_0_ecdsa_signature)); + ret = rustsecp256k1_v0_11_ecdsa_sign(ctx, &signature, msg, key, NULL, NULL); + SECP256K1_CHECKMEM_DEFINE(&signature, sizeof(rustsecp256k1_v0_11_ecdsa_signature)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature)); #ifdef ENABLE_MODULE_ECDH /* Test ECDH. */ SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ecdh(ctx, msg, &pubkey, key, NULL, NULL); + ret = rustsecp256k1_v0_11_ecdh(ctx, msg, &pubkey, key, NULL, NULL); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); #endif @@ -120,87 +125,139 @@ static void run_tests(rustsecp256k1_v0_10_0_context *ctx, unsigned char *key) { #ifdef ENABLE_MODULE_RECOVERY /* Test signing a recoverable signature. */ SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL); + ret = rustsecp256k1_v0_11_ecdsa_sign_recoverable(ctx, &recoverable_signature, msg, key, NULL, NULL); SECP256K1_CHECKMEM_DEFINE(&recoverable_signature, sizeof(recoverable_signature)); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &recoverable_signature)); CHECK(recid >= 0 && recid <= 3); #endif SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ec_seckey_verify(ctx, key); + ret = rustsecp256k1_v0_11_ec_seckey_verify(ctx, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ec_seckey_negate(ctx, key); + ret = rustsecp256k1_v0_11_ec_seckey_negate(ctx, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); SECP256K1_CHECKMEM_UNDEFINE(key, 32); SECP256K1_CHECKMEM_UNDEFINE(msg, 32); - ret = rustsecp256k1_v0_10_0_ec_seckey_tweak_add(ctx, key, msg); + ret = rustsecp256k1_v0_11_ec_seckey_tweak_add(ctx, key, msg); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); SECP256K1_CHECKMEM_UNDEFINE(key, 32); SECP256K1_CHECKMEM_UNDEFINE(msg, 32); - ret = rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(ctx, key, msg); + ret = rustsecp256k1_v0_11_ec_seckey_tweak_mul(ctx, key, msg); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); /* Test keypair_create and keypair_xonly_tweak_add. */ #ifdef ENABLE_MODULE_EXTRAKEYS SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_keypair_create(ctx, &keypair, key); + ret = rustsecp256k1_v0_11_keypair_create(ctx, &keypair, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); /* The tweak is not treated as a secret in keypair_tweak_add */ SECP256K1_CHECKMEM_DEFINE(msg, 32); - ret = rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(ctx, &keypair, msg); + ret = rustsecp256k1_v0_11_keypair_xonly_tweak_add(ctx, &keypair, msg); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); SECP256K1_CHECKMEM_UNDEFINE(key, 32); SECP256K1_CHECKMEM_UNDEFINE(&keypair, sizeof(keypair)); - ret = rustsecp256k1_v0_10_0_keypair_sec(ctx, key, &keypair); + ret = rustsecp256k1_v0_11_keypair_sec(ctx, key, &keypair); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); #endif #ifdef ENABLE_MODULE_SCHNORRSIG SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_keypair_create(ctx, &keypair, key); + ret = rustsecp256k1_v0_11_keypair_create(ctx, &keypair, key); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); - ret = rustsecp256k1_v0_10_0_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL); + ret = rustsecp256k1_v0_11_schnorrsig_sign32(ctx, sig, msg, &keypair, NULL); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); #endif +#ifdef ENABLE_MODULE_MUSIG + { + rustsecp256k1_v0_11_pubkey pk; + const rustsecp256k1_v0_11_pubkey *pk_ptr[1]; + rustsecp256k1_v0_11_xonly_pubkey agg_pk; + unsigned char session_secrand[32]; + uint64_t nonrepeating_cnt = 0; + rustsecp256k1_v0_11_musig_secnonce secnonce; + rustsecp256k1_v0_11_musig_pubnonce pubnonce; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[1]; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_musig_keyagg_cache cache; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_keypair_create(ctx, &keypair, key)); + CHECK(rustsecp256k1_v0_11_keypair_pub(ctx, &pk, &keypair)); + CHECK(rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_musig_nonce_gen(ctx, &secnonce, &pubnonce, session_secrand, key, &pk, msg, &cache, extra_input); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + ret = rustsecp256k1_v0_11_musig_nonce_gen_counter(ctx, &secnonce, &pubnonce, nonrepeating_cnt, &keypair, msg, &cache, extra_input); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_process(ctx, &session, &aggnonce, msg, &cache) == 1); + + ret = rustsecp256k1_v0_11_keypair_create(ctx, &keypair, key); + SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); + CHECK(ret == 1); + ret = rustsecp256k1_v0_11_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 = rustsecp256k1_v0_10_0_ellswift_create(ctx, ellswift, key, NULL); + ret = rustsecp256k1_v0_11_ellswift_create(ctx, ellswift, key, NULL); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); SECP256K1_CHECKMEM_UNDEFINE(key, 32); - ret = rustsecp256k1_v0_10_0_ellswift_create(ctx, ellswift, key, ellswift); + ret = rustsecp256k1_v0_11_ellswift_create(ctx, ellswift, key, ellswift); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); for (i = 0; i < 2; i++) { SECP256K1_CHECKMEM_UNDEFINE(key, 32); SECP256K1_CHECKMEM_DEFINE(&ellswift, sizeof(ellswift)); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324, NULL); + ret = rustsecp256k1_v0_11_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324, NULL); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); SECP256K1_CHECKMEM_UNDEFINE(key, 32); SECP256K1_CHECKMEM_DEFINE(&ellswift, sizeof(ellswift)); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_prefix, (void *)prefix); + ret = rustsecp256k1_v0_11_ellswift_xdh(ctx, msg, ellswift, ellswift, key, i, rustsecp256k1_v0_11_ellswift_xdh_hash_function_prefix, (void *)prefix); SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret)); CHECK(ret == 1); } diff --git a/secp256k1-sys/depend/secp256k1/src/ecdsa.h b/secp256k1-sys/depend/secp256k1/src/ecdsa.h index 79a6f3071..77ae94988 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecdsa.h +++ b/secp256k1-sys/depend/secp256k1/src/ecdsa.h @@ -13,9 +13,9 @@ #include "group.h" #include "ecmult.h" -static int rustsecp256k1_v0_10_0_ecdsa_sig_parse(rustsecp256k1_v0_10_0_scalar *r, rustsecp256k1_v0_10_0_scalar *s, const unsigned char *sig, size_t size); -static int rustsecp256k1_v0_10_0_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *s); -static int rustsecp256k1_v0_10_0_ecdsa_sig_verify(const rustsecp256k1_v0_10_0_scalar* r, const rustsecp256k1_v0_10_0_scalar* s, const rustsecp256k1_v0_10_0_ge *pubkey, const rustsecp256k1_v0_10_0_scalar *message); -static int rustsecp256k1_v0_10_0_ecdsa_sig_sign(const rustsecp256k1_v0_10_0_ecmult_gen_context *ctx, rustsecp256k1_v0_10_0_scalar* r, rustsecp256k1_v0_10_0_scalar* s, const rustsecp256k1_v0_10_0_scalar *seckey, const rustsecp256k1_v0_10_0_scalar *message, const rustsecp256k1_v0_10_0_scalar *nonce, int *recid); +static int rustsecp256k1_v0_11_ecdsa_sig_parse(rustsecp256k1_v0_11_scalar *r, rustsecp256k1_v0_11_scalar *s, const unsigned char *sig, size_t size); +static int rustsecp256k1_v0_11_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *s); +static int rustsecp256k1_v0_11_ecdsa_sig_verify(const rustsecp256k1_v0_11_scalar* r, const rustsecp256k1_v0_11_scalar* s, const rustsecp256k1_v0_11_ge *pubkey, const rustsecp256k1_v0_11_scalar *message); +static int rustsecp256k1_v0_11_ecdsa_sig_sign(const rustsecp256k1_v0_11_ecmult_gen_context *ctx, rustsecp256k1_v0_11_scalar* r, rustsecp256k1_v0_11_scalar* s, const rustsecp256k1_v0_11_scalar *seckey, const rustsecp256k1_v0_11_scalar *message, const rustsecp256k1_v0_11_scalar *nonce, int *recid); #endif /* SECP256K1_ECDSA_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h b/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h index 0bede02ad..2c8cb4dd6 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecdsa_impl.h @@ -16,24 +16,24 @@ #include "ecdsa.h" /** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 - * $ sage -c 'load("rustsecp256k1_v0_10_0_params.sage"); print(hex(N))' + * $ sage -c 'load("rustsecp256k1_v0_11_params.sage"); print(hex(N))' * 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 */ -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL ); /** Difference between field and order, values 'p' and 'n' values defined in * "Standards for Efficient Cryptography" (SEC2) 2.7.1. - * $ sage -c 'load("rustsecp256k1_v0_10_0_params.sage"); print(hex(P-N))' + * $ sage -c 'load("rustsecp256k1_v0_11_params.sage"); print(hex(P-N))' * 0x14551231950b75fc4402da1722fc9baee */ -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL ); -static int rustsecp256k1_v0_10_0_der_read_len(size_t *len, const unsigned char **sigp, const unsigned char *sigend) { +static int rustsecp256k1_v0_11_der_read_len(size_t *len, const unsigned char **sigp, const unsigned char *sigend) { size_t lenleft; unsigned char b1; VERIFY_CHECK(len != NULL); @@ -87,7 +87,7 @@ static int rustsecp256k1_v0_10_0_der_read_len(size_t *len, const unsigned char * return 1; } -static int rustsecp256k1_v0_10_0_der_parse_integer(rustsecp256k1_v0_10_0_scalar *r, const unsigned char **sig, const unsigned char *sigend) { +static int rustsecp256k1_v0_11_der_parse_integer(rustsecp256k1_v0_11_scalar *r, const unsigned char **sig, const unsigned char *sigend) { int overflow = 0; unsigned char ra[32] = {0}; size_t rlen; @@ -97,7 +97,7 @@ static int rustsecp256k1_v0_10_0_der_parse_integer(rustsecp256k1_v0_10_0_scalar return 0; } (*sig)++; - if (rustsecp256k1_v0_10_0_der_read_len(&rlen, sig, sigend) == 0) { + if (rustsecp256k1_v0_11_der_read_len(&rlen, sig, sigend) == 0) { return 0; } if (rlen == 0 || rlen > (size_t)(sigend - *sig)) { @@ -129,23 +129,23 @@ static int rustsecp256k1_v0_10_0_der_parse_integer(rustsecp256k1_v0_10_0_scalar } if (!overflow) { if (rlen) memcpy(ra + 32 - rlen, *sig, rlen); - rustsecp256k1_v0_10_0_scalar_set_b32(r, ra, &overflow); + rustsecp256k1_v0_11_scalar_set_b32(r, ra, &overflow); } if (overflow) { - rustsecp256k1_v0_10_0_scalar_set_int(r, 0); + rustsecp256k1_v0_11_scalar_set_int(r, 0); } (*sig) += rlen; return 1; } -static int rustsecp256k1_v0_10_0_ecdsa_sig_parse(rustsecp256k1_v0_10_0_scalar *rr, rustsecp256k1_v0_10_0_scalar *rs, const unsigned char *sig, size_t size) { +static int rustsecp256k1_v0_11_ecdsa_sig_parse(rustsecp256k1_v0_11_scalar *rr, rustsecp256k1_v0_11_scalar *rs, const unsigned char *sig, size_t size) { const unsigned char *sigend = sig + size; size_t rlen; if (sig == sigend || *(sig++) != 0x30) { /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ return 0; } - if (rustsecp256k1_v0_10_0_der_read_len(&rlen, &sig, sigend) == 0) { + if (rustsecp256k1_v0_11_der_read_len(&rlen, &sig, sigend) == 0) { return 0; } if (rlen != (size_t)(sigend - sig)) { @@ -153,10 +153,10 @@ static int rustsecp256k1_v0_10_0_ecdsa_sig_parse(rustsecp256k1_v0_10_0_scalar *r return 0; } - if (!rustsecp256k1_v0_10_0_der_parse_integer(rr, &sig, sigend)) { + if (!rustsecp256k1_v0_11_der_parse_integer(rr, &sig, sigend)) { return 0; } - if (!rustsecp256k1_v0_10_0_der_parse_integer(rs, &sig, sigend)) { + if (!rustsecp256k1_v0_11_der_parse_integer(rs, &sig, sigend)) { return 0; } @@ -168,12 +168,12 @@ static int rustsecp256k1_v0_10_0_ecdsa_sig_parse(rustsecp256k1_v0_10_0_scalar *r return 1; } -static int rustsecp256k1_v0_10_0_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const rustsecp256k1_v0_10_0_scalar* ar, const rustsecp256k1_v0_10_0_scalar* as) { +static int rustsecp256k1_v0_11_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const rustsecp256k1_v0_11_scalar* ar, const rustsecp256k1_v0_11_scalar* as) { unsigned char r[33] = {0}, s[33] = {0}; unsigned char *rp = r, *sp = s; size_t lenR = 33, lenS = 33; - rustsecp256k1_v0_10_0_scalar_get_b32(&r[1], ar); - rustsecp256k1_v0_10_0_scalar_get_b32(&s[1], as); + rustsecp256k1_v0_11_scalar_get_b32(&r[1], ar); + rustsecp256k1_v0_11_scalar_get_b32(&s[1], as); while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } if (*size < 6+lenS+lenR) { @@ -192,43 +192,43 @@ static int rustsecp256k1_v0_10_0_ecdsa_sig_serialize(unsigned char *sig, size_t return 1; } -static int rustsecp256k1_v0_10_0_ecdsa_sig_verify(const rustsecp256k1_v0_10_0_scalar *sigr, const rustsecp256k1_v0_10_0_scalar *sigs, const rustsecp256k1_v0_10_0_ge *pubkey, const rustsecp256k1_v0_10_0_scalar *message) { +static int rustsecp256k1_v0_11_ecdsa_sig_verify(const rustsecp256k1_v0_11_scalar *sigr, const rustsecp256k1_v0_11_scalar *sigs, const rustsecp256k1_v0_11_ge *pubkey, const rustsecp256k1_v0_11_scalar *message) { unsigned char c[32]; - rustsecp256k1_v0_10_0_scalar sn, u1, u2; + rustsecp256k1_v0_11_scalar sn, u1, u2; #if !defined(EXHAUSTIVE_TEST_ORDER) - rustsecp256k1_v0_10_0_fe xr; + rustsecp256k1_v0_11_fe xr; #endif - rustsecp256k1_v0_10_0_gej pubkeyj; - rustsecp256k1_v0_10_0_gej pr; + rustsecp256k1_v0_11_gej pubkeyj; + rustsecp256k1_v0_11_gej pr; - if (rustsecp256k1_v0_10_0_scalar_is_zero(sigr) || rustsecp256k1_v0_10_0_scalar_is_zero(sigs)) { + if (rustsecp256k1_v0_11_scalar_is_zero(sigr) || rustsecp256k1_v0_11_scalar_is_zero(sigs)) { return 0; } - rustsecp256k1_v0_10_0_scalar_inverse_var(&sn, sigs); - rustsecp256k1_v0_10_0_scalar_mul(&u1, &sn, message); - rustsecp256k1_v0_10_0_scalar_mul(&u2, &sn, sigr); - rustsecp256k1_v0_10_0_gej_set_ge(&pubkeyj, pubkey); - rustsecp256k1_v0_10_0_ecmult(&pr, &pubkeyj, &u2, &u1); - if (rustsecp256k1_v0_10_0_gej_is_infinity(&pr)) { + rustsecp256k1_v0_11_scalar_inverse_var(&sn, sigs); + rustsecp256k1_v0_11_scalar_mul(&u1, &sn, message); + rustsecp256k1_v0_11_scalar_mul(&u2, &sn, sigr); + rustsecp256k1_v0_11_gej_set_ge(&pubkeyj, pubkey); + rustsecp256k1_v0_11_ecmult(&pr, &pubkeyj, &u2, &u1); + if (rustsecp256k1_v0_11_gej_is_infinity(&pr)) { return 0; } #if defined(EXHAUSTIVE_TEST_ORDER) { - rustsecp256k1_v0_10_0_scalar computed_r; - rustsecp256k1_v0_10_0_ge pr_ge; - rustsecp256k1_v0_10_0_ge_set_gej(&pr_ge, &pr); - rustsecp256k1_v0_10_0_fe_normalize(&pr_ge.x); + rustsecp256k1_v0_11_scalar computed_r; + rustsecp256k1_v0_11_ge pr_ge; + rustsecp256k1_v0_11_ge_set_gej(&pr_ge, &pr); + rustsecp256k1_v0_11_fe_normalize(&pr_ge.x); - rustsecp256k1_v0_10_0_fe_get_b32(c, &pr_ge.x); - rustsecp256k1_v0_10_0_scalar_set_b32(&computed_r, c, NULL); - return rustsecp256k1_v0_10_0_scalar_eq(sigr, &computed_r); + rustsecp256k1_v0_11_fe_get_b32(c, &pr_ge.x); + rustsecp256k1_v0_11_scalar_set_b32(&computed_r, c, NULL); + return rustsecp256k1_v0_11_scalar_eq(sigr, &computed_r); } #else - rustsecp256k1_v0_10_0_scalar_get_b32(c, sigr); + rustsecp256k1_v0_11_scalar_get_b32(c, sigr); /* we can ignore the fe_set_b32_limit return value, because we know the input is in range */ - (void)rustsecp256k1_v0_10_0_fe_set_b32_limit(&xr, c); + (void)rustsecp256k1_v0_11_fe_set_b32_limit(&xr, c); /** 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), @@ -244,18 +244,18 @@ static int rustsecp256k1_v0_10_0_ecdsa_sig_verify(const rustsecp256k1_v0_10_0_sc * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) * * Thus, we can avoid the inversion, but we have to check both cases separately. - * rustsecp256k1_v0_10_0_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. + * rustsecp256k1_v0_11_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. */ - if (rustsecp256k1_v0_10_0_gej_eq_x_var(&xr, &pr)) { + if (rustsecp256k1_v0_11_gej_eq_x_var(&xr, &pr)) { /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ return 1; } - if (rustsecp256k1_v0_10_0_fe_cmp_var(&xr, &rustsecp256k1_v0_10_0_ecdsa_const_p_minus_order) >= 0) { + if (rustsecp256k1_v0_11_fe_cmp_var(&xr, &rustsecp256k1_v0_11_ecdsa_const_p_minus_order) >= 0) { /* xr + n >= p, so we can skip testing the second case. */ return 0; } - rustsecp256k1_v0_10_0_fe_add(&xr, &rustsecp256k1_v0_10_0_ecdsa_const_order_as_fe); - if (rustsecp256k1_v0_10_0_gej_eq_x_var(&xr, &pr)) { + rustsecp256k1_v0_11_fe_add(&xr, &rustsecp256k1_v0_11_ecdsa_const_order_as_fe); + if (rustsecp256k1_v0_11_gej_eq_x_var(&xr, &pr)) { /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ return 1; } @@ -263,42 +263,42 @@ static int rustsecp256k1_v0_10_0_ecdsa_sig_verify(const rustsecp256k1_v0_10_0_sc #endif } -static int rustsecp256k1_v0_10_0_ecdsa_sig_sign(const rustsecp256k1_v0_10_0_ecmult_gen_context *ctx, rustsecp256k1_v0_10_0_scalar *sigr, rustsecp256k1_v0_10_0_scalar *sigs, const rustsecp256k1_v0_10_0_scalar *seckey, const rustsecp256k1_v0_10_0_scalar *message, const rustsecp256k1_v0_10_0_scalar *nonce, int *recid) { +static int rustsecp256k1_v0_11_ecdsa_sig_sign(const rustsecp256k1_v0_11_ecmult_gen_context *ctx, rustsecp256k1_v0_11_scalar *sigr, rustsecp256k1_v0_11_scalar *sigs, const rustsecp256k1_v0_11_scalar *seckey, const rustsecp256k1_v0_11_scalar *message, const rustsecp256k1_v0_11_scalar *nonce, int *recid) { unsigned char b[32]; - rustsecp256k1_v0_10_0_gej rp; - rustsecp256k1_v0_10_0_ge r; - rustsecp256k1_v0_10_0_scalar n; + rustsecp256k1_v0_11_gej rp; + rustsecp256k1_v0_11_ge r; + rustsecp256k1_v0_11_scalar n; int overflow = 0; int high; - rustsecp256k1_v0_10_0_ecmult_gen(ctx, &rp, nonce); - rustsecp256k1_v0_10_0_ge_set_gej(&r, &rp); - rustsecp256k1_v0_10_0_fe_normalize(&r.x); - rustsecp256k1_v0_10_0_fe_normalize(&r.y); - rustsecp256k1_v0_10_0_fe_get_b32(b, &r.x); - rustsecp256k1_v0_10_0_scalar_set_b32(sigr, b, &overflow); + rustsecp256k1_v0_11_ecmult_gen(ctx, &rp, nonce); + rustsecp256k1_v0_11_ge_set_gej(&r, &rp); + rustsecp256k1_v0_11_fe_normalize(&r.x); + rustsecp256k1_v0_11_fe_normalize(&r.y); + rustsecp256k1_v0_11_fe_get_b32(b, &r.x); + rustsecp256k1_v0_11_scalar_set_b32(sigr, b, &overflow); if (recid) { /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. */ - *recid = (overflow << 1) | rustsecp256k1_v0_10_0_fe_is_odd(&r.y); - } - rustsecp256k1_v0_10_0_scalar_mul(&n, sigr, seckey); - rustsecp256k1_v0_10_0_scalar_add(&n, &n, message); - rustsecp256k1_v0_10_0_scalar_inverse(sigs, nonce); - rustsecp256k1_v0_10_0_scalar_mul(sigs, sigs, &n); - rustsecp256k1_v0_10_0_scalar_clear(&n); - rustsecp256k1_v0_10_0_gej_clear(&rp); - rustsecp256k1_v0_10_0_ge_clear(&r); - high = rustsecp256k1_v0_10_0_scalar_is_high(sigs); - rustsecp256k1_v0_10_0_scalar_cond_negate(sigs, high); + *recid = (overflow << 1) | rustsecp256k1_v0_11_fe_is_odd(&r.y); + } + rustsecp256k1_v0_11_scalar_mul(&n, sigr, seckey); + rustsecp256k1_v0_11_scalar_add(&n, &n, message); + rustsecp256k1_v0_11_scalar_inverse(sigs, nonce); + rustsecp256k1_v0_11_scalar_mul(sigs, sigs, &n); + rustsecp256k1_v0_11_scalar_clear(&n); + rustsecp256k1_v0_11_gej_clear(&rp); + rustsecp256k1_v0_11_ge_clear(&r); + high = rustsecp256k1_v0_11_scalar_is_high(sigs); + rustsecp256k1_v0_11_scalar_cond_negate(sigs, high); if (recid) { *recid ^= high; } /* P.x = order is on the curve, so technically sig->r could end up being zero, which would be an invalid signature. * This is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. */ - return (int)(!rustsecp256k1_v0_10_0_scalar_is_zero(sigr)) & (int)(!rustsecp256k1_v0_10_0_scalar_is_zero(sigs)); + return (int)(!rustsecp256k1_v0_11_scalar_is_zero(sigr)) & (int)(!rustsecp256k1_v0_11_scalar_is_zero(sigs)); } #endif /* SECP256K1_ECDSA_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/eckey.h b/secp256k1-sys/depend/secp256k1/src/eckey.h index 5ccf8ced1..10eefa9b0 100644 --- a/secp256k1-sys/depend/secp256k1/src/eckey.h +++ b/secp256k1-sys/depend/secp256k1/src/eckey.h @@ -14,12 +14,12 @@ #include "ecmult.h" #include "ecmult_gen.h" -static int rustsecp256k1_v0_10_0_eckey_pubkey_parse(rustsecp256k1_v0_10_0_ge *elem, const unsigned char *pub, size_t size); -static int rustsecp256k1_v0_10_0_eckey_pubkey_serialize(rustsecp256k1_v0_10_0_ge *elem, unsigned char *pub, size_t *size, int compressed); +static int rustsecp256k1_v0_11_eckey_pubkey_parse(rustsecp256k1_v0_11_ge *elem, const unsigned char *pub, size_t size); +static int rustsecp256k1_v0_11_eckey_pubkey_serialize(rustsecp256k1_v0_11_ge *elem, unsigned char *pub, size_t *size, int compressed); -static int rustsecp256k1_v0_10_0_eckey_privkey_tweak_add(rustsecp256k1_v0_10_0_scalar *key, const rustsecp256k1_v0_10_0_scalar *tweak); -static int rustsecp256k1_v0_10_0_eckey_pubkey_tweak_add(rustsecp256k1_v0_10_0_ge *key, const rustsecp256k1_v0_10_0_scalar *tweak); -static int rustsecp256k1_v0_10_0_eckey_privkey_tweak_mul(rustsecp256k1_v0_10_0_scalar *key, const rustsecp256k1_v0_10_0_scalar *tweak); -static int rustsecp256k1_v0_10_0_eckey_pubkey_tweak_mul(rustsecp256k1_v0_10_0_ge *key, const rustsecp256k1_v0_10_0_scalar *tweak); +static int rustsecp256k1_v0_11_eckey_privkey_tweak_add(rustsecp256k1_v0_11_scalar *key, const rustsecp256k1_v0_11_scalar *tweak); +static int rustsecp256k1_v0_11_eckey_pubkey_tweak_add(rustsecp256k1_v0_11_ge *key, const rustsecp256k1_v0_11_scalar *tweak); +static int rustsecp256k1_v0_11_eckey_privkey_tweak_mul(rustsecp256k1_v0_11_scalar *key, const rustsecp256k1_v0_11_scalar *tweak); +static int rustsecp256k1_v0_11_eckey_pubkey_tweak_mul(rustsecp256k1_v0_11_ge *key, const rustsecp256k1_v0_11_scalar *tweak); #endif /* SECP256K1_ECKEY_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/eckey_impl.h b/secp256k1-sys/depend/secp256k1/src/eckey_impl.h index 5e90ead47..2bd1bdb0b 100644 --- a/secp256k1-sys/depend/secp256k1/src/eckey_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/eckey_impl.h @@ -14,78 +14,78 @@ #include "group.h" #include "ecmult_gen.h" -static int rustsecp256k1_v0_10_0_eckey_pubkey_parse(rustsecp256k1_v0_10_0_ge *elem, const unsigned char *pub, size_t size) { +static int rustsecp256k1_v0_11_eckey_pubkey_parse(rustsecp256k1_v0_11_ge *elem, const unsigned char *pub, size_t size) { if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) { - rustsecp256k1_v0_10_0_fe x; - return rustsecp256k1_v0_10_0_fe_set_b32_limit(&x, pub+1) && rustsecp256k1_v0_10_0_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); + rustsecp256k1_v0_11_fe x; + return rustsecp256k1_v0_11_fe_set_b32_limit(&x, pub+1) && rustsecp256k1_v0_11_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD); } else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { - rustsecp256k1_v0_10_0_fe x, y; - if (!rustsecp256k1_v0_10_0_fe_set_b32_limit(&x, pub+1) || !rustsecp256k1_v0_10_0_fe_set_b32_limit(&y, pub+33)) { + rustsecp256k1_v0_11_fe x, y; + if (!rustsecp256k1_v0_11_fe_set_b32_limit(&x, pub+1) || !rustsecp256k1_v0_11_fe_set_b32_limit(&y, pub+33)) { return 0; } - rustsecp256k1_v0_10_0_ge_set_xy(elem, &x, &y); + rustsecp256k1_v0_11_ge_set_xy(elem, &x, &y); if ((pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD) && - rustsecp256k1_v0_10_0_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { + rustsecp256k1_v0_11_fe_is_odd(&y) != (pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) { return 0; } - return rustsecp256k1_v0_10_0_ge_is_valid_var(elem); + return rustsecp256k1_v0_11_ge_is_valid_var(elem); } else { return 0; } } -static int rustsecp256k1_v0_10_0_eckey_pubkey_serialize(rustsecp256k1_v0_10_0_ge *elem, unsigned char *pub, size_t *size, int compressed) { - if (rustsecp256k1_v0_10_0_ge_is_infinity(elem)) { +static int rustsecp256k1_v0_11_eckey_pubkey_serialize(rustsecp256k1_v0_11_ge *elem, unsigned char *pub, size_t *size, int compressed) { + if (rustsecp256k1_v0_11_ge_is_infinity(elem)) { return 0; } - rustsecp256k1_v0_10_0_fe_normalize_var(&elem->x); - rustsecp256k1_v0_10_0_fe_normalize_var(&elem->y); - rustsecp256k1_v0_10_0_fe_get_b32(&pub[1], &elem->x); + rustsecp256k1_v0_11_fe_normalize_var(&elem->x); + rustsecp256k1_v0_11_fe_normalize_var(&elem->y); + rustsecp256k1_v0_11_fe_get_b32(&pub[1], &elem->x); if (compressed) { *size = 33; - pub[0] = rustsecp256k1_v0_10_0_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; + pub[0] = rustsecp256k1_v0_11_fe_is_odd(&elem->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN; } else { *size = 65; pub[0] = SECP256K1_TAG_PUBKEY_UNCOMPRESSED; - rustsecp256k1_v0_10_0_fe_get_b32(&pub[33], &elem->y); + rustsecp256k1_v0_11_fe_get_b32(&pub[33], &elem->y); } return 1; } -static int rustsecp256k1_v0_10_0_eckey_privkey_tweak_add(rustsecp256k1_v0_10_0_scalar *key, const rustsecp256k1_v0_10_0_scalar *tweak) { - rustsecp256k1_v0_10_0_scalar_add(key, key, tweak); - return !rustsecp256k1_v0_10_0_scalar_is_zero(key); +static int rustsecp256k1_v0_11_eckey_privkey_tweak_add(rustsecp256k1_v0_11_scalar *key, const rustsecp256k1_v0_11_scalar *tweak) { + rustsecp256k1_v0_11_scalar_add(key, key, tweak); + return !rustsecp256k1_v0_11_scalar_is_zero(key); } -static int rustsecp256k1_v0_10_0_eckey_pubkey_tweak_add(rustsecp256k1_v0_10_0_ge *key, const rustsecp256k1_v0_10_0_scalar *tweak) { - rustsecp256k1_v0_10_0_gej pt; - rustsecp256k1_v0_10_0_gej_set_ge(&pt, key); - rustsecp256k1_v0_10_0_ecmult(&pt, &pt, &rustsecp256k1_v0_10_0_scalar_one, tweak); +static int rustsecp256k1_v0_11_eckey_pubkey_tweak_add(rustsecp256k1_v0_11_ge *key, const rustsecp256k1_v0_11_scalar *tweak) { + rustsecp256k1_v0_11_gej pt; + rustsecp256k1_v0_11_gej_set_ge(&pt, key); + rustsecp256k1_v0_11_ecmult(&pt, &pt, &rustsecp256k1_v0_11_scalar_one, tweak); - if (rustsecp256k1_v0_10_0_gej_is_infinity(&pt)) { + if (rustsecp256k1_v0_11_gej_is_infinity(&pt)) { return 0; } - rustsecp256k1_v0_10_0_ge_set_gej(key, &pt); + rustsecp256k1_v0_11_ge_set_gej(key, &pt); return 1; } -static int rustsecp256k1_v0_10_0_eckey_privkey_tweak_mul(rustsecp256k1_v0_10_0_scalar *key, const rustsecp256k1_v0_10_0_scalar *tweak) { +static int rustsecp256k1_v0_11_eckey_privkey_tweak_mul(rustsecp256k1_v0_11_scalar *key, const rustsecp256k1_v0_11_scalar *tweak) { int ret; - ret = !rustsecp256k1_v0_10_0_scalar_is_zero(tweak); + ret = !rustsecp256k1_v0_11_scalar_is_zero(tweak); - rustsecp256k1_v0_10_0_scalar_mul(key, key, tweak); + rustsecp256k1_v0_11_scalar_mul(key, key, tweak); return ret; } -static int rustsecp256k1_v0_10_0_eckey_pubkey_tweak_mul(rustsecp256k1_v0_10_0_ge *key, const rustsecp256k1_v0_10_0_scalar *tweak) { - rustsecp256k1_v0_10_0_gej pt; - if (rustsecp256k1_v0_10_0_scalar_is_zero(tweak)) { +static int rustsecp256k1_v0_11_eckey_pubkey_tweak_mul(rustsecp256k1_v0_11_ge *key, const rustsecp256k1_v0_11_scalar *tweak) { + rustsecp256k1_v0_11_gej pt; + if (rustsecp256k1_v0_11_scalar_is_zero(tweak)) { return 0; } - rustsecp256k1_v0_10_0_gej_set_ge(&pt, key); - rustsecp256k1_v0_10_0_ecmult(&pt, &pt, tweak, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ge_set_gej(key, &pt); + rustsecp256k1_v0_11_gej_set_ge(&pt, key); + rustsecp256k1_v0_11_ecmult(&pt, &pt, tweak, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ge_set_gej(key, &pt); return 1; } diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult.h b/secp256k1-sys/depend/secp256k1/src/ecmult.h index 3a2b1d5a2..3eb3acf09 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult.h @@ -41,9 +41,9 @@ #define ECMULT_TABLE_SIZE(w) (1L << ((w)-2)) /** Double multiply: R = na*A + ng*G */ -static void rustsecp256k1_v0_10_0_ecmult(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_scalar *na, const rustsecp256k1_v0_10_0_scalar *ng); +static void rustsecp256k1_v0_11_ecmult(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_scalar *na, const rustsecp256k1_v0_11_scalar *ng); -typedef int (rustsecp256k1_v0_10_0_ecmult_multi_callback)(rustsecp256k1_v0_10_0_scalar *sc, rustsecp256k1_v0_10_0_ge *pt, size_t idx, void *data); +typedef int (rustsecp256k1_v0_11_ecmult_multi_callback)(rustsecp256k1_v0_11_scalar *sc, rustsecp256k1_v0_11_ge *pt, size_t idx, void *data); /** * Multi-multiply: R = inp_g_sc * G + sum_i ni * Ai. @@ -56,6 +56,6 @@ typedef int (rustsecp256k1_v0_10_0_ecmult_multi_callback)(rustsecp256k1_v0_10_0_ * 0 if there is not enough scratch space for a single point or * callback returns 0 */ -static int rustsecp256k1_v0_10_0_ecmult_multi_var(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch *scratch, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *inp_g_sc, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void *cbdata, size_t n); +static int rustsecp256k1_v0_11_ecmult_multi_var(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch *scratch, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *inp_g_sc, rustsecp256k1_v0_11_ecmult_multi_callback cb, void *cbdata, size_t n); #endif /* SECP256K1_ECMULT_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table.h b/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table.h index 223cbaad7..714fa0041 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table.h @@ -8,9 +8,9 @@ #define SECP256K1_ECMULT_COMPUTE_TABLE_H /* Construct table of all odd multiples of gen in range 1..(2**(window_g-1)-1). */ -static void rustsecp256k1_v0_10_0_ecmult_compute_table(rustsecp256k1_v0_10_0_ge_storage* table, int window_g, const rustsecp256k1_v0_10_0_gej* gen); +static void rustsecp256k1_v0_11_ecmult_compute_table(rustsecp256k1_v0_11_ge_storage* table, int window_g, const rustsecp256k1_v0_11_gej* gen); -/* Like rustsecp256k1_v0_10_0_ecmult_compute_table, but one for both gen and gen*2^128. */ -static void rustsecp256k1_v0_10_0_ecmult_compute_two_tables(rustsecp256k1_v0_10_0_ge_storage* table, rustsecp256k1_v0_10_0_ge_storage* table_128, int window_g, const rustsecp256k1_v0_10_0_ge* gen); +/* Like rustsecp256k1_v0_11_ecmult_compute_table, but one for both gen and gen*2^128. */ +static void rustsecp256k1_v0_11_ecmult_compute_two_tables(rustsecp256k1_v0_11_ge_storage* table, rustsecp256k1_v0_11_ge_storage* table_128, int window_g, const rustsecp256k1_v0_11_ge* gen); #endif /* SECP256K1_ECMULT_COMPUTE_TABLE_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table_impl.h index a83af1ea9..f8096f8c8 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_compute_table_impl.h @@ -13,37 +13,37 @@ #include "ecmult.h" #include "util.h" -static void rustsecp256k1_v0_10_0_ecmult_compute_table(rustsecp256k1_v0_10_0_ge_storage* table, int window_g, const rustsecp256k1_v0_10_0_gej* gen) { - rustsecp256k1_v0_10_0_gej gj; - rustsecp256k1_v0_10_0_ge ge, dgen; +static void rustsecp256k1_v0_11_ecmult_compute_table(rustsecp256k1_v0_11_ge_storage* table, int window_g, const rustsecp256k1_v0_11_gej* gen) { + rustsecp256k1_v0_11_gej gj; + rustsecp256k1_v0_11_ge ge, dgen; int j; gj = *gen; - rustsecp256k1_v0_10_0_ge_set_gej_var(&ge, &gj); - rustsecp256k1_v0_10_0_ge_to_storage(&table[0], &ge); + rustsecp256k1_v0_11_ge_set_gej_var(&ge, &gj); + rustsecp256k1_v0_11_ge_to_storage(&table[0], &ge); - rustsecp256k1_v0_10_0_gej_double_var(&gj, gen, NULL); - rustsecp256k1_v0_10_0_ge_set_gej_var(&dgen, &gj); + rustsecp256k1_v0_11_gej_double_var(&gj, gen, NULL); + rustsecp256k1_v0_11_ge_set_gej_var(&dgen, &gj); for (j = 1; j < ECMULT_TABLE_SIZE(window_g); ++j) { - rustsecp256k1_v0_10_0_gej_set_ge(&gj, &ge); - rustsecp256k1_v0_10_0_gej_add_ge_var(&gj, &gj, &dgen, NULL); - rustsecp256k1_v0_10_0_ge_set_gej_var(&ge, &gj); - rustsecp256k1_v0_10_0_ge_to_storage(&table[j], &ge); + rustsecp256k1_v0_11_gej_set_ge(&gj, &ge); + rustsecp256k1_v0_11_gej_add_ge_var(&gj, &gj, &dgen, NULL); + rustsecp256k1_v0_11_ge_set_gej_var(&ge, &gj); + rustsecp256k1_v0_11_ge_to_storage(&table[j], &ge); } } -/* Like rustsecp256k1_v0_10_0_ecmult_compute_table, but one for both gen and gen*2^128. */ -static void rustsecp256k1_v0_10_0_ecmult_compute_two_tables(rustsecp256k1_v0_10_0_ge_storage* table, rustsecp256k1_v0_10_0_ge_storage* table_128, int window_g, const rustsecp256k1_v0_10_0_ge* gen) { - rustsecp256k1_v0_10_0_gej gj; +/* Like rustsecp256k1_v0_11_ecmult_compute_table, but one for both gen and gen*2^128. */ +static void rustsecp256k1_v0_11_ecmult_compute_two_tables(rustsecp256k1_v0_11_ge_storage* table, rustsecp256k1_v0_11_ge_storage* table_128, int window_g, const rustsecp256k1_v0_11_ge* gen) { + rustsecp256k1_v0_11_gej gj; int i; - rustsecp256k1_v0_10_0_gej_set_ge(&gj, gen); - rustsecp256k1_v0_10_0_ecmult_compute_table(table, window_g, &gj); + rustsecp256k1_v0_11_gej_set_ge(&gj, gen); + rustsecp256k1_v0_11_ecmult_compute_table(table, window_g, &gj); for (i = 0; i < 128; ++i) { - rustsecp256k1_v0_10_0_gej_double_var(&gj, &gj, NULL); + rustsecp256k1_v0_11_gej_double_var(&gj, &gj, NULL); } - rustsecp256k1_v0_10_0_ecmult_compute_table(table_128, window_g, &gj); + rustsecp256k1_v0_11_ecmult_compute_table(table_128, window_g, &gj); } #endif /* SECP256K1_ECMULT_COMPUTE_TABLE_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_const.h b/secp256k1-sys/depend/secp256k1/src/ecmult_const.h index 06dc9bfa5..a13d4468d 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_const.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_const.h @@ -13,10 +13,10 @@ /** * Multiply: R = q*A (in constant-time for q) */ -static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_scalar *q); +static void rustsecp256k1_v0_11_ecmult_const(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_scalar *q); /** - * Same as rustsecp256k1_v0_10_0_ecmult_const, but takes in an x coordinate of the base point + * Same as rustsecp256k1_v0_11_ecmult_const, but takes in an x coordinate of the base point * only, specified as fraction n/d (numerator/denominator). Only the x coordinate of the result is * returned. * @@ -27,11 +27,11 @@ static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, con * * Constant time in the value of q, but not any other inputs. */ -static int rustsecp256k1_v0_10_0_ecmult_const_xonly( - rustsecp256k1_v0_10_0_fe *r, - const rustsecp256k1_v0_10_0_fe *n, - const rustsecp256k1_v0_10_0_fe *d, - const rustsecp256k1_v0_10_0_scalar *q, +static int rustsecp256k1_v0_11_ecmult_const_xonly( + rustsecp256k1_v0_11_fe *r, + const rustsecp256k1_v0_11_fe *n, + const rustsecp256k1_v0_11_fe *d, + const rustsecp256k1_v0_11_scalar *q, int known_on_curve ); diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h index 5a9b3fd92..ba258de9d 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_const_impl.h @@ -41,11 +41,11 @@ * * 'pre' must be an array of size ECMULT_CONST_TABLE_SIZE. */ -static void rustsecp256k1_v0_10_0_ecmult_const_odd_multiples_table_globalz(rustsecp256k1_v0_10_0_ge *pre, rustsecp256k1_v0_10_0_fe *globalz, const rustsecp256k1_v0_10_0_gej *a) { - rustsecp256k1_v0_10_0_fe zr[ECMULT_CONST_TABLE_SIZE]; +static void rustsecp256k1_v0_11_ecmult_const_odd_multiples_table_globalz(rustsecp256k1_v0_11_ge *pre, rustsecp256k1_v0_11_fe *globalz, const rustsecp256k1_v0_11_gej *a) { + rustsecp256k1_v0_11_fe zr[ECMULT_CONST_TABLE_SIZE]; - rustsecp256k1_v0_10_0_ecmult_odd_multiples_table(ECMULT_CONST_TABLE_SIZE, pre, zr, globalz, a); - rustsecp256k1_v0_10_0_ge_table_set_globalz(ECMULT_CONST_TABLE_SIZE, pre, zr); + rustsecp256k1_v0_11_ecmult_odd_multiples_table(ECMULT_CONST_TABLE_SIZE, pre, zr, globalz, a); + rustsecp256k1_v0_11_ge_table_set_globalz(ECMULT_CONST_TABLE_SIZE, pre, zr); } /* Given a table 'pre' with odd multiples of a point, put in r the signed-bit multiplication of n with that point. @@ -84,7 +84,7 @@ static void rustsecp256k1_v0_10_0_ecmult_const_odd_multiples_table_globalz(rusts * = sum((1 - n[i]) * 2^i, i=0..l-2) */ \ unsigned int index = ((unsigned int)(-negative) ^ n) & ((1U << (ECMULT_CONST_GROUP_SIZE - 1)) - 1U); \ - rustsecp256k1_v0_10_0_fe neg_y; \ + rustsecp256k1_v0_11_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 @@ -94,34 +94,34 @@ static void rustsecp256k1_v0_10_0_ecmult_const_odd_multiples_table_globalz(rusts 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. */ \ - rustsecp256k1_v0_10_0_fe_cmov(&(r)->x, &(pre)[m].x, m == index); \ - rustsecp256k1_v0_10_0_fe_cmov(&(r)->y, &(pre)[m].y, m == index); \ + rustsecp256k1_v0_11_fe_cmov(&(r)->x, &(pre)[m].x, m == index); \ + rustsecp256k1_v0_11_fe_cmov(&(r)->y, &(pre)[m].y, m == index); \ } \ (r)->infinity = 0; \ - rustsecp256k1_v0_10_0_fe_negate(&neg_y, &(r)->y, 1); \ - rustsecp256k1_v0_10_0_fe_cmov(&(r)->y, &neg_y, negative); \ + rustsecp256k1_v0_11_fe_negate(&neg_y, &(r)->y, 1); \ + rustsecp256k1_v0_11_fe_cmov(&(r)->y, &neg_y, negative); \ } while(0) -/* For K as defined in the comment of rustsecp256k1_v0_10_0_ecmult_const, we have several precomputed +/* For K as defined in the comment of rustsecp256k1_v0_11_ecmult_const, we have several precomputed * formulas/constants. * - in exhaustive test mode, we give an explicit expression to compute it at compile time: */ #ifdef EXHAUSTIVE_TEST_ORDER -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_ecmult_const_K = ((SECP256K1_SCALAR_CONST(0, 0, 0, (1U << (ECMULT_CONST_BITS - 128)) - 2U, 0, 0, 0, 0) + EXHAUSTIVE_TEST_ORDER - 1U) * (1U + EXHAUSTIVE_TEST_LAMBDA)) % EXHAUSTIVE_TEST_ORDER; +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_ecmult_const_K = ((SECP256K1_SCALAR_CONST(0, 0, 0, (1U << (ECMULT_CONST_BITS - 128)) - 2U, 0, 0, 0, 0) + EXHAUSTIVE_TEST_ORDER - 1U) * (1U + EXHAUSTIVE_TEST_LAMBDA)) % EXHAUSTIVE_TEST_ORDER; /* - for the real secp256k1 group we have constants for various ECMULT_CONST_BITS values. */ #elif ECMULT_CONST_BITS == 129 /* For GROUP_SIZE = 1,3. */ -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_ecmult_const_K = SECP256K1_SCALAR_CONST(0xac9c52b3ul, 0x3fa3cf1ful, 0x5ad9e3fdul, 0x77ed9ba4ul, 0xa880b9fcul, 0x8ec739c2ul, 0xe0cfc810ul, 0xb51283ceul); +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_ecmult_const_K = SECP256K1_SCALAR_CONST(0xac9c52b3ul, 0x3fa3cf1ful, 0x5ad9e3fdul, 0x77ed9ba4ul, 0xa880b9fcul, 0x8ec739c2ul, 0xe0cfc810ul, 0xb51283ceul); #elif ECMULT_CONST_BITS == 130 /* For GROUP_SIZE = 2,5. */ -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_ecmult_const_K = SECP256K1_SCALAR_CONST(0xa4e88a7dul, 0xcb13034eul, 0xc2bdd6bful, 0x7c118d6bul, 0x589ae848ul, 0x26ba29e4ul, 0xb5c2c1dcul, 0xde9798d9ul); +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_ecmult_const_K = SECP256K1_SCALAR_CONST(0xa4e88a7dul, 0xcb13034eul, 0xc2bdd6bful, 0x7c118d6bul, 0x589ae848ul, 0x26ba29e4ul, 0xb5c2c1dcul, 0xde9798d9ul); #elif ECMULT_CONST_BITS == 132 /* For GROUP_SIZE = 4,6 */ -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_ecmult_const_K = SECP256K1_SCALAR_CONST(0x76b1d93dul, 0x0fae3c6bul, 0x3215874bul, 0x94e93813ul, 0x7937fe0dul, 0xb66bcaaful, 0xb3749ca5ul, 0xd7b6171bul); +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_ecmult_const_K = SECP256K1_SCALAR_CONST(0x76b1d93dul, 0x0fae3c6bul, 0x3215874bul, 0x94e93813ul, 0x7937fe0dul, 0xb66bcaaful, 0xb3749ca5ul, 0xd7b6171bul); #else # error "Unknown ECMULT_CONST_BITS" #endif -static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_scalar *q) { +static void rustsecp256k1_v0_11_ecmult_const(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_scalar *q) { /* The approach below combines the signed-digit logic from Mike Hamburg's * "Fast and compact elliptic-curve cryptography" (https://eprint.iacr.org/2012/309) * Section 3.3, with the GLV endomorphism. @@ -142,7 +142,7 @@ static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, con * It is appealing to try to combine this with the GLV optimization: the idea that a scalar * s can be written as s1 + lambda*s2, where lambda is a curve-specific constant such that * lambda*A is easy to compute, and where s1 and s2 are small. In particular we have the - * rustsecp256k1_v0_10_0_scalar_split_lambda function which performs such a split with the resulting s1 + * rustsecp256k1_v0_11_scalar_split_lambda function which performs such a split with the resulting s1 * and s2 in range (-2^128, 2^128) mod n. This does work, but is uninteresting: * * To compute q*A: @@ -189,33 +189,33 @@ static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, con */ /* The offset to add to s1 and s2 to make them non-negative. Equal to 2^128. */ - static const rustsecp256k1_v0_10_0_scalar S_OFFSET = SECP256K1_SCALAR_CONST(0, 0, 0, 1, 0, 0, 0, 0); - rustsecp256k1_v0_10_0_scalar s, v1, v2; - rustsecp256k1_v0_10_0_ge pre_a[ECMULT_CONST_TABLE_SIZE]; - rustsecp256k1_v0_10_0_ge pre_a_lam[ECMULT_CONST_TABLE_SIZE]; - rustsecp256k1_v0_10_0_fe global_z; + static const rustsecp256k1_v0_11_scalar S_OFFSET = SECP256K1_SCALAR_CONST(0, 0, 0, 1, 0, 0, 0, 0); + rustsecp256k1_v0_11_scalar s, v1, v2; + rustsecp256k1_v0_11_ge pre_a[ECMULT_CONST_TABLE_SIZE]; + rustsecp256k1_v0_11_ge pre_a_lam[ECMULT_CONST_TABLE_SIZE]; + rustsecp256k1_v0_11_fe global_z; int group, i; /* We're allowed to be non-constant time in the point, and the code below (in particular, - * rustsecp256k1_v0_10_0_ecmult_const_odd_multiples_table_globalz) cannot deal with infinity in a + * rustsecp256k1_v0_11_ecmult_const_odd_multiples_table_globalz) cannot deal with infinity in a * constant-time manner anyway. */ - if (rustsecp256k1_v0_10_0_ge_is_infinity(a)) { - rustsecp256k1_v0_10_0_gej_set_infinity(r); + if (rustsecp256k1_v0_11_ge_is_infinity(a)) { + rustsecp256k1_v0_11_gej_set_infinity(r); return; } /* Compute v1 and v2. */ - rustsecp256k1_v0_10_0_scalar_add(&s, q, &rustsecp256k1_v0_10_0_ecmult_const_K); - rustsecp256k1_v0_10_0_scalar_half(&s, &s); - rustsecp256k1_v0_10_0_scalar_split_lambda(&v1, &v2, &s); - rustsecp256k1_v0_10_0_scalar_add(&v1, &v1, &S_OFFSET); - rustsecp256k1_v0_10_0_scalar_add(&v2, &v2, &S_OFFSET); + rustsecp256k1_v0_11_scalar_add(&s, q, &rustsecp256k1_v0_11_ecmult_const_K); + rustsecp256k1_v0_11_scalar_half(&s, &s); + rustsecp256k1_v0_11_scalar_split_lambda(&v1, &v2, &s); + rustsecp256k1_v0_11_scalar_add(&v1, &v1, &S_OFFSET); + rustsecp256k1_v0_11_scalar_add(&v2, &v2, &S_OFFSET); #ifdef VERIFY /* Verify that v1 and v2 are in range [0, 2^129-1]. */ for (i = 129; i < 256; ++i) { - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_get_bits(&v1, i, 1) == 0); - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_get_bits(&v2, i, 1) == 0); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_get_bits_limb32(&v1, i, 1) == 0); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_get_bits_limb32(&v2, i, 1) == 0); } #endif @@ -225,10 +225,10 @@ static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, con * that the Z coordinate was 1, use affine addition formulae, and correct * the Z coordinate of the result once at the end. */ - rustsecp256k1_v0_10_0_gej_set_ge(r, a); - rustsecp256k1_v0_10_0_ecmult_const_odd_multiples_table_globalz(pre_a, &global_z, r); + rustsecp256k1_v0_11_gej_set_ge(r, a); + rustsecp256k1_v0_11_ecmult_const_odd_multiples_table_globalz(pre_a, &global_z, r); for (i = 0; i < ECMULT_CONST_TABLE_SIZE; i++) { - rustsecp256k1_v0_10_0_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + rustsecp256k1_v0_11_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); } /* Next, we compute r = C_l(v1, A) + C_l(v2, lambda*A). @@ -243,31 +243,31 @@ static void rustsecp256k1_v0_10_0_ecmult_const(rustsecp256k1_v0_10_0_gej *r, con */ for (group = ECMULT_CONST_GROUPS - 1; group >= 0; --group) { /* Using the _var get_bits function is ok here, since it's only variable in offset and count, not in the scalar. */ - unsigned int bits1 = rustsecp256k1_v0_10_0_scalar_get_bits_var(&v1, group * ECMULT_CONST_GROUP_SIZE, ECMULT_CONST_GROUP_SIZE); - unsigned int bits2 = rustsecp256k1_v0_10_0_scalar_get_bits_var(&v2, group * ECMULT_CONST_GROUP_SIZE, ECMULT_CONST_GROUP_SIZE); - rustsecp256k1_v0_10_0_ge t; + unsigned int bits1 = rustsecp256k1_v0_11_scalar_get_bits_var(&v1, group * ECMULT_CONST_GROUP_SIZE, ECMULT_CONST_GROUP_SIZE); + unsigned int bits2 = rustsecp256k1_v0_11_scalar_get_bits_var(&v2, group * ECMULT_CONST_GROUP_SIZE, ECMULT_CONST_GROUP_SIZE); + rustsecp256k1_v0_11_ge t; int j; ECMULT_CONST_TABLE_GET_GE(&t, pre_a, bits1); if (group == ECMULT_CONST_GROUPS - 1) { /* Directly set r in the first iteration. */ - rustsecp256k1_v0_10_0_gej_set_ge(r, &t); + rustsecp256k1_v0_11_gej_set_ge(r, &t); } else { /* Shift the result so far up. */ for (j = 0; j < ECMULT_CONST_GROUP_SIZE; ++j) { - rustsecp256k1_v0_10_0_gej_double(r, r); + rustsecp256k1_v0_11_gej_double(r, r); } - rustsecp256k1_v0_10_0_gej_add_ge(r, r, &t); + rustsecp256k1_v0_11_gej_add_ge(r, r, &t); } ECMULT_CONST_TABLE_GET_GE(&t, pre_a_lam, bits2); - rustsecp256k1_v0_10_0_gej_add_ge(r, r, &t); + rustsecp256k1_v0_11_gej_add_ge(r, r, &t); } /* Map the result back to the secp256k1 curve from the isomorphic curve. */ - rustsecp256k1_v0_10_0_fe_mul(&r->z, &r->z, &global_z); + rustsecp256k1_v0_11_fe_mul(&r->z, &r->z, &global_z); } -static int rustsecp256k1_v0_10_0_ecmult_const_xonly(rustsecp256k1_v0_10_0_fe* r, const rustsecp256k1_v0_10_0_fe *n, const rustsecp256k1_v0_10_0_fe *d, const rustsecp256k1_v0_10_0_scalar *q, int known_on_curve) { +static int rustsecp256k1_v0_11_ecmult_const_xonly(rustsecp256k1_v0_11_fe* r, const rustsecp256k1_v0_11_fe *n, const rustsecp256k1_v0_11_fe *d, const rustsecp256k1_v0_11_scalar *q, int known_on_curve) { /* This algorithm is a generalization of Peter Dettman's technique for * avoiding the square root in a random-basepoint x-only multiplication @@ -338,21 +338,21 @@ static int rustsecp256k1_v0_10_0_ecmult_const_xonly(rustsecp256k1_v0_10_0_fe* r, * is needed anywhere in this computation. */ - rustsecp256k1_v0_10_0_fe g, i; - rustsecp256k1_v0_10_0_ge p; - rustsecp256k1_v0_10_0_gej rj; + rustsecp256k1_v0_11_fe g, i; + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_gej rj; /* Compute g = (n^3 + B*d^3). */ - rustsecp256k1_v0_10_0_fe_sqr(&g, n); - rustsecp256k1_v0_10_0_fe_mul(&g, &g, n); + rustsecp256k1_v0_11_fe_sqr(&g, n); + rustsecp256k1_v0_11_fe_mul(&g, &g, n); if (d) { - rustsecp256k1_v0_10_0_fe b; - VERIFY_CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero(d)); - rustsecp256k1_v0_10_0_fe_sqr(&b, d); + rustsecp256k1_v0_11_fe b; + VERIFY_CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero(d)); + rustsecp256k1_v0_11_fe_sqr(&b, d); VERIFY_CHECK(SECP256K1_B <= 8); /* magnitude of b will be <= 8 after the next call */ - rustsecp256k1_v0_10_0_fe_mul_int(&b, SECP256K1_B); - rustsecp256k1_v0_10_0_fe_mul(&b, &b, d); - rustsecp256k1_v0_10_0_fe_add(&g, &b); + rustsecp256k1_v0_11_fe_mul_int(&b, SECP256K1_B); + rustsecp256k1_v0_11_fe_mul(&b, &b, d); + rustsecp256k1_v0_11_fe_add(&g, &b); if (!known_on_curve) { /* We need to determine whether (n/d)^3 + 7 is square. * @@ -361,37 +361,37 @@ static int rustsecp256k1_v0_10_0_ecmult_const_xonly(rustsecp256k1_v0_10_0_fe* r, * <=> is_square((n^3 + 7*d^3) * d) * <=> is_square(g * d) */ - rustsecp256k1_v0_10_0_fe c; - rustsecp256k1_v0_10_0_fe_mul(&c, &g, d); - if (!rustsecp256k1_v0_10_0_fe_is_square_var(&c)) return 0; + rustsecp256k1_v0_11_fe c; + rustsecp256k1_v0_11_fe_mul(&c, &g, d); + if (!rustsecp256k1_v0_11_fe_is_square_var(&c)) return 0; } } else { - rustsecp256k1_v0_10_0_fe_add_int(&g, SECP256K1_B); + rustsecp256k1_v0_11_fe_add_int(&g, SECP256K1_B); if (!known_on_curve) { /* g at this point equals x^3 + 7. Test if it is square. */ - if (!rustsecp256k1_v0_10_0_fe_is_square_var(&g)) return 0; + if (!rustsecp256k1_v0_11_fe_is_square_var(&g)) return 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. */ - rustsecp256k1_v0_10_0_fe_mul(&p.x, &g, n); - rustsecp256k1_v0_10_0_fe_sqr(&p.y, &g); + rustsecp256k1_v0_11_fe_mul(&p.x, &g, n); + rustsecp256k1_v0_11_fe_sqr(&p.y, &g); p.infinity = 0; /* Perform x-only EC multiplication of P with q. */ - VERIFY_CHECK(!rustsecp256k1_v0_10_0_scalar_is_zero(q)); - rustsecp256k1_v0_10_0_ecmult_const(&rj, &p, q); - VERIFY_CHECK(!rustsecp256k1_v0_10_0_gej_is_infinity(&rj)); + VERIFY_CHECK(!rustsecp256k1_v0_11_scalar_is_zero(q)); + rustsecp256k1_v0_11_ecmult_const(&rj, &p, q); + VERIFY_CHECK(!rustsecp256k1_v0_11_gej_is_infinity(&rj)); /* The resulting (X, Y, Z) point on the effective-affine isomorphic curve corresponds to * (X, Y, Z*v) on the secp256k1 curve. The affine version of that has X coordinate * (X / (Z^2*d*g)). */ - rustsecp256k1_v0_10_0_fe_sqr(&i, &rj.z); - rustsecp256k1_v0_10_0_fe_mul(&i, &i, &g); - if (d) rustsecp256k1_v0_10_0_fe_mul(&i, &i, d); - rustsecp256k1_v0_10_0_fe_inv(&i, &i); - rustsecp256k1_v0_10_0_fe_mul(r, &rj.x, &i); + rustsecp256k1_v0_11_fe_sqr(&i, &rj.z); + rustsecp256k1_v0_11_fe_mul(&i, &i, &g); + if (d) rustsecp256k1_v0_11_fe_mul(&i, &i, d); + rustsecp256k1_v0_11_fe_inv(&i, &i); + rustsecp256k1_v0_11_fe_mul(r, &rj.x, &i); return 1; } diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen.h index ba431a482..10f73288a 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_gen.h +++ b/secp256k1-sys/depend/secp256k1/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,39 +10,134 @@ #include "scalar.h" #include "group.h" -#ifndef ECMULT_GEN_PREC_BITS -# define ECMULT_GEN_PREC_BITS 4 + +/* 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. + * - 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(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)) + * rustsecp256k1_v0_11_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 (rustsecp256k1_v0_11_ge_storage + * doesn't support infinities) */ +# undef COMB_BLOCKS +# undef COMB_TEETH +# 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 +# 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) */ +# 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("ECMULT_GEN_PREC_BITS undefined, assuming default value") +# 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) -#ifdef DEBUG_CONFIG -# pragma message DEBUG_CONFIG_DEF(ECMULT_GEN_PREC_BITS) +/* 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 -#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." +/* 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 +#if COMB_BLOCKS * (COMB_TEETH - 1) * COMB_SPACING >= 256 +# error "COMB_TEETH can be reduced" #endif -#define ECMULT_GEN_PREC_G(bits) (1 << bits) -#define ECMULT_GEN_PREC_N(bits) (256 / bits) +#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 { /* Whether the context has been built. */ int built; - /* Blinding values used when computing (n-b)G + bG. */ - rustsecp256k1_v0_10_0_scalar blind; /* -b */ - rustsecp256k1_v0_10_0_gej initial; /* bG */ -} rustsecp256k1_v0_10_0_ecmult_gen_context; + /* Values chosen such that + * + * 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. */ + rustsecp256k1_v0_11_scalar scalar_offset; + rustsecp256k1_v0_11_ge ge_offset; + + /* Factor used for projective blinding. This value is used to rescale the Z + * coordinate of the first table lookup. */ + rustsecp256k1_v0_11_fe proj_blind; +} rustsecp256k1_v0_11_ecmult_gen_context; -static void rustsecp256k1_v0_10_0_ecmult_gen_context_build(rustsecp256k1_v0_10_0_ecmult_gen_context* ctx); -static void rustsecp256k1_v0_10_0_ecmult_gen_context_clear(rustsecp256k1_v0_10_0_ecmult_gen_context* ctx); +static void rustsecp256k1_v0_11_ecmult_gen_context_build(rustsecp256k1_v0_11_ecmult_gen_context* ctx); +static void rustsecp256k1_v0_11_ecmult_gen_context_clear(rustsecp256k1_v0_11_ecmult_gen_context* ctx); /** Multiply with the generator: R = a*G */ -static void rustsecp256k1_v0_10_0_ecmult_gen(const rustsecp256k1_v0_10_0_ecmult_gen_context* ctx, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *a); +static void rustsecp256k1_v0_11_ecmult_gen(const rustsecp256k1_v0_11_ecmult_gen_context* ctx, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *a); -static void rustsecp256k1_v0_10_0_ecmult_gen_blind(rustsecp256k1_v0_10_0_ecmult_gen_context *ctx, const unsigned char *seed32); +static void rustsecp256k1_v0_11_ecmult_gen_blind(rustsecp256k1_v0_11_ecmult_gen_context *ctx, const unsigned char *seed32); #endif /* SECP256K1_ECMULT_GEN_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table.h index d608eda76..666901743 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table.h +++ b/secp256k1-sys/depend/secp256k1/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 rustsecp256k1_v0_10_0_ecmult_gen_compute_table(rustsecp256k1_v0_10_0_ge_storage* table, const rustsecp256k1_v0_10_0_ge* gen, int bits); +static void rustsecp256k1_v0_11_ecmult_gen_compute_table(rustsecp256k1_v0_11_ge_storage* table, const rustsecp256k1_v0_11_ge* gen, int blocks, int teeth, int spacing); #endif /* SECP256K1_ECMULT_GEN_COMPUTE_TABLE_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h index f85c1282d..4d44ccc93 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_compute_table_impl.h +++ b/secp256k1-sys/depend/secp256k1/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,98 @@ #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 rustsecp256k1_v0_10_0_ecmult_gen_compute_table(rustsecp256k1_v0_10_0_ge_storage* table, const rustsecp256k1_v0_10_0_ge* gen, int bits) { - int g = ECMULT_GEN_PREC_G(bits); - int n = ECMULT_GEN_PREC_N(bits); +static void rustsecp256k1_v0_11_ecmult_gen_compute_table(rustsecp256k1_v0_11_ge_storage* table, const rustsecp256k1_v0_11_ge* gen, int blocks, int teeth, int spacing) { + size_t points = ((size_t)1) << (teeth - 1); + size_t points_total = points * blocks; + rustsecp256k1_v0_11_ge* prec = checked_malloc(&default_error_callback, points_total * sizeof(*prec)); + rustsecp256k1_v0_11_gej* ds = checked_malloc(&default_error_callback, teeth * sizeof(*ds)); + rustsecp256k1_v0_11_gej* vs = checked_malloc(&default_error_callback, points_total * sizeof(*vs)); + rustsecp256k1_v0_11_gej u; + size_t vs_pos = 0; + rustsecp256k1_v0_11_scalar half; + int block, i; - rustsecp256k1_v0_10_0_ge* prec = checked_malloc(&default_error_callback, n * g * sizeof(*prec)); - rustsecp256k1_v0_10_0_gej gj; - rustsecp256k1_v0_10_0_gej nums_gej; - int i, j; + VERIFY_CHECK(points_total > 0); - VERIFY_CHECK(g > 0); - VERIFY_CHECK(n > 0); - - /* get the generator */ - rustsecp256k1_v0_10_0_gej_set_ge(&gj, gen); - - /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ + /* u is the running power of two times gen we're working with, initially gen/2. */ + rustsecp256k1_v0_11_scalar_half(&half, &rustsecp256k1_v0_11_scalar_one); + rustsecp256k1_v0_11_gej_set_infinity(&u); + for (i = 255; i >= 0; --i) { + /* Use a very simple multiplication ladder to avoid dependency on ecmult. */ + rustsecp256k1_v0_11_gej_double_var(&u, &u, NULL); + if (rustsecp256k1_v0_11_scalar_get_bits_limb32(&half, i, 1)) { + rustsecp256k1_v0_11_gej_add_ge_var(&u, &u, gen, NULL); + } + } +#ifdef VERIFY { - static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; - rustsecp256k1_v0_10_0_fe nums_x; - rustsecp256k1_v0_10_0_ge nums_ge; - int r; - r = rustsecp256k1_v0_10_0_fe_set_b32_limit(&nums_x, nums_b32); - (void)r; - VERIFY_CHECK(r); - r = rustsecp256k1_v0_10_0_ge_set_xo_var(&nums_ge, &nums_x, 0); - (void)r; - VERIFY_CHECK(r); - rustsecp256k1_v0_10_0_gej_set_ge(&nums_gej, &nums_ge); - /* Add G to make the bits in x uniformly distributed. */ - rustsecp256k1_v0_10_0_gej_add_ge_var(&nums_gej, &nums_gej, gen, NULL); + /* Verify that u*2 = gen. */ + rustsecp256k1_v0_11_gej double_u; + rustsecp256k1_v0_11_gej_double_var(&double_u, &u, NULL); + VERIFY_CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&double_u, gen)); } +#endif - /* compute prec. */ - { - rustsecp256k1_v0_10_0_gej gbase; - rustsecp256k1_v0_10_0_gej numsbase; - rustsecp256k1_v0_10_0_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++) { - rustsecp256k1_v0_10_0_gej_add_var(&precj[j*g + i], &precj[j*g + i - 1], &gbase, NULL); + for (block = 0; block < blocks; ++block) { + int tooth; + /* Here u = 2^(block*teeth*spacing) * gen/2. */ + rustsecp256k1_v0_11_gej sum; + rustsecp256k1_v0_11_gej_set_infinity(&sum); + for (tooth = 0; tooth < teeth; ++tooth) { + /* Here u = 2^((block*teeth + tooth)*spacing) * gen/2. */ + /* Make sum = sum(2^((block*teeth + t)*spacing), t=0..tooth) * gen/2. */ + rustsecp256k1_v0_11_gej_add_var(&sum, &sum, &u, NULL); + /* Make u = 2^((block*teeth + tooth)*spacing + 1) * gen/2. */ + rustsecp256k1_v0_11_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, unless at the end. */ + if (block + tooth != blocks + teeth - 2) { + int bit_off; + for (bit_off = 1; bit_off < spacing; ++bit_off) { + rustsecp256k1_v0_11_gej_double_var(&u, &u, NULL); + } } - /* Multiply gbase by PREC_G. */ - for (i = 0; i < bits; i++) { - rustsecp256k1_v0_10_0_gej_double_var(&gbase, &gbase, NULL); - } - /* Multiply numbase by 2. */ - rustsecp256k1_v0_10_0_gej_double_var(&numsbase, &numsbase, NULL); - if (j == n - 2) { - /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ - rustsecp256k1_v0_10_0_gej_neg(&numsbase, &numsbase); - rustsecp256k1_v0_10_0_gej_add_var(&numsbase, &numsbase, &nums_gej, 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. */ + rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_gej_add_var(&vs[vs_pos], &vs[vs_pos - stride], &ds[tooth], NULL); } } - rustsecp256k1_v0_10_0_ge_set_all_gej_var(prec, precj, n * g); - free(precj); } - for (j = 0; j < n; j++) { - for (i = 0; i < g; i++) { - rustsecp256k1_v0_10_0_ge_to_storage(&table[j*g + i], &prec[j*g + i]); + VERIFY_CHECK(vs_pos == points_total); + + /* Convert all points simultaneously from rustsecp256k1_v0_11_gej to rustsecp256k1_v0_11_ge. */ + rustsecp256k1_v0_11_ge_set_all_gej_var(prec, vs, points_total); + /* Convert all points from rustsecp256k1_v0_11_ge to rustsecp256k1_v0_11_ge_storage output. */ + for (block = 0; block < blocks; ++block) { + size_t index; + for (index = 0; index < points; ++index) { + VERIFY_CHECK(!rustsecp256k1_v0_11_ge_is_infinity(&prec[block * points + index])); + rustsecp256k1_v0_11_ge_to_storage(&table[block * points + index], &prec[block * points + index]); } } + + /* Free memory. */ + free(vs); + free(ds); free(prec); } diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h index cbdafe7a7..b6cf0cd92 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_gen_impl.h +++ b/secp256k1-sys/depend/secp256k1/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.* ***********************************************************************/ @@ -14,52 +14,226 @@ #include "hash_impl.h" #include "precomputed_ecmult_gen.h" -static void rustsecp256k1_v0_10_0_ecmult_gen_context_build(rustsecp256k1_v0_10_0_ecmult_gen_context *ctx) { - rustsecp256k1_v0_10_0_ecmult_gen_blind(ctx, NULL); +static void rustsecp256k1_v0_11_ecmult_gen_context_build(rustsecp256k1_v0_11_ecmult_gen_context *ctx) { + rustsecp256k1_v0_11_ecmult_gen_blind(ctx, NULL); ctx->built = 1; } -static int rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(const rustsecp256k1_v0_10_0_ecmult_gen_context* ctx) { +static int rustsecp256k1_v0_11_ecmult_gen_context_is_built(const rustsecp256k1_v0_11_ecmult_gen_context* ctx) { return ctx->built; } -static void rustsecp256k1_v0_10_0_ecmult_gen_context_clear(rustsecp256k1_v0_10_0_ecmult_gen_context *ctx) { +static void rustsecp256k1_v0_11_ecmult_gen_context_clear(rustsecp256k1_v0_11_ecmult_gen_context *ctx) { ctx->built = 0; - rustsecp256k1_v0_10_0_scalar_clear(&ctx->blind); - rustsecp256k1_v0_10_0_gej_clear(&ctx->initial); + rustsecp256k1_v0_11_scalar_clear(&ctx->scalar_offset); + rustsecp256k1_v0_11_ge_clear(&ctx->ge_offset); + rustsecp256k1_v0_11_fe_clear(&ctx->proj_blind); } -/* 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 rustsecp256k1_v0_10_0_ecmult_gen_prec_table[i][n_i] = n_i * (PREC_G)^i * G + U_i. - */ -static void rustsecp256k1_v0_10_0_ecmult_gen(const rustsecp256k1_v0_10_0_ecmult_gen_context *ctx, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *gn) { - int bits = ECMULT_GEN_PREC_BITS; - int g = ECMULT_GEN_PREC_G(bits); - int n = ECMULT_GEN_PREC_N(bits); - - rustsecp256k1_v0_10_0_ge add; - rustsecp256k1_v0_10_0_ge_storage adds; - rustsecp256k1_v0_10_0_scalar gnb; - int i, j, n_i; - +/* Compute the scalar (2^COMB_BITS - 1) / 2, the difference between the gn argument to + * rustsecp256k1_v0_11_ecmult_gen, and the scalar whose encoding the table lookup bits are drawn + * from (before applying blinding). */ +static void rustsecp256k1_v0_11_ecmult_gen_scalar_diff(rustsecp256k1_v0_11_scalar* diff) { + int i; + + /* Compute scalar -1/2. */ + rustsecp256k1_v0_11_scalar neghalf; + rustsecp256k1_v0_11_scalar_half(&neghalf, &rustsecp256k1_v0_11_scalar_one); + rustsecp256k1_v0_11_scalar_negate(&neghalf, &neghalf); + + /* Compute offset = 2^(COMB_BITS - 1). */ + *diff = rustsecp256k1_v0_11_scalar_one; + for (i = 0; i < COMB_BITS - 1; ++i) { + rustsecp256k1_v0_11_scalar_add(diff, diff, diff); + } + + /* The result is the sum 2^(COMB_BITS - 1) + (-1/2). */ + rustsecp256k1_v0_11_scalar_add(diff, diff, &neghalf); +} + +static void rustsecp256k1_v0_11_ecmult_gen(const rustsecp256k1_v0_11_ecmult_gen_context *ctx, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *gn) { + uint32_t comb_off; + rustsecp256k1_v0_11_ge add; + rustsecp256k1_v0_11_fe neg; + rustsecp256k1_v0_11_ge_storage adds; + rustsecp256k1_v0_11_scalar d; + /* 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)); - *r = ctx->initial; - /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ - rustsecp256k1_v0_10_0_scalar_add(&gnb, gn, &ctx->blind); - add.infinity = 0; - for (i = 0; i < n; i++) { - n_i = rustsecp256k1_v0_10_0_scalar_get_bits(&gnb, i * bits, bits); - for (j = 0; j < g; j++) { + + /* 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 = (2^COMB_BITS - 1)/2 - b (mod order) + * ctx->ge_offset = b*G + * 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). */ + rustsecp256k1_v0_11_scalar_add(&d, &ctx->scalar_offset, gn); + /* Convert to recoded array. */ + for (i = 0; i < 8 && i < ((COMB_BITS + 31) >> 5); ++i) { + recoded[i] = rustsecp256k1_v0_11_scalar_get_bits_limb32(&d, 32 * i, 32); + } + rustsecp256k1_v0_11_scalar_clear(&d); + + /* In rustsecp256k1_v0_11_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. + * + * rustsecp256k1_v0_11_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. */ + + /* 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; + /* 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) { + /* 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 = rustsecp256k1_v0_11_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; + } + + /* 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); + /** 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. @@ -70,61 +244,98 @@ static void rustsecp256k1_v0_10_0_ecmult_gen(const rustsecp256k1_v0_10_0_ecmult_ * by Dag Arne Osvik, Adi Shamir, and Eran Tromer * (https://www.tau.ac.il/~tromer/papers/cache.pdf) */ - rustsecp256k1_v0_10_0_ge_storage_cmov(&adds, &rustsecp256k1_v0_10_0_ecmult_gen_prec_table[i][j], j == n_i); + for (index = 0; index < COMB_POINTS; ++index) { + rustsecp256k1_v0_11_ge_storage_cmov(&adds, &rustsecp256k1_v0_11_ecmult_gen_prec_table[block][index], index == abs); + } + + /* Set add=adds or add=-adds, in constant time, based on sign. */ + rustsecp256k1_v0_11_ge_from_storage(&add, &adds); + rustsecp256k1_v0_11_fe_negate(&neg, &add.y, 1); + rustsecp256k1_v0_11_fe_cmov(&add.y, &neg, sign); + + /* Add the looked up and conditionally negated value to r. */ + if (EXPECT(first, 0)) { + /* If this is the first table lookup, we can skip addition. */ + rustsecp256k1_v0_11_gej_set_ge(r, &add); + /* Give the entry a random Z coordinate to blind intermediary results. */ + rustsecp256k1_v0_11_gej_rescale(r, &ctx->proj_blind); + first = 0; + } else { + rustsecp256k1_v0_11_gej_add_ge(r, r, &add); + } } - rustsecp256k1_v0_10_0_ge_from_storage(&add, &adds); - rustsecp256k1_v0_10_0_gej_add_ge(r, r, &add); + + /* Double the result, except in the last iteration. */ + if (comb_off-- == 0) break; + rustsecp256k1_v0_11_gej_double(r, r); } - n_i = 0; - rustsecp256k1_v0_10_0_ge_clear(&add); - rustsecp256k1_v0_10_0_scalar_clear(&gnb); + + /* Correct for the scalar_offset added at the start (ge_offset = b*G, while b was + * subtracted from the input scalar gn). */ + rustsecp256k1_v0_11_gej_add_ge(r, r, &ctx->ge_offset); + + /* Cleanup. */ + rustsecp256k1_v0_11_fe_clear(&neg); + rustsecp256k1_v0_11_ge_clear(&add); + rustsecp256k1_v0_11_memclear(&adds, sizeof(adds)); + rustsecp256k1_v0_11_memclear(&recoded, sizeof(recoded)); } -/* Setup blinding values for rustsecp256k1_v0_10_0_ecmult_gen. */ -static void rustsecp256k1_v0_10_0_ecmult_gen_blind(rustsecp256k1_v0_10_0_ecmult_gen_context *ctx, const unsigned char *seed32) { - rustsecp256k1_v0_10_0_scalar b; - rustsecp256k1_v0_10_0_gej gb; - rustsecp256k1_v0_10_0_fe s; +/* Setup blinding values for rustsecp256k1_v0_11_ecmult_gen. */ +static void rustsecp256k1_v0_11_ecmult_gen_blind(rustsecp256k1_v0_11_ecmult_gen_context *ctx, const unsigned char *seed32) { + rustsecp256k1_v0_11_scalar b; + rustsecp256k1_v0_11_scalar diff; + rustsecp256k1_v0_11_gej gb; + rustsecp256k1_v0_11_fe f; unsigned char nonce32[32]; - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 rng; + rustsecp256k1_v0_11_rfc6979_hmac_sha256 rng; unsigned char keydata[64]; + + /* Compute the (2^COMB_BITS - 1)/2 term once. */ + rustsecp256k1_v0_11_ecmult_gen_scalar_diff(&diff); + if (seed32 == NULL) { - /* When seed is NULL, reset the initial point and blinding value. */ - rustsecp256k1_v0_10_0_gej_set_ge(&ctx->initial, &rustsecp256k1_v0_10_0_ge_const_g); - rustsecp256k1_v0_10_0_gej_neg(&ctx->initial, &ctx->initial); - rustsecp256k1_v0_10_0_scalar_set_int(&ctx->blind, 1); + /* When seed is NULL, reset the final point and blinding value. */ + rustsecp256k1_v0_11_ge_neg(&ctx->ge_offset, &rustsecp256k1_v0_11_ge_const_g); + rustsecp256k1_v0_11_scalar_add(&ctx->scalar_offset, &rustsecp256k1_v0_11_scalar_one, &diff); + ctx->proj_blind = rustsecp256k1_v0_11_fe_one; return; } /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ - rustsecp256k1_v0_10_0_scalar_get_b32(keydata, &ctx->blind); + rustsecp256k1_v0_11_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. */ VERIFY_CHECK(seed32 != NULL); memcpy(keydata + 32, seed32, 32); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); - memset(keydata, 0, sizeof(keydata)); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&s, nonce32); - rustsecp256k1_v0_10_0_fe_cmov(&s, &rustsecp256k1_v0_10_0_fe_one, rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&s)); - /* Randomize the projection to defend against multiplier sidechannels. - Do this before our own call to rustsecp256k1_v0_10_0_ecmult_gen below. */ - rustsecp256k1_v0_10_0_gej_rescale(&ctx->initial, &s); - rustsecp256k1_v0_10_0_fe_clear(&s); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); - rustsecp256k1_v0_10_0_scalar_set_b32(&b, nonce32, NULL); - /* A blinding value of 0 works, but would undermine the projection hardening. */ - rustsecp256k1_v0_10_0_scalar_cmov(&b, &rustsecp256k1_v0_10_0_scalar_one, rustsecp256k1_v0_10_0_scalar_is_zero(&b)); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(&rng); - memset(nonce32, 0, 32); - /* The random projection in ctx->initial ensures that gb will have a random projection. */ - rustsecp256k1_v0_10_0_ecmult_gen(ctx, &gb, &b); - rustsecp256k1_v0_10_0_scalar_negate(&b, &b); - ctx->blind = b; - ctx->initial = gb; - rustsecp256k1_v0_10_0_scalar_clear(&b); - rustsecp256k1_v0_10_0_gej_clear(&gb); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, keydata, 64); + rustsecp256k1_v0_11_memclear(keydata, sizeof(keydata)); + + /* Compute projective blinding factor (cannot be 0). */ + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + rustsecp256k1_v0_11_fe_set_b32_mod(&f, nonce32); + rustsecp256k1_v0_11_fe_cmov(&f, &rustsecp256k1_v0_11_fe_one, rustsecp256k1_v0_11_fe_normalizes_to_zero(&f)); + ctx->proj_blind = f; + + /* For a random blinding value b, set scalar_offset=diff-b, ge_offset=bG */ + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + rustsecp256k1_v0_11_scalar_set_b32(&b, nonce32, NULL); + /* The blinding value cannot be zero, as that would mean ge_offset = infinity, + * which rustsecp256k1_v0_11_gej_add_ge cannot handle. */ + rustsecp256k1_v0_11_scalar_cmov(&b, &rustsecp256k1_v0_11_scalar_one, rustsecp256k1_v0_11_scalar_is_zero(&b)); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_11_ecmult_gen(ctx, &gb, &b); + rustsecp256k1_v0_11_scalar_negate(&b, &b); + rustsecp256k1_v0_11_scalar_add(&ctx->scalar_offset, &b, &diff); + rustsecp256k1_v0_11_ge_set_gej(&ctx->ge_offset, &gb); + + /* Clean up. */ + rustsecp256k1_v0_11_memclear(nonce32, sizeof(nonce32)); + rustsecp256k1_v0_11_scalar_clear(&b); + rustsecp256k1_v0_11_gej_clear(&gb); + rustsecp256k1_v0_11_fe_clear(&f); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_clear(&rng); } #endif /* SECP256K1_ECMULT_GEN_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h b/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h index dbd5215ae..2077c1db6 100644 --- a/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/ecmult_impl.h @@ -33,8 +33,8 @@ /** Larger values for ECMULT_WINDOW_SIZE result in possibly better * performance at the cost of an exponentially larger precomputed * table. The exact table size is - * (1 << (WINDOW_G - 2)) * sizeof(rustsecp256k1_v0_10_0_ge_storage) bytes, - * where sizeof(rustsecp256k1_v0_10_0_ge_storage) is typically 64 bytes but can + * (1 << (WINDOW_G - 2)) * sizeof(rustsecp256k1_v0_11_ge_storage) bytes, + * where sizeof(rustsecp256k1_v0_11_ge_storage) is typically 64 bytes but can * be larger due to platform-specific padding and alignment. * Two tables of this size are used (due to the endomorphism * optimization). @@ -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 */ @@ -70,14 +70,14 @@ * Lastly the zr[0] value, which isn't used above, is set so that: * - a.z = z(pre_a[0]) / zr[0] */ -static void rustsecp256k1_v0_10_0_ecmult_odd_multiples_table(int n, rustsecp256k1_v0_10_0_ge *pre_a, rustsecp256k1_v0_10_0_fe *zr, rustsecp256k1_v0_10_0_fe *z, const rustsecp256k1_v0_10_0_gej *a) { - rustsecp256k1_v0_10_0_gej d, ai; - rustsecp256k1_v0_10_0_ge d_ge; +static void rustsecp256k1_v0_11_ecmult_odd_multiples_table(int n, rustsecp256k1_v0_11_ge *pre_a, rustsecp256k1_v0_11_fe *zr, rustsecp256k1_v0_11_fe *z, const rustsecp256k1_v0_11_gej *a) { + rustsecp256k1_v0_11_gej d, ai; + rustsecp256k1_v0_11_ge d_ge; int i; VERIFY_CHECK(!a->infinity); - rustsecp256k1_v0_10_0_gej_double_var(&d, a, NULL); + rustsecp256k1_v0_11_gej_double_var(&d, a, NULL); /* * Perform the additions using an isomorphic curve Y^2 = X^3 + 7*C^6 where C := d.z. @@ -90,11 +90,11 @@ static void rustsecp256k1_v0_10_0_ecmult_odd_multiples_table(int n, rustsecp256k * * The group addition functions work correctly on these isomorphic curves. * In particular phi(d) is easy to represent in affine coordinates under this isomorphism. - * This lets us use the faster rustsecp256k1_v0_10_0_gej_add_ge_var group addition function that we wouldn't be able to use otherwise. + * This lets us use the faster rustsecp256k1_v0_11_gej_add_ge_var group addition function that we wouldn't be able to use otherwise. */ - rustsecp256k1_v0_10_0_ge_set_xy(&d_ge, &d.x, &d.y); - rustsecp256k1_v0_10_0_ge_set_gej_zinv(&pre_a[0], a, &d.z); - rustsecp256k1_v0_10_0_gej_set_ge(&ai, &pre_a[0]); + rustsecp256k1_v0_11_ge_set_xy(&d_ge, &d.x, &d.y); + rustsecp256k1_v0_11_ge_set_gej_zinv(&pre_a[0], a, &d.z); + rustsecp256k1_v0_11_gej_set_ge(&ai, &pre_a[0]); ai.z = a->z; /* pre_a[0] is the point (a.x*C^2, a.y*C^3, a.z*C) which is equivalent to a. @@ -103,18 +103,18 @@ static void rustsecp256k1_v0_10_0_ecmult_odd_multiples_table(int n, rustsecp256k zr[0] = d.z; for (i = 1; i < n; i++) { - rustsecp256k1_v0_10_0_gej_add_ge_var(&ai, &ai, &d_ge, &zr[i]); - rustsecp256k1_v0_10_0_ge_set_xy(&pre_a[i], &ai.x, &ai.y); + rustsecp256k1_v0_11_gej_add_ge_var(&ai, &ai, &d_ge, &zr[i]); + rustsecp256k1_v0_11_ge_set_xy(&pre_a[i], &ai.x, &ai.y); } /* Multiply the last z-coordinate by C to undo the isomorphism. * Since the z-coordinates of the pre_a values are implied by the zr array of z-coordinate ratios, * undoing the isomorphism here undoes the isomorphism for all pre_a values. */ - rustsecp256k1_v0_10_0_fe_mul(z, &ai.z, &d.z); + rustsecp256k1_v0_11_fe_mul(z, &ai.z, &d.z); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_table_verify(int n, int w) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_ecmult_table_verify(int n, int w) { (void)n; (void)w; VERIFY_CHECK(((n) & 1) == 1); @@ -122,33 +122,33 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_table_verify(int n, in VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_table_get_ge(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *pre, int n, int w) { - rustsecp256k1_v0_10_0_ecmult_table_verify(n,w); +SECP256K1_INLINE static void rustsecp256k1_v0_11_ecmult_table_get_ge(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *pre, int n, int w) { + rustsecp256k1_v0_11_ecmult_table_verify(n,w); if (n > 0) { *r = pre[(n-1)/2]; } else { *r = pre[(-n-1)/2]; - rustsecp256k1_v0_10_0_fe_negate(&(r->y), &(r->y), 1); + rustsecp256k1_v0_11_fe_negate(&(r->y), &(r->y), 1); } } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_table_get_ge_lambda(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *pre, const rustsecp256k1_v0_10_0_fe *x, int n, int w) { - rustsecp256k1_v0_10_0_ecmult_table_verify(n,w); +SECP256K1_INLINE static void rustsecp256k1_v0_11_ecmult_table_get_ge_lambda(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *pre, const rustsecp256k1_v0_11_fe *x, int n, int w) { + rustsecp256k1_v0_11_ecmult_table_verify(n,w); if (n > 0) { - rustsecp256k1_v0_10_0_ge_set_xy(r, &x[(n-1)/2], &pre[(n-1)/2].y); + rustsecp256k1_v0_11_ge_set_xy(r, &x[(n-1)/2], &pre[(n-1)/2].y); } else { - rustsecp256k1_v0_10_0_ge_set_xy(r, &x[(-n-1)/2], &pre[(-n-1)/2].y); - rustsecp256k1_v0_10_0_fe_negate(&(r->y), &(r->y), 1); + rustsecp256k1_v0_11_ge_set_xy(r, &x[(-n-1)/2], &pre[(-n-1)/2].y); + rustsecp256k1_v0_11_fe_negate(&(r->y), &(r->y), 1); } } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_table_get_ge_storage(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge_storage *pre, int n, int w) { - rustsecp256k1_v0_10_0_ecmult_table_verify(n,w); +SECP256K1_INLINE static void rustsecp256k1_v0_11_ecmult_table_get_ge_storage(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge_storage *pre, int n, int w) { + rustsecp256k1_v0_11_ecmult_table_verify(n,w); if (n > 0) { - rustsecp256k1_v0_10_0_ge_from_storage(r, &pre[(n-1)/2]); + rustsecp256k1_v0_11_ge_from_storage(r, &pre[(n-1)/2]); } else { - rustsecp256k1_v0_10_0_ge_from_storage(r, &pre[(-n-1)/2]); - rustsecp256k1_v0_10_0_fe_negate(&(r->y), &(r->y), 1); + rustsecp256k1_v0_11_ge_from_storage(r, &pre[(-n-1)/2]); + rustsecp256k1_v0_11_fe_negate(&(r->y), &(r->y), 1); } } @@ -159,8 +159,8 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_table_get_ge_storage(r * - the number of set values in wnaf is returned. This number is at most 256, and at most one more * than the number of bits in the (absolute value) of the input. */ -static int rustsecp256k1_v0_10_0_ecmult_wnaf(int *wnaf, int len, const rustsecp256k1_v0_10_0_scalar *a, int w) { - rustsecp256k1_v0_10_0_scalar s; +static int rustsecp256k1_v0_11_ecmult_wnaf(int *wnaf, int len, const rustsecp256k1_v0_11_scalar *a, int w) { + rustsecp256k1_v0_11_scalar s; int last_set_bit = -1; int bit = 0; int sign = 1; @@ -171,18 +171,21 @@ static int rustsecp256k1_v0_10_0_ecmult_wnaf(int *wnaf, int len, const rustsecp2 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 (rustsecp256k1_v0_10_0_scalar_get_bits(&s, 255, 1)) { - rustsecp256k1_v0_10_0_scalar_negate(&s, &s); + if (rustsecp256k1_v0_11_scalar_get_bits_limb32(&s, 255, 1)) { + rustsecp256k1_v0_11_scalar_negate(&s, &s); sign = -1; } + bit = 0; while (bit < len) { int now; int word; - if (rustsecp256k1_v0_10_0_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { + if (rustsecp256k1_v0_11_scalar_get_bits_limb32(&s, bit, 1) == (unsigned int)carry) { bit++; continue; } @@ -192,7 +195,7 @@ static int rustsecp256k1_v0_10_0_ecmult_wnaf(int *wnaf, int len, const rustsecp2 now = len - bit; } - word = rustsecp256k1_v0_10_0_scalar_get_bits_var(&s, bit, now) + carry; + word = rustsecp256k1_v0_11_scalar_get_bits_var(&s, bit, now) + carry; carry = (word >> (w-1)) & 1; word -= carry << w; @@ -209,7 +212,7 @@ static int rustsecp256k1_v0_10_0_ecmult_wnaf(int *wnaf, int len, const rustsecp2 VERIFY_CHECK(carry == 0); while (verify_bit < 256) { - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_get_bits(&s, verify_bit, 1) == 0); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_get_bits_limb32(&s, verify_bit, 1) == 0); verify_bit++; } } @@ -217,25 +220,25 @@ static int rustsecp256k1_v0_10_0_ecmult_wnaf(int *wnaf, int len, const rustsecp2 return last_set_bit + 1; } -struct rustsecp256k1_v0_10_0_strauss_point_state { +struct rustsecp256k1_v0_11_strauss_point_state { int wnaf_na_1[129]; int wnaf_na_lam[129]; int bits_na_1; int bits_na_lam; }; -struct rustsecp256k1_v0_10_0_strauss_state { +struct rustsecp256k1_v0_11_strauss_state { /* aux is used to hold z-ratios, and then used to hold pre_a[i].x * BETA values. */ - rustsecp256k1_v0_10_0_fe* aux; - rustsecp256k1_v0_10_0_ge* pre_a; - struct rustsecp256k1_v0_10_0_strauss_point_state* ps; + rustsecp256k1_v0_11_fe* aux; + rustsecp256k1_v0_11_ge* pre_a; + struct rustsecp256k1_v0_11_strauss_point_state* ps; }; -static void rustsecp256k1_v0_10_0_ecmult_strauss_wnaf(const struct rustsecp256k1_v0_10_0_strauss_state *state, rustsecp256k1_v0_10_0_gej *r, size_t num, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_scalar *na, const rustsecp256k1_v0_10_0_scalar *ng) { - rustsecp256k1_v0_10_0_ge tmpa; - rustsecp256k1_v0_10_0_fe Z; +static void rustsecp256k1_v0_11_ecmult_strauss_wnaf(const struct rustsecp256k1_v0_11_strauss_state *state, rustsecp256k1_v0_11_gej *r, size_t num, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_scalar *na, const rustsecp256k1_v0_11_scalar *ng) { + rustsecp256k1_v0_11_ge tmpa; + rustsecp256k1_v0_11_fe Z; /* Split G factors. */ - rustsecp256k1_v0_10_0_scalar ng_1, ng_128; + rustsecp256k1_v0_11_scalar ng_1, ng_128; int wnaf_ng_1[129]; int bits_ng_1 = 0; int wnaf_ng_128[129]; @@ -245,19 +248,19 @@ static void rustsecp256k1_v0_10_0_ecmult_strauss_wnaf(const struct rustsecp256k1 size_t np; size_t no = 0; - rustsecp256k1_v0_10_0_fe_set_int(&Z, 1); + rustsecp256k1_v0_11_fe_set_int(&Z, 1); for (np = 0; np < num; ++np) { - rustsecp256k1_v0_10_0_gej tmp; - rustsecp256k1_v0_10_0_scalar na_1, na_lam; - if (rustsecp256k1_v0_10_0_scalar_is_zero(&na[np]) || rustsecp256k1_v0_10_0_gej_is_infinity(&a[np])) { + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_scalar na_1, na_lam; + if (rustsecp256k1_v0_11_scalar_is_zero(&na[np]) || rustsecp256k1_v0_11_gej_is_infinity(&a[np])) { continue; } /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ - rustsecp256k1_v0_10_0_scalar_split_lambda(&na_1, &na_lam, &na[np]); + rustsecp256k1_v0_11_scalar_split_lambda(&na_1, &na_lam, &na[np]); /* build wnaf representation for na_1 and na_lam. */ - state->ps[no].bits_na_1 = rustsecp256k1_v0_10_0_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A); - state->ps[no].bits_na_lam = rustsecp256k1_v0_10_0_ecmult_wnaf(state->ps[no].wnaf_na_lam, 129, &na_lam, WINDOW_A); + state->ps[no].bits_na_1 = rustsecp256k1_v0_11_ecmult_wnaf(state->ps[no].wnaf_na_1, 129, &na_1, WINDOW_A); + state->ps[no].bits_na_lam = rustsecp256k1_v0_11_ecmult_wnaf(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) { @@ -274,37 +277,37 @@ static void rustsecp256k1_v0_10_0_ecmult_strauss_wnaf(const struct rustsecp256k1 * the Z coordinate of the result once at the end. * The exception is the precomputed G table points, which are actually * affine. Compared to the base used for other points, they have a Z ratio - * of 1/Z, so we can use rustsecp256k1_v0_10_0_gej_add_zinv_var, which uses the same + * of 1/Z, so we can use rustsecp256k1_v0_11_gej_add_zinv_var, which uses the same * isomorphism to efficiently add with a known Z inverse. */ tmp = a[np]; if (no) { - rustsecp256k1_v0_10_0_gej_rescale(&tmp, &Z); + rustsecp256k1_v0_11_gej_rescale(&tmp, &Z); } - rustsecp256k1_v0_10_0_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp); - if (no) rustsecp256k1_v0_10_0_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &(a[np].z)); + rustsecp256k1_v0_11_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp); + if (no) rustsecp256k1_v0_11_fe_mul(state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &(a[np].z)); ++no; } /* Bring them to the same Z denominator. */ if (no) { - rustsecp256k1_v0_10_0_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux); + rustsecp256k1_v0_11_ge_table_set_globalz(ECMULT_TABLE_SIZE(WINDOW_A) * no, state->pre_a, state->aux); } for (np = 0; np < no; ++np) { for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { - rustsecp256k1_v0_10_0_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i].x, &rustsecp256k1_v0_10_0_const_beta); + rustsecp256k1_v0_11_fe_mul(&state->aux[np * ECMULT_TABLE_SIZE(WINDOW_A) + i], &state->pre_a[np * ECMULT_TABLE_SIZE(WINDOW_A) + i].x, &rustsecp256k1_v0_11_const_beta); } } if (ng) { /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ - rustsecp256k1_v0_10_0_scalar_split_128(&ng_1, &ng_128, ng); + rustsecp256k1_v0_11_scalar_split_128(&ng_1, &ng_128, ng); /* Build wnaf representation for ng_1 and ng_128 */ - bits_ng_1 = rustsecp256k1_v0_10_0_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); - bits_ng_128 = rustsecp256k1_v0_10_0_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + bits_ng_1 = rustsecp256k1_v0_11_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = rustsecp256k1_v0_11_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); if (bits_ng_1 > bits) { bits = bits_ng_1; } @@ -313,61 +316,61 @@ static void rustsecp256k1_v0_10_0_ecmult_strauss_wnaf(const struct rustsecp256k1 } } - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); for (i = bits - 1; i >= 0; i--) { int n; - rustsecp256k1_v0_10_0_gej_double_var(r, r, NULL); + rustsecp256k1_v0_11_gej_double_var(r, r, NULL); for (np = 0; np < no; ++np) { if (i < state->ps[np].bits_na_1 && (n = state->ps[np].wnaf_na_1[i])) { - rustsecp256k1_v0_10_0_ecmult_table_get_ge(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - rustsecp256k1_v0_10_0_gej_add_ge_var(r, r, &tmpa, NULL); + rustsecp256k1_v0_11_ecmult_table_get_ge(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); + rustsecp256k1_v0_11_gej_add_ge_var(r, r, &tmpa, NULL); } if (i < state->ps[np].bits_na_lam && (n = state->ps[np].wnaf_na_lam[i])) { - rustsecp256k1_v0_10_0_ecmult_table_get_ge_lambda(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); - rustsecp256k1_v0_10_0_gej_add_ge_var(r, r, &tmpa, NULL); + rustsecp256k1_v0_11_ecmult_table_get_ge_lambda(&tmpa, state->pre_a + np * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + np * ECMULT_TABLE_SIZE(WINDOW_A), n, WINDOW_A); + rustsecp256k1_v0_11_gej_add_ge_var(r, r, &tmpa, NULL); } } if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { - rustsecp256k1_v0_10_0_ecmult_table_get_ge_storage(&tmpa, rustsecp256k1_v0_10_0_pre_g, n, WINDOW_G); - rustsecp256k1_v0_10_0_gej_add_zinv_var(r, r, &tmpa, &Z); + rustsecp256k1_v0_11_ecmult_table_get_ge_storage(&tmpa, rustsecp256k1_v0_11_pre_g, n, WINDOW_G); + rustsecp256k1_v0_11_gej_add_zinv_var(r, r, &tmpa, &Z); } if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { - rustsecp256k1_v0_10_0_ecmult_table_get_ge_storage(&tmpa, rustsecp256k1_v0_10_0_pre_g_128, n, WINDOW_G); - rustsecp256k1_v0_10_0_gej_add_zinv_var(r, r, &tmpa, &Z); + rustsecp256k1_v0_11_ecmult_table_get_ge_storage(&tmpa, rustsecp256k1_v0_11_pre_g_128, n, WINDOW_G); + rustsecp256k1_v0_11_gej_add_zinv_var(r, r, &tmpa, &Z); } } if (!r->infinity) { - rustsecp256k1_v0_10_0_fe_mul(&r->z, &r->z, &Z); + rustsecp256k1_v0_11_fe_mul(&r->z, &r->z, &Z); } } -static void rustsecp256k1_v0_10_0_ecmult(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_scalar *na, const rustsecp256k1_v0_10_0_scalar *ng) { - rustsecp256k1_v0_10_0_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)]; - rustsecp256k1_v0_10_0_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; - struct rustsecp256k1_v0_10_0_strauss_point_state ps[1]; - struct rustsecp256k1_v0_10_0_strauss_state state; +static void rustsecp256k1_v0_11_ecmult(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_scalar *na, const rustsecp256k1_v0_11_scalar *ng) { + rustsecp256k1_v0_11_fe aux[ECMULT_TABLE_SIZE(WINDOW_A)]; + rustsecp256k1_v0_11_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + struct rustsecp256k1_v0_11_strauss_point_state ps[1]; + struct rustsecp256k1_v0_11_strauss_state state; state.aux = aux; state.pre_a = pre_a; state.ps = ps; - rustsecp256k1_v0_10_0_ecmult_strauss_wnaf(&state, r, 1, a, na, ng); + rustsecp256k1_v0_11_ecmult_strauss_wnaf(&state, r, 1, a, na, ng); } -static size_t rustsecp256k1_v0_10_0_strauss_scratch_size(size_t n_points) { - static const size_t point_size = (sizeof(rustsecp256k1_v0_10_0_ge) + sizeof(rustsecp256k1_v0_10_0_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct rustsecp256k1_v0_10_0_strauss_point_state) + sizeof(rustsecp256k1_v0_10_0_gej) + sizeof(rustsecp256k1_v0_10_0_scalar); +static size_t rustsecp256k1_v0_11_strauss_scratch_size(size_t n_points) { + static const size_t point_size = (sizeof(rustsecp256k1_v0_11_ge) + sizeof(rustsecp256k1_v0_11_fe)) * ECMULT_TABLE_SIZE(WINDOW_A) + sizeof(struct rustsecp256k1_v0_11_strauss_point_state) + sizeof(rustsecp256k1_v0_11_gej) + sizeof(rustsecp256k1_v0_11_scalar); return n_points*point_size; } -static int rustsecp256k1_v0_10_0_ecmult_strauss_batch(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch *scratch, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *inp_g_sc, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { - rustsecp256k1_v0_10_0_gej* points; - rustsecp256k1_v0_10_0_scalar* scalars; - struct rustsecp256k1_v0_10_0_strauss_state state; +static int rustsecp256k1_v0_11_ecmult_strauss_batch(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch *scratch, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *inp_g_sc, rustsecp256k1_v0_11_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { + rustsecp256k1_v0_11_gej* points; + rustsecp256k1_v0_11_scalar* scalars; + struct rustsecp256k1_v0_11_strauss_state state; size_t i; - const size_t scratch_checkpoint = rustsecp256k1_v0_10_0_scratch_checkpoint(error_callback, scratch); + const size_t scratch_checkpoint = rustsecp256k1_v0_11_scratch_checkpoint(error_callback, scratch); - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); if (inp_g_sc == NULL && n_points == 0) { return 1; } @@ -375,37 +378,37 @@ static int rustsecp256k1_v0_10_0_ecmult_strauss_batch(const rustsecp256k1_v0_10_ /* We allocate STRAUSS_SCRATCH_OBJECTS objects on the scratch space. If these * allocations change, make sure to update the STRAUSS_SCRATCH_OBJECTS * constant and strauss_scratch_size accordingly. */ - points = (rustsecp256k1_v0_10_0_gej*)rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, n_points * sizeof(rustsecp256k1_v0_10_0_gej)); - scalars = (rustsecp256k1_v0_10_0_scalar*)rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, n_points * sizeof(rustsecp256k1_v0_10_0_scalar)); - state.aux = (rustsecp256k1_v0_10_0_fe*)rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_10_0_fe)); - state.pre_a = (rustsecp256k1_v0_10_0_ge*)rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_10_0_ge)); - state.ps = (struct rustsecp256k1_v0_10_0_strauss_point_state*)rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, n_points * sizeof(struct rustsecp256k1_v0_10_0_strauss_point_state)); + points = (rustsecp256k1_v0_11_gej*)rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, n_points * sizeof(rustsecp256k1_v0_11_gej)); + scalars = (rustsecp256k1_v0_11_scalar*)rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, n_points * sizeof(rustsecp256k1_v0_11_scalar)); + state.aux = (rustsecp256k1_v0_11_fe*)rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_11_fe)); + state.pre_a = (rustsecp256k1_v0_11_ge*)rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, n_points * ECMULT_TABLE_SIZE(WINDOW_A) * sizeof(rustsecp256k1_v0_11_ge)); + state.ps = (struct rustsecp256k1_v0_11_strauss_point_state*)rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, n_points * sizeof(struct rustsecp256k1_v0_11_strauss_point_state)); if (points == NULL || scalars == NULL || state.aux == NULL || state.pre_a == NULL || state.ps == NULL) { - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + rustsecp256k1_v0_11_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } for (i = 0; i < n_points; i++) { - rustsecp256k1_v0_10_0_ge point; + rustsecp256k1_v0_11_ge point; if (!cb(&scalars[i], &point, i+cb_offset, cbdata)) { - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + rustsecp256k1_v0_11_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } - rustsecp256k1_v0_10_0_gej_set_ge(&points[i], &point); + rustsecp256k1_v0_11_gej_set_ge(&points[i], &point); } - rustsecp256k1_v0_10_0_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc); - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + rustsecp256k1_v0_11_ecmult_strauss_wnaf(&state, r, n_points, points, scalars, inp_g_sc); + rustsecp256k1_v0_11_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 1; } -/* Wrapper for rustsecp256k1_v0_10_0_ecmult_multi_func interface */ -static int rustsecp256k1_v0_10_0_ecmult_strauss_batch_single(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch *scratch, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *inp_g_sc, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void *cbdata, size_t n) { - return rustsecp256k1_v0_10_0_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0); +/* Wrapper for rustsecp256k1_v0_11_ecmult_multi_func interface */ +static int rustsecp256k1_v0_11_ecmult_strauss_batch_single(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch *scratch, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *inp_g_sc, rustsecp256k1_v0_11_ecmult_multi_callback cb, void *cbdata, size_t n) { + return rustsecp256k1_v0_11_ecmult_strauss_batch(error_callback, scratch, r, inp_g_sc, cb, cbdata, n, 0); } -static size_t rustsecp256k1_v0_10_0_strauss_max_points(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch *scratch) { - return rustsecp256k1_v0_10_0_scratch_max_allocation(error_callback, scratch, STRAUSS_SCRATCH_OBJECTS) / rustsecp256k1_v0_10_0_strauss_scratch_size(1); +static size_t rustsecp256k1_v0_11_strauss_max_points(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch *scratch) { + return rustsecp256k1_v0_11_scratch_max_allocation(error_callback, scratch, STRAUSS_SCRATCH_OBJECTS) / rustsecp256k1_v0_11_strauss_scratch_size(1); } /** Convert a number to WNAF notation. @@ -415,25 +418,25 @@ static size_t rustsecp256k1_v0_10_0_strauss_max_points(const rustsecp256k1_v0_10 * - the number of words set is always WNAF_SIZE(w) * - the returned skew is 0 or 1 */ -static int rustsecp256k1_v0_10_0_wnaf_fixed(int *wnaf, const rustsecp256k1_v0_10_0_scalar *s, int w) { +static int rustsecp256k1_v0_11_wnaf_fixed(int *wnaf, const rustsecp256k1_v0_11_scalar *s, int w) { int skew = 0; int pos; int max_pos; int last_w; - const rustsecp256k1_v0_10_0_scalar *work = s; + const rustsecp256k1_v0_11_scalar *work = s; - if (rustsecp256k1_v0_10_0_scalar_is_zero(s)) { + if (rustsecp256k1_v0_11_scalar_is_zero(s)) { for (pos = 0; pos < WNAF_SIZE(w); pos++) { wnaf[pos] = 0; } return 0; } - if (rustsecp256k1_v0_10_0_scalar_is_even(s)) { + if (rustsecp256k1_v0_11_scalar_is_even(s)) { skew = 1; } - wnaf[0] = rustsecp256k1_v0_10_0_scalar_get_bits_var(work, 0, w) + skew; + wnaf[0] = rustsecp256k1_v0_11_scalar_get_bits_var(work, 0, w) + skew; /* Compute last window size. Relevant when window size doesn't divide the * number of bits in the scalar */ last_w = WNAF_BITS - (WNAF_SIZE(w) - 1) * w; @@ -441,7 +444,7 @@ static int rustsecp256k1_v0_10_0_wnaf_fixed(int *wnaf, const rustsecp256k1_v0_10 /* Store the position of the first nonzero word in max_pos to allow * skipping leading zeros when calculating the wnaf. */ for (pos = WNAF_SIZE(w) - 1; pos > 0; pos--) { - int val = rustsecp256k1_v0_10_0_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); + int val = rustsecp256k1_v0_11_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); if(val != 0) { break; } @@ -451,7 +454,7 @@ static int rustsecp256k1_v0_10_0_wnaf_fixed(int *wnaf, const rustsecp256k1_v0_10 pos = 1; while (pos <= max_pos) { - int val = rustsecp256k1_v0_10_0_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); + int val = rustsecp256k1_v0_11_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w); if ((val & 1) == 0) { wnaf[pos - 1] -= (1 << w); wnaf[pos] = (val + 1); @@ -477,14 +480,14 @@ static int rustsecp256k1_v0_10_0_wnaf_fixed(int *wnaf, const rustsecp256k1_v0_10 return skew; } -struct rustsecp256k1_v0_10_0_pippenger_point_state { +struct rustsecp256k1_v0_11_pippenger_point_state { int skew_na; size_t input_pos; }; -struct rustsecp256k1_v0_10_0_pippenger_state { +struct rustsecp256k1_v0_11_pippenger_state { int *wnaf_na; - struct rustsecp256k1_v0_10_0_pippenger_point_state* ps; + struct rustsecp256k1_v0_11_pippenger_point_state* ps; }; /* @@ -494,7 +497,7 @@ struct rustsecp256k1_v0_10_0_pippenger_state { * to the point's wnaf[i]. Second, the buckets are added together such that * r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ... */ -static int rustsecp256k1_v0_10_0_ecmult_pippenger_wnaf(rustsecp256k1_v0_10_0_gej *buckets, int bucket_window, struct rustsecp256k1_v0_10_0_pippenger_state *state, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *sc, const rustsecp256k1_v0_10_0_ge *pt, size_t num) { +static int rustsecp256k1_v0_11_ecmult_pippenger_wnaf(rustsecp256k1_v0_11_gej *buckets, int bucket_window, struct rustsecp256k1_v0_11_pippenger_state *state, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *sc, const rustsecp256k1_v0_11_ge *pt, size_t num) { size_t n_wnaf = WNAF_SIZE(bucket_window+1); size_t np; size_t no = 0; @@ -502,55 +505,55 @@ static int rustsecp256k1_v0_10_0_ecmult_pippenger_wnaf(rustsecp256k1_v0_10_0_gej int j; for (np = 0; np < num; ++np) { - if (rustsecp256k1_v0_10_0_scalar_is_zero(&sc[np]) || rustsecp256k1_v0_10_0_ge_is_infinity(&pt[np])) { + if (rustsecp256k1_v0_11_scalar_is_zero(&sc[np]) || rustsecp256k1_v0_11_ge_is_infinity(&pt[np])) { continue; } state->ps[no].input_pos = np; - state->ps[no].skew_na = rustsecp256k1_v0_10_0_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); + state->ps[no].skew_na = rustsecp256k1_v0_11_wnaf_fixed(&state->wnaf_na[no*n_wnaf], &sc[np], bucket_window+1); no++; } - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); if (no == 0) { return 1; } for (i = n_wnaf - 1; i >= 0; i--) { - rustsecp256k1_v0_10_0_gej running_sum; + rustsecp256k1_v0_11_gej running_sum; for(j = 0; j < ECMULT_TABLE_SIZE(bucket_window+2); j++) { - rustsecp256k1_v0_10_0_gej_set_infinity(&buckets[j]); + rustsecp256k1_v0_11_gej_set_infinity(&buckets[j]); } for (np = 0; np < no; ++np) { int n = state->wnaf_na[np*n_wnaf + i]; - struct rustsecp256k1_v0_10_0_pippenger_point_state point_state = state->ps[np]; - rustsecp256k1_v0_10_0_ge tmp; + struct rustsecp256k1_v0_11_pippenger_point_state point_state = state->ps[np]; + rustsecp256k1_v0_11_ge tmp; int idx; if (i == 0) { /* correct for wnaf skew */ int skew = point_state.skew_na; if (skew) { - rustsecp256k1_v0_10_0_ge_neg(&tmp, &pt[point_state.input_pos]); - rustsecp256k1_v0_10_0_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); + rustsecp256k1_v0_11_ge_neg(&tmp, &pt[point_state.input_pos]); + rustsecp256k1_v0_11_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL); } } if (n > 0) { idx = (n - 1)/2; - rustsecp256k1_v0_10_0_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); + rustsecp256k1_v0_11_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL); } else if (n < 0) { idx = -(n + 1)/2; - rustsecp256k1_v0_10_0_ge_neg(&tmp, &pt[point_state.input_pos]); - rustsecp256k1_v0_10_0_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); + rustsecp256k1_v0_11_ge_neg(&tmp, &pt[point_state.input_pos]); + rustsecp256k1_v0_11_gej_add_ge_var(&buckets[idx], &buckets[idx], &tmp, NULL); } } for(j = 0; j < bucket_window; j++) { - rustsecp256k1_v0_10_0_gej_double_var(r, r, NULL); + rustsecp256k1_v0_11_gej_double_var(r, r, NULL); } - rustsecp256k1_v0_10_0_gej_set_infinity(&running_sum); + rustsecp256k1_v0_11_gej_set_infinity(&running_sum); /* Accumulate the sum: bucket[0] + 3*bucket[1] + 5*bucket[2] + 7*bucket[3] + ... * = bucket[0] + bucket[1] + bucket[2] + bucket[3] + ... * + 2 * (bucket[1] + 2*bucket[2] + 3*bucket[3] + ...) @@ -560,13 +563,13 @@ static int rustsecp256k1_v0_10_0_ecmult_pippenger_wnaf(rustsecp256k1_v0_10_0_gej * 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--) { - rustsecp256k1_v0_10_0_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); - rustsecp256k1_v0_10_0_gej_add_var(r, r, &running_sum, NULL); + rustsecp256k1_v0_11_gej_add_var(&running_sum, &running_sum, &buckets[j], NULL); + rustsecp256k1_v0_11_gej_add_var(r, r, &running_sum, NULL); } - rustsecp256k1_v0_10_0_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); - rustsecp256k1_v0_10_0_gej_double_var(r, r, NULL); - rustsecp256k1_v0_10_0_gej_add_var(r, r, &running_sum, NULL); + rustsecp256k1_v0_11_gej_add_var(&running_sum, &running_sum, &buckets[0], NULL); + rustsecp256k1_v0_11_gej_double_var(r, r, NULL); + rustsecp256k1_v0_11_gej_add_var(r, r, &running_sum, NULL); } return 1; } @@ -575,7 +578,7 @@ static int rustsecp256k1_v0_10_0_ecmult_pippenger_wnaf(rustsecp256k1_v0_10_0_gej * Returns optimal bucket_window (number of bits of a scalar represented by a * set of buckets) for a given number of points. */ -static int rustsecp256k1_v0_10_0_pippenger_bucket_window(size_t n) { +static int rustsecp256k1_v0_11_pippenger_bucket_window(size_t n) { if (n <= 1) { return 1; } else if (n <= 4) { @@ -604,7 +607,7 @@ static int rustsecp256k1_v0_10_0_pippenger_bucket_window(size_t n) { /** * Returns the maximum optimal number of points for a bucket_window. */ -static size_t rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(int bucket_window) { +static size_t rustsecp256k1_v0_11_pippenger_bucket_window_inv(int bucket_window) { switch(bucket_window) { case 1: return 1; case 2: return 4; @@ -623,18 +626,18 @@ static size_t rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(int bucket_windo } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_endo_split(rustsecp256k1_v0_10_0_scalar *s1, rustsecp256k1_v0_10_0_scalar *s2, rustsecp256k1_v0_10_0_ge *p1, rustsecp256k1_v0_10_0_ge *p2) { - rustsecp256k1_v0_10_0_scalar tmp = *s1; - rustsecp256k1_v0_10_0_scalar_split_lambda(s1, s2, &tmp); - rustsecp256k1_v0_10_0_ge_mul_lambda(p2, p1); +SECP256K1_INLINE static void rustsecp256k1_v0_11_ecmult_endo_split(rustsecp256k1_v0_11_scalar *s1, rustsecp256k1_v0_11_scalar *s2, rustsecp256k1_v0_11_ge *p1, rustsecp256k1_v0_11_ge *p2) { + rustsecp256k1_v0_11_scalar tmp = *s1; + rustsecp256k1_v0_11_scalar_split_lambda(s1, s2, &tmp); + rustsecp256k1_v0_11_ge_mul_lambda(p2, p1); - if (rustsecp256k1_v0_10_0_scalar_is_high(s1)) { - rustsecp256k1_v0_10_0_scalar_negate(s1, s1); - rustsecp256k1_v0_10_0_ge_neg(p1, p1); + if (rustsecp256k1_v0_11_scalar_is_high(s1)) { + rustsecp256k1_v0_11_scalar_negate(s1, s1); + rustsecp256k1_v0_11_ge_neg(p1, p1); } - if (rustsecp256k1_v0_10_0_scalar_is_high(s2)) { - rustsecp256k1_v0_10_0_scalar_negate(s2, s2); - rustsecp256k1_v0_10_0_ge_neg(p2, p2); + if (rustsecp256k1_v0_11_scalar_is_high(s2)) { + rustsecp256k1_v0_11_scalar_negate(s2, s2); + rustsecp256k1_v0_11_ge_neg(p2, p2); } } @@ -642,91 +645,78 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_ecmult_endo_split(rustsecp256 * Returns the scratch size required for a given number of points (excluding * base point G) without considering alignment. */ -static size_t rustsecp256k1_v0_10_0_pippenger_scratch_size(size_t n_points, int bucket_window) { +static size_t rustsecp256k1_v0_11_pippenger_scratch_size(size_t n_points, int bucket_window) { size_t entries = 2*n_points + 2; - size_t entry_size = sizeof(rustsecp256k1_v0_10_0_ge) + sizeof(rustsecp256k1_v0_10_0_scalar) + sizeof(struct rustsecp256k1_v0_10_0_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); - return (sizeof(rustsecp256k1_v0_10_0_gej) << bucket_window) + sizeof(struct rustsecp256k1_v0_10_0_pippenger_state) + entries * entry_size; + size_t entry_size = sizeof(rustsecp256k1_v0_11_ge) + sizeof(rustsecp256k1_v0_11_scalar) + sizeof(struct rustsecp256k1_v0_11_pippenger_point_state) + (WNAF_SIZE(bucket_window+1)+1)*sizeof(int); + return (sizeof(rustsecp256k1_v0_11_gej) << bucket_window) + sizeof(struct rustsecp256k1_v0_11_pippenger_state) + entries * entry_size; } -static int rustsecp256k1_v0_10_0_ecmult_pippenger_batch(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch *scratch, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *inp_g_sc, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { - const size_t scratch_checkpoint = rustsecp256k1_v0_10_0_scratch_checkpoint(error_callback, scratch); +static int rustsecp256k1_v0_11_ecmult_pippenger_batch(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch *scratch, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *inp_g_sc, rustsecp256k1_v0_11_ecmult_multi_callback cb, void *cbdata, size_t n_points, size_t cb_offset) { + const size_t scratch_checkpoint = rustsecp256k1_v0_11_scratch_checkpoint(error_callback, scratch); /* Use 2(n+1) with the endomorphism, when calculating batch * sizes. The reason for +1 is that we add the G scalar to the list of * other scalars. */ size_t entries = 2*n_points + 2; - rustsecp256k1_v0_10_0_ge *points; - rustsecp256k1_v0_10_0_scalar *scalars; - rustsecp256k1_v0_10_0_gej *buckets; - struct rustsecp256k1_v0_10_0_pippenger_state *state_space; + rustsecp256k1_v0_11_ge *points; + rustsecp256k1_v0_11_scalar *scalars; + rustsecp256k1_v0_11_gej *buckets; + struct rustsecp256k1_v0_11_pippenger_state *state_space; size_t idx = 0; size_t point_idx = 0; - int i, j; int bucket_window; - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); if (inp_g_sc == NULL && n_points == 0) { return 1; } - bucket_window = rustsecp256k1_v0_10_0_pippenger_bucket_window(n_points); + bucket_window = rustsecp256k1_v0_11_pippenger_bucket_window(n_points); /* We allocate PIPPENGER_SCRATCH_OBJECTS objects on the scratch space. If * these allocations change, make sure to update the * PIPPENGER_SCRATCH_OBJECTS constant and pippenger_scratch_size * accordingly. */ - points = (rustsecp256k1_v0_10_0_ge *) rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, entries * sizeof(*points)); - scalars = (rustsecp256k1_v0_10_0_scalar *) rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, entries * sizeof(*scalars)); - state_space = (struct rustsecp256k1_v0_10_0_pippenger_state *) rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, sizeof(*state_space)); + points = (rustsecp256k1_v0_11_ge *) rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, entries * sizeof(*points)); + scalars = (rustsecp256k1_v0_11_scalar *) rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, entries * sizeof(*scalars)); + state_space = (struct rustsecp256k1_v0_11_pippenger_state *) rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, sizeof(*state_space)); if (points == NULL || scalars == NULL || state_space == NULL) { - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + rustsecp256k1_v0_11_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } - state_space->ps = (struct rustsecp256k1_v0_10_0_pippenger_point_state *) rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps)); - state_space->wnaf_na = (int *) rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); - buckets = (rustsecp256k1_v0_10_0_gej *) rustsecp256k1_v0_10_0_scratch_alloc(error_callback, scratch, ((size_t)1 << bucket_window) * sizeof(*buckets)); + state_space->ps = (struct rustsecp256k1_v0_11_pippenger_point_state *) rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps)); + state_space->wnaf_na = (int *) rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int)); + buckets = (rustsecp256k1_v0_11_gej *) rustsecp256k1_v0_11_scratch_alloc(error_callback, scratch, ((size_t)1 << bucket_window) * sizeof(*buckets)); if (state_space->ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) { - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + rustsecp256k1_v0_11_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } if (inp_g_sc != NULL) { scalars[0] = *inp_g_sc; - points[0] = rustsecp256k1_v0_10_0_ge_const_g; + points[0] = rustsecp256k1_v0_11_ge_const_g; idx++; - rustsecp256k1_v0_10_0_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]); + rustsecp256k1_v0_11_ecmult_endo_split(&scalars[0], &scalars[1], &points[0], &points[1]); idx++; } while (point_idx < n_points) { if (!cb(&scalars[idx], &points[idx], point_idx + cb_offset, cbdata)) { - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); + rustsecp256k1_v0_11_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint); return 0; } idx++; - rustsecp256k1_v0_10_0_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]); + rustsecp256k1_v0_11_ecmult_endo_split(&scalars[idx - 1], &scalars[idx], &points[idx - 1], &points[idx]); idx++; point_idx++; } - rustsecp256k1_v0_10_0_ecmult_pippenger_wnaf(buckets, bucket_window, state_space, r, scalars, points, idx); - - /* Clear data */ - for(i = 0; (size_t)i < idx; i++) { - rustsecp256k1_v0_10_0_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< max_alloc) { break; } @@ -770,32 +760,32 @@ static size_t rustsecp256k1_v0_10_0_pippenger_max_points(const rustsecp256k1_v0_ /* Computes ecmult_multi by simply multiplying and adding each point. Does not * require a scratch space */ -static int rustsecp256k1_v0_10_0_ecmult_multi_simple_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *inp_g_sc, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void *cbdata, size_t n_points) { +static int rustsecp256k1_v0_11_ecmult_multi_simple_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *inp_g_sc, rustsecp256k1_v0_11_ecmult_multi_callback cb, void *cbdata, size_t n_points) { size_t point_idx; - rustsecp256k1_v0_10_0_gej tmpj; + rustsecp256k1_v0_11_gej tmpj; - rustsecp256k1_v0_10_0_gej_set_infinity(r); - rustsecp256k1_v0_10_0_gej_set_infinity(&tmpj); + rustsecp256k1_v0_11_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(&tmpj); /* r = inp_g_sc*G */ - rustsecp256k1_v0_10_0_ecmult(r, &tmpj, &rustsecp256k1_v0_10_0_scalar_zero, inp_g_sc); + rustsecp256k1_v0_11_ecmult(r, &tmpj, &rustsecp256k1_v0_11_scalar_zero, inp_g_sc); for (point_idx = 0; point_idx < n_points; point_idx++) { - rustsecp256k1_v0_10_0_ge point; - rustsecp256k1_v0_10_0_gej pointj; - rustsecp256k1_v0_10_0_scalar scalar; + rustsecp256k1_v0_11_ge point; + rustsecp256k1_v0_11_gej pointj; + rustsecp256k1_v0_11_scalar scalar; if (!cb(&scalar, &point, point_idx, cbdata)) { return 0; } /* r += scalar*point */ - rustsecp256k1_v0_10_0_gej_set_ge(&pointj, &point); - rustsecp256k1_v0_10_0_ecmult(&tmpj, &pointj, &scalar, NULL); - rustsecp256k1_v0_10_0_gej_add_var(r, r, &tmpj, NULL); + rustsecp256k1_v0_11_gej_set_ge(&pointj, &point); + rustsecp256k1_v0_11_ecmult(&tmpj, &pointj, &scalar, NULL); + rustsecp256k1_v0_11_gej_add_var(r, r, &tmpj, NULL); } return 1; } /* Compute the number of batches and the batch size given the maximum batch size and the * total number of points */ -static int rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n_batch_points, size_t max_n_batch_points, size_t n) { +static int rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(size_t *n_batches, size_t *n_batch_points, size_t max_n_batch_points, size_t n) { if (max_n_batch_points == 0) { return 0; } @@ -808,53 +798,53 @@ static int rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(size_t *n_batche 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; } -typedef int (*rustsecp256k1_v0_10_0_ecmult_multi_func)(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch*, rustsecp256k1_v0_10_0_gej*, const rustsecp256k1_v0_10_0_scalar*, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void*, size_t); -static int rustsecp256k1_v0_10_0_ecmult_multi_var(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch *scratch, rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_scalar *inp_g_sc, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void *cbdata, size_t n) { +typedef int (*rustsecp256k1_v0_11_ecmult_multi_func)(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch*, rustsecp256k1_v0_11_gej*, const rustsecp256k1_v0_11_scalar*, rustsecp256k1_v0_11_ecmult_multi_callback cb, void*, size_t); +static int rustsecp256k1_v0_11_ecmult_multi_var(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch *scratch, rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_scalar *inp_g_sc, rustsecp256k1_v0_11_ecmult_multi_callback cb, void *cbdata, size_t n) { size_t i; - int (*f)(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch*, rustsecp256k1_v0_10_0_gej*, const rustsecp256k1_v0_10_0_scalar*, rustsecp256k1_v0_10_0_ecmult_multi_callback cb, void*, size_t, size_t); + int (*f)(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch*, rustsecp256k1_v0_11_gej*, const rustsecp256k1_v0_11_scalar*, rustsecp256k1_v0_11_ecmult_multi_callback cb, void*, size_t, size_t); size_t n_batches; size_t n_batch_points; - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); if (inp_g_sc == NULL && n == 0) { return 1; } else if (n == 0) { - rustsecp256k1_v0_10_0_ecmult(r, r, &rustsecp256k1_v0_10_0_scalar_zero, inp_g_sc); + rustsecp256k1_v0_11_ecmult(r, r, &rustsecp256k1_v0_11_scalar_zero, inp_g_sc); return 1; } if (scratch == NULL) { - return rustsecp256k1_v0_10_0_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); + return rustsecp256k1_v0_11_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); } /* Compute the batch sizes for Pippenger's algorithm given a scratch space. If it's greater than * a threshold use Pippenger's algorithm. Otherwise use Strauss' algorithm. * As a first step check if there's enough space for Pippenger's algo (which requires less space * than Strauss' algo) and if not, use the simple algorithm. */ - if (!rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, rustsecp256k1_v0_10_0_pippenger_max_points(error_callback, scratch), n)) { - return rustsecp256k1_v0_10_0_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); + if (!rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, rustsecp256k1_v0_11_pippenger_max_points(error_callback, scratch), n)) { + return rustsecp256k1_v0_11_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); } if (n_batch_points >= ECMULT_PIPPENGER_THRESHOLD) { - f = rustsecp256k1_v0_10_0_ecmult_pippenger_batch; + f = rustsecp256k1_v0_11_ecmult_pippenger_batch; } else { - if (!rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, rustsecp256k1_v0_10_0_strauss_max_points(error_callback, scratch), n)) { - return rustsecp256k1_v0_10_0_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); + if (!rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, rustsecp256k1_v0_11_strauss_max_points(error_callback, scratch), n)) { + return rustsecp256k1_v0_11_ecmult_multi_simple_var(r, inp_g_sc, cb, cbdata, n); } - f = rustsecp256k1_v0_10_0_ecmult_strauss_batch; + f = rustsecp256k1_v0_11_ecmult_strauss_batch; } for(i = 0; i < n_batches; i++) { size_t nbp = n < n_batch_points ? n : n_batch_points; size_t offset = n_batch_points*i; - rustsecp256k1_v0_10_0_gej tmp; + rustsecp256k1_v0_11_gej tmp; if (!f(error_callback, scratch, &tmp, i == 0 ? inp_g_sc : NULL, cb, cbdata, nbp, offset)) { return 0; } - rustsecp256k1_v0_10_0_gej_add_var(r, r, &tmp, NULL); + rustsecp256k1_v0_11_gej_add_var(r, r, &tmp, NULL); n -= nbp; } return 1; diff --git a/secp256k1-sys/depend/secp256k1/src/field.h b/secp256k1-sys/depend/secp256k1/src/field.h index e0064615f..dd4e38358 100644 --- a/secp256k1-sys/depend/secp256k1/src/field.h +++ b/secp256k1-sys/depend/secp256k1/src/field.h @@ -9,15 +9,15 @@ #include "util.h" -/* This file defines the generic interface for working with rustsecp256k1_v0_10_0_fe +/* This file defines the generic interface for working with rustsecp256k1_v0_11_fe * objects, which represent field elements (integers modulo 2^256 - 2^32 - 977). * - * The actual definition of the rustsecp256k1_v0_10_0_fe type depends on the chosen field + * The actual definition of the rustsecp256k1_v0_11_fe type depends on the chosen field * implementation; see the field_5x52.h and field_10x26.h files for details. * - * All rustsecp256k1_v0_10_0_fe objects have implicit properties that determine what + * All rustsecp256k1_v0_11_fe objects have implicit properties that determine what * operations are permitted on it. These are purely a function of what - * rustsecp256k1_v0_10_0_fe_ operations are applied on it, generally (implicitly) fixed at + * rustsecp256k1_v0_11_fe_ operations are applied on it, generally (implicitly) fixed at * compile time, and do not depend on the chosen field implementation. Despite * that, what these properties actually entail for the field representation * values depends on the chosen field implementation. These properties are: @@ -26,7 +26,7 @@ * * In VERIFY mode, they are materialized explicitly as fields in the struct, * allowing run-time verification of these properties. In that case, the field - * implementation also provides a rustsecp256k1_v0_10_0_fe_verify routine to verify that + * implementation also provides a rustsecp256k1_v0_11_fe_verify routine to verify that * these fields match the run-time value and perform internal consistency * checks. */ #ifdef VERIFY @@ -56,7 +56,7 @@ #define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) #endif -/** This expands to an initializer for a rustsecp256k1_v0_10_0_fe valued sum((i*32) * d_i, i=0..7) mod p. +/** This expands to an initializer for a rustsecp256k1_v0_11_fe valued sum((i*32) * d_i, i=0..7) mod p. * * It has magnitude 1, unless d_i are all 0, in which case the magnitude is 0. * It is normalized, unless sum(2^(i*32) * d_i, i=0..7) >= p. @@ -65,8 +65,8 @@ */ #define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) SECP256K1_FE_VERIFY_CONST((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) } -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_const_beta = SECP256K1_FE_CONST( +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_const_beta = SECP256K1_FE_CONST( 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul ); @@ -75,33 +75,32 @@ static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_const_beta = SECP256 /* In non-VERIFY mode, we #define the fe operations to be identical to their * internal field implementation, to avoid the potential overhead of a * function call (even though presumably inlinable). */ -# define rustsecp256k1_v0_10_0_fe_normalize rustsecp256k1_v0_10_0_fe_impl_normalize -# define rustsecp256k1_v0_10_0_fe_normalize_weak rustsecp256k1_v0_10_0_fe_impl_normalize_weak -# define rustsecp256k1_v0_10_0_fe_normalize_var rustsecp256k1_v0_10_0_fe_impl_normalize_var -# define rustsecp256k1_v0_10_0_fe_normalizes_to_zero rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero -# define rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var -# define rustsecp256k1_v0_10_0_fe_set_int rustsecp256k1_v0_10_0_fe_impl_set_int -# define rustsecp256k1_v0_10_0_fe_clear rustsecp256k1_v0_10_0_fe_impl_clear -# define rustsecp256k1_v0_10_0_fe_is_zero rustsecp256k1_v0_10_0_fe_impl_is_zero -# define rustsecp256k1_v0_10_0_fe_is_odd rustsecp256k1_v0_10_0_fe_impl_is_odd -# define rustsecp256k1_v0_10_0_fe_cmp_var rustsecp256k1_v0_10_0_fe_impl_cmp_var -# define rustsecp256k1_v0_10_0_fe_set_b32_mod rustsecp256k1_v0_10_0_fe_impl_set_b32_mod -# define rustsecp256k1_v0_10_0_fe_set_b32_limit rustsecp256k1_v0_10_0_fe_impl_set_b32_limit -# define rustsecp256k1_v0_10_0_fe_get_b32 rustsecp256k1_v0_10_0_fe_impl_get_b32 -# define rustsecp256k1_v0_10_0_fe_negate_unchecked rustsecp256k1_v0_10_0_fe_impl_negate_unchecked -# define rustsecp256k1_v0_10_0_fe_mul_int_unchecked rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked -# define rustsecp256k1_v0_10_0_fe_add rustsecp256k1_v0_10_0_fe_impl_add -# define rustsecp256k1_v0_10_0_fe_mul rustsecp256k1_v0_10_0_fe_impl_mul -# define rustsecp256k1_v0_10_0_fe_sqr rustsecp256k1_v0_10_0_fe_impl_sqr -# define rustsecp256k1_v0_10_0_fe_cmov rustsecp256k1_v0_10_0_fe_impl_cmov -# define rustsecp256k1_v0_10_0_fe_to_storage rustsecp256k1_v0_10_0_fe_impl_to_storage -# define rustsecp256k1_v0_10_0_fe_from_storage rustsecp256k1_v0_10_0_fe_impl_from_storage -# define rustsecp256k1_v0_10_0_fe_inv rustsecp256k1_v0_10_0_fe_impl_inv -# define rustsecp256k1_v0_10_0_fe_inv_var rustsecp256k1_v0_10_0_fe_impl_inv_var -# define rustsecp256k1_v0_10_0_fe_get_bounds rustsecp256k1_v0_10_0_fe_impl_get_bounds -# define rustsecp256k1_v0_10_0_fe_half rustsecp256k1_v0_10_0_fe_impl_half -# define rustsecp256k1_v0_10_0_fe_add_int rustsecp256k1_v0_10_0_fe_impl_add_int -# define rustsecp256k1_v0_10_0_fe_is_square_var rustsecp256k1_v0_10_0_fe_impl_is_square_var +# define rustsecp256k1_v0_11_fe_normalize rustsecp256k1_v0_11_fe_impl_normalize +# define rustsecp256k1_v0_11_fe_normalize_weak rustsecp256k1_v0_11_fe_impl_normalize_weak +# define rustsecp256k1_v0_11_fe_normalize_var rustsecp256k1_v0_11_fe_impl_normalize_var +# define rustsecp256k1_v0_11_fe_normalizes_to_zero rustsecp256k1_v0_11_fe_impl_normalizes_to_zero +# define rustsecp256k1_v0_11_fe_normalizes_to_zero_var rustsecp256k1_v0_11_fe_impl_normalizes_to_zero_var +# define rustsecp256k1_v0_11_fe_set_int rustsecp256k1_v0_11_fe_impl_set_int +# define rustsecp256k1_v0_11_fe_is_zero rustsecp256k1_v0_11_fe_impl_is_zero +# define rustsecp256k1_v0_11_fe_is_odd rustsecp256k1_v0_11_fe_impl_is_odd +# define rustsecp256k1_v0_11_fe_cmp_var rustsecp256k1_v0_11_fe_impl_cmp_var +# define rustsecp256k1_v0_11_fe_set_b32_mod rustsecp256k1_v0_11_fe_impl_set_b32_mod +# define rustsecp256k1_v0_11_fe_set_b32_limit rustsecp256k1_v0_11_fe_impl_set_b32_limit +# define rustsecp256k1_v0_11_fe_get_b32 rustsecp256k1_v0_11_fe_impl_get_b32 +# define rustsecp256k1_v0_11_fe_negate_unchecked rustsecp256k1_v0_11_fe_impl_negate_unchecked +# define rustsecp256k1_v0_11_fe_mul_int_unchecked rustsecp256k1_v0_11_fe_impl_mul_int_unchecked +# define rustsecp256k1_v0_11_fe_add rustsecp256k1_v0_11_fe_impl_add +# define rustsecp256k1_v0_11_fe_mul rustsecp256k1_v0_11_fe_impl_mul +# define rustsecp256k1_v0_11_fe_sqr rustsecp256k1_v0_11_fe_impl_sqr +# define rustsecp256k1_v0_11_fe_cmov rustsecp256k1_v0_11_fe_impl_cmov +# define rustsecp256k1_v0_11_fe_to_storage rustsecp256k1_v0_11_fe_impl_to_storage +# define rustsecp256k1_v0_11_fe_from_storage rustsecp256k1_v0_11_fe_impl_from_storage +# define rustsecp256k1_v0_11_fe_inv rustsecp256k1_v0_11_fe_impl_inv +# define rustsecp256k1_v0_11_fe_inv_var rustsecp256k1_v0_11_fe_impl_inv_var +# define rustsecp256k1_v0_11_fe_get_bounds rustsecp256k1_v0_11_fe_impl_get_bounds +# define rustsecp256k1_v0_11_fe_half rustsecp256k1_v0_11_fe_impl_half +# define rustsecp256k1_v0_11_fe_add_int rustsecp256k1_v0_11_fe_impl_add_int +# define rustsecp256k1_v0_11_fe_is_square_var rustsecp256k1_v0_11_fe_impl_is_square_var #endif /* !defined(VERIFY) */ /** Normalize a field element. @@ -109,64 +108,60 @@ static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_const_beta = SECP256 * On input, r must be a valid field element. * On output, r represents the same value but has normalized=1 and magnitude=1. */ -static void rustsecp256k1_v0_10_0_fe_normalize(rustsecp256k1_v0_10_0_fe *r); +static void rustsecp256k1_v0_11_fe_normalize(rustsecp256k1_v0_11_fe *r); /** Give a field element magnitude 1. * * On input, r must be a valid field element. * On output, r represents the same value but has magnitude=1. Normalized is unchanged. */ -static void rustsecp256k1_v0_10_0_fe_normalize_weak(rustsecp256k1_v0_10_0_fe *r); +static void rustsecp256k1_v0_11_fe_normalize_weak(rustsecp256k1_v0_11_fe *r); /** Normalize a field element, without constant-time guarantee. * - * Identical in behavior to rustsecp256k1_v0_10_0_fe_normalize, but not constant time in r. + * Identical in behavior to rustsecp256k1_v0_11_fe_normalize, but not constant time in r. */ -static void rustsecp256k1_v0_10_0_fe_normalize_var(rustsecp256k1_v0_10_0_fe *r); +static void rustsecp256k1_v0_11_fe_normalize_var(rustsecp256k1_v0_11_fe *r); /** Determine whether r represents field element 0. * * On input, r must be a valid field element. * Returns whether r = 0 (mod p). */ -static int rustsecp256k1_v0_10_0_fe_normalizes_to_zero(const rustsecp256k1_v0_10_0_fe *r); +static int rustsecp256k1_v0_11_fe_normalizes_to_zero(const rustsecp256k1_v0_11_fe *r); /** Determine whether r represents field element 0, without constant-time guarantee. * - * Identical in behavior to rustsecp256k1_v0_10_0_normalizes_to_zero, but not constant time in r. + * Identical in behavior to rustsecp256k1_v0_11_normalizes_to_zero, but not constant time in r. */ -static int rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(const rustsecp256k1_v0_10_0_fe *r); +static int rustsecp256k1_v0_11_fe_normalizes_to_zero_var(const rustsecp256k1_v0_11_fe *r); /** Set a field element to an integer in range [0,0x7FFF]. * * On input, r does not need to be initialized, a must be in [0,0x7FFF]. * On output, r represents value a, is normalized and has magnitude (a!=0). */ -static void rustsecp256k1_v0_10_0_fe_set_int(rustsecp256k1_v0_10_0_fe *r, int a); +static void rustsecp256k1_v0_11_fe_set_int(rustsecp256k1_v0_11_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. - */ -static void rustsecp256k1_v0_10_0_fe_clear(rustsecp256k1_v0_10_0_fe *a); +/** Clear a field element to prevent leaking sensitive information. */ +static void rustsecp256k1_v0_11_fe_clear(rustsecp256k1_v0_11_fe *a); /** Determine whether a represents field element 0. * * On input, a must be a valid normalized field element. * Returns whether a = 0 (mod p). * - * This behaves identical to rustsecp256k1_v0_10_0_normalizes_to_zero{,_var}, but requires + * This behaves identical to rustsecp256k1_v0_11_normalizes_to_zero{,_var}, but requires * normalized input (and is much faster). */ -static int rustsecp256k1_v0_10_0_fe_is_zero(const rustsecp256k1_v0_10_0_fe *a); +static int rustsecp256k1_v0_11_fe_is_zero(const rustsecp256k1_v0_11_fe *a); /** Determine whether a (mod p) is odd. * * On input, a must be a valid normalized field element. * Returns (int(a) mod p) & 1. */ -static int rustsecp256k1_v0_10_0_fe_is_odd(const rustsecp256k1_v0_10_0_fe *a); +static int rustsecp256k1_v0_11_fe_is_odd(const rustsecp256k1_v0_11_fe *a); /** Determine whether two field elements are equal. * @@ -174,7 +169,7 @@ static int rustsecp256k1_v0_10_0_fe_is_odd(const rustsecp256k1_v0_10_0_fe *a); * 1 and 31, respectively. * Returns a = b (mod p). */ -static int rustsecp256k1_v0_10_0_fe_equal(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b); +static int rustsecp256k1_v0_11_fe_equal(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b); /** Compare the values represented by 2 field elements, without constant-time guarantee. * @@ -182,7 +177,7 @@ static int rustsecp256k1_v0_10_0_fe_equal(const rustsecp256k1_v0_10_0_fe *a, con * Returns 1 if a > b, -1 if a < b, and 0 if a = b (comparisons are done as integers * in range 0..p-1). */ -static int rustsecp256k1_v0_10_0_fe_cmp_var(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b); +static int rustsecp256k1_v0_11_fe_cmp_var(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b); /** Set a field element equal to the element represented by a provided 32-byte big endian value * interpreted modulo p. @@ -190,7 +185,7 @@ static int rustsecp256k1_v0_10_0_fe_cmp_var(const rustsecp256k1_v0_10_0_fe *a, c * On input, r does not need to be initialized. a must be a pointer to an initialized 32-byte array. * On output, r = a (mod p). It will have magnitude 1, and not be normalized. */ -static void rustsecp256k1_v0_10_0_fe_set_b32_mod(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a); +static void rustsecp256k1_v0_11_fe_set_b32_mod(rustsecp256k1_v0_11_fe *r, const unsigned char *a); /** Set a field element equal to a provided 32-byte big endian value, checking for overflow. * @@ -198,13 +193,13 @@ static void rustsecp256k1_v0_10_0_fe_set_b32_mod(rustsecp256k1_v0_10_0_fe *r, co * On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned. * If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting). */ -static int rustsecp256k1_v0_10_0_fe_set_b32_limit(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a); +static int rustsecp256k1_v0_11_fe_set_b32_limit(rustsecp256k1_v0_11_fe *r, const unsigned char *a); /** Convert a field element to 32-byte big endian byte array. * On input, a must be a valid normalized field element, and r a pointer to a 32-byte array. * On output, r = a (mod p). */ -static void rustsecp256k1_v0_10_0_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_10_0_fe *a); +static void rustsecp256k1_v0_11_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_11_fe *a); /** Negate a field element. * @@ -213,20 +208,20 @@ static void rustsecp256k1_v0_10_0_fe_get_b32(unsigned char *r, const rustsecp256 * Performs {r = -a}. * On output, r will not be normalized, and will have magnitude m+1. */ -#define rustsecp256k1_v0_10_0_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, rustsecp256k1_v0_10_0_fe_negate_unchecked(r, a, m)) +#define rustsecp256k1_v0_11_fe_negate(r, a, m) ASSERT_INT_CONST_AND_DO(m, rustsecp256k1_v0_11_fe_negate_unchecked(r, a, m)) -/** Like rustsecp256k1_v0_10_0_fe_negate_unchecked but m is not checked to be an integer constant expression. +/** Like rustsecp256k1_v0_11_fe_negate_unchecked but m is not checked to be an integer constant expression. * * Should not be called directly outside of tests. */ -static void rustsecp256k1_v0_10_0_fe_negate_unchecked(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int m); +static void rustsecp256k1_v0_11_fe_negate_unchecked(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int m); /** Add a small integer to a field element. * * Performs {r += a}. The magnitude of r increases by 1, and normalized is cleared. * a must be in range [0,0x7FFF]. */ -static void rustsecp256k1_v0_10_0_fe_add_int(rustsecp256k1_v0_10_0_fe *r, int a); +static void rustsecp256k1_v0_11_fe_add_int(rustsecp256k1_v0_11_fe *r, int a); /** Multiply a field element with a small integer. * @@ -235,13 +230,13 @@ static void rustsecp256k1_v0_10_0_fe_add_int(rustsecp256k1_v0_10_0_fe *r, int a) * Performs {r *= a}. * On output, r's magnitude is multiplied by a, and r will not be normalized. */ -#define rustsecp256k1_v0_10_0_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, rustsecp256k1_v0_10_0_fe_mul_int_unchecked(r, a)) +#define rustsecp256k1_v0_11_fe_mul_int(r, a) ASSERT_INT_CONST_AND_DO(a, rustsecp256k1_v0_11_fe_mul_int_unchecked(r, a)) -/** Like rustsecp256k1_v0_10_0_fe_mul_int but a is not checked to be an integer constant expression. +/** Like rustsecp256k1_v0_11_fe_mul_int but a is not checked to be an integer constant expression. * * Should not be called directly outside of tests. */ -static void rustsecp256k1_v0_10_0_fe_mul_int_unchecked(rustsecp256k1_v0_10_0_fe *r, int a); +static void rustsecp256k1_v0_11_fe_mul_int_unchecked(rustsecp256k1_v0_11_fe *r, int a); /** Increment a field element by another. * @@ -250,17 +245,17 @@ static void rustsecp256k1_v0_10_0_fe_mul_int_unchecked(rustsecp256k1_v0_10_0_fe * Performs {r += a}. * On output, r will not be normalized, and will have magnitude incremented by a's. */ -static void rustsecp256k1_v0_10_0_fe_add(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a); +static void rustsecp256k1_v0_11_fe_add(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_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. */ -static void rustsecp256k1_v0_10_0_fe_mul(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT b); +static void rustsecp256k1_v0_11_fe_mul(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT b); /** Square a field element. * @@ -269,7 +264,7 @@ static void rustsecp256k1_v0_10_0_fe_mul(rustsecp256k1_v0_10_0_fe *r, const rust * Performs {r = a**2} * On output, r will have magnitude 1, but won't be normalized. */ -static void rustsecp256k1_v0_10_0_fe_sqr(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a); +static void rustsecp256k1_v0_11_fe_sqr(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a); /** Compute a square root of a field element. * @@ -280,7 +275,7 @@ static void rustsecp256k1_v0_10_0_fe_sqr(rustsecp256k1_v0_10_0_fe *r, const rust * Variables r and a must not point to the same object. * On output, r will have magnitude 1 but will not be normalized. */ -static int rustsecp256k1_v0_10_0_fe_sqrt(rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT r, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT a); +static int rustsecp256k1_v0_11_fe_sqrt(rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT r, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT a); /** Compute the modular inverse of a field element. * @@ -289,31 +284,31 @@ static int rustsecp256k1_v0_10_0_fe_sqrt(rustsecp256k1_v0_10_0_fe * SECP256K1_RE * inverse). * On output, r will have magnitude (a.magnitude != 0) and be normalized. */ -static void rustsecp256k1_v0_10_0_fe_inv(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a); +static void rustsecp256k1_v0_11_fe_inv(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a); /** Compute the modular inverse of a field element, without constant-time guarantee. * - * Behaves identically to rustsecp256k1_v0_10_0_fe_inv, but is not constant-time in a. + * Behaves identically to rustsecp256k1_v0_11_fe_inv, but is not constant-time in a. */ -static void rustsecp256k1_v0_10_0_fe_inv_var(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a); +static void rustsecp256k1_v0_11_fe_inv_var(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a); -/** Convert a field element to rustsecp256k1_v0_10_0_fe_storage. +/** Convert a field element to rustsecp256k1_v0_11_fe_storage. * * On input, a must be a valid normalized field element. * Performs {r = a}. */ -static void rustsecp256k1_v0_10_0_fe_to_storage(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe *a); +static void rustsecp256k1_v0_11_fe_to_storage(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe *a); -/** Convert a field element back from rustsecp256k1_v0_10_0_fe_storage. +/** Convert a field element back from rustsecp256k1_v0_11_fe_storage. * * On input, r need not be initialized. * Performs {r = a}. * On output, r will be normalized and will have magnitude 1. */ -static void rustsecp256k1_v0_10_0_fe_from_storage(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe_storage *a); +static void rustsecp256k1_v0_11_fe_from_storage(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe_storage *a); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ -static void rustsecp256k1_v0_10_0_fe_storage_cmov(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe_storage *a, int flag); +static void rustsecp256k1_v0_11_fe_storage_cmov(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe_storage *a, int flag); /** Conditionally move a field element in constant time. * @@ -323,7 +318,7 @@ static void rustsecp256k1_v0_10_0_fe_storage_cmov(rustsecp256k1_v0_10_0_fe_stora * On output, r's magnitude will be the maximum of both input magnitudes. * It will be normalized if and only if both inputs were normalized. */ -static void rustsecp256k1_v0_10_0_fe_cmov(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int flag); +static void rustsecp256k1_v0_11_fe_cmov(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int flag); /** Halve the value of a field element modulo the field prime in constant-time. * @@ -331,25 +326,25 @@ static void rustsecp256k1_v0_10_0_fe_cmov(rustsecp256k1_v0_10_0_fe *r, const rus * On output, r will be normalized and have magnitude floor(m/2) + 1 where m is * the magnitude of r on input. */ -static void rustsecp256k1_v0_10_0_fe_half(rustsecp256k1_v0_10_0_fe *r); +static void rustsecp256k1_v0_11_fe_half(rustsecp256k1_v0_11_fe *r); /** Sets r to a field element with magnitude m, normalized if (and only if) m==0. * The value is chosen so that it is likely to trigger edge cases related to * internal overflows. */ -static void rustsecp256k1_v0_10_0_fe_get_bounds(rustsecp256k1_v0_10_0_fe *r, int m); +static void rustsecp256k1_v0_11_fe_get_bounds(rustsecp256k1_v0_11_fe *r, int m); /** Determine whether a is a square (modulo p). * * On input, a must be a valid field element. */ -static int rustsecp256k1_v0_10_0_fe_is_square_var(const rustsecp256k1_v0_10_0_fe *a); +static int rustsecp256k1_v0_11_fe_is_square_var(const rustsecp256k1_v0_11_fe *a); /** Check invariants on a field element (no-op unless VERIFY is enabled). */ -static void rustsecp256k1_v0_10_0_fe_verify(const rustsecp256k1_v0_10_0_fe *a); -#define SECP256K1_FE_VERIFY(a) rustsecp256k1_v0_10_0_fe_verify(a) +static void rustsecp256k1_v0_11_fe_verify(const rustsecp256k1_v0_11_fe *a); +#define SECP256K1_FE_VERIFY(a) rustsecp256k1_v0_11_fe_verify(a) /** Check that magnitude of a is at most m (no-op unless VERIFY is enabled). */ -static void rustsecp256k1_v0_10_0_fe_verify_magnitude(const rustsecp256k1_v0_10_0_fe *a, int m); -#define SECP256K1_FE_VERIFY_MAGNITUDE(a, m) rustsecp256k1_v0_10_0_fe_verify_magnitude(a, m) +static void rustsecp256k1_v0_11_fe_verify_magnitude(const rustsecp256k1_v0_11_fe *a, int m); +#define SECP256K1_FE_VERIFY_MAGNITUDE(a, m) rustsecp256k1_v0_11_fe_verify_magnitude(a, m) #endif /* SECP256K1_FIELD_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/field_10x26.h b/secp256k1-sys/depend/secp256k1/src/field_10x26.h index 9029e3a84..0371dc410 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_10x26.h +++ b/secp256k1-sys/depend/secp256k1/src/field_10x26.h @@ -31,7 +31,7 @@ typedef struct { * (together these imply n[9] <= 2^22 - 1) */ SECP256K1_FE_VERIFY_FIELDS -} rustsecp256k1_v0_10_0_fe; +} rustsecp256k1_v0_11_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ @@ -49,7 +49,7 @@ typedef struct { typedef struct { uint32_t n[8]; -} rustsecp256k1_v0_10_0_fe_storage; +} rustsecp256k1_v0_11_fe_storage; #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} #define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] diff --git a/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h b/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h index a925b5e51..a85241b9e 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_10x26_impl.h @@ -13,7 +13,7 @@ #include "modinv32_impl.h" #ifdef VERIFY -static void rustsecp256k1_v0_10_0_fe_impl_verify(const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_verify(const rustsecp256k1_v0_11_fe *a) { const uint32_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude; VERIFY_CHECK(d[0] <= 0x3FFFFFFUL * m); @@ -37,7 +37,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_verify(const rustsecp256k1_v0_10_0_fe } #endif -static void rustsecp256k1_v0_10_0_fe_impl_get_bounds(rustsecp256k1_v0_10_0_fe *r, int m) { +static void rustsecp256k1_v0_11_fe_impl_get_bounds(rustsecp256k1_v0_11_fe *r, int m) { r->n[0] = 0x3FFFFFFUL * 2 * m; r->n[1] = 0x3FFFFFFUL * 2 * m; r->n[2] = 0x3FFFFFFUL * 2 * m; @@ -50,7 +50,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_get_bounds(rustsecp256k1_v0_10_0_fe *r r->n[9] = 0x03FFFFFUL * 2 * m; } -static void rustsecp256k1_v0_10_0_fe_impl_normalize(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize(rustsecp256k1_v0_11_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; @@ -99,7 +99,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_normalize(rustsecp256k1_v0_10_0_fe *r) r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; } -static void rustsecp256k1_v0_10_0_fe_impl_normalize_weak(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize_weak(rustsecp256k1_v0_11_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; @@ -125,7 +125,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_normalize_weak(rustsecp256k1_v0_10_0_f r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; } -static void rustsecp256k1_v0_10_0_fe_impl_normalize_var(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize_var(rustsecp256k1_v0_11_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; @@ -175,7 +175,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_normalize_var(rustsecp256k1_v0_10_0_fe r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; } -static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero(const rustsecp256k1_v0_10_0_fe *r) { +static int rustsecp256k1_v0_11_fe_impl_normalizes_to_zero(const rustsecp256k1_v0_11_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; @@ -204,7 +204,7 @@ static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero(const rustsecp256k1_ return (z0 == 0) | (z1 == 0x3FFFFFFUL); } -static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var(const rustsecp256k1_v0_10_0_fe *r) { +static int rustsecp256k1_v0_11_fe_impl_normalizes_to_zero_var(const rustsecp256k1_v0_11_fe *r) { uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; uint32_t z0, z1; uint32_t x; @@ -256,28 +256,21 @@ static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var(const rustsecp25 return (z0 == 0) | (z1 == 0x3FFFFFFUL); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_set_int(rustsecp256k1_v0_10_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_set_int(rustsecp256k1_v0_11_fe *r, int a) { r->n[0] = a; r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_impl_is_zero(const rustsecp256k1_v0_10_0_fe *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_impl_is_zero(const rustsecp256k1_v0_11_fe *a) { const uint32_t *t = a->n; return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_impl_is_odd(const rustsecp256k1_v0_10_0_fe *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_impl_is_odd(const rustsecp256k1_v0_11_fe *a) { return a->n[0] & 1; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_clear(rustsecp256k1_v0_10_0_fe *a) { - int i; - for (i=0; i<10; i++) { - a->n[i] = 0; - } -} - -static int rustsecp256k1_v0_10_0_fe_impl_cmp_var(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b) { +static int rustsecp256k1_v0_11_fe_impl_cmp_var(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b) { int i; for (i = 9; i >= 0; i--) { if (a->n[i] > b->n[i]) { @@ -290,7 +283,7 @@ static int rustsecp256k1_v0_10_0_fe_impl_cmp_var(const rustsecp256k1_v0_10_0_fe return 0; } -static void rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a) { +static void rustsecp256k1_v0_11_fe_impl_set_b32_mod(rustsecp256k1_v0_11_fe *r, const unsigned char *a) { r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); @@ -303,13 +296,13 @@ static void rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(rustsecp256k1_v0_10_0_fe * r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); } -static int rustsecp256k1_v0_10_0_fe_impl_set_b32_limit(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a) { - rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(r, a); +static int rustsecp256k1_v0_11_fe_impl_set_b32_limit(rustsecp256k1_v0_11_fe *r, const unsigned char *a) { + rustsecp256k1_v0_11_fe_impl_set_b32_mod(r, a); return !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); } /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void rustsecp256k1_v0_10_0_fe_impl_get_b32(unsigned char *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_get_b32(unsigned char *r, const rustsecp256k1_v0_11_fe *a) { r[0] = (a->n[9] >> 14) & 0xff; r[1] = (a->n[9] >> 6) & 0xff; r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3); @@ -344,7 +337,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_get_b32(unsigned char *r, const rustse r[31] = a->n[0] & 0xff; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_negate_unchecked(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int m) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_negate_unchecked(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int m) { /* For all legal values of m (0..31), the following properties hold: */ VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m); VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m); @@ -365,7 +358,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_negate_unchecked(rust r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked(rustsecp256k1_v0_10_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_mul_int_unchecked(rustsecp256k1_v0_11_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; @@ -378,7 +371,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked(rus r->n[9] *= a; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_add(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_add(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a) { r->n[0] += a->n[0]; r->n[1] += a->n[1]; r->n[2] += a->n[2]; @@ -391,21 +384,21 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_add(rustsecp256k1_v0_ r->n[9] += a->n[9]; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_add_int(rustsecp256k1_v0_10_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_add_int(rustsecp256k1_v0_11_fe *r, int a) { r->n[0] += a; } #if defined(USE_EXTERNAL_ASM) /* External assembler implementation */ -void rustsecp256k1_v0_10_0_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); -void rustsecp256k1_v0_10_0_fe_sqr_inner(uint32_t *r, const uint32_t *a); +void rustsecp256k1_v0_11_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); +void rustsecp256k1_v0_11_fe_sqr_inner(uint32_t *r, const uint32_t *a); #else #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { uint64_t c, d; uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; @@ -735,7 +728,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_inner(uint32_t *r, con /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr_inner(uint32_t *r, const uint32_t *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_sqr_inner(uint32_t *r, const uint32_t *a) { uint64_t c, d; uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; @@ -1010,15 +1003,15 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr_inner(uint32_t *r, con } #endif -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_mul(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT b) { - rustsecp256k1_v0_10_0_fe_mul_inner(r->n, a->n, b->n); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_mul(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT b) { + rustsecp256k1_v0_11_fe_mul_inner(r->n, a->n, b->n); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_sqr(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a) { - rustsecp256k1_v0_10_0_fe_sqr_inner(r->n, a->n); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_sqr(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a) { + rustsecp256k1_v0_11_fe_sqr_inner(r->n, a->n); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_cmov(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int flag) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_cmov(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); @@ -1036,7 +1029,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_cmov(rustsecp256k1_v0 r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_half(rustsecp256k1_v0_10_0_fe *r) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_fe_impl_half(rustsecp256k1_v0_11_fe *r) { uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; uint32_t one = (uint32_t)1; @@ -1101,7 +1094,7 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_half(rustsecp256k1_v0 */ } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_storage_cmov(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe_storage *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_fe_storage_cmov(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe_storage *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); @@ -1117,7 +1110,7 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_storage_cmov(rustsecp256k1 r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); } -static void rustsecp256k1_v0_10_0_fe_impl_to_storage(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_to_storage(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe *a) { r->n[0] = a->n[0] | a->n[1] << 26; r->n[1] = a->n[1] >> 6 | a->n[2] << 20; r->n[2] = a->n[2] >> 12 | a->n[3] << 14; @@ -1128,7 +1121,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_to_storage(rustsecp256k1_v0_10_0_fe_st r->n[7] = a->n[8] >> 16 | a->n[9] << 10; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_from_storage(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe_storage *a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_fe_impl_from_storage(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe_storage *a) { r->n[0] = a->n[0] & 0x3FFFFFFUL; r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); @@ -1141,12 +1134,12 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_from_storage(rustsecp r->n[9] = a->n[7] >> 10; } -static void rustsecp256k1_v0_10_0_fe_from_signed30(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_modinv32_signed30 *a) { +static void rustsecp256k1_v0_11_fe_from_signed30(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_modinv32_signed30 *a) { const uint32_t M26 = UINT32_MAX >> 6; const uint32_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4], a5 = a->v[5], a6 = a->v[6], a7 = a->v[7], a8 = a->v[8]; - /* The output from rustsecp256k1_v0_10_0_modinv32{_var} should be normalized to range [0,modulus), and + /* The output from rustsecp256k1_v0_11_modinv32{_var} should be normalized to range [0,modulus), and * have limbs in [0,2^30). The modulus is < 2^256, so the top limb must be below 2^(256-30*8). */ VERIFY_CHECK(a0 >> 30 == 0); @@ -1171,7 +1164,7 @@ static void rustsecp256k1_v0_10_0_fe_from_signed30(rustsecp256k1_v0_10_0_fe *r, r->n[9] = (a7 >> 24 | a8 << 6); } -static void rustsecp256k1_v0_10_0_fe_to_signed30(rustsecp256k1_v0_10_0_modinv32_signed30 *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_to_signed30(rustsecp256k1_v0_11_modinv32_signed30 *r, const rustsecp256k1_v0_11_fe *a) { const uint32_t M30 = UINT32_MAX >> 2; const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4], a5 = a->n[5], a6 = a->n[6], a7 = a->n[7], a8 = a->n[8], a9 = a->n[9]; @@ -1188,48 +1181,48 @@ static void rustsecp256k1_v0_10_0_fe_to_signed30(rustsecp256k1_v0_10_0_modinv32_ r->v[8] = a9 >> 6; } -static const rustsecp256k1_v0_10_0_modinv32_modinfo rustsecp256k1_v0_10_0_const_modinfo_fe = { +static const rustsecp256k1_v0_11_modinv32_modinfo rustsecp256k1_v0_11_const_modinfo_fe = { {{-0x3D1, -4, 0, 0, 0, 0, 0, 0, 65536}}, 0x2DDACACFL }; -static void rustsecp256k1_v0_10_0_fe_impl_inv(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe tmp = *x; - rustsecp256k1_v0_10_0_modinv32_signed30 s; +static void rustsecp256k1_v0_11_fe_impl_inv(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe tmp = *x; + rustsecp256k1_v0_11_modinv32_signed30 s; - rustsecp256k1_v0_10_0_fe_normalize(&tmp); - rustsecp256k1_v0_10_0_fe_to_signed30(&s, &tmp); - rustsecp256k1_v0_10_0_modinv32(&s, &rustsecp256k1_v0_10_0_const_modinfo_fe); - rustsecp256k1_v0_10_0_fe_from_signed30(r, &s); + rustsecp256k1_v0_11_fe_normalize(&tmp); + rustsecp256k1_v0_11_fe_to_signed30(&s, &tmp); + rustsecp256k1_v0_11_modinv32(&s, &rustsecp256k1_v0_11_const_modinfo_fe); + rustsecp256k1_v0_11_fe_from_signed30(r, &s); } -static void rustsecp256k1_v0_10_0_fe_impl_inv_var(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe tmp = *x; - rustsecp256k1_v0_10_0_modinv32_signed30 s; +static void rustsecp256k1_v0_11_fe_impl_inv_var(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe tmp = *x; + rustsecp256k1_v0_11_modinv32_signed30 s; - rustsecp256k1_v0_10_0_fe_normalize_var(&tmp); - rustsecp256k1_v0_10_0_fe_to_signed30(&s, &tmp); - rustsecp256k1_v0_10_0_modinv32_var(&s, &rustsecp256k1_v0_10_0_const_modinfo_fe); - rustsecp256k1_v0_10_0_fe_from_signed30(r, &s); + rustsecp256k1_v0_11_fe_normalize_var(&tmp); + rustsecp256k1_v0_11_fe_to_signed30(&s, &tmp); + rustsecp256k1_v0_11_modinv32_var(&s, &rustsecp256k1_v0_11_const_modinfo_fe); + rustsecp256k1_v0_11_fe_from_signed30(r, &s); } -static int rustsecp256k1_v0_10_0_fe_impl_is_square_var(const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe tmp; - rustsecp256k1_v0_10_0_modinv32_signed30 s; +static int rustsecp256k1_v0_11_fe_impl_is_square_var(const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe tmp; + rustsecp256k1_v0_11_modinv32_signed30 s; int jac, ret; tmp = *x; - rustsecp256k1_v0_10_0_fe_normalize_var(&tmp); - /* rustsecp256k1_v0_10_0_jacobi32_maybe_var cannot deal with input 0. */ - if (rustsecp256k1_v0_10_0_fe_is_zero(&tmp)) return 1; - rustsecp256k1_v0_10_0_fe_to_signed30(&s, &tmp); - jac = rustsecp256k1_v0_10_0_jacobi32_maybe_var(&s, &rustsecp256k1_v0_10_0_const_modinfo_fe); + rustsecp256k1_v0_11_fe_normalize_var(&tmp); + /* rustsecp256k1_v0_11_jacobi32_maybe_var cannot deal with input 0. */ + if (rustsecp256k1_v0_11_fe_is_zero(&tmp)) return 1; + rustsecp256k1_v0_11_fe_to_signed30(&s, &tmp); + jac = rustsecp256k1_v0_11_jacobi32_maybe_var(&s, &rustsecp256k1_v0_11_const_modinfo_fe); if (jac == 0) { - /* rustsecp256k1_v0_10_0_jacobi32_maybe_var failed to compute the Jacobi symbol. Fall back + /* rustsecp256k1_v0_11_jacobi32_maybe_var failed to compute the Jacobi symbol. Fall back * to computing a square root. This should be extremely rare with random * input (except in VERIFY mode, where a lower iteration count is used). */ - rustsecp256k1_v0_10_0_fe dummy; - ret = rustsecp256k1_v0_10_0_fe_sqrt(&dummy, &tmp); + rustsecp256k1_v0_11_fe dummy; + ret = rustsecp256k1_v0_11_fe_sqrt(&dummy, &tmp); } else { ret = jac >= 0; } diff --git a/secp256k1-sys/depend/secp256k1/src/field_5x52.h b/secp256k1-sys/depend/secp256k1/src/field_5x52.h index 25f95b6fc..d14ae4d8e 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_5x52.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52.h @@ -31,7 +31,7 @@ typedef struct { * (together these imply n[4] <= 2^48 - 1) */ SECP256K1_FE_VERIFY_FIELDS -} rustsecp256k1_v0_10_0_fe; +} rustsecp256k1_v0_11_fe; /* Unpacks a constant into a overlapping multi-limbed FE element. */ #define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ @@ -44,7 +44,7 @@ typedef struct { typedef struct { uint64_t n[4]; -} rustsecp256k1_v0_10_0_fe_storage; +} rustsecp256k1_v0_11_fe_storage; #define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ (d0) | (((uint64_t)(d1)) << 32), \ diff --git a/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h b/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h index 8938e6517..1387e8913 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52_impl.h @@ -15,7 +15,7 @@ #include "field_5x52_int128_impl.h" #ifdef VERIFY -static void rustsecp256k1_v0_10_0_fe_impl_verify(const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_verify(const rustsecp256k1_v0_11_fe *a) { const uint64_t *d = a->n; int m = a->normalized ? 1 : 2 * a->magnitude; /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ @@ -32,7 +32,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_verify(const rustsecp256k1_v0_10_0_fe } #endif -static void rustsecp256k1_v0_10_0_fe_impl_get_bounds(rustsecp256k1_v0_10_0_fe *r, int m) { +static void rustsecp256k1_v0_11_fe_impl_get_bounds(rustsecp256k1_v0_11_fe *r, int m) { r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m; r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m; r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m; @@ -40,7 +40,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_get_bounds(rustsecp256k1_v0_10_0_fe *r r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m; } -static void rustsecp256k1_v0_10_0_fe_impl_normalize(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize(rustsecp256k1_v0_11_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ @@ -77,7 +77,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_normalize(rustsecp256k1_v0_10_0_fe *r) r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; } -static void rustsecp256k1_v0_10_0_fe_impl_normalize_weak(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize_weak(rustsecp256k1_v0_11_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ @@ -96,7 +96,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_normalize_weak(rustsecp256k1_v0_10_0_f r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; } -static void rustsecp256k1_v0_10_0_fe_impl_normalize_var(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize_var(rustsecp256k1_v0_11_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* Reduce t4 at the start so there will be at most a single carry from the first pass */ @@ -134,7 +134,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_normalize_var(rustsecp256k1_v0_10_0_fe r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; } -static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero(const rustsecp256k1_v0_10_0_fe *r) { +static int rustsecp256k1_v0_11_fe_impl_normalizes_to_zero(const rustsecp256k1_v0_11_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ @@ -157,7 +157,7 @@ static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero(const rustsecp256k1_ return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); } -static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var(const rustsecp256k1_v0_10_0_fe *r) { +static int rustsecp256k1_v0_11_fe_impl_normalizes_to_zero_var(const rustsecp256k1_v0_11_fe *r) { uint64_t t0, t1, t2, t3, t4; uint64_t z0, z1; uint64_t x; @@ -198,28 +198,21 @@ static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var(const rustsecp25 return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_set_int(rustsecp256k1_v0_10_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_set_int(rustsecp256k1_v0_11_fe *r, int a) { r->n[0] = a; r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_impl_is_zero(const rustsecp256k1_v0_10_0_fe *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_impl_is_zero(const rustsecp256k1_v0_11_fe *a) { const uint64_t *t = a->n; return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_impl_is_odd(const rustsecp256k1_v0_10_0_fe *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_impl_is_odd(const rustsecp256k1_v0_11_fe *a) { return a->n[0] & 1; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_clear(rustsecp256k1_v0_10_0_fe *a) { - int i; - for (i=0; i<5; i++) { - a->n[i] = 0; - } -} - -static int rustsecp256k1_v0_10_0_fe_impl_cmp_var(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b) { +static int rustsecp256k1_v0_11_fe_impl_cmp_var(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b) { int i; for (i = 4; i >= 0; i--) { if (a->n[i] > b->n[i]) { @@ -232,7 +225,7 @@ static int rustsecp256k1_v0_10_0_fe_impl_cmp_var(const rustsecp256k1_v0_10_0_fe return 0; } -static void rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a) { +static void rustsecp256k1_v0_11_fe_impl_set_b32_mod(rustsecp256k1_v0_11_fe *r, const unsigned char *a) { r->n[0] = (uint64_t)a[31] | ((uint64_t)a[30] << 8) | ((uint64_t)a[29] << 16) @@ -269,13 +262,13 @@ static void rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(rustsecp256k1_v0_10_0_fe * | ((uint64_t)a[0] << 40); } -static int rustsecp256k1_v0_10_0_fe_impl_set_b32_limit(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a) { - rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(r, a); +static int rustsecp256k1_v0_11_fe_impl_set_b32_limit(rustsecp256k1_v0_11_fe *r, const unsigned char *a) { + rustsecp256k1_v0_11_fe_impl_set_b32_mod(r, a); return !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL)); } /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ -static void rustsecp256k1_v0_10_0_fe_impl_get_b32(unsigned char *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_get_b32(unsigned char *r, const rustsecp256k1_v0_11_fe *a) { r[0] = (a->n[4] >> 40) & 0xFF; r[1] = (a->n[4] >> 32) & 0xFF; r[2] = (a->n[4] >> 24) & 0xFF; @@ -310,7 +303,7 @@ static void rustsecp256k1_v0_10_0_fe_impl_get_b32(unsigned char *r, const rustse r[31] = a->n[0] & 0xFF; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_negate_unchecked(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int m) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_negate_unchecked(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int m) { /* For all legal values of m (0..31), the following properties hold: */ VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m); VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m); @@ -325,7 +318,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_negate_unchecked(rust r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked(rustsecp256k1_v0_10_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_mul_int_unchecked(rustsecp256k1_v0_11_fe *r, int a) { r->n[0] *= a; r->n[1] *= a; r->n[2] *= a; @@ -333,11 +326,11 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked(rus r->n[4] *= a; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_add_int(rustsecp256k1_v0_10_0_fe *r, int a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_add_int(rustsecp256k1_v0_11_fe *r, int a) { r->n[0] += a; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_add(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_add(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a) { r->n[0] += a->n[0]; r->n[1] += a->n[1]; r->n[2] += a->n[2]; @@ -345,15 +338,15 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_add(rustsecp256k1_v0_ r->n[4] += a->n[4]; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_mul(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT b) { - rustsecp256k1_v0_10_0_fe_mul_inner(r->n, a->n, b->n); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_mul(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT b) { + rustsecp256k1_v0_11_fe_mul_inner(r->n, a->n, b->n); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_sqr(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a) { - rustsecp256k1_v0_10_0_fe_sqr_inner(r->n, a->n); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_sqr(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a) { + rustsecp256k1_v0_11_fe_sqr_inner(r->n, a->n); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_cmov(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int flag) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_impl_cmov(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); @@ -366,7 +359,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_impl_cmov(rustsecp256k1_v0 r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_half(rustsecp256k1_v0_10_0_fe *r) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_fe_impl_half(rustsecp256k1_v0_11_fe *r) { uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; uint64_t one = (uint64_t)1; uint64_t mask = -(t0 & one) >> 12; @@ -420,7 +413,7 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_half(rustsecp256k1_v0 */ } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_storage_cmov(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe_storage *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_fe_storage_cmov(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe_storage *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n)); @@ -432,14 +425,14 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_storage_cmov(rustsecp256k1 r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); } -static void rustsecp256k1_v0_10_0_fe_impl_to_storage(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_to_storage(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe *a) { r->n[0] = a->n[0] | a->n[1] << 52; r->n[1] = a->n[1] >> 12 | a->n[2] << 40; r->n[2] = a->n[2] >> 24 | a->n[3] << 28; r->n[3] = a->n[3] >> 36 | a->n[4] << 16; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_from_storage(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe_storage *a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_fe_impl_from_storage(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe_storage *a) { r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); @@ -447,11 +440,11 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_fe_impl_from_storage(rustsecp r->n[4] = a->n[3] >> 16; } -static void rustsecp256k1_v0_10_0_fe_from_signed62(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_modinv64_signed62 *a) { +static void rustsecp256k1_v0_11_fe_from_signed62(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_modinv64_signed62 *a) { const uint64_t M52 = UINT64_MAX >> 12; const uint64_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4]; - /* The output from rustsecp256k1_v0_10_0_modinv64{_var} should be normalized to range [0,modulus), and + /* The output from rustsecp256k1_v0_11_modinv64{_var} should be normalized to range [0,modulus), and * have limbs in [0,2^62). The modulus is < 2^256, so the top limb must be below 2^(256-62*4). */ VERIFY_CHECK(a0 >> 62 == 0); @@ -467,7 +460,7 @@ static void rustsecp256k1_v0_10_0_fe_from_signed62(rustsecp256k1_v0_10_0_fe *r, r->n[4] = (a3 >> 22 | a4 << 40); } -static void rustsecp256k1_v0_10_0_fe_to_signed62(rustsecp256k1_v0_10_0_modinv64_signed62 *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_to_signed62(rustsecp256k1_v0_11_modinv64_signed62 *r, const rustsecp256k1_v0_11_fe *a) { const uint64_t M62 = UINT64_MAX >> 2; const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4]; @@ -478,48 +471,48 @@ static void rustsecp256k1_v0_10_0_fe_to_signed62(rustsecp256k1_v0_10_0_modinv64_ r->v[4] = a4 >> 40; } -static const rustsecp256k1_v0_10_0_modinv64_modinfo rustsecp256k1_v0_10_0_const_modinfo_fe = { +static const rustsecp256k1_v0_11_modinv64_modinfo rustsecp256k1_v0_11_const_modinfo_fe = { {{-0x1000003D1LL, 0, 0, 0, 256}}, 0x27C7F6E22DDACACFLL }; -static void rustsecp256k1_v0_10_0_fe_impl_inv(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe tmp = *x; - rustsecp256k1_v0_10_0_modinv64_signed62 s; +static void rustsecp256k1_v0_11_fe_impl_inv(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe tmp = *x; + rustsecp256k1_v0_11_modinv64_signed62 s; - rustsecp256k1_v0_10_0_fe_normalize(&tmp); - rustsecp256k1_v0_10_0_fe_to_signed62(&s, &tmp); - rustsecp256k1_v0_10_0_modinv64(&s, &rustsecp256k1_v0_10_0_const_modinfo_fe); - rustsecp256k1_v0_10_0_fe_from_signed62(r, &s); + rustsecp256k1_v0_11_fe_normalize(&tmp); + rustsecp256k1_v0_11_fe_to_signed62(&s, &tmp); + rustsecp256k1_v0_11_modinv64(&s, &rustsecp256k1_v0_11_const_modinfo_fe); + rustsecp256k1_v0_11_fe_from_signed62(r, &s); } -static void rustsecp256k1_v0_10_0_fe_impl_inv_var(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe tmp = *x; - rustsecp256k1_v0_10_0_modinv64_signed62 s; +static void rustsecp256k1_v0_11_fe_impl_inv_var(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe tmp = *x; + rustsecp256k1_v0_11_modinv64_signed62 s; - rustsecp256k1_v0_10_0_fe_normalize_var(&tmp); - rustsecp256k1_v0_10_0_fe_to_signed62(&s, &tmp); - rustsecp256k1_v0_10_0_modinv64_var(&s, &rustsecp256k1_v0_10_0_const_modinfo_fe); - rustsecp256k1_v0_10_0_fe_from_signed62(r, &s); + rustsecp256k1_v0_11_fe_normalize_var(&tmp); + rustsecp256k1_v0_11_fe_to_signed62(&s, &tmp); + rustsecp256k1_v0_11_modinv64_var(&s, &rustsecp256k1_v0_11_const_modinfo_fe); + rustsecp256k1_v0_11_fe_from_signed62(r, &s); } -static int rustsecp256k1_v0_10_0_fe_impl_is_square_var(const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe tmp; - rustsecp256k1_v0_10_0_modinv64_signed62 s; +static int rustsecp256k1_v0_11_fe_impl_is_square_var(const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe tmp; + rustsecp256k1_v0_11_modinv64_signed62 s; int jac, ret; tmp = *x; - rustsecp256k1_v0_10_0_fe_normalize_var(&tmp); - /* rustsecp256k1_v0_10_0_jacobi64_maybe_var cannot deal with input 0. */ - if (rustsecp256k1_v0_10_0_fe_is_zero(&tmp)) return 1; - rustsecp256k1_v0_10_0_fe_to_signed62(&s, &tmp); - jac = rustsecp256k1_v0_10_0_jacobi64_maybe_var(&s, &rustsecp256k1_v0_10_0_const_modinfo_fe); + rustsecp256k1_v0_11_fe_normalize_var(&tmp); + /* rustsecp256k1_v0_11_jacobi64_maybe_var cannot deal with input 0. */ + if (rustsecp256k1_v0_11_fe_is_zero(&tmp)) return 1; + rustsecp256k1_v0_11_fe_to_signed62(&s, &tmp); + jac = rustsecp256k1_v0_11_jacobi64_maybe_var(&s, &rustsecp256k1_v0_11_const_modinfo_fe); if (jac == 0) { - /* rustsecp256k1_v0_10_0_jacobi64_maybe_var failed to compute the Jacobi symbol. Fall back + /* rustsecp256k1_v0_11_jacobi64_maybe_var failed to compute the Jacobi symbol. Fall back * to computing a square root. This should be extremely rare with random * input (except in VERIFY mode, where a lower iteration count is used). */ - rustsecp256k1_v0_10_0_fe dummy; - ret = rustsecp256k1_v0_10_0_fe_sqrt(&dummy, &tmp); + rustsecp256k1_v0_11_fe dummy; + ret = rustsecp256k1_v0_11_fe_sqrt(&dummy, &tmp); } else { ret = jac >= 0; } diff --git a/secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h b/secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h index aad6ad4bd..042b14708 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_5x52_int128_impl.h @@ -13,10 +13,10 @@ #include "util.h" #define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) -#define VERIFY_BITS_128(x, n) VERIFY_CHECK(rustsecp256k1_v0_10_0_u128_check_bits((x), (n))) +#define VERIFY_BITS_128(x, n) VERIFY_CHECK(rustsecp256k1_v0_11_u128_check_bits((x), (n))) -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { - rustsecp256k1_v0_10_0_uint128 c, d; +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { + rustsecp256k1_v0_11_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]; const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; @@ -40,35 +40,35 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_inner(uint64_t *r, con * Note that [x 0 0 0 0 0] = [x*R]. */ - rustsecp256k1_v0_10_0_u128_mul(&d, a0, b[3]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a1, b[2]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2, b[1]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, b[0]); + rustsecp256k1_v0_11_u128_mul(&d, a0, b[3]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a1, b[2]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2, b[1]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, b[0]); VERIFY_BITS_128(&d, 114); /* [d 0 0 0] = [p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_mul(&c, a4, b[4]); + rustsecp256k1_v0_11_u128_mul(&c, a4, b[4]); VERIFY_BITS_128(&c, 112); /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, R, rustsecp256k1_v0_10_0_u128_to_u64(&c)); rustsecp256k1_v0_10_0_u128_rshift(&c, 64); + rustsecp256k1_v0_11_u128_accum_mul(&d, R, rustsecp256k1_v0_11_u128_to_u64(&c)); rustsecp256k1_v0_11_u128_rshift(&c, 64); VERIFY_BITS_128(&d, 115); VERIFY_BITS_128(&c, 48); /* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = rustsecp256k1_v0_10_0_u128_to_u64(&d) & M; rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + t3 = rustsecp256k1_v0_11_u128_to_u64(&d) & M; rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS(t3, 52); VERIFY_BITS_128(&d, 63); /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a0, b[4]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a1, b[3]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2, b[2]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, b[1]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a4, b[0]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a0, b[4]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a1, b[3]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2, b[2]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, b[1]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a4, b[0]); VERIFY_BITS_128(&d, 115); /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, R << 12, rustsecp256k1_v0_10_0_u128_to_u64(&c)); + rustsecp256k1_v0_11_u128_accum_mul(&d, R << 12, rustsecp256k1_v0_11_u128_to_u64(&c)); VERIFY_BITS_128(&d, 116); /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = rustsecp256k1_v0_10_0_u128_to_u64(&d) & M; rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + t4 = rustsecp256k1_v0_11_u128_to_u64(&d) & M; rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS(t4, 52); VERIFY_BITS_128(&d, 64); /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ @@ -77,16 +77,16 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_inner(uint64_t *r, con VERIFY_BITS(t4, 48); /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_mul(&c, a0, b[0]); + rustsecp256k1_v0_11_u128_mul(&c, a0, b[0]); VERIFY_BITS_128(&c, 112); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a1, b[4]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2, b[3]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, b[2]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a4, b[1]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a1, b[4]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2, b[3]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, b[2]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a4, b[1]); VERIFY_BITS_128(&d, 114); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = rustsecp256k1_v0_10_0_u128_to_u64(&d) & M; rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + u0 = rustsecp256k1_v0_11_u128_to_u64(&d) & M; rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS(u0, 52); VERIFY_BITS_128(&d, 62); /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ @@ -94,65 +94,65 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_inner(uint64_t *r, con u0 = (u0 << 4) | tx; VERIFY_BITS(u0, 56); /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, u0, R >> 4); + rustsecp256k1_v0_11_u128_accum_mul(&c, u0, R >> 4); VERIFY_BITS_128(&c, 113); /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[0] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[0], 52); VERIFY_BITS_128(&c, 61); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a0, b[1]); - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a1, b[0]); + rustsecp256k1_v0_11_u128_accum_mul(&c, a0, b[1]); + rustsecp256k1_v0_11_u128_accum_mul(&c, a1, b[0]); VERIFY_BITS_128(&c, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2, b[4]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, b[3]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a4, b[2]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2, b[4]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, b[3]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a4, b[2]); VERIFY_BITS_128(&d, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, rustsecp256k1_v0_10_0_u128_to_u64(&d) & M, R); rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + rustsecp256k1_v0_11_u128_accum_mul(&c, rustsecp256k1_v0_11_u128_to_u64(&d) & M, R); rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS_128(&c, 115); VERIFY_BITS_128(&d, 62); /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[1] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[1], 52); VERIFY_BITS_128(&c, 63); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a0, b[2]); - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a1, b[1]); - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a2, b[0]); + rustsecp256k1_v0_11_u128_accum_mul(&c, a0, b[2]); + rustsecp256k1_v0_11_u128_accum_mul(&c, a1, b[1]); + rustsecp256k1_v0_11_u128_accum_mul(&c, a2, b[0]); VERIFY_BITS_128(&c, 114); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, b[4]); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a4, b[3]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, b[4]); + rustsecp256k1_v0_11_u128_accum_mul(&d, a4, b[3]); VERIFY_BITS_128(&d, 114); /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, R, rustsecp256k1_v0_10_0_u128_to_u64(&d)); rustsecp256k1_v0_10_0_u128_rshift(&d, 64); + rustsecp256k1_v0_11_u128_accum_mul(&c, R, rustsecp256k1_v0_11_u128_to_u64(&d)); rustsecp256k1_v0_11_u128_rshift(&d, 64); VERIFY_BITS_128(&c, 115); VERIFY_BITS_128(&d, 50); /* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[2] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[2], 52); VERIFY_BITS_128(&c, 63); /* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, R << 12, rustsecp256k1_v0_10_0_u128_to_u64(&d)); - rustsecp256k1_v0_10_0_u128_accum_u64(&c, t3); + rustsecp256k1_v0_11_u128_accum_mul(&c, R << 12, rustsecp256k1_v0_11_u128_to_u64(&d)); + rustsecp256k1_v0_11_u128_accum_u64(&c, t3); VERIFY_BITS_128(&c, 100); /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[3] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[3], 52); VERIFY_BITS_128(&c, 48); /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = rustsecp256k1_v0_10_0_u128_to_u64(&c) + t4; + r[4] = rustsecp256k1_v0_11_u128_to_u64(&c) + t4; VERIFY_BITS(r[4], 49); /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr_inner(uint64_t *r, const uint64_t *a) { - rustsecp256k1_v0_10_0_uint128 c, d; +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_sqr_inner(uint64_t *r, const uint64_t *a) { + rustsecp256k1_v0_11_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; const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; @@ -168,32 +168,32 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr_inner(uint64_t *r, con * Note that [x 0 0 0 0 0] = [x*R]. */ - rustsecp256k1_v0_10_0_u128_mul(&d, a0*2, a3); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a1*2, a2); + rustsecp256k1_v0_11_u128_mul(&d, a0*2, a3); + rustsecp256k1_v0_11_u128_accum_mul(&d, a1*2, a2); VERIFY_BITS_128(&d, 114); /* [d 0 0 0] = [p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_mul(&c, a4, a4); + rustsecp256k1_v0_11_u128_mul(&c, a4, a4); VERIFY_BITS_128(&c, 112); /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, R, rustsecp256k1_v0_10_0_u128_to_u64(&c)); rustsecp256k1_v0_10_0_u128_rshift(&c, 64); + rustsecp256k1_v0_11_u128_accum_mul(&d, R, rustsecp256k1_v0_11_u128_to_u64(&c)); rustsecp256k1_v0_11_u128_rshift(&c, 64); VERIFY_BITS_128(&d, 115); VERIFY_BITS_128(&c, 48); /* [(c<<12) 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ - t3 = rustsecp256k1_v0_10_0_u128_to_u64(&d) & M; rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + t3 = rustsecp256k1_v0_11_u128_to_u64(&d) & M; rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS(t3, 52); VERIFY_BITS_128(&d, 63); /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ a4 *= 2; - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a0, a4); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a1*2, a3); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2, a2); + rustsecp256k1_v0_11_u128_accum_mul(&d, a0, a4); + rustsecp256k1_v0_11_u128_accum_mul(&d, a1*2, a3); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2, a2); VERIFY_BITS_128(&d, 115); /* [(c<<12) 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, R << 12, rustsecp256k1_v0_10_0_u128_to_u64(&c)); + rustsecp256k1_v0_11_u128_accum_mul(&d, R << 12, rustsecp256k1_v0_11_u128_to_u64(&c)); VERIFY_BITS_128(&d, 116); /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - t4 = rustsecp256k1_v0_10_0_u128_to_u64(&d) & M; rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + t4 = rustsecp256k1_v0_11_u128_to_u64(&d) & M; rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS(t4, 52); VERIFY_BITS_128(&d, 64); /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ @@ -202,14 +202,14 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr_inner(uint64_t *r, con VERIFY_BITS(t4, 48); /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ - rustsecp256k1_v0_10_0_u128_mul(&c, a0, a0); + rustsecp256k1_v0_11_u128_mul(&c, a0, a0); VERIFY_BITS_128(&c, 112); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a1, a4); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2*2, a3); + rustsecp256k1_v0_11_u128_accum_mul(&d, a1, a4); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2*2, a3); VERIFY_BITS_128(&d, 114); /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - u0 = rustsecp256k1_v0_10_0_u128_to_u64(&d) & M; rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + u0 = rustsecp256k1_v0_11_u128_to_u64(&d) & M; rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS(u0, 52); VERIFY_BITS_128(&d, 62); /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ @@ -217,56 +217,56 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr_inner(uint64_t *r, con u0 = (u0 << 4) | tx; VERIFY_BITS(u0, 56); /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, u0, R >> 4); + rustsecp256k1_v0_11_u128_accum_mul(&c, u0, R >> 4); VERIFY_BITS_128(&c, 113); /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ - r[0] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[0] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[0], 52); VERIFY_BITS_128(&c, 61); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ a0 *= 2; - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a0, a1); + rustsecp256k1_v0_11_u128_accum_mul(&c, a0, a1); VERIFY_BITS_128(&c, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a2, a4); - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, a3); + rustsecp256k1_v0_11_u128_accum_mul(&d, a2, a4); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, a3); VERIFY_BITS_128(&d, 114); /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, rustsecp256k1_v0_10_0_u128_to_u64(&d) & M, R); rustsecp256k1_v0_10_0_u128_rshift(&d, 52); + rustsecp256k1_v0_11_u128_accum_mul(&c, rustsecp256k1_v0_11_u128_to_u64(&d) & M, R); rustsecp256k1_v0_11_u128_rshift(&d, 52); VERIFY_BITS_128(&c, 115); VERIFY_BITS_128(&d, 62); /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - r[1] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[1] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[1], 52); VERIFY_BITS_128(&c, 63); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a0, a2); - rustsecp256k1_v0_10_0_u128_accum_mul(&c, a1, a1); + rustsecp256k1_v0_11_u128_accum_mul(&c, a0, a2); + rustsecp256k1_v0_11_u128_accum_mul(&c, a1, a1); VERIFY_BITS_128(&c, 114); /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&d, a3, a4); + rustsecp256k1_v0_11_u128_accum_mul(&d, a3, a4); VERIFY_BITS_128(&d, 114); /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, R, rustsecp256k1_v0_10_0_u128_to_u64(&d)); rustsecp256k1_v0_10_0_u128_rshift(&d, 64); + rustsecp256k1_v0_11_u128_accum_mul(&c, R, rustsecp256k1_v0_11_u128_to_u64(&d)); rustsecp256k1_v0_11_u128_rshift(&d, 64); VERIFY_BITS_128(&c, 115); VERIFY_BITS_128(&d, 50); /* [(d<<12) 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[2] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[2] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[2], 52); VERIFY_BITS_128(&c, 63); /* [(d<<12) 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - rustsecp256k1_v0_10_0_u128_accum_mul(&c, R << 12, rustsecp256k1_v0_10_0_u128_to_u64(&d)); - rustsecp256k1_v0_10_0_u128_accum_u64(&c, t3); + rustsecp256k1_v0_11_u128_accum_mul(&c, R << 12, rustsecp256k1_v0_11_u128_to_u64(&d)); + rustsecp256k1_v0_11_u128_accum_u64(&c, t3); VERIFY_BITS_128(&c, 100); /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[3] = rustsecp256k1_v0_10_0_u128_to_u64(&c) & M; rustsecp256k1_v0_10_0_u128_rshift(&c, 52); + r[3] = rustsecp256k1_v0_11_u128_to_u64(&c) & M; rustsecp256k1_v0_11_u128_rshift(&c, 52); VERIFY_BITS(r[3], 52); VERIFY_BITS_128(&c, 48); /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ - r[4] = rustsecp256k1_v0_10_0_u128_to_u64(&c) + t4; + r[4] = rustsecp256k1_v0_11_u128_to_u64(&c) + t4; VERIFY_BITS(r[4], 49); /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ } diff --git a/secp256k1-sys/depend/secp256k1/src/field_impl.h b/secp256k1-sys/depend/secp256k1/src/field_impl.h index 0943f959b..d44d4d457 100644 --- a/secp256k1-sys/depend/secp256k1/src/field_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/field_impl.h @@ -18,19 +18,23 @@ #error "Please select wide multiplication implementation" #endif -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_equal(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b) { - rustsecp256k1_v0_10_0_fe na; +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_clear(rustsecp256k1_v0_11_fe *a) { + rustsecp256k1_v0_11_memclear(a, sizeof(rustsecp256k1_v0_11_fe)); +} + +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_equal(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b) { + rustsecp256k1_v0_11_fe na; SECP256K1_FE_VERIFY(a); SECP256K1_FE_VERIFY(b); SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); SECP256K1_FE_VERIFY_MAGNITUDE(b, 31); - rustsecp256k1_v0_10_0_fe_negate(&na, a, 1); - rustsecp256k1_v0_10_0_fe_add(&na, b); - return rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&na); + rustsecp256k1_v0_11_fe_negate(&na, a, 1); + rustsecp256k1_v0_11_fe_add(&na, b); + return rustsecp256k1_v0_11_fe_normalizes_to_zero(&na); } -static int rustsecp256k1_v0_10_0_fe_sqrt(rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT r, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT a) { +static int rustsecp256k1_v0_11_fe_sqrt(rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT r, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT a) { /** Given that p is congruent to 3 mod 4, we can compute the square root of * a mod p as the (p+1)/4'th power of a. * @@ -40,7 +44,7 @@ static int rustsecp256k1_v0_10_0_fe_sqrt(rustsecp256k1_v0_10_0_fe * SECP256K1_RE * Also because (p+1)/4 is an even number, the computed square root is * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). */ - rustsecp256k1_v0_10_0_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; + rustsecp256k1_v0_11_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; int j, ret; VERIFY_CHECK(r != a); @@ -52,101 +56,101 @@ static int rustsecp256k1_v0_10_0_fe_sqrt(rustsecp256k1_v0_10_0_fe * SECP256K1_RE * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] */ - rustsecp256k1_v0_10_0_fe_sqr(&x2, a); - rustsecp256k1_v0_10_0_fe_mul(&x2, &x2, a); + rustsecp256k1_v0_11_fe_sqr(&x2, a); + rustsecp256k1_v0_11_fe_mul(&x2, &x2, a); - rustsecp256k1_v0_10_0_fe_sqr(&x3, &x2); - rustsecp256k1_v0_10_0_fe_mul(&x3, &x3, a); + rustsecp256k1_v0_11_fe_sqr(&x3, &x2); + rustsecp256k1_v0_11_fe_mul(&x3, &x3, a); x6 = x3; for (j=0; j<3; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x6, &x6); + rustsecp256k1_v0_11_fe_sqr(&x6, &x6); } - rustsecp256k1_v0_10_0_fe_mul(&x6, &x6, &x3); + rustsecp256k1_v0_11_fe_mul(&x6, &x6, &x3); x9 = x6; for (j=0; j<3; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x9, &x9); + rustsecp256k1_v0_11_fe_sqr(&x9, &x9); } - rustsecp256k1_v0_10_0_fe_mul(&x9, &x9, &x3); + rustsecp256k1_v0_11_fe_mul(&x9, &x9, &x3); x11 = x9; for (j=0; j<2; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x11, &x11); + rustsecp256k1_v0_11_fe_sqr(&x11, &x11); } - rustsecp256k1_v0_10_0_fe_mul(&x11, &x11, &x2); + rustsecp256k1_v0_11_fe_mul(&x11, &x11, &x2); x22 = x11; for (j=0; j<11; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x22, &x22); + rustsecp256k1_v0_11_fe_sqr(&x22, &x22); } - rustsecp256k1_v0_10_0_fe_mul(&x22, &x22, &x11); + rustsecp256k1_v0_11_fe_mul(&x22, &x22, &x11); x44 = x22; for (j=0; j<22; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x44, &x44); + rustsecp256k1_v0_11_fe_sqr(&x44, &x44); } - rustsecp256k1_v0_10_0_fe_mul(&x44, &x44, &x22); + rustsecp256k1_v0_11_fe_mul(&x44, &x44, &x22); x88 = x44; for (j=0; j<44; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x88, &x88); + rustsecp256k1_v0_11_fe_sqr(&x88, &x88); } - rustsecp256k1_v0_10_0_fe_mul(&x88, &x88, &x44); + rustsecp256k1_v0_11_fe_mul(&x88, &x88, &x44); x176 = x88; for (j=0; j<88; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x176, &x176); + rustsecp256k1_v0_11_fe_sqr(&x176, &x176); } - rustsecp256k1_v0_10_0_fe_mul(&x176, &x176, &x88); + rustsecp256k1_v0_11_fe_mul(&x176, &x176, &x88); x220 = x176; for (j=0; j<44; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x220, &x220); + rustsecp256k1_v0_11_fe_sqr(&x220, &x220); } - rustsecp256k1_v0_10_0_fe_mul(&x220, &x220, &x44); + rustsecp256k1_v0_11_fe_mul(&x220, &x220, &x44); x223 = x220; for (j=0; j<3; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&x223, &x223); + rustsecp256k1_v0_11_fe_sqr(&x223, &x223); } - rustsecp256k1_v0_10_0_fe_mul(&x223, &x223, &x3); + rustsecp256k1_v0_11_fe_mul(&x223, &x223, &x3); /* The final result is then assembled using a sliding window over the blocks. */ t1 = x223; for (j=0; j<23; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&t1, &t1); + rustsecp256k1_v0_11_fe_sqr(&t1, &t1); } - rustsecp256k1_v0_10_0_fe_mul(&t1, &t1, &x22); + rustsecp256k1_v0_11_fe_mul(&t1, &t1, &x22); for (j=0; j<6; j++) { - rustsecp256k1_v0_10_0_fe_sqr(&t1, &t1); + rustsecp256k1_v0_11_fe_sqr(&t1, &t1); } - rustsecp256k1_v0_10_0_fe_mul(&t1, &t1, &x2); - rustsecp256k1_v0_10_0_fe_sqr(&t1, &t1); - rustsecp256k1_v0_10_0_fe_sqr(r, &t1); + rustsecp256k1_v0_11_fe_mul(&t1, &t1, &x2); + rustsecp256k1_v0_11_fe_sqr(&t1, &t1); + rustsecp256k1_v0_11_fe_sqr(r, &t1); /* Check that a square root was actually calculated */ - rustsecp256k1_v0_10_0_fe_sqr(&t1, r); - ret = rustsecp256k1_v0_10_0_fe_equal(&t1, a); + rustsecp256k1_v0_11_fe_sqr(&t1, r); + ret = rustsecp256k1_v0_11_fe_equal(&t1, a); #ifdef VERIFY if (!ret) { - rustsecp256k1_v0_10_0_fe_negate(&t1, &t1, 1); - rustsecp256k1_v0_10_0_fe_normalize_var(&t1); - VERIFY_CHECK(rustsecp256k1_v0_10_0_fe_equal(&t1, a)); + rustsecp256k1_v0_11_fe_negate(&t1, &t1, 1); + rustsecp256k1_v0_11_fe_normalize_var(&t1); + VERIFY_CHECK(rustsecp256k1_v0_11_fe_equal(&t1, a)); } #endif return ret; } #ifndef VERIFY -static void rustsecp256k1_v0_10_0_fe_verify(const rustsecp256k1_v0_10_0_fe *a) { (void)a; } -static void rustsecp256k1_v0_10_0_fe_verify_magnitude(const rustsecp256k1_v0_10_0_fe *a, int m) { (void)a; (void)m; } +static void rustsecp256k1_v0_11_fe_verify(const rustsecp256k1_v0_11_fe *a) { (void)a; } +static void rustsecp256k1_v0_11_fe_verify_magnitude(const rustsecp256k1_v0_11_fe *a, int m) { (void)a; (void)m; } #else -static void rustsecp256k1_v0_10_0_fe_impl_verify(const rustsecp256k1_v0_10_0_fe *a); -static void rustsecp256k1_v0_10_0_fe_verify(const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_verify(const rustsecp256k1_v0_11_fe *a); +static void rustsecp256k1_v0_11_fe_verify(const rustsecp256k1_v0_11_fe *a) { /* Magnitude between 0 and 32. */ SECP256K1_FE_VERIFY_MAGNITUDE(a, 32); /* Normalized is 0 or 1. */ @@ -154,131 +158,122 @@ static void rustsecp256k1_v0_10_0_fe_verify(const rustsecp256k1_v0_10_0_fe *a) { /* If normalized, magnitude must be 0 or 1. */ if (a->normalized) SECP256K1_FE_VERIFY_MAGNITUDE(a, 1); /* Invoke implementation-specific checks. */ - rustsecp256k1_v0_10_0_fe_impl_verify(a); + rustsecp256k1_v0_11_fe_impl_verify(a); } -static void rustsecp256k1_v0_10_0_fe_verify_magnitude(const rustsecp256k1_v0_10_0_fe *a, int m) { +static void rustsecp256k1_v0_11_fe_verify_magnitude(const rustsecp256k1_v0_11_fe *a, int m) { VERIFY_CHECK(m >= 0); VERIFY_CHECK(m <= 32); VERIFY_CHECK(a->magnitude <= m); } -static void rustsecp256k1_v0_10_0_fe_impl_normalize(rustsecp256k1_v0_10_0_fe *r); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_normalize(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize(rustsecp256k1_v0_11_fe *r); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_normalize(rustsecp256k1_v0_11_fe *r) { SECP256K1_FE_VERIFY(r); - rustsecp256k1_v0_10_0_fe_impl_normalize(r); + rustsecp256k1_v0_11_fe_impl_normalize(r); r->magnitude = 1; r->normalized = 1; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_normalize_weak(rustsecp256k1_v0_10_0_fe *r); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_normalize_weak(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize_weak(rustsecp256k1_v0_11_fe *r); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_normalize_weak(rustsecp256k1_v0_11_fe *r) { SECP256K1_FE_VERIFY(r); - rustsecp256k1_v0_10_0_fe_impl_normalize_weak(r); + rustsecp256k1_v0_11_fe_impl_normalize_weak(r); r->magnitude = 1; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_normalize_var(rustsecp256k1_v0_10_0_fe *r); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_normalize_var(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_normalize_var(rustsecp256k1_v0_11_fe *r); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_normalize_var(rustsecp256k1_v0_11_fe *r) { SECP256K1_FE_VERIFY(r); - rustsecp256k1_v0_10_0_fe_impl_normalize_var(r); + rustsecp256k1_v0_11_fe_impl_normalize_var(r); r->magnitude = 1; r->normalized = 1; SECP256K1_FE_VERIFY(r); } -static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero(const rustsecp256k1_v0_10_0_fe *r); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_normalizes_to_zero(const rustsecp256k1_v0_10_0_fe *r) { +static int rustsecp256k1_v0_11_fe_impl_normalizes_to_zero(const rustsecp256k1_v0_11_fe *r); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_normalizes_to_zero(const rustsecp256k1_v0_11_fe *r) { SECP256K1_FE_VERIFY(r); - return rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero(r); + return rustsecp256k1_v0_11_fe_impl_normalizes_to_zero(r); } -static int rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var(const rustsecp256k1_v0_10_0_fe *r); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(const rustsecp256k1_v0_10_0_fe *r) { +static int rustsecp256k1_v0_11_fe_impl_normalizes_to_zero_var(const rustsecp256k1_v0_11_fe *r); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_normalizes_to_zero_var(const rustsecp256k1_v0_11_fe *r) { SECP256K1_FE_VERIFY(r); - return rustsecp256k1_v0_10_0_fe_impl_normalizes_to_zero_var(r); + return rustsecp256k1_v0_11_fe_impl_normalizes_to_zero_var(r); } -static void rustsecp256k1_v0_10_0_fe_impl_set_int(rustsecp256k1_v0_10_0_fe *r, int a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_set_int(rustsecp256k1_v0_10_0_fe *r, int a) { +static void rustsecp256k1_v0_11_fe_impl_set_int(rustsecp256k1_v0_11_fe *r, int a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_set_int(rustsecp256k1_v0_11_fe *r, int a) { VERIFY_CHECK(0 <= a && a <= 0x7FFF); - rustsecp256k1_v0_10_0_fe_impl_set_int(r, a); + rustsecp256k1_v0_11_fe_impl_set_int(r, a); r->magnitude = (a != 0); r->normalized = 1; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_add_int(rustsecp256k1_v0_10_0_fe *r, int a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_add_int(rustsecp256k1_v0_10_0_fe *r, int a) { +static void rustsecp256k1_v0_11_fe_impl_add_int(rustsecp256k1_v0_11_fe *r, int a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_add_int(rustsecp256k1_v0_11_fe *r, int a) { VERIFY_CHECK(0 <= a && a <= 0x7FFF); SECP256K1_FE_VERIFY(r); - rustsecp256k1_v0_10_0_fe_impl_add_int(r, a); + rustsecp256k1_v0_11_fe_impl_add_int(r, a); r->magnitude += 1; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_clear(rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_clear(rustsecp256k1_v0_10_0_fe *a) { - a->magnitude = 0; - a->normalized = 1; - rustsecp256k1_v0_10_0_fe_impl_clear(a); - - SECP256K1_FE_VERIFY(a); -} - -static int rustsecp256k1_v0_10_0_fe_impl_is_zero(const rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_is_zero(const rustsecp256k1_v0_10_0_fe *a) { +static int rustsecp256k1_v0_11_fe_impl_is_zero(const rustsecp256k1_v0_11_fe *a); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_is_zero(const rustsecp256k1_v0_11_fe *a) { SECP256K1_FE_VERIFY(a); VERIFY_CHECK(a->normalized); - return rustsecp256k1_v0_10_0_fe_impl_is_zero(a); + return rustsecp256k1_v0_11_fe_impl_is_zero(a); } -static int rustsecp256k1_v0_10_0_fe_impl_is_odd(const rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_is_odd(const rustsecp256k1_v0_10_0_fe *a) { +static int rustsecp256k1_v0_11_fe_impl_is_odd(const rustsecp256k1_v0_11_fe *a); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_is_odd(const rustsecp256k1_v0_11_fe *a) { SECP256K1_FE_VERIFY(a); VERIFY_CHECK(a->normalized); - return rustsecp256k1_v0_10_0_fe_impl_is_odd(a); + return rustsecp256k1_v0_11_fe_impl_is_odd(a); } -static int rustsecp256k1_v0_10_0_fe_impl_cmp_var(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_cmp_var(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b) { +static int rustsecp256k1_v0_11_fe_impl_cmp_var(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_cmp_var(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b) { SECP256K1_FE_VERIFY(a); SECP256K1_FE_VERIFY(b); VERIFY_CHECK(a->normalized); VERIFY_CHECK(b->normalized); - return rustsecp256k1_v0_10_0_fe_impl_cmp_var(a, b); + return rustsecp256k1_v0_11_fe_impl_cmp_var(a, b); } -static void rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_set_b32_mod(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a) { - rustsecp256k1_v0_10_0_fe_impl_set_b32_mod(r, a); +static void rustsecp256k1_v0_11_fe_impl_set_b32_mod(rustsecp256k1_v0_11_fe *r, const unsigned char *a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_set_b32_mod(rustsecp256k1_v0_11_fe *r, const unsigned char *a) { + rustsecp256k1_v0_11_fe_impl_set_b32_mod(r, a); r->magnitude = 1; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static int rustsecp256k1_v0_10_0_fe_impl_set_b32_limit(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_set_b32_limit(rustsecp256k1_v0_10_0_fe *r, const unsigned char *a) { - if (rustsecp256k1_v0_10_0_fe_impl_set_b32_limit(r, a)) { +static int rustsecp256k1_v0_11_fe_impl_set_b32_limit(rustsecp256k1_v0_11_fe *r, const unsigned char *a); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_set_b32_limit(rustsecp256k1_v0_11_fe *r, const unsigned char *a) { + if (rustsecp256k1_v0_11_fe_impl_set_b32_limit(r, a)) { r->magnitude = 1; r->normalized = 1; SECP256K1_FE_VERIFY(r); @@ -290,55 +285,55 @@ SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_set_b32_limit(rustsecp256k1 } } -static void rustsecp256k1_v0_10_0_fe_impl_get_b32(unsigned char *r, const rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_get_b32(unsigned char *r, const rustsecp256k1_v0_11_fe *a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_get_b32(unsigned char *r, const rustsecp256k1_v0_11_fe *a) { SECP256K1_FE_VERIFY(a); VERIFY_CHECK(a->normalized); - rustsecp256k1_v0_10_0_fe_impl_get_b32(r, a); + rustsecp256k1_v0_11_fe_impl_get_b32(r, a); } -static void rustsecp256k1_v0_10_0_fe_impl_negate_unchecked(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int m); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_negate_unchecked(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int m) { +static void rustsecp256k1_v0_11_fe_impl_negate_unchecked(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int m); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_negate_unchecked(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int m) { SECP256K1_FE_VERIFY(a); VERIFY_CHECK(m >= 0 && m <= 31); SECP256K1_FE_VERIFY_MAGNITUDE(a, m); - rustsecp256k1_v0_10_0_fe_impl_negate_unchecked(r, a, m); + rustsecp256k1_v0_11_fe_impl_negate_unchecked(r, a, m); r->magnitude = m + 1; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked(rustsecp256k1_v0_10_0_fe *r, int a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul_int_unchecked(rustsecp256k1_v0_10_0_fe *r, int a) { +static void rustsecp256k1_v0_11_fe_impl_mul_int_unchecked(rustsecp256k1_v0_11_fe *r, int a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_mul_int_unchecked(rustsecp256k1_v0_11_fe *r, int a) { SECP256K1_FE_VERIFY(r); VERIFY_CHECK(a >= 0 && a <= 32); VERIFY_CHECK(a*r->magnitude <= 32); - rustsecp256k1_v0_10_0_fe_impl_mul_int_unchecked(r, a); + rustsecp256k1_v0_11_fe_impl_mul_int_unchecked(r, a); r->magnitude *= a; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_add(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_add(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_add(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_add(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a) { SECP256K1_FE_VERIFY(r); SECP256K1_FE_VERIFY(a); VERIFY_CHECK(r->magnitude + a->magnitude <= 32); - rustsecp256k1_v0_10_0_fe_impl_add(r, a); + rustsecp256k1_v0_11_fe_impl_add(r, a); r->magnitude += a->magnitude; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_mul(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT b); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe * SECP256K1_RESTRICT b) { +static void rustsecp256k1_v0_11_fe_impl_mul(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT b); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_mul(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe * SECP256K1_RESTRICT b) { SECP256K1_FE_VERIFY(a); SECP256K1_FE_VERIFY(b); SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); @@ -346,111 +341,111 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_mul(rustsecp256k1_v0_10_0_ VERIFY_CHECK(r != b); VERIFY_CHECK(a != b); - rustsecp256k1_v0_10_0_fe_impl_mul(r, a, b); + rustsecp256k1_v0_11_fe_impl_mul(r, a, b); r->magnitude = 1; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_sqr(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_sqr(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_sqr(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_sqr(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a) { SECP256K1_FE_VERIFY(a); SECP256K1_FE_VERIFY_MAGNITUDE(a, 8); - rustsecp256k1_v0_10_0_fe_impl_sqr(r, a); + rustsecp256k1_v0_11_fe_impl_sqr(r, a); r->magnitude = 1; r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_cmov(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int flag); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_cmov(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *a, int flag) { +static void rustsecp256k1_v0_11_fe_impl_cmov(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int flag); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_cmov(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *a, int flag) { VERIFY_CHECK(flag == 0 || flag == 1); SECP256K1_FE_VERIFY(a); SECP256K1_FE_VERIFY(r); - rustsecp256k1_v0_10_0_fe_impl_cmov(r, a, flag); + rustsecp256k1_v0_11_fe_impl_cmov(r, a, flag); if (a->magnitude > r->magnitude) r->magnitude = a->magnitude; if (!a->normalized) r->normalized = 0; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_to_storage(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_to_storage(rustsecp256k1_v0_10_0_fe_storage *r, const rustsecp256k1_v0_10_0_fe *a) { +static void rustsecp256k1_v0_11_fe_impl_to_storage(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe *a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_to_storage(rustsecp256k1_v0_11_fe_storage *r, const rustsecp256k1_v0_11_fe *a) { SECP256K1_FE_VERIFY(a); VERIFY_CHECK(a->normalized); - rustsecp256k1_v0_10_0_fe_impl_to_storage(r, a); + rustsecp256k1_v0_11_fe_impl_to_storage(r, a); } -static void rustsecp256k1_v0_10_0_fe_impl_from_storage(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe_storage *a); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_from_storage(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe_storage *a) { - rustsecp256k1_v0_10_0_fe_impl_from_storage(r, a); +static void rustsecp256k1_v0_11_fe_impl_from_storage(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe_storage *a); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_from_storage(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe_storage *a) { + rustsecp256k1_v0_11_fe_impl_from_storage(r, a); r->magnitude = 1; r->normalized = 1; SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_inv(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_inv(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x) { - int input_is_zero = rustsecp256k1_v0_10_0_fe_normalizes_to_zero(x); +static void rustsecp256k1_v0_11_fe_impl_inv(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_inv(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x) { + int input_is_zero = rustsecp256k1_v0_11_fe_normalizes_to_zero(x); SECP256K1_FE_VERIFY(x); - rustsecp256k1_v0_10_0_fe_impl_inv(r, x); + rustsecp256k1_v0_11_fe_impl_inv(r, x); r->magnitude = x->magnitude > 0; r->normalized = 1; - VERIFY_CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero(r) == input_is_zero); + VERIFY_CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero(r) == input_is_zero); SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_inv_var(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_inv_var(rustsecp256k1_v0_10_0_fe *r, const rustsecp256k1_v0_10_0_fe *x) { - int input_is_zero = rustsecp256k1_v0_10_0_fe_normalizes_to_zero(x); +static void rustsecp256k1_v0_11_fe_impl_inv_var(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_inv_var(rustsecp256k1_v0_11_fe *r, const rustsecp256k1_v0_11_fe *x) { + int input_is_zero = rustsecp256k1_v0_11_fe_normalizes_to_zero(x); SECP256K1_FE_VERIFY(x); - rustsecp256k1_v0_10_0_fe_impl_inv_var(r, x); + rustsecp256k1_v0_11_fe_impl_inv_var(r, x); r->magnitude = x->magnitude > 0; r->normalized = 1; - VERIFY_CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero(r) == input_is_zero); + VERIFY_CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero(r) == input_is_zero); SECP256K1_FE_VERIFY(r); } -static int rustsecp256k1_v0_10_0_fe_impl_is_square_var(const rustsecp256k1_v0_10_0_fe *x); -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_fe_is_square_var(const rustsecp256k1_v0_10_0_fe *x) { +static int rustsecp256k1_v0_11_fe_impl_is_square_var(const rustsecp256k1_v0_11_fe *x); +SECP256K1_INLINE static int rustsecp256k1_v0_11_fe_is_square_var(const rustsecp256k1_v0_11_fe *x) { int ret; - rustsecp256k1_v0_10_0_fe tmp = *x, sqrt; + rustsecp256k1_v0_11_fe tmp = *x, sqrt; SECP256K1_FE_VERIFY(x); - ret = rustsecp256k1_v0_10_0_fe_impl_is_square_var(x); - rustsecp256k1_v0_10_0_fe_normalize_weak(&tmp); - VERIFY_CHECK(ret == rustsecp256k1_v0_10_0_fe_sqrt(&sqrt, &tmp)); + ret = rustsecp256k1_v0_11_fe_impl_is_square_var(x); + rustsecp256k1_v0_11_fe_normalize_weak(&tmp); + VERIFY_CHECK(ret == rustsecp256k1_v0_11_fe_sqrt(&sqrt, &tmp)); return ret; } -static void rustsecp256k1_v0_10_0_fe_impl_get_bounds(rustsecp256k1_v0_10_0_fe* r, int m); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_get_bounds(rustsecp256k1_v0_10_0_fe* r, int m) { +static void rustsecp256k1_v0_11_fe_impl_get_bounds(rustsecp256k1_v0_11_fe* r, int m); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_get_bounds(rustsecp256k1_v0_11_fe* r, int m) { VERIFY_CHECK(m >= 0); VERIFY_CHECK(m <= 32); - rustsecp256k1_v0_10_0_fe_impl_get_bounds(r, m); + rustsecp256k1_v0_11_fe_impl_get_bounds(r, m); r->magnitude = m; r->normalized = (m == 0); SECP256K1_FE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_fe_impl_half(rustsecp256k1_v0_10_0_fe *r); -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_fe_half(rustsecp256k1_v0_10_0_fe *r) { +static void rustsecp256k1_v0_11_fe_impl_half(rustsecp256k1_v0_11_fe *r); +SECP256K1_INLINE static void rustsecp256k1_v0_11_fe_half(rustsecp256k1_v0_11_fe *r) { SECP256K1_FE_VERIFY(r); SECP256K1_FE_VERIFY_MAGNITUDE(r, 31); - rustsecp256k1_v0_10_0_fe_impl_half(r); + rustsecp256k1_v0_11_fe_impl_half(r); r->magnitude = (r->magnitude >> 1) + 1; r->normalized = 0; diff --git a/secp256k1-sys/depend/secp256k1/src/group.h b/secp256k1-sys/depend/secp256k1/src/group.h index db2c57747..afc71916a 100644 --- a/secp256k1-sys/depend/secp256k1/src/group.h +++ b/secp256k1-sys/depend/secp256k1/src/group.h @@ -14,10 +14,10 @@ * Note: For exhaustive test mode, secp256k1 is replaced by a small subgroup of a different curve. */ typedef struct { - rustsecp256k1_v0_10_0_fe x; - rustsecp256k1_v0_10_0_fe y; + rustsecp256k1_v0_11_fe x; + rustsecp256k1_v0_11_fe y; int infinity; /* whether this represents the point at infinity */ -} rustsecp256k1_v0_10_0_ge; +} rustsecp256k1_v0_11_ge; #define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} #define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} @@ -26,19 +26,19 @@ typedef struct { * Note: For exhastive test mode, secp256k1 is replaced by a small subgroup of a different curve. */ typedef struct { - rustsecp256k1_v0_10_0_fe x; /* actual X: x/z^2 */ - rustsecp256k1_v0_10_0_fe y; /* actual Y: y/z^3 */ - rustsecp256k1_v0_10_0_fe z; + rustsecp256k1_v0_11_fe x; /* actual X: x/z^2 */ + rustsecp256k1_v0_11_fe y; /* actual Y: y/z^3 */ + rustsecp256k1_v0_11_fe z; int infinity; /* whether this represents the point at infinity */ -} rustsecp256k1_v0_10_0_gej; +} rustsecp256k1_v0_11_gej; #define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} #define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} typedef struct { - rustsecp256k1_v0_10_0_fe_storage x; - rustsecp256k1_v0_10_0_fe_storage y; -} rustsecp256k1_v0_10_0_ge_storage; + rustsecp256k1_v0_11_fe_storage x; + rustsecp256k1_v0_11_fe_storage y; +} rustsecp256k1_v0_11_ge_storage; #define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} @@ -53,35 +53,35 @@ typedef struct { #define SECP256K1_GEJ_Z_MAGNITUDE_MAX 1 /** Set a group element equal to the point with given X and Y coordinates */ -static void rustsecp256k1_v0_10_0_ge_set_xy(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_fe *x, const rustsecp256k1_v0_10_0_fe *y); +static void rustsecp256k1_v0_11_ge_set_xy(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_fe *x, const rustsecp256k1_v0_11_fe *y); /** Set a group element (affine) equal to the point with the given X coordinate, and given oddness * for Y. Return value indicates whether the result is valid. */ -static int rustsecp256k1_v0_10_0_ge_set_xo_var(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_fe *x, int odd); +static int rustsecp256k1_v0_11_ge_set_xo_var(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_fe *x, int odd); /** Determine whether x is a valid X coordinate on the curve. */ -static int rustsecp256k1_v0_10_0_ge_x_on_curve_var(const rustsecp256k1_v0_10_0_fe *x); +static int rustsecp256k1_v0_11_ge_x_on_curve_var(const rustsecp256k1_v0_11_fe *x); /** Determine whether fraction xn/xd is a valid X coordinate on the curve (xd != 0). */ -static int rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(const rustsecp256k1_v0_10_0_fe *xn, const rustsecp256k1_v0_10_0_fe *xd); +static int rustsecp256k1_v0_11_ge_x_frac_on_curve_var(const rustsecp256k1_v0_11_fe *xn, const rustsecp256k1_v0_11_fe *xd); /** Check whether a group element is the point at infinity. */ -static int rustsecp256k1_v0_10_0_ge_is_infinity(const rustsecp256k1_v0_10_0_ge *a); +static int rustsecp256k1_v0_11_ge_is_infinity(const rustsecp256k1_v0_11_ge *a); /** Check whether a group element is valid (i.e., on the curve). */ -static int rustsecp256k1_v0_10_0_ge_is_valid_var(const rustsecp256k1_v0_10_0_ge *a); +static int rustsecp256k1_v0_11_ge_is_valid_var(const rustsecp256k1_v0_11_ge *a); /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ -static void rustsecp256k1_v0_10_0_ge_neg(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *a); +static void rustsecp256k1_v0_11_ge_neg(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *a); /** Set a group element equal to another which is given in jacobian coordinates. Constant time. */ -static void rustsecp256k1_v0_10_0_ge_set_gej(rustsecp256k1_v0_10_0_ge *r, rustsecp256k1_v0_10_0_gej *a); +static void rustsecp256k1_v0_11_ge_set_gej(rustsecp256k1_v0_11_ge *r, rustsecp256k1_v0_11_gej *a); /** Set a group element equal to another which is given in jacobian coordinates. */ -static void rustsecp256k1_v0_10_0_ge_set_gej_var(rustsecp256k1_v0_10_0_ge *r, rustsecp256k1_v0_10_0_gej *a); +static void rustsecp256k1_v0_11_ge_set_gej_var(rustsecp256k1_v0_11_ge *r, rustsecp256k1_v0_11_gej *a); /** Set a batch of group elements equal to the inputs given in jacobian coordinates */ -static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_gej *a, size_t len); +static void rustsecp256k1_v0_11_ge_set_all_gej_var(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_gej *a, size_t len); /** Bring a batch of inputs to the same global z "denominator", based on ratios between * (omitted) z coordinates of adjacent elements. @@ -100,79 +100,95 @@ static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r * * The coordinates of the final element a[len-1] are not changed. */ -static void rustsecp256k1_v0_10_0_ge_table_set_globalz(size_t len, rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_fe *zr); +static void rustsecp256k1_v0_11_ge_table_set_globalz(size_t len, rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_fe *zr); /** Check two group elements (affine) for equality in variable time. */ -static int rustsecp256k1_v0_10_0_ge_eq_var(const rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_ge *b); +static int rustsecp256k1_v0_11_ge_eq_var(const rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_ge *b); /** Set a group element (affine) equal to the point at infinity. */ -static void rustsecp256k1_v0_10_0_ge_set_infinity(rustsecp256k1_v0_10_0_ge *r); +static void rustsecp256k1_v0_11_ge_set_infinity(rustsecp256k1_v0_11_ge *r); /** Set a group element (jacobian) equal to the point at infinity. */ -static void rustsecp256k1_v0_10_0_gej_set_infinity(rustsecp256k1_v0_10_0_gej *r); +static void rustsecp256k1_v0_11_gej_set_infinity(rustsecp256k1_v0_11_gej *r); /** Set a group element (jacobian) equal to another which is given in affine coordinates. */ -static void rustsecp256k1_v0_10_0_gej_set_ge(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_ge *a); +static void rustsecp256k1_v0_11_gej_set_ge(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_ge *a); /** Check two group elements (jacobian) for equality in variable time. */ -static int rustsecp256k1_v0_10_0_gej_eq_var(const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_gej *b); +static int rustsecp256k1_v0_11_gej_eq_var(const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_gej *b); /** Check two group elements (jacobian and affine) for equality in variable time. */ -static int rustsecp256k1_v0_10_0_gej_eq_ge_var(const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b); +static int rustsecp256k1_v0_11_gej_eq_ge_var(const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b); /** Compare the X coordinate of a group element (jacobian). * The magnitude of the group element's X coordinate must not exceed 31. */ -static int rustsecp256k1_v0_10_0_gej_eq_x_var(const rustsecp256k1_v0_10_0_fe *x, const rustsecp256k1_v0_10_0_gej *a); +static int rustsecp256k1_v0_11_gej_eq_x_var(const rustsecp256k1_v0_11_fe *x, const rustsecp256k1_v0_11_gej *a); /** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ -static void rustsecp256k1_v0_10_0_gej_neg(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a); +static void rustsecp256k1_v0_11_gej_neg(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a); /** Check whether a group element is the point at infinity. */ -static int rustsecp256k1_v0_10_0_gej_is_infinity(const rustsecp256k1_v0_10_0_gej *a); +static int rustsecp256k1_v0_11_gej_is_infinity(const rustsecp256k1_v0_11_gej *a); /** Set r equal to the double of a. Constant time. */ -static void rustsecp256k1_v0_10_0_gej_double(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a); +static void rustsecp256k1_v0_11_gej_double(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a); /** Set r equal to the double of a. If rzr is not-NULL this sets *rzr such that r->z == a->z * *rzr (where infinity means an implicit z = 0). */ -static void rustsecp256k1_v0_10_0_gej_double_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, rustsecp256k1_v0_10_0_fe *rzr); +static void rustsecp256k1_v0_11_gej_double_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, rustsecp256k1_v0_11_fe *rzr); /** Set r equal to the sum of a and b. If rzr is non-NULL this sets *rzr such that r->z == a->z * *rzr (a cannot be infinity in that case). */ -static void rustsecp256k1_v0_10_0_gej_add_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_gej *b, rustsecp256k1_v0_10_0_fe *rzr); +static void rustsecp256k1_v0_11_gej_add_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_gej *b, rustsecp256k1_v0_11_fe *rzr); /** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ -static void rustsecp256k1_v0_10_0_gej_add_ge(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b); +static void rustsecp256k1_v0_11_gej_add_ge(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b); /** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient - than rustsecp256k1_v0_10_0_gej_add_var. It is identical to rustsecp256k1_v0_10_0_gej_add_ge but without constant-time + than rustsecp256k1_v0_11_gej_add_var. It is identical to rustsecp256k1_v0_11_gej_add_ge but without constant-time guarantee, and b is allowed to be infinity. If rzr is non-NULL this sets *rzr such that r->z == a->z * *rzr (a cannot be infinity in that case). */ -static void rustsecp256k1_v0_10_0_gej_add_ge_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b, rustsecp256k1_v0_10_0_fe *rzr); +static void rustsecp256k1_v0_11_gej_add_ge_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b, rustsecp256k1_v0_11_fe *rzr); /** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ -static void rustsecp256k1_v0_10_0_gej_add_zinv_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b, const rustsecp256k1_v0_10_0_fe *bzinv); +static void rustsecp256k1_v0_11_gej_add_zinv_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b, const rustsecp256k1_v0_11_fe *bzinv); /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ -static void rustsecp256k1_v0_10_0_ge_mul_lambda(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *a); +static void rustsecp256k1_v0_11_ge_mul_lambda(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *a); -/** Clear a rustsecp256k1_v0_10_0_gej to prevent leaking sensitive information. */ -static void rustsecp256k1_v0_10_0_gej_clear(rustsecp256k1_v0_10_0_gej *r); +/** Clear a rustsecp256k1_v0_11_gej to prevent leaking sensitive information. */ +static void rustsecp256k1_v0_11_gej_clear(rustsecp256k1_v0_11_gej *r); -/** Clear a rustsecp256k1_v0_10_0_ge to prevent leaking sensitive information. */ -static void rustsecp256k1_v0_10_0_ge_clear(rustsecp256k1_v0_10_0_ge *r); +/** Clear a rustsecp256k1_v0_11_ge to prevent leaking sensitive information. */ +static void rustsecp256k1_v0_11_ge_clear(rustsecp256k1_v0_11_ge *r); /** Convert a group element to the storage type. */ -static void rustsecp256k1_v0_10_0_ge_to_storage(rustsecp256k1_v0_10_0_ge_storage *r, const rustsecp256k1_v0_10_0_ge *a); +static void rustsecp256k1_v0_11_ge_to_storage(rustsecp256k1_v0_11_ge_storage *r, const rustsecp256k1_v0_11_ge *a); /** Convert a group element back from the storage type. */ -static void rustsecp256k1_v0_10_0_ge_from_storage(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge_storage *a); +static void rustsecp256k1_v0_11_ge_from_storage(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge_storage *a); /** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/ -static void rustsecp256k1_v0_10_0_gej_cmov(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, int flag); +static void rustsecp256k1_v0_11_gej_cmov(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_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.*/ -static void rustsecp256k1_v0_10_0_ge_storage_cmov(rustsecp256k1_v0_10_0_ge_storage *r, const rustsecp256k1_v0_10_0_ge_storage *a, int flag); +static void rustsecp256k1_v0_11_ge_storage_cmov(rustsecp256k1_v0_11_ge_storage *r, const rustsecp256k1_v0_11_ge_storage *a, int flag); /** Rescale a jacobian point by b which must be non-zero. Constant-time. */ -static void rustsecp256k1_v0_10_0_gej_rescale(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_fe *b); +static void rustsecp256k1_v0_11_gej_rescale(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_fe *b); + +/** Convert a group element that is not infinity to a 64-byte array. The output + * array is platform-dependent. */ +static void rustsecp256k1_v0_11_ge_to_bytes(unsigned char *buf, const rustsecp256k1_v0_11_ge *a); + +/** Convert a 64-byte array into group element. This function assumes that the + * provided buffer correctly encodes a group element. */ +static void rustsecp256k1_v0_11_ge_from_bytes(rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_ge_to_bytes_ext(unsigned char *data, const rustsecp256k1_v0_11_ge *ge); + +/** Convert a 64-byte array into a group element. This function assumes that the + * provided buffer is the output of rustsecp256k1_v0_11_ge_to_bytes_ext. */ +static void rustsecp256k1_v0_11_ge_from_bytes_ext(rustsecp256k1_v0_11_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. * @@ -183,14 +199,14 @@ static void rustsecp256k1_v0_10_0_gej_rescale(rustsecp256k1_v0_10_0_gej *r, cons * (very) small subgroup, and that subgroup is what is used for all cryptographic operations. In that mode, this * function checks whether a point that is on the curve is in fact also in that subgroup. */ -static int rustsecp256k1_v0_10_0_ge_is_in_correct_subgroup(const rustsecp256k1_v0_10_0_ge* ge); +static int rustsecp256k1_v0_11_ge_is_in_correct_subgroup(const rustsecp256k1_v0_11_ge* ge); /** Check invariants on an affine group element (no-op unless VERIFY is enabled). */ -static void rustsecp256k1_v0_10_0_ge_verify(const rustsecp256k1_v0_10_0_ge *a); -#define SECP256K1_GE_VERIFY(a) rustsecp256k1_v0_10_0_ge_verify(a) +static void rustsecp256k1_v0_11_ge_verify(const rustsecp256k1_v0_11_ge *a); +#define SECP256K1_GE_VERIFY(a) rustsecp256k1_v0_11_ge_verify(a) /** Check invariants on a Jacobian group element (no-op unless VERIFY is enabled). */ -static void rustsecp256k1_v0_10_0_gej_verify(const rustsecp256k1_v0_10_0_gej *a); -#define SECP256K1_GEJ_VERIFY(a) rustsecp256k1_v0_10_0_gej_verify(a) +static void rustsecp256k1_v0_11_gej_verify(const rustsecp256k1_v0_11_gej *a); +#define SECP256K1_GEJ_VERIFY(a) rustsecp256k1_v0_11_gej_verify(a) #endif /* SECP256K1_GROUP_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/group_impl.h b/secp256k1-sys/depend/secp256k1/src/group_impl.h index 8c40e77d1..765bf595c 100644 --- a/secp256k1-sys/depend/secp256k1/src/group_impl.h +++ b/secp256k1-sys/depend/secp256k1/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" @@ -49,17 +51,17 @@ #if defined(EXHAUSTIVE_TEST_ORDER) # if EXHAUSTIVE_TEST_ORDER == 7 -static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256K1_G_ORDER_7; +static const rustsecp256k1_v0_11_ge rustsecp256k1_v0_11_ge_const_g = SECP256K1_G_ORDER_7; #define SECP256K1_B 6 # elif EXHAUSTIVE_TEST_ORDER == 13 -static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256K1_G_ORDER_13; +static const rustsecp256k1_v0_11_ge rustsecp256k1_v0_11_ge_const_g = SECP256K1_G_ORDER_13; #define SECP256K1_B 2 # elif EXHAUSTIVE_TEST_ORDER == 199 -static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256K1_G_ORDER_199; +static const rustsecp256k1_v0_11_ge rustsecp256k1_v0_11_ge_const_g = SECP256K1_G_ORDER_199; #define SECP256K1_B 4 # else @@ -67,13 +69,13 @@ static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256 # endif #else -static const rustsecp256k1_v0_10_0_ge rustsecp256k1_v0_10_0_ge_const_g = SECP256K1_G; +static const rustsecp256k1_v0_11_ge rustsecp256k1_v0_11_ge_const_g = SECP256K1_G; #define SECP256K1_B 7 #endif /* End of section generated by sage/gen_exhaustive_groups.sage. */ -static void rustsecp256k1_v0_10_0_ge_verify(const rustsecp256k1_v0_10_0_ge *a) { +static void rustsecp256k1_v0_11_ge_verify(const rustsecp256k1_v0_11_ge *a) { SECP256K1_FE_VERIFY(&a->x); SECP256K1_FE_VERIFY(&a->y); SECP256K1_FE_VERIFY_MAGNITUDE(&a->x, SECP256K1_GE_X_MAGNITUDE_MAX); @@ -82,7 +84,7 @@ static void rustsecp256k1_v0_10_0_ge_verify(const rustsecp256k1_v0_10_0_ge *a) { (void)a; } -static void rustsecp256k1_v0_10_0_gej_verify(const rustsecp256k1_v0_10_0_gej *a) { +static void rustsecp256k1_v0_11_gej_verify(const rustsecp256k1_v0_11_gej *a) { SECP256K1_FE_VERIFY(&a->x); SECP256K1_FE_VERIFY(&a->y); SECP256K1_FE_VERIFY(&a->z); @@ -94,40 +96,40 @@ static void rustsecp256k1_v0_10_0_gej_verify(const rustsecp256k1_v0_10_0_gej *a) } /* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ -static void rustsecp256k1_v0_10_0_ge_set_gej_zinv(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_fe *zi) { - rustsecp256k1_v0_10_0_fe zi2; - rustsecp256k1_v0_10_0_fe zi3; +static void rustsecp256k1_v0_11_ge_set_gej_zinv(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_fe *zi) { + rustsecp256k1_v0_11_fe zi2; + rustsecp256k1_v0_11_fe zi3; SECP256K1_GEJ_VERIFY(a); SECP256K1_FE_VERIFY(zi); VERIFY_CHECK(!a->infinity); - rustsecp256k1_v0_10_0_fe_sqr(&zi2, zi); - rustsecp256k1_v0_10_0_fe_mul(&zi3, &zi2, zi); - rustsecp256k1_v0_10_0_fe_mul(&r->x, &a->x, &zi2); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &a->y, &zi3); + rustsecp256k1_v0_11_fe_sqr(&zi2, zi); + rustsecp256k1_v0_11_fe_mul(&zi3, &zi2, zi); + rustsecp256k1_v0_11_fe_mul(&r->x, &a->x, &zi2); + rustsecp256k1_v0_11_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; SECP256K1_GE_VERIFY(r); } /* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */ -static void rustsecp256k1_v0_10_0_ge_set_ge_zinv(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_fe *zi) { - rustsecp256k1_v0_10_0_fe zi2; - rustsecp256k1_v0_10_0_fe zi3; +static void rustsecp256k1_v0_11_ge_set_ge_zinv(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_fe *zi) { + rustsecp256k1_v0_11_fe zi2; + rustsecp256k1_v0_11_fe zi3; SECP256K1_GE_VERIFY(a); SECP256K1_FE_VERIFY(zi); VERIFY_CHECK(!a->infinity); - rustsecp256k1_v0_10_0_fe_sqr(&zi2, zi); - rustsecp256k1_v0_10_0_fe_mul(&zi3, &zi2, zi); - rustsecp256k1_v0_10_0_fe_mul(&r->x, &a->x, &zi2); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &a->y, &zi3); + rustsecp256k1_v0_11_fe_sqr(&zi2, zi); + rustsecp256k1_v0_11_fe_mul(&zi3, &zi2, zi); + rustsecp256k1_v0_11_fe_mul(&r->x, &a->x, &zi2); + rustsecp256k1_v0_11_fe_mul(&r->y, &a->y, &zi3); r->infinity = a->infinity; SECP256K1_GE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_ge_set_xy(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_fe *x, const rustsecp256k1_v0_10_0_fe *y) { +static void rustsecp256k1_v0_11_ge_set_xy(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_fe *x, const rustsecp256k1_v0_11_fe *y) { SECP256K1_FE_VERIFY(x); SECP256K1_FE_VERIFY(y); @@ -138,33 +140,33 @@ static void rustsecp256k1_v0_10_0_ge_set_xy(rustsecp256k1_v0_10_0_ge *r, const r SECP256K1_GE_VERIFY(r); } -static int rustsecp256k1_v0_10_0_ge_is_infinity(const rustsecp256k1_v0_10_0_ge *a) { +static int rustsecp256k1_v0_11_ge_is_infinity(const rustsecp256k1_v0_11_ge *a) { SECP256K1_GE_VERIFY(a); return a->infinity; } -static void rustsecp256k1_v0_10_0_ge_neg(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *a) { +static void rustsecp256k1_v0_11_ge_neg(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *a) { SECP256K1_GE_VERIFY(a); *r = *a; - rustsecp256k1_v0_10_0_fe_normalize_weak(&r->y); - rustsecp256k1_v0_10_0_fe_negate(&r->y, &r->y, 1); + rustsecp256k1_v0_11_fe_normalize_weak(&r->y); + rustsecp256k1_v0_11_fe_negate(&r->y, &r->y, 1); SECP256K1_GE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_ge_set_gej(rustsecp256k1_v0_10_0_ge *r, rustsecp256k1_v0_10_0_gej *a) { - rustsecp256k1_v0_10_0_fe z2, z3; +static void rustsecp256k1_v0_11_ge_set_gej(rustsecp256k1_v0_11_ge *r, rustsecp256k1_v0_11_gej *a) { + rustsecp256k1_v0_11_fe z2, z3; SECP256K1_GEJ_VERIFY(a); r->infinity = a->infinity; - rustsecp256k1_v0_10_0_fe_inv(&a->z, &a->z); - rustsecp256k1_v0_10_0_fe_sqr(&z2, &a->z); - rustsecp256k1_v0_10_0_fe_mul(&z3, &a->z, &z2); - rustsecp256k1_v0_10_0_fe_mul(&a->x, &a->x, &z2); - rustsecp256k1_v0_10_0_fe_mul(&a->y, &a->y, &z3); - rustsecp256k1_v0_10_0_fe_set_int(&a->z, 1); + rustsecp256k1_v0_11_fe_inv(&a->z, &a->z); + rustsecp256k1_v0_11_fe_sqr(&z2, &a->z); + rustsecp256k1_v0_11_fe_mul(&z3, &a->z, &z2); + rustsecp256k1_v0_11_fe_mul(&a->x, &a->x, &z2); + rustsecp256k1_v0_11_fe_mul(&a->y, &a->y, &z3); + rustsecp256k1_v0_11_fe_set_int(&a->z, 1); r->x = a->x; r->y = a->y; @@ -172,29 +174,29 @@ static void rustsecp256k1_v0_10_0_ge_set_gej(rustsecp256k1_v0_10_0_ge *r, rustse SECP256K1_GE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_ge_set_gej_var(rustsecp256k1_v0_10_0_ge *r, rustsecp256k1_v0_10_0_gej *a) { - rustsecp256k1_v0_10_0_fe z2, z3; +static void rustsecp256k1_v0_11_ge_set_gej_var(rustsecp256k1_v0_11_ge *r, rustsecp256k1_v0_11_gej *a) { + rustsecp256k1_v0_11_fe z2, z3; SECP256K1_GEJ_VERIFY(a); - if (rustsecp256k1_v0_10_0_gej_is_infinity(a)) { - rustsecp256k1_v0_10_0_ge_set_infinity(r); + if (rustsecp256k1_v0_11_gej_is_infinity(a)) { + rustsecp256k1_v0_11_ge_set_infinity(r); return; } r->infinity = 0; - rustsecp256k1_v0_10_0_fe_inv_var(&a->z, &a->z); - rustsecp256k1_v0_10_0_fe_sqr(&z2, &a->z); - rustsecp256k1_v0_10_0_fe_mul(&z3, &a->z, &z2); - rustsecp256k1_v0_10_0_fe_mul(&a->x, &a->x, &z2); - rustsecp256k1_v0_10_0_fe_mul(&a->y, &a->y, &z3); - rustsecp256k1_v0_10_0_fe_set_int(&a->z, 1); - rustsecp256k1_v0_10_0_ge_set_xy(r, &a->x, &a->y); + rustsecp256k1_v0_11_fe_inv_var(&a->z, &a->z); + rustsecp256k1_v0_11_fe_sqr(&z2, &a->z); + rustsecp256k1_v0_11_fe_mul(&z3, &a->z, &z2); + rustsecp256k1_v0_11_fe_mul(&a->x, &a->x, &z2); + rustsecp256k1_v0_11_fe_mul(&a->y, &a->y, &z3); + rustsecp256k1_v0_11_fe_set_int(&a->z, 1); + rustsecp256k1_v0_11_ge_set_xy(r, &a->x, &a->y); SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_gej *a, size_t len) { - rustsecp256k1_v0_10_0_fe u; +static void rustsecp256k1_v0_11_ge_set_all_gej_var(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_gej *a, size_t len) { + rustsecp256k1_v0_11_fe u; size_t i; size_t last_i = SIZE_MAX; #ifdef VERIFY @@ -205,13 +207,13 @@ static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r for (i = 0; i < len; i++) { if (a[i].infinity) { - rustsecp256k1_v0_10_0_ge_set_infinity(&r[i]); + rustsecp256k1_v0_11_ge_set_infinity(&r[i]); } else { /* Use destination's x coordinates as scratch space */ if (last_i == SIZE_MAX) { r[i].x = a[i].z; } else { - rustsecp256k1_v0_10_0_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); + rustsecp256k1_v0_11_fe_mul(&r[i].x, &r[last_i].x, &a[i].z); } last_i = i; } @@ -219,14 +221,14 @@ static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r if (last_i == SIZE_MAX) { return; } - rustsecp256k1_v0_10_0_fe_inv_var(&u, &r[last_i].x); + rustsecp256k1_v0_11_fe_inv_var(&u, &r[last_i].x); i = last_i; while (i > 0) { i--; if (!a[i].infinity) { - rustsecp256k1_v0_10_0_fe_mul(&r[last_i].x, &r[i].x, &u); - rustsecp256k1_v0_10_0_fe_mul(&u, &u, &a[last_i].z); + rustsecp256k1_v0_11_fe_mul(&r[last_i].x, &r[i].x, &u); + rustsecp256k1_v0_11_fe_mul(&u, &u, &a[last_i].z); last_i = i; } } @@ -235,7 +237,7 @@ static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r for (i = 0; i < len; i++) { if (!a[i].infinity) { - rustsecp256k1_v0_10_0_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); + rustsecp256k1_v0_11_ge_set_gej_zinv(&r[i], &a[i], &r[i].x); } } @@ -246,9 +248,9 @@ static void rustsecp256k1_v0_10_0_ge_set_all_gej_var(rustsecp256k1_v0_10_0_ge *r #endif } -static void rustsecp256k1_v0_10_0_ge_table_set_globalz(size_t len, rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_fe *zr) { +static void rustsecp256k1_v0_11_ge_table_set_globalz(size_t len, rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_fe *zr) { size_t i; - rustsecp256k1_v0_10_0_fe zs; + rustsecp256k1_v0_11_fe zs; #ifdef VERIFY for (i = 0; i < len; i++) { SECP256K1_GE_VERIFY(&a[i]); @@ -259,16 +261,16 @@ static void rustsecp256k1_v0_10_0_ge_table_set_globalz(size_t len, rustsecp256k1 if (len > 0) { i = len - 1; /* Ensure all y values are in weak normal form for fast negation of points */ - rustsecp256k1_v0_10_0_fe_normalize_weak(&a[i].y); + rustsecp256k1_v0_11_fe_normalize_weak(&a[i].y); zs = zr[i]; /* Work our way backwards, using the z-ratios to scale the x/y values. */ while (i > 0) { if (i != len - 1) { - rustsecp256k1_v0_10_0_fe_mul(&zs, &zs, &zr[i]); + rustsecp256k1_v0_11_fe_mul(&zs, &zs, &zr[i]); } i--; - rustsecp256k1_v0_10_0_ge_set_ge_zinv(&a[i], &a[i], &zs); + rustsecp256k1_v0_11_ge_set_ge_zinv(&a[i], &a[i], &zs); } } @@ -279,93 +281,84 @@ static void rustsecp256k1_v0_10_0_ge_table_set_globalz(size_t len, rustsecp256k1 #endif } -static void rustsecp256k1_v0_10_0_gej_set_infinity(rustsecp256k1_v0_10_0_gej *r) { +static void rustsecp256k1_v0_11_gej_set_infinity(rustsecp256k1_v0_11_gej *r) { r->infinity = 1; - rustsecp256k1_v0_10_0_fe_clear(&r->x); - rustsecp256k1_v0_10_0_fe_clear(&r->y); - rustsecp256k1_v0_10_0_fe_clear(&r->z); + rustsecp256k1_v0_11_fe_set_int(&r->x, 0); + rustsecp256k1_v0_11_fe_set_int(&r->y, 0); + rustsecp256k1_v0_11_fe_set_int(&r->z, 0); SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_ge_set_infinity(rustsecp256k1_v0_10_0_ge *r) { +static void rustsecp256k1_v0_11_ge_set_infinity(rustsecp256k1_v0_11_ge *r) { r->infinity = 1; - rustsecp256k1_v0_10_0_fe_clear(&r->x); - rustsecp256k1_v0_10_0_fe_clear(&r->y); + rustsecp256k1_v0_11_fe_set_int(&r->x, 0); + rustsecp256k1_v0_11_fe_set_int(&r->y, 0); SECP256K1_GE_VERIFY(r); } -static void rustsecp256k1_v0_10_0_gej_clear(rustsecp256k1_v0_10_0_gej *r) { - r->infinity = 0; - rustsecp256k1_v0_10_0_fe_clear(&r->x); - rustsecp256k1_v0_10_0_fe_clear(&r->y); - rustsecp256k1_v0_10_0_fe_clear(&r->z); - - SECP256K1_GEJ_VERIFY(r); +static void rustsecp256k1_v0_11_gej_clear(rustsecp256k1_v0_11_gej *r) { + rustsecp256k1_v0_11_memclear(r, sizeof(rustsecp256k1_v0_11_gej)); } -static void rustsecp256k1_v0_10_0_ge_clear(rustsecp256k1_v0_10_0_ge *r) { - r->infinity = 0; - rustsecp256k1_v0_10_0_fe_clear(&r->x); - rustsecp256k1_v0_10_0_fe_clear(&r->y); - - SECP256K1_GE_VERIFY(r); +static void rustsecp256k1_v0_11_ge_clear(rustsecp256k1_v0_11_ge *r) { + rustsecp256k1_v0_11_memclear(r, sizeof(rustsecp256k1_v0_11_ge)); } -static int rustsecp256k1_v0_10_0_ge_set_xo_var(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_fe *x, int odd) { - rustsecp256k1_v0_10_0_fe x2, x3; +static int rustsecp256k1_v0_11_ge_set_xo_var(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_fe *x, int odd) { + rustsecp256k1_v0_11_fe x2, x3; int ret; SECP256K1_FE_VERIFY(x); r->x = *x; - rustsecp256k1_v0_10_0_fe_sqr(&x2, x); - rustsecp256k1_v0_10_0_fe_mul(&x3, x, &x2); + rustsecp256k1_v0_11_fe_sqr(&x2, x); + rustsecp256k1_v0_11_fe_mul(&x3, x, &x2); r->infinity = 0; - rustsecp256k1_v0_10_0_fe_add_int(&x3, SECP256K1_B); - ret = rustsecp256k1_v0_10_0_fe_sqrt(&r->y, &x3); - rustsecp256k1_v0_10_0_fe_normalize_var(&r->y); - if (rustsecp256k1_v0_10_0_fe_is_odd(&r->y) != odd) { - rustsecp256k1_v0_10_0_fe_negate(&r->y, &r->y, 1); + rustsecp256k1_v0_11_fe_add_int(&x3, SECP256K1_B); + ret = rustsecp256k1_v0_11_fe_sqrt(&r->y, &x3); + rustsecp256k1_v0_11_fe_normalize_var(&r->y); + if (rustsecp256k1_v0_11_fe_is_odd(&r->y) != odd) { + rustsecp256k1_v0_11_fe_negate(&r->y, &r->y, 1); } SECP256K1_GE_VERIFY(r); return ret; } -static void rustsecp256k1_v0_10_0_gej_set_ge(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_ge *a) { +static void rustsecp256k1_v0_11_gej_set_ge(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_ge *a) { SECP256K1_GE_VERIFY(a); r->infinity = a->infinity; r->x = a->x; r->y = a->y; - rustsecp256k1_v0_10_0_fe_set_int(&r->z, 1); + rustsecp256k1_v0_11_fe_set_int(&r->z, 1); SECP256K1_GEJ_VERIFY(r); } -static int rustsecp256k1_v0_10_0_gej_eq_var(const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_gej *b) { - rustsecp256k1_v0_10_0_gej tmp; +static int rustsecp256k1_v0_11_gej_eq_var(const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_gej *b) { + rustsecp256k1_v0_11_gej tmp; SECP256K1_GEJ_VERIFY(b); SECP256K1_GEJ_VERIFY(a); - rustsecp256k1_v0_10_0_gej_neg(&tmp, a); - rustsecp256k1_v0_10_0_gej_add_var(&tmp, &tmp, b, NULL); - return rustsecp256k1_v0_10_0_gej_is_infinity(&tmp); + rustsecp256k1_v0_11_gej_neg(&tmp, a); + rustsecp256k1_v0_11_gej_add_var(&tmp, &tmp, b, NULL); + return rustsecp256k1_v0_11_gej_is_infinity(&tmp); } -static int rustsecp256k1_v0_10_0_gej_eq_ge_var(const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b) { - rustsecp256k1_v0_10_0_gej tmp; +static int rustsecp256k1_v0_11_gej_eq_ge_var(const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b) { + rustsecp256k1_v0_11_gej tmp; SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b); - rustsecp256k1_v0_10_0_gej_neg(&tmp, a); - rustsecp256k1_v0_10_0_gej_add_ge_var(&tmp, &tmp, b, NULL); - return rustsecp256k1_v0_10_0_gej_is_infinity(&tmp); + rustsecp256k1_v0_11_gej_neg(&tmp, a); + rustsecp256k1_v0_11_gej_add_ge_var(&tmp, &tmp, b, NULL); + return rustsecp256k1_v0_11_gej_is_infinity(&tmp); } -static int rustsecp256k1_v0_10_0_ge_eq_var(const rustsecp256k1_v0_10_0_ge *a, const rustsecp256k1_v0_10_0_ge *b) { - rustsecp256k1_v0_10_0_fe tmp; +static int rustsecp256k1_v0_11_ge_eq_var(const rustsecp256k1_v0_11_ge *a, const rustsecp256k1_v0_11_ge *b) { + rustsecp256k1_v0_11_fe tmp; SECP256K1_GE_VERIFY(a); SECP256K1_GE_VERIFY(b); @@ -373,62 +366,62 @@ static int rustsecp256k1_v0_10_0_ge_eq_var(const rustsecp256k1_v0_10_0_ge *a, co if (a->infinity) return 1; tmp = a->x; - rustsecp256k1_v0_10_0_fe_normalize_weak(&tmp); - if (!rustsecp256k1_v0_10_0_fe_equal(&tmp, &b->x)) return 0; + rustsecp256k1_v0_11_fe_normalize_weak(&tmp); + if (!rustsecp256k1_v0_11_fe_equal(&tmp, &b->x)) return 0; tmp = a->y; - rustsecp256k1_v0_10_0_fe_normalize_weak(&tmp); - if (!rustsecp256k1_v0_10_0_fe_equal(&tmp, &b->y)) return 0; + rustsecp256k1_v0_11_fe_normalize_weak(&tmp); + if (!rustsecp256k1_v0_11_fe_equal(&tmp, &b->y)) return 0; return 1; } -static int rustsecp256k1_v0_10_0_gej_eq_x_var(const rustsecp256k1_v0_10_0_fe *x, const rustsecp256k1_v0_10_0_gej *a) { - rustsecp256k1_v0_10_0_fe r; +static int rustsecp256k1_v0_11_gej_eq_x_var(const rustsecp256k1_v0_11_fe *x, const rustsecp256k1_v0_11_gej *a) { + rustsecp256k1_v0_11_fe r; SECP256K1_FE_VERIFY(x); SECP256K1_GEJ_VERIFY(a); VERIFY_CHECK(!a->infinity); - rustsecp256k1_v0_10_0_fe_sqr(&r, &a->z); rustsecp256k1_v0_10_0_fe_mul(&r, &r, x); - return rustsecp256k1_v0_10_0_fe_equal(&r, &a->x); + rustsecp256k1_v0_11_fe_sqr(&r, &a->z); rustsecp256k1_v0_11_fe_mul(&r, &r, x); + return rustsecp256k1_v0_11_fe_equal(&r, &a->x); } -static void rustsecp256k1_v0_10_0_gej_neg(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a) { +static void rustsecp256k1_v0_11_gej_neg(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a) { SECP256K1_GEJ_VERIFY(a); r->infinity = a->infinity; r->x = a->x; r->y = a->y; r->z = a->z; - rustsecp256k1_v0_10_0_fe_normalize_weak(&r->y); - rustsecp256k1_v0_10_0_fe_negate(&r->y, &r->y, 1); + rustsecp256k1_v0_11_fe_normalize_weak(&r->y); + rustsecp256k1_v0_11_fe_negate(&r->y, &r->y, 1); SECP256K1_GEJ_VERIFY(r); } -static int rustsecp256k1_v0_10_0_gej_is_infinity(const rustsecp256k1_v0_10_0_gej *a) { +static int rustsecp256k1_v0_11_gej_is_infinity(const rustsecp256k1_v0_11_gej *a) { SECP256K1_GEJ_VERIFY(a); return a->infinity; } -static int rustsecp256k1_v0_10_0_ge_is_valid_var(const rustsecp256k1_v0_10_0_ge *a) { - rustsecp256k1_v0_10_0_fe y2, x3; +static int rustsecp256k1_v0_11_ge_is_valid_var(const rustsecp256k1_v0_11_ge *a) { + rustsecp256k1_v0_11_fe y2, x3; SECP256K1_GE_VERIFY(a); if (a->infinity) { return 0; } /* y^2 = x^3 + 7 */ - rustsecp256k1_v0_10_0_fe_sqr(&y2, &a->y); - rustsecp256k1_v0_10_0_fe_sqr(&x3, &a->x); rustsecp256k1_v0_10_0_fe_mul(&x3, &x3, &a->x); - rustsecp256k1_v0_10_0_fe_add_int(&x3, SECP256K1_B); - return rustsecp256k1_v0_10_0_fe_equal(&y2, &x3); + rustsecp256k1_v0_11_fe_sqr(&y2, &a->y); + rustsecp256k1_v0_11_fe_sqr(&x3, &a->x); rustsecp256k1_v0_11_fe_mul(&x3, &x3, &a->x); + rustsecp256k1_v0_11_fe_add_int(&x3, SECP256K1_B); + return rustsecp256k1_v0_11_fe_equal(&y2, &x3); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_gej_double(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_gej_double(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a) { /* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */ - rustsecp256k1_v0_10_0_fe l, s, t; + rustsecp256k1_v0_11_fe l, s, t; SECP256K1_GEJ_VERIFY(a); r->infinity = a->infinity; @@ -442,26 +435,26 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_gej_double(rustsecp256k1_v0_1 * Z3 = Y1*Z1 */ - rustsecp256k1_v0_10_0_fe_mul(&r->z, &a->z, &a->y); /* Z3 = Y1*Z1 (1) */ - rustsecp256k1_v0_10_0_fe_sqr(&s, &a->y); /* S = Y1^2 (1) */ - rustsecp256k1_v0_10_0_fe_sqr(&l, &a->x); /* L = X1^2 (1) */ - rustsecp256k1_v0_10_0_fe_mul_int(&l, 3); /* L = 3*X1^2 (3) */ - rustsecp256k1_v0_10_0_fe_half(&l); /* L = 3/2*X1^2 (2) */ - rustsecp256k1_v0_10_0_fe_negate(&t, &s, 1); /* T = -S (2) */ - rustsecp256k1_v0_10_0_fe_mul(&t, &t, &a->x); /* T = -X1*S (1) */ - rustsecp256k1_v0_10_0_fe_sqr(&r->x, &l); /* X3 = L^2 (1) */ - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); /* X3 = L^2 + T (2) */ - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); /* X3 = L^2 + 2*T (3) */ - rustsecp256k1_v0_10_0_fe_sqr(&s, &s); /* S' = S^2 (1) */ - rustsecp256k1_v0_10_0_fe_add(&t, &r->x); /* T' = X3 + T (4) */ - rustsecp256k1_v0_10_0_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */ - rustsecp256k1_v0_10_0_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */ - rustsecp256k1_v0_10_0_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */ + rustsecp256k1_v0_11_fe_mul(&r->z, &a->z, &a->y); /* Z3 = Y1*Z1 (1) */ + rustsecp256k1_v0_11_fe_sqr(&s, &a->y); /* S = Y1^2 (1) */ + rustsecp256k1_v0_11_fe_sqr(&l, &a->x); /* L = X1^2 (1) */ + rustsecp256k1_v0_11_fe_mul_int(&l, 3); /* L = 3*X1^2 (3) */ + rustsecp256k1_v0_11_fe_half(&l); /* L = 3/2*X1^2 (2) */ + rustsecp256k1_v0_11_fe_negate(&t, &s, 1); /* T = -S (2) */ + rustsecp256k1_v0_11_fe_mul(&t, &t, &a->x); /* T = -X1*S (1) */ + rustsecp256k1_v0_11_fe_sqr(&r->x, &l); /* X3 = L^2 (1) */ + rustsecp256k1_v0_11_fe_add(&r->x, &t); /* X3 = L^2 + T (2) */ + rustsecp256k1_v0_11_fe_add(&r->x, &t); /* X3 = L^2 + 2*T (3) */ + rustsecp256k1_v0_11_fe_sqr(&s, &s); /* S' = S^2 (1) */ + rustsecp256k1_v0_11_fe_add(&t, &r->x); /* T' = X3 + T (4) */ + rustsecp256k1_v0_11_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */ + rustsecp256k1_v0_11_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */ + rustsecp256k1_v0_11_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */ SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_gej_double_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, rustsecp256k1_v0_10_0_fe *rzr) { +static void rustsecp256k1_v0_11_gej_double_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, rustsecp256k1_v0_11_fe *rzr) { SECP256K1_GEJ_VERIFY(a); /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, @@ -475,26 +468,26 @@ static void rustsecp256k1_v0_10_0_gej_double_var(rustsecp256k1_v0_10_0_gej *r, c * point will be gibberish (z = 0 but infinity = 0). */ if (a->infinity) { - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); if (rzr != NULL) { - rustsecp256k1_v0_10_0_fe_set_int(rzr, 1); + rustsecp256k1_v0_11_fe_set_int(rzr, 1); } return; } if (rzr != NULL) { *rzr = a->y; - rustsecp256k1_v0_10_0_fe_normalize_weak(rzr); + rustsecp256k1_v0_11_fe_normalize_weak(rzr); } - rustsecp256k1_v0_10_0_gej_double(r, a); + rustsecp256k1_v0_11_gej_double(r, a); SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_gej_add_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_gej *b, rustsecp256k1_v0_10_0_fe *rzr) { +static void rustsecp256k1_v0_11_gej_add_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_gej *b, rustsecp256k1_v0_11_fe *rzr) { /* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ - rustsecp256k1_v0_10_0_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t; + rustsecp256k1_v0_11_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t; SECP256K1_GEJ_VERIFY(a); SECP256K1_GEJ_VERIFY(b); @@ -505,91 +498,91 @@ static void rustsecp256k1_v0_10_0_gej_add_var(rustsecp256k1_v0_10_0_gej *r, cons } if (b->infinity) { if (rzr != NULL) { - rustsecp256k1_v0_10_0_fe_set_int(rzr, 1); + rustsecp256k1_v0_11_fe_set_int(rzr, 1); } *r = *a; return; } - rustsecp256k1_v0_10_0_fe_sqr(&z22, &b->z); - rustsecp256k1_v0_10_0_fe_sqr(&z12, &a->z); - rustsecp256k1_v0_10_0_fe_mul(&u1, &a->x, &z22); - rustsecp256k1_v0_10_0_fe_mul(&u2, &b->x, &z12); - rustsecp256k1_v0_10_0_fe_mul(&s1, &a->y, &z22); rustsecp256k1_v0_10_0_fe_mul(&s1, &s1, &b->z); - rustsecp256k1_v0_10_0_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_10_0_fe_mul(&s2, &s2, &a->z); - rustsecp256k1_v0_10_0_fe_negate(&h, &u1, 1); rustsecp256k1_v0_10_0_fe_add(&h, &u2); - rustsecp256k1_v0_10_0_fe_negate(&i, &s2, 1); rustsecp256k1_v0_10_0_fe_add(&i, &s1); - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&h)) { - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&i)) { - rustsecp256k1_v0_10_0_gej_double_var(r, a, rzr); + rustsecp256k1_v0_11_fe_sqr(&z22, &b->z); + rustsecp256k1_v0_11_fe_sqr(&z12, &a->z); + rustsecp256k1_v0_11_fe_mul(&u1, &a->x, &z22); + rustsecp256k1_v0_11_fe_mul(&u2, &b->x, &z12); + rustsecp256k1_v0_11_fe_mul(&s1, &a->y, &z22); rustsecp256k1_v0_11_fe_mul(&s1, &s1, &b->z); + rustsecp256k1_v0_11_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_11_fe_mul(&s2, &s2, &a->z); + rustsecp256k1_v0_11_fe_negate(&h, &u1, 1); rustsecp256k1_v0_11_fe_add(&h, &u2); + rustsecp256k1_v0_11_fe_negate(&i, &s2, 1); rustsecp256k1_v0_11_fe_add(&i, &s1); + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&h)) { + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&i)) { + rustsecp256k1_v0_11_gej_double_var(r, a, rzr); } else { if (rzr != NULL) { - rustsecp256k1_v0_10_0_fe_set_int(rzr, 0); + rustsecp256k1_v0_11_fe_set_int(rzr, 0); } - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); } return; } r->infinity = 0; - rustsecp256k1_v0_10_0_fe_mul(&t, &h, &b->z); + rustsecp256k1_v0_11_fe_mul(&t, &h, &b->z); if (rzr != NULL) { *rzr = t; } - rustsecp256k1_v0_10_0_fe_mul(&r->z, &a->z, &t); + rustsecp256k1_v0_11_fe_mul(&r->z, &a->z, &t); - rustsecp256k1_v0_10_0_fe_sqr(&h2, &h); - rustsecp256k1_v0_10_0_fe_negate(&h2, &h2, 1); - rustsecp256k1_v0_10_0_fe_mul(&h3, &h2, &h); - rustsecp256k1_v0_10_0_fe_mul(&t, &u1, &h2); + rustsecp256k1_v0_11_fe_sqr(&h2, &h); + rustsecp256k1_v0_11_fe_negate(&h2, &h2, 1); + rustsecp256k1_v0_11_fe_mul(&h3, &h2, &h); + rustsecp256k1_v0_11_fe_mul(&t, &u1, &h2); - rustsecp256k1_v0_10_0_fe_sqr(&r->x, &i); - rustsecp256k1_v0_10_0_fe_add(&r->x, &h3); - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); + rustsecp256k1_v0_11_fe_sqr(&r->x, &i); + rustsecp256k1_v0_11_fe_add(&r->x, &h3); + rustsecp256k1_v0_11_fe_add(&r->x, &t); + rustsecp256k1_v0_11_fe_add(&r->x, &t); - rustsecp256k1_v0_10_0_fe_add(&t, &r->x); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &t, &i); - rustsecp256k1_v0_10_0_fe_mul(&h3, &h3, &s1); - rustsecp256k1_v0_10_0_fe_add(&r->y, &h3); + rustsecp256k1_v0_11_fe_add(&t, &r->x); + rustsecp256k1_v0_11_fe_mul(&r->y, &t, &i); + rustsecp256k1_v0_11_fe_mul(&h3, &h3, &s1); + rustsecp256k1_v0_11_fe_add(&r->y, &h3); SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_gej_add_ge_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b, rustsecp256k1_v0_10_0_fe *rzr) { +static void rustsecp256k1_v0_11_gej_add_ge_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b, rustsecp256k1_v0_11_fe *rzr) { /* Operations: 8 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ - rustsecp256k1_v0_10_0_fe z12, u1, u2, s1, s2, h, i, h2, h3, t; + rustsecp256k1_v0_11_fe z12, u1, u2, s1, s2, h, i, h2, h3, t; SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b); if (a->infinity) { VERIFY_CHECK(rzr == NULL); - rustsecp256k1_v0_10_0_gej_set_ge(r, b); + rustsecp256k1_v0_11_gej_set_ge(r, b); return; } if (b->infinity) { if (rzr != NULL) { - rustsecp256k1_v0_10_0_fe_set_int(rzr, 1); + rustsecp256k1_v0_11_fe_set_int(rzr, 1); } *r = *a; return; } - rustsecp256k1_v0_10_0_fe_sqr(&z12, &a->z); + rustsecp256k1_v0_11_fe_sqr(&z12, &a->z); u1 = a->x; - rustsecp256k1_v0_10_0_fe_mul(&u2, &b->x, &z12); + rustsecp256k1_v0_11_fe_mul(&u2, &b->x, &z12); s1 = a->y; - rustsecp256k1_v0_10_0_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_10_0_fe_mul(&s2, &s2, &a->z); - rustsecp256k1_v0_10_0_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); rustsecp256k1_v0_10_0_fe_add(&h, &u2); - rustsecp256k1_v0_10_0_fe_negate(&i, &s2, 1); rustsecp256k1_v0_10_0_fe_add(&i, &s1); - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&h)) { - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&i)) { - rustsecp256k1_v0_10_0_gej_double_var(r, a, rzr); + rustsecp256k1_v0_11_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_11_fe_mul(&s2, &s2, &a->z); + rustsecp256k1_v0_11_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); rustsecp256k1_v0_11_fe_add(&h, &u2); + rustsecp256k1_v0_11_fe_negate(&i, &s2, 1); rustsecp256k1_v0_11_fe_add(&i, &s1); + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&h)) { + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&i)) { + rustsecp256k1_v0_11_gej_double_var(r, a, rzr); } else { if (rzr != NULL) { - rustsecp256k1_v0_10_0_fe_set_int(rzr, 0); + rustsecp256k1_v0_11_fe_set_int(rzr, 0); } - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); } return; } @@ -598,42 +591,42 @@ static void rustsecp256k1_v0_10_0_gej_add_ge_var(rustsecp256k1_v0_10_0_gej *r, c if (rzr != NULL) { *rzr = h; } - rustsecp256k1_v0_10_0_fe_mul(&r->z, &a->z, &h); + rustsecp256k1_v0_11_fe_mul(&r->z, &a->z, &h); - rustsecp256k1_v0_10_0_fe_sqr(&h2, &h); - rustsecp256k1_v0_10_0_fe_negate(&h2, &h2, 1); - rustsecp256k1_v0_10_0_fe_mul(&h3, &h2, &h); - rustsecp256k1_v0_10_0_fe_mul(&t, &u1, &h2); + rustsecp256k1_v0_11_fe_sqr(&h2, &h); + rustsecp256k1_v0_11_fe_negate(&h2, &h2, 1); + rustsecp256k1_v0_11_fe_mul(&h3, &h2, &h); + rustsecp256k1_v0_11_fe_mul(&t, &u1, &h2); - rustsecp256k1_v0_10_0_fe_sqr(&r->x, &i); - rustsecp256k1_v0_10_0_fe_add(&r->x, &h3); - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); + rustsecp256k1_v0_11_fe_sqr(&r->x, &i); + rustsecp256k1_v0_11_fe_add(&r->x, &h3); + rustsecp256k1_v0_11_fe_add(&r->x, &t); + rustsecp256k1_v0_11_fe_add(&r->x, &t); - rustsecp256k1_v0_10_0_fe_add(&t, &r->x); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &t, &i); - rustsecp256k1_v0_10_0_fe_mul(&h3, &h3, &s1); - rustsecp256k1_v0_10_0_fe_add(&r->y, &h3); + rustsecp256k1_v0_11_fe_add(&t, &r->x); + rustsecp256k1_v0_11_fe_mul(&r->y, &t, &i); + rustsecp256k1_v0_11_fe_mul(&h3, &h3, &s1); + rustsecp256k1_v0_11_fe_add(&r->y, &h3); SECP256K1_GEJ_VERIFY(r); if (rzr != NULL) SECP256K1_FE_VERIFY(rzr); } -static void rustsecp256k1_v0_10_0_gej_add_zinv_var(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b, const rustsecp256k1_v0_10_0_fe *bzinv) { +static void rustsecp256k1_v0_11_gej_add_zinv_var(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b, const rustsecp256k1_v0_11_fe *bzinv) { /* Operations: 9 mul, 3 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */ - rustsecp256k1_v0_10_0_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t; + rustsecp256k1_v0_11_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t; SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b); SECP256K1_FE_VERIFY(bzinv); if (a->infinity) { - rustsecp256k1_v0_10_0_fe bzinv2, bzinv3; + rustsecp256k1_v0_11_fe bzinv2, bzinv3; r->infinity = b->infinity; - rustsecp256k1_v0_10_0_fe_sqr(&bzinv2, bzinv); - rustsecp256k1_v0_10_0_fe_mul(&bzinv3, &bzinv2, bzinv); - rustsecp256k1_v0_10_0_fe_mul(&r->x, &b->x, &bzinv2); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &b->y, &bzinv3); - rustsecp256k1_v0_10_0_fe_set_int(&r->z, 1); + rustsecp256k1_v0_11_fe_sqr(&bzinv2, bzinv); + rustsecp256k1_v0_11_fe_mul(&bzinv3, &bzinv2, bzinv); + rustsecp256k1_v0_11_fe_mul(&r->x, &b->x, &bzinv2); + rustsecp256k1_v0_11_fe_mul(&r->y, &b->y, &bzinv3); + rustsecp256k1_v0_11_fe_set_int(&r->z, 1); SECP256K1_GEJ_VERIFY(r); return; } @@ -650,50 +643,50 @@ static void rustsecp256k1_v0_10_0_gej_add_zinv_var(rustsecp256k1_v0_10_0_gej *r, * The variable az below holds the modified Z coordinate for a, which is used * for the computation of rx and ry, but not for rz. */ - rustsecp256k1_v0_10_0_fe_mul(&az, &a->z, bzinv); + rustsecp256k1_v0_11_fe_mul(&az, &a->z, bzinv); - rustsecp256k1_v0_10_0_fe_sqr(&z12, &az); + rustsecp256k1_v0_11_fe_sqr(&z12, &az); u1 = a->x; - rustsecp256k1_v0_10_0_fe_mul(&u2, &b->x, &z12); + rustsecp256k1_v0_11_fe_mul(&u2, &b->x, &z12); s1 = a->y; - rustsecp256k1_v0_10_0_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_10_0_fe_mul(&s2, &s2, &az); - rustsecp256k1_v0_10_0_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); rustsecp256k1_v0_10_0_fe_add(&h, &u2); - rustsecp256k1_v0_10_0_fe_negate(&i, &s2, 1); rustsecp256k1_v0_10_0_fe_add(&i, &s1); - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&h)) { - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&i)) { - rustsecp256k1_v0_10_0_gej_double_var(r, a, NULL); + rustsecp256k1_v0_11_fe_mul(&s2, &b->y, &z12); rustsecp256k1_v0_11_fe_mul(&s2, &s2, &az); + rustsecp256k1_v0_11_fe_negate(&h, &u1, SECP256K1_GEJ_X_MAGNITUDE_MAX); rustsecp256k1_v0_11_fe_add(&h, &u2); + rustsecp256k1_v0_11_fe_negate(&i, &s2, 1); rustsecp256k1_v0_11_fe_add(&i, &s1); + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&h)) { + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&i)) { + rustsecp256k1_v0_11_gej_double_var(r, a, NULL); } else { - rustsecp256k1_v0_10_0_gej_set_infinity(r); + rustsecp256k1_v0_11_gej_set_infinity(r); } return; } r->infinity = 0; - rustsecp256k1_v0_10_0_fe_mul(&r->z, &a->z, &h); + rustsecp256k1_v0_11_fe_mul(&r->z, &a->z, &h); - rustsecp256k1_v0_10_0_fe_sqr(&h2, &h); - rustsecp256k1_v0_10_0_fe_negate(&h2, &h2, 1); - rustsecp256k1_v0_10_0_fe_mul(&h3, &h2, &h); - rustsecp256k1_v0_10_0_fe_mul(&t, &u1, &h2); + rustsecp256k1_v0_11_fe_sqr(&h2, &h); + rustsecp256k1_v0_11_fe_negate(&h2, &h2, 1); + rustsecp256k1_v0_11_fe_mul(&h3, &h2, &h); + rustsecp256k1_v0_11_fe_mul(&t, &u1, &h2); - rustsecp256k1_v0_10_0_fe_sqr(&r->x, &i); - rustsecp256k1_v0_10_0_fe_add(&r->x, &h3); - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); - rustsecp256k1_v0_10_0_fe_add(&r->x, &t); + rustsecp256k1_v0_11_fe_sqr(&r->x, &i); + rustsecp256k1_v0_11_fe_add(&r->x, &h3); + rustsecp256k1_v0_11_fe_add(&r->x, &t); + rustsecp256k1_v0_11_fe_add(&r->x, &t); - rustsecp256k1_v0_10_0_fe_add(&t, &r->x); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &t, &i); - rustsecp256k1_v0_10_0_fe_mul(&h3, &h3, &s1); - rustsecp256k1_v0_10_0_fe_add(&r->y, &h3); + rustsecp256k1_v0_11_fe_add(&t, &r->x); + rustsecp256k1_v0_11_fe_mul(&r->y, &t, &i); + rustsecp256k1_v0_11_fe_mul(&h3, &h3, &s1); + rustsecp256k1_v0_11_fe_add(&r->y, &h3); SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_gej_add_ge(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_ge *b) { +static void rustsecp256k1_v0_11_gej_add_ge(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_ge *b) { /* Operations: 7 mul, 5 sqr, 21 add/cmov/half/mul_int/negate/normalizes_to_zero */ - rustsecp256k1_v0_10_0_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; - rustsecp256k1_v0_10_0_fe m_alt, rr_alt; + rustsecp256k1_v0_11_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; + rustsecp256k1_v0_11_fe m_alt, rr_alt; int degenerate; SECP256K1_GEJ_VERIFY(a); SECP256K1_GE_VERIFY(b); @@ -749,62 +742,62 @@ static void rustsecp256k1_v0_10_0_gej_add_ge(rustsecp256k1_v0_10_0_gej *r, const * so this covers everything. */ - rustsecp256k1_v0_10_0_fe_sqr(&zz, &a->z); /* z = Z1^2 */ + rustsecp256k1_v0_11_fe_sqr(&zz, &a->z); /* z = Z1^2 */ u1 = a->x; /* u1 = U1 = X1*Z2^2 (GEJ_X_M) */ - rustsecp256k1_v0_10_0_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ + rustsecp256k1_v0_11_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ s1 = a->y; /* s1 = S1 = Y1*Z2^3 (GEJ_Y_M) */ - rustsecp256k1_v0_10_0_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ - rustsecp256k1_v0_10_0_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ - t = u1; rustsecp256k1_v0_10_0_fe_add(&t, &u2); /* t = T = U1+U2 (GEJ_X_M+1) */ - m = s1; rustsecp256k1_v0_10_0_fe_add(&m, &s2); /* m = M = S1+S2 (GEJ_Y_M+1) */ - rustsecp256k1_v0_10_0_fe_sqr(&rr, &t); /* rr = T^2 (1) */ - rustsecp256k1_v0_10_0_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 (2) */ - rustsecp256k1_v0_10_0_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (1) */ - rustsecp256k1_v0_10_0_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (2) */ + rustsecp256k1_v0_11_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ + rustsecp256k1_v0_11_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ + t = u1; rustsecp256k1_v0_11_fe_add(&t, &u2); /* t = T = U1+U2 (GEJ_X_M+1) */ + m = s1; rustsecp256k1_v0_11_fe_add(&m, &s2); /* m = M = S1+S2 (GEJ_Y_M+1) */ + rustsecp256k1_v0_11_fe_sqr(&rr, &t); /* rr = T^2 (1) */ + rustsecp256k1_v0_11_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 (2) */ + rustsecp256k1_v0_11_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (1) */ + rustsecp256k1_v0_11_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (2) */ /* If lambda = R/M = R/0 we have a problem (except in the "trivial" * case that Z = z1z2 = 0, and this is special-cased later on). */ - degenerate = rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&m); + degenerate = rustsecp256k1_v0_11_fe_normalizes_to_zero(&m); /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. * This means either x1 == beta*x2 or beta*x1 == x2, where beta is * a nontrivial cube root of one. In either case, an alternate * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), * so we set R/M equal to this. */ rr_alt = s1; - rustsecp256k1_v0_10_0_fe_mul_int(&rr_alt, 2); /* rr_alt = Y1*Z2^3 - Y2*Z1^3 (GEJ_Y_M*2) */ - rustsecp256k1_v0_10_0_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 (GEJ_X_M+2) */ + rustsecp256k1_v0_11_fe_mul_int(&rr_alt, 2); /* rr_alt = Y1*Z2^3 - Y2*Z1^3 (GEJ_Y_M*2) */ + rustsecp256k1_v0_11_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 (GEJ_X_M+2) */ - rustsecp256k1_v0_10_0_fe_cmov(&rr_alt, &rr, !degenerate); /* rr_alt (GEJ_Y_M*2) */ - rustsecp256k1_v0_10_0_fe_cmov(&m_alt, &m, !degenerate); /* m_alt (GEJ_X_M+2) */ + rustsecp256k1_v0_11_fe_cmov(&rr_alt, &rr, !degenerate); /* rr_alt (GEJ_Y_M*2) */ + rustsecp256k1_v0_11_fe_cmov(&m_alt, &m, !degenerate); /* m_alt (GEJ_X_M+2) */ /* Now Ralt / Malt = lambda and is guaranteed not to be Ralt / 0. * From here on out Ralt and Malt represent the numerator * and denominator of lambda; R and M represent the explicit * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ - rustsecp256k1_v0_10_0_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ - rustsecp256k1_v0_10_0_fe_negate(&q, &t, + rustsecp256k1_v0_11_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ + rustsecp256k1_v0_11_fe_negate(&q, &t, SECP256K1_GEJ_X_MAGNITUDE_MAX + 1); /* q = -T (GEJ_X_M+2) */ - rustsecp256k1_v0_10_0_fe_mul(&q, &q, &n); /* q = Q = -T*Malt^2 (1) */ + rustsecp256k1_v0_11_fe_mul(&q, &q, &n); /* q = Q = -T*Malt^2 (1) */ /* These two lines use the observation that either M == Malt or M == 0, * so M^3 * Malt is either Malt^4 (which is computed by squaring), or * zero (which is "computed" by cmov). So the cost is one squaring * versus two multiplications. */ - rustsecp256k1_v0_10_0_fe_sqr(&n, &n); /* n = Malt^4 (1) */ - rustsecp256k1_v0_10_0_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (GEJ_Y_M+1) */ - rustsecp256k1_v0_10_0_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ - rustsecp256k1_v0_10_0_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */ - rustsecp256k1_v0_10_0_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */ + rustsecp256k1_v0_11_fe_sqr(&n, &n); /* n = Malt^4 (1) */ + rustsecp256k1_v0_11_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (GEJ_Y_M+1) */ + rustsecp256k1_v0_11_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ + rustsecp256k1_v0_11_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Z3 = Malt*Z (1) */ + rustsecp256k1_v0_11_fe_add(&t, &q); /* t = Ralt^2 + Q (2) */ r->x = t; /* r->x = X3 = Ralt^2 + Q (2) */ - rustsecp256k1_v0_10_0_fe_mul_int(&t, 2); /* t = 2*X3 (4) */ - rustsecp256k1_v0_10_0_fe_add(&t, &q); /* t = 2*X3 + Q (5) */ - rustsecp256k1_v0_10_0_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*X3 + Q) (1) */ - rustsecp256k1_v0_10_0_fe_add(&t, &n); /* t = Ralt*(2*X3 + Q) + M^3*Malt (GEJ_Y_M+2) */ - rustsecp256k1_v0_10_0_fe_negate(&r->y, &t, + rustsecp256k1_v0_11_fe_mul_int(&t, 2); /* t = 2*X3 (4) */ + rustsecp256k1_v0_11_fe_add(&t, &q); /* t = 2*X3 + Q (5) */ + rustsecp256k1_v0_11_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*X3 + Q) (1) */ + rustsecp256k1_v0_11_fe_add(&t, &n); /* t = Ralt*(2*X3 + Q) + M^3*Malt (GEJ_Y_M+2) */ + rustsecp256k1_v0_11_fe_negate(&r->y, &t, SECP256K1_GEJ_Y_MAGNITUDE_MAX + 2); /* r->y = -(Ralt*(2*X3 + Q) + M^3*Malt) (GEJ_Y_M+3) */ - rustsecp256k1_v0_10_0_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 ((GEJ_Y_M+3)/2 + 1) */ + rustsecp256k1_v0_11_fe_half(&r->y); /* r->y = Y3 = -(Ralt*(2*X3 + Q) + M^3*Malt)/2 ((GEJ_Y_M+3)/2 + 1) */ /* In case a->infinity == 1, replace r with (b->x, b->y, 1). */ - rustsecp256k1_v0_10_0_fe_cmov(&r->x, &b->x, a->infinity); - rustsecp256k1_v0_10_0_fe_cmov(&r->y, &b->y, a->infinity); - rustsecp256k1_v0_10_0_fe_cmov(&r->z, &rustsecp256k1_v0_10_0_fe_one, a->infinity); + rustsecp256k1_v0_11_fe_cmov(&r->x, &b->x, a->infinity); + rustsecp256k1_v0_11_fe_cmov(&r->y, &b->y, a->infinity); + rustsecp256k1_v0_11_fe_cmov(&r->z, &rustsecp256k1_v0_11_fe_one, a->infinity); /* Set r->infinity if r->z is 0. * @@ -822,89 +815,89 @@ static void rustsecp256k1_v0_10_0_gej_add_ge(rustsecp256k1_v0_10_0_gej *r, const * In this case, we can't have a = -b. * We have degenerate = false, r->z = (y1 + y2) * Z. * Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */ - r->infinity = rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&r->z); + r->infinity = rustsecp256k1_v0_11_fe_normalizes_to_zero(&r->z); SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_gej_rescale(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_fe *s) { +static void rustsecp256k1_v0_11_gej_rescale(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_fe *s) { /* Operations: 4 mul, 1 sqr */ - rustsecp256k1_v0_10_0_fe zz; + rustsecp256k1_v0_11_fe zz; SECP256K1_GEJ_VERIFY(r); SECP256K1_FE_VERIFY(s); - VERIFY_CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(s)); + VERIFY_CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero_var(s)); - rustsecp256k1_v0_10_0_fe_sqr(&zz, s); - rustsecp256k1_v0_10_0_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ - rustsecp256k1_v0_10_0_fe_mul(&r->y, &r->y, &zz); - rustsecp256k1_v0_10_0_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ - rustsecp256k1_v0_10_0_fe_mul(&r->z, &r->z, s); /* r->z *= s */ + rustsecp256k1_v0_11_fe_sqr(&zz, s); + rustsecp256k1_v0_11_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ + rustsecp256k1_v0_11_fe_mul(&r->y, &r->y, &zz); + rustsecp256k1_v0_11_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ + rustsecp256k1_v0_11_fe_mul(&r->z, &r->z, s); /* r->z *= s */ SECP256K1_GEJ_VERIFY(r); } -static void rustsecp256k1_v0_10_0_ge_to_storage(rustsecp256k1_v0_10_0_ge_storage *r, const rustsecp256k1_v0_10_0_ge *a) { - rustsecp256k1_v0_10_0_fe x, y; +static void rustsecp256k1_v0_11_ge_to_storage(rustsecp256k1_v0_11_ge_storage *r, const rustsecp256k1_v0_11_ge *a) { + rustsecp256k1_v0_11_fe x, y; SECP256K1_GE_VERIFY(a); VERIFY_CHECK(!a->infinity); x = a->x; - rustsecp256k1_v0_10_0_fe_normalize(&x); + rustsecp256k1_v0_11_fe_normalize(&x); y = a->y; - rustsecp256k1_v0_10_0_fe_normalize(&y); - rustsecp256k1_v0_10_0_fe_to_storage(&r->x, &x); - rustsecp256k1_v0_10_0_fe_to_storage(&r->y, &y); + rustsecp256k1_v0_11_fe_normalize(&y); + rustsecp256k1_v0_11_fe_to_storage(&r->x, &x); + rustsecp256k1_v0_11_fe_to_storage(&r->y, &y); } -static void rustsecp256k1_v0_10_0_ge_from_storage(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge_storage *a) { - rustsecp256k1_v0_10_0_fe_from_storage(&r->x, &a->x); - rustsecp256k1_v0_10_0_fe_from_storage(&r->y, &a->y); +static void rustsecp256k1_v0_11_ge_from_storage(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge_storage *a) { + rustsecp256k1_v0_11_fe_from_storage(&r->x, &a->x); + rustsecp256k1_v0_11_fe_from_storage(&r->y, &a->y); r->infinity = 0; SECP256K1_GE_VERIFY(r); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_gej_cmov(rustsecp256k1_v0_10_0_gej *r, const rustsecp256k1_v0_10_0_gej *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_gej_cmov(rustsecp256k1_v0_11_gej *r, const rustsecp256k1_v0_11_gej *a, int flag) { SECP256K1_GEJ_VERIFY(r); SECP256K1_GEJ_VERIFY(a); - rustsecp256k1_v0_10_0_fe_cmov(&r->x, &a->x, flag); - rustsecp256k1_v0_10_0_fe_cmov(&r->y, &a->y, flag); - rustsecp256k1_v0_10_0_fe_cmov(&r->z, &a->z, flag); + rustsecp256k1_v0_11_fe_cmov(&r->x, &a->x, flag); + rustsecp256k1_v0_11_fe_cmov(&r->y, &a->y, flag); + rustsecp256k1_v0_11_fe_cmov(&r->z, &a->z, flag); r->infinity ^= (r->infinity ^ a->infinity) & flag; SECP256K1_GEJ_VERIFY(r); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_ge_storage_cmov(rustsecp256k1_v0_10_0_ge_storage *r, const rustsecp256k1_v0_10_0_ge_storage *a, int flag) { - rustsecp256k1_v0_10_0_fe_storage_cmov(&r->x, &a->x, flag); - rustsecp256k1_v0_10_0_fe_storage_cmov(&r->y, &a->y, flag); +static SECP256K1_INLINE void rustsecp256k1_v0_11_ge_storage_cmov(rustsecp256k1_v0_11_ge_storage *r, const rustsecp256k1_v0_11_ge_storage *a, int flag) { + rustsecp256k1_v0_11_fe_storage_cmov(&r->x, &a->x, flag); + rustsecp256k1_v0_11_fe_storage_cmov(&r->y, &a->y, flag); } -static void rustsecp256k1_v0_10_0_ge_mul_lambda(rustsecp256k1_v0_10_0_ge *r, const rustsecp256k1_v0_10_0_ge *a) { +static void rustsecp256k1_v0_11_ge_mul_lambda(rustsecp256k1_v0_11_ge *r, const rustsecp256k1_v0_11_ge *a) { SECP256K1_GE_VERIFY(a); *r = *a; - rustsecp256k1_v0_10_0_fe_mul(&r->x, &r->x, &rustsecp256k1_v0_10_0_const_beta); + rustsecp256k1_v0_11_fe_mul(&r->x, &r->x, &rustsecp256k1_v0_11_const_beta); SECP256K1_GE_VERIFY(r); } -static int rustsecp256k1_v0_10_0_ge_is_in_correct_subgroup(const rustsecp256k1_v0_10_0_ge* ge) { +static int rustsecp256k1_v0_11_ge_is_in_correct_subgroup(const rustsecp256k1_v0_11_ge* ge) { #ifdef EXHAUSTIVE_TEST_ORDER - rustsecp256k1_v0_10_0_gej out; + rustsecp256k1_v0_11_gej out; int i; SECP256K1_GE_VERIFY(ge); /* A very simple EC multiplication ladder that avoids a dependency on ecmult. */ - rustsecp256k1_v0_10_0_gej_set_infinity(&out); + rustsecp256k1_v0_11_gej_set_infinity(&out); for (i = 0; i < 32; ++i) { - rustsecp256k1_v0_10_0_gej_double_var(&out, &out, NULL); + rustsecp256k1_v0_11_gej_double_var(&out, &out, NULL); if ((((uint32_t)EXHAUSTIVE_TEST_ORDER) >> (31 - i)) & 1) { - rustsecp256k1_v0_10_0_gej_add_ge_var(&out, &out, ge, NULL); + rustsecp256k1_v0_11_gej_add_ge_var(&out, &out, ge, NULL); } } - return rustsecp256k1_v0_10_0_gej_is_infinity(&out); + return rustsecp256k1_v0_11_gej_is_infinity(&out); #else SECP256K1_GE_VERIFY(ge); @@ -914,31 +907,68 @@ static int rustsecp256k1_v0_10_0_ge_is_in_correct_subgroup(const rustsecp256k1_v #endif } -static int rustsecp256k1_v0_10_0_ge_x_on_curve_var(const rustsecp256k1_v0_10_0_fe *x) { - rustsecp256k1_v0_10_0_fe c; - rustsecp256k1_v0_10_0_fe_sqr(&c, x); - rustsecp256k1_v0_10_0_fe_mul(&c, &c, x); - rustsecp256k1_v0_10_0_fe_add_int(&c, SECP256K1_B); - return rustsecp256k1_v0_10_0_fe_is_square_var(&c); +static int rustsecp256k1_v0_11_ge_x_on_curve_var(const rustsecp256k1_v0_11_fe *x) { + rustsecp256k1_v0_11_fe c; + rustsecp256k1_v0_11_fe_sqr(&c, x); + rustsecp256k1_v0_11_fe_mul(&c, &c, x); + rustsecp256k1_v0_11_fe_add_int(&c, SECP256K1_B); + return rustsecp256k1_v0_11_fe_is_square_var(&c); } -static int rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(const rustsecp256k1_v0_10_0_fe *xn, const rustsecp256k1_v0_10_0_fe *xd) { +static int rustsecp256k1_v0_11_ge_x_frac_on_curve_var(const rustsecp256k1_v0_11_fe *xn, const rustsecp256k1_v0_11_fe *xd) { /* We want to determine whether (xn/xd) is on the curve. * * (xn/xd)^3 + 7 is square <=> xd*xn^3 + 7*xd^4 is square (multiplying by xd^4, a square). */ - rustsecp256k1_v0_10_0_fe r, t; - VERIFY_CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(xd)); - - rustsecp256k1_v0_10_0_fe_mul(&r, xd, xn); /* r = xd*xn */ - rustsecp256k1_v0_10_0_fe_sqr(&t, xn); /* t = xn^2 */ - rustsecp256k1_v0_10_0_fe_mul(&r, &r, &t); /* r = xd*xn^3 */ - rustsecp256k1_v0_10_0_fe_sqr(&t, xd); /* t = xd^2 */ - rustsecp256k1_v0_10_0_fe_sqr(&t, &t); /* t = xd^4 */ + rustsecp256k1_v0_11_fe r, t; + VERIFY_CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero_var(xd)); + + rustsecp256k1_v0_11_fe_mul(&r, xd, xn); /* r = xd*xn */ + rustsecp256k1_v0_11_fe_sqr(&t, xn); /* t = xn^2 */ + rustsecp256k1_v0_11_fe_mul(&r, &r, &t); /* r = xd*xn^3 */ + rustsecp256k1_v0_11_fe_sqr(&t, xd); /* t = xd^2 */ + rustsecp256k1_v0_11_fe_sqr(&t, &t); /* t = xd^4 */ VERIFY_CHECK(SECP256K1_B <= 31); - rustsecp256k1_v0_10_0_fe_mul_int(&t, SECP256K1_B); /* t = 7*xd^4 */ - rustsecp256k1_v0_10_0_fe_add(&r, &t); /* r = xd*xn^3 + 7*xd^4 */ - return rustsecp256k1_v0_10_0_fe_is_square_var(&r); + rustsecp256k1_v0_11_fe_mul_int(&t, SECP256K1_B); /* t = 7*xd^4 */ + rustsecp256k1_v0_11_fe_add(&r, &t); /* r = xd*xn^3 + 7*xd^4 */ + return rustsecp256k1_v0_11_fe_is_square_var(&r); +} + +static void rustsecp256k1_v0_11_ge_to_bytes(unsigned char *buf, const rustsecp256k1_v0_11_ge *a) { + rustsecp256k1_v0_11_ge_storage s; + + /* We require that the rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_ge_storage) == 64); + VERIFY_CHECK(!rustsecp256k1_v0_11_ge_is_infinity(a)); + rustsecp256k1_v0_11_ge_to_storage(&s, a); + memcpy(buf, &s, 64); +} + +static void rustsecp256k1_v0_11_ge_from_bytes(rustsecp256k1_v0_11_ge *r, const unsigned char *buf) { + rustsecp256k1_v0_11_ge_storage s; + + STATIC_ASSERT(sizeof(rustsecp256k1_v0_11_ge_storage) == 64); + memcpy(&s, buf, 64); + rustsecp256k1_v0_11_ge_from_storage(r, &s); +} + +static void rustsecp256k1_v0_11_ge_to_bytes_ext(unsigned char *data, const rustsecp256k1_v0_11_ge *ge) { + if (rustsecp256k1_v0_11_ge_is_infinity(ge)) { + memset(data, 0, 64); + } else { + rustsecp256k1_v0_11_ge_to_bytes(data, ge); + } +} + +static void rustsecp256k1_v0_11_ge_from_bytes_ext(rustsecp256k1_v0_11_ge *ge, const unsigned char *data) { + static const unsigned char zeros[64] = { 0 }; + if (rustsecp256k1_v0_11_memcmp_var(data, zeros, sizeof(zeros)) == 0) { + rustsecp256k1_v0_11_ge_set_infinity(ge); + } else { + rustsecp256k1_v0_11_ge_from_bytes(ge, data); + } } #endif /* SECP256K1_GROUP_IMPL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/hash.h b/secp256k1-sys/depend/secp256k1/src/hash.h index cdf439eeb..357763aaa 100644 --- a/secp256k1-sys/depend/secp256k1/src/hash.h +++ b/secp256k1-sys/depend/secp256k1/src/hash.h @@ -14,28 +14,31 @@ typedef struct { uint32_t s[8]; unsigned char buf[64]; uint64_t bytes; -} rustsecp256k1_v0_10_0_sha256; +} rustsecp256k1_v0_11_sha256; -static void rustsecp256k1_v0_10_0_sha256_initialize(rustsecp256k1_v0_10_0_sha256 *hash); -static void rustsecp256k1_v0_10_0_sha256_write(rustsecp256k1_v0_10_0_sha256 *hash, const unsigned char *data, size_t size); -static void rustsecp256k1_v0_10_0_sha256_finalize(rustsecp256k1_v0_10_0_sha256 *hash, unsigned char *out32); +static void rustsecp256k1_v0_11_sha256_initialize(rustsecp256k1_v0_11_sha256 *hash); +static void rustsecp256k1_v0_11_sha256_write(rustsecp256k1_v0_11_sha256 *hash, const unsigned char *data, size_t size); +static void rustsecp256k1_v0_11_sha256_finalize(rustsecp256k1_v0_11_sha256 *hash, unsigned char *out32); +static void rustsecp256k1_v0_11_sha256_clear(rustsecp256k1_v0_11_sha256 *hash); typedef struct { - rustsecp256k1_v0_10_0_sha256 inner, outer; -} rustsecp256k1_v0_10_0_hmac_sha256; + rustsecp256k1_v0_11_sha256 inner, outer; +} rustsecp256k1_v0_11_hmac_sha256; -static void rustsecp256k1_v0_10_0_hmac_sha256_initialize(rustsecp256k1_v0_10_0_hmac_sha256 *hash, const unsigned char *key, size_t size); -static void rustsecp256k1_v0_10_0_hmac_sha256_write(rustsecp256k1_v0_10_0_hmac_sha256 *hash, const unsigned char *data, size_t size); -static void rustsecp256k1_v0_10_0_hmac_sha256_finalize(rustsecp256k1_v0_10_0_hmac_sha256 *hash, unsigned char *out32); +static void rustsecp256k1_v0_11_hmac_sha256_initialize(rustsecp256k1_v0_11_hmac_sha256 *hash, const unsigned char *key, size_t size); +static void rustsecp256k1_v0_11_hmac_sha256_write(rustsecp256k1_v0_11_hmac_sha256 *hash, const unsigned char *data, size_t size); +static void rustsecp256k1_v0_11_hmac_sha256_finalize(rustsecp256k1_v0_11_hmac_sha256 *hash, unsigned char *out32); +static void rustsecp256k1_v0_11_hmac_sha256_clear(rustsecp256k1_v0_11_hmac_sha256 *hash); typedef struct { unsigned char v[32]; unsigned char k[32]; int retry; -} rustsecp256k1_v0_10_0_rfc6979_hmac_sha256; +} rustsecp256k1_v0_11_rfc6979_hmac_sha256; -static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); -static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); -static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 *rng); +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen); +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen); +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng); +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_clear(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng); #endif /* SECP256K1_HASH_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/hash_impl.h b/secp256k1-sys/depend/secp256k1/src/hash_impl.h index 8a1000de1..373af72d4 100644 --- a/secp256k1-sys/depend/secp256k1/src/hash_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/hash_impl.h @@ -28,7 +28,7 @@ (h) = t1 + t2; \ } while(0) -static void rustsecp256k1_v0_10_0_sha256_initialize(rustsecp256k1_v0_10_0_sha256 *hash) { +static void rustsecp256k1_v0_11_sha256_initialize(rustsecp256k1_v0_11_sha256 *hash) { hash->s[0] = 0x6a09e667ul; hash->s[1] = 0xbb67ae85ul; hash->s[2] = 0x3c6ef372ul; @@ -41,26 +41,26 @@ static void rustsecp256k1_v0_10_0_sha256_initialize(rustsecp256k1_v0_10_0_sha256 } /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ -static void rustsecp256k1_v0_10_0_sha256_transform(uint32_t* s, const unsigned char* buf) { +static void rustsecp256k1_v0_11_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]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = rustsecp256k1_v0_10_0_read_be32(&buf[0])); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = rustsecp256k1_v0_10_0_read_be32(&buf[4])); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = rustsecp256k1_v0_10_0_read_be32(&buf[8])); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = rustsecp256k1_v0_10_0_read_be32(&buf[12])); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = rustsecp256k1_v0_10_0_read_be32(&buf[16])); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = rustsecp256k1_v0_10_0_read_be32(&buf[20])); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = rustsecp256k1_v0_10_0_read_be32(&buf[24])); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = rustsecp256k1_v0_10_0_read_be32(&buf[28])); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = rustsecp256k1_v0_10_0_read_be32(&buf[32])); - Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = rustsecp256k1_v0_10_0_read_be32(&buf[36])); - Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = rustsecp256k1_v0_10_0_read_be32(&buf[40])); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = rustsecp256k1_v0_10_0_read_be32(&buf[44])); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = rustsecp256k1_v0_10_0_read_be32(&buf[48])); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = rustsecp256k1_v0_10_0_read_be32(&buf[52])); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = rustsecp256k1_v0_10_0_read_be32(&buf[56])); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = rustsecp256k1_v0_10_0_read_be32(&buf[60])); + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = rustsecp256k1_v0_11_read_be32(&buf[0])); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = rustsecp256k1_v0_11_read_be32(&buf[4])); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = rustsecp256k1_v0_11_read_be32(&buf[8])); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = rustsecp256k1_v0_11_read_be32(&buf[12])); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = rustsecp256k1_v0_11_read_be32(&buf[16])); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = rustsecp256k1_v0_11_read_be32(&buf[20])); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = rustsecp256k1_v0_11_read_be32(&buf[24])); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = rustsecp256k1_v0_11_read_be32(&buf[28])); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = rustsecp256k1_v0_11_read_be32(&buf[32])); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = rustsecp256k1_v0_11_read_be32(&buf[36])); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = rustsecp256k1_v0_11_read_be32(&buf[40])); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = rustsecp256k1_v0_11_read_be32(&buf[44])); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = rustsecp256k1_v0_11_read_be32(&buf[48])); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = rustsecp256k1_v0_11_read_be32(&buf[52])); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = rustsecp256k1_v0_11_read_be32(&buf[56])); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = rustsecp256k1_v0_11_read_be32(&buf[60])); Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); @@ -123,7 +123,7 @@ static void rustsecp256k1_v0_10_0_sha256_transform(uint32_t* s, const unsigned c s[7] += h; } -static void rustsecp256k1_v0_10_0_sha256_write(rustsecp256k1_v0_10_0_sha256 *hash, const unsigned char *data, size_t len) { +static void rustsecp256k1_v0_11_sha256_write(rustsecp256k1_v0_11_sha256 *hash, const unsigned char *data, size_t len) { size_t bufsize = hash->bytes & 0x3F; hash->bytes += len; VERIFY_CHECK(hash->bytes >= len); @@ -133,7 +133,7 @@ static void rustsecp256k1_v0_10_0_sha256_write(rustsecp256k1_v0_10_0_sha256 *has memcpy(hash->buf + bufsize, data, chunk_len); data += chunk_len; len -= chunk_len; - rustsecp256k1_v0_10_0_sha256_transform(hash->s, hash->buf); + rustsecp256k1_v0_11_sha256_transform(hash->s, hash->buf); bufsize = 0; } if (len) { @@ -142,78 +142,85 @@ static void rustsecp256k1_v0_10_0_sha256_write(rustsecp256k1_v0_10_0_sha256 *has } } -static void rustsecp256k1_v0_10_0_sha256_finalize(rustsecp256k1_v0_10_0_sha256 *hash, unsigned char *out32) { +static void rustsecp256k1_v0_11_sha256_finalize(rustsecp256k1_v0_11_sha256 *hash, unsigned char *out32) { static const unsigned char pad[64] = {0x80}; unsigned char sizedesc[8]; int i; /* The maximum message size of SHA256 is 2^64-1 bits. */ VERIFY_CHECK(hash->bytes < ((uint64_t)1 << 61)); - rustsecp256k1_v0_10_0_write_be32(&sizedesc[0], hash->bytes >> 29); - rustsecp256k1_v0_10_0_write_be32(&sizedesc[4], hash->bytes << 3); - rustsecp256k1_v0_10_0_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); - rustsecp256k1_v0_10_0_sha256_write(hash, sizedesc, 8); + rustsecp256k1_v0_11_write_be32(&sizedesc[0], hash->bytes >> 29); + rustsecp256k1_v0_11_write_be32(&sizedesc[4], hash->bytes << 3); + rustsecp256k1_v0_11_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); + rustsecp256k1_v0_11_sha256_write(hash, sizedesc, 8); for (i = 0; i < 8; i++) { - rustsecp256k1_v0_10_0_write_be32(&out32[4*i], hash->s[i]); + rustsecp256k1_v0_11_write_be32(&out32[4*i], hash->s[i]); hash->s[i] = 0; } } /* Initializes a sha256 struct and writes the 64 byte string * SHA256(tag)||SHA256(tag) into it. */ -static void rustsecp256k1_v0_10_0_sha256_initialize_tagged(rustsecp256k1_v0_10_0_sha256 *hash, const unsigned char *tag, size_t taglen) { +static void rustsecp256k1_v0_11_sha256_initialize_tagged(rustsecp256k1_v0_11_sha256 *hash, const unsigned char *tag, size_t taglen) { unsigned char buf[32]; - rustsecp256k1_v0_10_0_sha256_initialize(hash); - rustsecp256k1_v0_10_0_sha256_write(hash, tag, taglen); - rustsecp256k1_v0_10_0_sha256_finalize(hash, buf); + rustsecp256k1_v0_11_sha256_initialize(hash); + rustsecp256k1_v0_11_sha256_write(hash, tag, taglen); + rustsecp256k1_v0_11_sha256_finalize(hash, buf); - rustsecp256k1_v0_10_0_sha256_initialize(hash); - rustsecp256k1_v0_10_0_sha256_write(hash, buf, 32); - rustsecp256k1_v0_10_0_sha256_write(hash, buf, 32); + rustsecp256k1_v0_11_sha256_initialize(hash); + rustsecp256k1_v0_11_sha256_write(hash, buf, 32); + rustsecp256k1_v0_11_sha256_write(hash, buf, 32); } -static void rustsecp256k1_v0_10_0_hmac_sha256_initialize(rustsecp256k1_v0_10_0_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { +static void rustsecp256k1_v0_11_sha256_clear(rustsecp256k1_v0_11_sha256 *hash) { + rustsecp256k1_v0_11_memclear(hash, sizeof(*hash)); +} + +static void rustsecp256k1_v0_11_hmac_sha256_initialize(rustsecp256k1_v0_11_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { size_t n; unsigned char rkey[64]; if (keylen <= sizeof(rkey)) { memcpy(rkey, key, keylen); memset(rkey + keylen, 0, sizeof(rkey) - keylen); } else { - rustsecp256k1_v0_10_0_sha256 sha256; - rustsecp256k1_v0_10_0_sha256_initialize(&sha256); - rustsecp256k1_v0_10_0_sha256_write(&sha256, key, keylen); - rustsecp256k1_v0_10_0_sha256_finalize(&sha256, rkey); + rustsecp256k1_v0_11_sha256 sha256; + rustsecp256k1_v0_11_sha256_initialize(&sha256); + rustsecp256k1_v0_11_sha256_write(&sha256, key, keylen); + rustsecp256k1_v0_11_sha256_finalize(&sha256, rkey); memset(rkey + 32, 0, 32); } - rustsecp256k1_v0_10_0_sha256_initialize(&hash->outer); + rustsecp256k1_v0_11_sha256_initialize(&hash->outer); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c; } - rustsecp256k1_v0_10_0_sha256_write(&hash->outer, rkey, sizeof(rkey)); + rustsecp256k1_v0_11_sha256_write(&hash->outer, rkey, sizeof(rkey)); - rustsecp256k1_v0_10_0_sha256_initialize(&hash->inner); + rustsecp256k1_v0_11_sha256_initialize(&hash->inner); for (n = 0; n < sizeof(rkey); n++) { rkey[n] ^= 0x5c ^ 0x36; } - rustsecp256k1_v0_10_0_sha256_write(&hash->inner, rkey, sizeof(rkey)); - memset(rkey, 0, sizeof(rkey)); + rustsecp256k1_v0_11_sha256_write(&hash->inner, rkey, sizeof(rkey)); + rustsecp256k1_v0_11_memclear(rkey, sizeof(rkey)); } -static void rustsecp256k1_v0_10_0_hmac_sha256_write(rustsecp256k1_v0_10_0_hmac_sha256 *hash, const unsigned char *data, size_t size) { - rustsecp256k1_v0_10_0_sha256_write(&hash->inner, data, size); +static void rustsecp256k1_v0_11_hmac_sha256_write(rustsecp256k1_v0_11_hmac_sha256 *hash, const unsigned char *data, size_t size) { + rustsecp256k1_v0_11_sha256_write(&hash->inner, data, size); } -static void rustsecp256k1_v0_10_0_hmac_sha256_finalize(rustsecp256k1_v0_10_0_hmac_sha256 *hash, unsigned char *out32) { +static void rustsecp256k1_v0_11_hmac_sha256_finalize(rustsecp256k1_v0_11_hmac_sha256 *hash, unsigned char *out32) { unsigned char temp[32]; - rustsecp256k1_v0_10_0_sha256_finalize(&hash->inner, temp); - rustsecp256k1_v0_10_0_sha256_write(&hash->outer, temp, 32); - memset(temp, 0, 32); - rustsecp256k1_v0_10_0_sha256_finalize(&hash->outer, out32); + rustsecp256k1_v0_11_sha256_finalize(&hash->inner, temp); + rustsecp256k1_v0_11_sha256_write(&hash->outer, temp, 32); + rustsecp256k1_v0_11_memclear(temp, sizeof(temp)); + rustsecp256k1_v0_11_sha256_finalize(&hash->outer, out32); } +static void rustsecp256k1_v0_11_hmac_sha256_clear(rustsecp256k1_v0_11_hmac_sha256 *hash) { + rustsecp256k1_v0_11_memclear(hash, sizeof(*hash)); +} -static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { - rustsecp256k1_v0_10_0_hmac_sha256 hmac; +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { + rustsecp256k1_v0_11_hmac_sha256 hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -221,47 +228,47 @@ static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(rustsecp256k1_v memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ /* RFC6979 3.2.d. */ - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, zero, 1); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, key, keylen); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->k); - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->v); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, zero, 1); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, key, keylen); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->k); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->v); /* RFC6979 3.2.f. */ - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, one, 1); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, key, keylen); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->k); - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->v); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, one, 1); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, key, keylen); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->k); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->v); rng->retry = 0; } -static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { /* RFC6979 3.2.h. */ static const unsigned char zero[1] = {0x00}; if (rng->retry) { - rustsecp256k1_v0_10_0_hmac_sha256 hmac; - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, zero, 1); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->k); - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->v); + rustsecp256k1_v0_11_hmac_sha256 hmac; + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, zero, 1); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->k); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->v); } while (outlen > 0) { - rustsecp256k1_v0_10_0_hmac_sha256 hmac; + rustsecp256k1_v0_11_hmac_sha256 hmac; int now = outlen; - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hmac, rng->k, 32); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hmac, rng->v, 32); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hmac, rng->v); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hmac, rng->k, 32); + rustsecp256k1_v0_11_hmac_sha256_write(&hmac, rng->v, 32); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hmac, rng->v); if (now > 32) { now = 32; } @@ -273,10 +280,12 @@ static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(rustsecp256k1_v0_ rng->retry = 1; } -static void rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 *rng) { - memset(rng->k, 0, 32); - memset(rng->v, 0, 32); - rng->retry = 0; +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng) { + (void) rng; +} + +static void rustsecp256k1_v0_11_rfc6979_hmac_sha256_clear(rustsecp256k1_v0_11_rfc6979_hmac_sha256 *rng) { + rustsecp256k1_v0_11_memclear(rng, sizeof(*rng)); } #undef Round diff --git a/secp256k1-sys/depend/secp256k1/src/hsort.h b/secp256k1-sys/depend/secp256k1/src/hsort.h new file mode 100644 index 000000000..8c8660ff5 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_hsort(void *ptr, size_t count, size_t size, + int (*cmp)(const void *, const void *, void *), + void *cmp_data); +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/hsort_impl.h b/secp256k1-sys/depend/secp256k1/src/hsort_impl.h new file mode 100644 index 000000000..310ec1972 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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 rustsecp256k1_v0_11_heap_child1(size_t i) { + VERIFY_CHECK(i <= (SIZE_MAX - 1)/2); + return 2*i + 1; +} + +static SECP256K1_INLINE size_t rustsecp256k1_v0_11_heap_child2(size_t i) { + VERIFY_CHECK(i <= SIZE_MAX/2 - 1); + return rustsecp256k1_v0_11_heap_child1(i)+1; +} + +static SECP256K1_INLINE void rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_heap_swap64(a + (len - 64), b + (len - 64), 64); + len -= 64; + } + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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 (rustsecp256k1_v0_11_heap_child2(i) < heap_size + && 0 <= cmp(arr + rustsecp256k1_v0_11_heap_child2(i)*stride, arr + rustsecp256k1_v0_11_heap_child1(i)*stride, cmp_data)) { + if (0 < cmp(arr + rustsecp256k1_v0_11_heap_child2(i)*stride, arr + i*stride, cmp_data)) { + rustsecp256k1_v0_11_heap_swap(arr, i, rustsecp256k1_v0_11_heap_child2(i), stride); + i = rustsecp256k1_v0_11_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 + rustsecp256k1_v0_11_heap_child1(i)*stride, arr + i*stride, cmp_data)) { + rustsecp256k1_v0_11_heap_swap(arr, i, rustsecp256k1_v0_11_heap_child1(i), stride); + i = rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_heap_down(ptr, i-1, count, size, cmp, cmp_data); + } + for (i = count; 1 < i; --i) { + /* Extract the largest value from the heap */ + rustsecp256k1_v0_11_heap_swap(ptr, 0, i-1, size); + + /* Repair the heap condition */ + rustsecp256k1_v0_11_heap_down(ptr, 0, i-1, size, cmp, cmp_data); + } +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/int128.h b/secp256k1-sys/depend/secp256k1/src/int128.h index fbdafa79d..85d557291 100644 --- a/secp256k1-sys/depend/secp256k1/src/int128.h +++ b/secp256k1-sys/depend/secp256k1/src/int128.h @@ -13,77 +13,77 @@ # endif /* Construct an unsigned 128-bit value from a high and a low 64-bit value. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_load(rustsecp256k1_v0_10_0_uint128 *r, uint64_t hi, uint64_t lo); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_load(rustsecp256k1_v0_11_uint128 *r, uint64_t hi, uint64_t lo); /* Multiply two unsigned 64-bit values a and b and write the result to r. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_mul(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a, uint64_t b); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_mul(rustsecp256k1_v0_11_uint128 *r, uint64_t a, uint64_t b); /* Multiply two unsigned 64-bit values a and b and add the result to r. * The final result is taken modulo 2^128. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_mul(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a, uint64_t b); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_accum_mul(rustsecp256k1_v0_11_uint128 *r, uint64_t a, uint64_t b); /* Add an unsigned 64-bit value a to r. * The final result is taken modulo 2^128. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_u64(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_accum_u64(rustsecp256k1_v0_11_uint128 *r, uint64_t a); /* Unsigned (logical) right shift. * Non-constant time in n. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_rshift(rustsecp256k1_v0_10_0_uint128 *r, unsigned int n); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_rshift(rustsecp256k1_v0_11_uint128 *r, unsigned int n); /* Return the low 64-bits of a 128-bit value as an unsigned 64-bit value. */ -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_u128_to_u64(const rustsecp256k1_v0_10_0_uint128 *a); +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_u128_to_u64(const rustsecp256k1_v0_11_uint128 *a); /* Return the high 64-bits of a 128-bit value as an unsigned 64-bit value. */ -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_u128_hi_u64(const rustsecp256k1_v0_10_0_uint128 *a); +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_u128_hi_u64(const rustsecp256k1_v0_11_uint128 *a); /* Write an unsigned 64-bit value to r. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_from_u64(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_from_u64(rustsecp256k1_v0_11_uint128 *r, uint64_t a); /* Tests if r is strictly less than to 2^n. * n must be strictly less than 128. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_u128_check_bits(const rustsecp256k1_v0_10_0_uint128 *r, unsigned int n); +static SECP256K1_INLINE int rustsecp256k1_v0_11_u128_check_bits(const rustsecp256k1_v0_11_uint128 *r, unsigned int n); /* Construct an signed 128-bit value from a high and a low 64-bit value. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_load(rustsecp256k1_v0_10_0_int128 *r, int64_t hi, uint64_t lo); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_load(rustsecp256k1_v0_11_int128 *r, int64_t hi, uint64_t lo); /* Multiply two signed 64-bit values a and b and write the result to r. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b); /* Multiply two signed 64-bit values a and b and add the result to r. * Overflow or underflow from the addition is undefined behaviour. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_accum_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_accum_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b); /* Compute a*d - b*c from signed 64-bit values and write the result to r. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_det(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_det(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d); /* Signed (arithmetic) right shift. * Non-constant time in b. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_rshift(rustsecp256k1_v0_10_0_int128 *r, unsigned int b); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_rshift(rustsecp256k1_v0_11_int128 *r, unsigned int b); /* Return the input value modulo 2^64. */ -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_i128_to_u64(const rustsecp256k1_v0_10_0_int128 *a); +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_i128_to_u64(const rustsecp256k1_v0_11_int128 *a); /* Return the value as a signed 64-bit value. * Requires the input to be between INT64_MIN and INT64_MAX. */ -static SECP256K1_INLINE int64_t rustsecp256k1_v0_10_0_i128_to_i64(const rustsecp256k1_v0_10_0_int128 *a); +static SECP256K1_INLINE int64_t rustsecp256k1_v0_11_i128_to_i64(const rustsecp256k1_v0_11_int128 *a); /* Write a signed 64-bit value to r. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_from_i64(rustsecp256k1_v0_10_0_int128 *r, int64_t a); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_from_i64(rustsecp256k1_v0_11_int128 *r, int64_t a); /* Compare two 128-bit values for equality. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_i128_eq_var(const rustsecp256k1_v0_10_0_int128 *a, const rustsecp256k1_v0_10_0_int128 *b); +static SECP256K1_INLINE int rustsecp256k1_v0_11_i128_eq_var(const rustsecp256k1_v0_11_int128 *a, const rustsecp256k1_v0_11_int128 *b); /* Tests if r is equal to sign*2^n (sign must be 1 or -1). * n must be strictly less than 127. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_i128_check_pow2(const rustsecp256k1_v0_10_0_int128 *r, unsigned int n, int sign); +static SECP256K1_INLINE int rustsecp256k1_v0_11_i128_check_pow2(const rustsecp256k1_v0_11_int128 *r, unsigned int n, int sign); #endif diff --git a/secp256k1-sys/depend/secp256k1/src/int128_native.h b/secp256k1-sys/depend/secp256k1/src/int128_native.h index a6000b70f..95c6361f2 100644 --- a/secp256k1-sys/depend/secp256k1/src/int128_native.h +++ b/secp256k1-sys/depend/secp256k1/src/int128_native.h @@ -13,7 +13,7 @@ SECP256K1_GNUC_EXT typedef __int128 int128_t; /* No (U)INT128_C macros because compilers providing __int128 do not support 128-bit literals. */ #endif -typedef uint128_t rustsecp256k1_v0_10_0_uint128; -typedef int128_t rustsecp256k1_v0_10_0_int128; +typedef uint128_t rustsecp256k1_v0_11_uint128; +typedef int128_t rustsecp256k1_v0_11_int128; #endif diff --git a/secp256k1-sys/depend/secp256k1/src/int128_native_impl.h b/secp256k1-sys/depend/secp256k1/src/int128_native_impl.h index 8c3f604ec..c708a0b60 100644 --- a/secp256k1-sys/depend/secp256k1/src/int128_native_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/int128_native_impl.h @@ -4,88 +4,88 @@ #include "int128.h" #include "util.h" -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_load(rustsecp256k1_v0_10_0_uint128 *r, uint64_t hi, uint64_t lo) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_load(rustsecp256k1_v0_11_uint128 *r, uint64_t hi, uint64_t lo) { *r = (((uint128_t)hi) << 64) + lo; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_mul(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a, uint64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_mul(rustsecp256k1_v0_11_uint128 *r, uint64_t a, uint64_t b) { *r = (uint128_t)a * b; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_mul(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a, uint64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_accum_mul(rustsecp256k1_v0_11_uint128 *r, uint64_t a, uint64_t b) { *r += (uint128_t)a * b; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_u64(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_accum_u64(rustsecp256k1_v0_11_uint128 *r, uint64_t a) { *r += a; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_rshift(rustsecp256k1_v0_10_0_uint128 *r, unsigned int n) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_rshift(rustsecp256k1_v0_11_uint128 *r, unsigned int n) { VERIFY_CHECK(n < 128); *r >>= n; } -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_u128_to_u64(const rustsecp256k1_v0_10_0_uint128 *a) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_u128_to_u64(const rustsecp256k1_v0_11_uint128 *a) { return (uint64_t)(*a); } -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_u128_hi_u64(const rustsecp256k1_v0_10_0_uint128 *a) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_u128_hi_u64(const rustsecp256k1_v0_11_uint128 *a) { return (uint64_t)(*a >> 64); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_from_u64(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_from_u64(rustsecp256k1_v0_11_uint128 *r, uint64_t a) { *r = a; } -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_u128_check_bits(const rustsecp256k1_v0_10_0_uint128 *r, unsigned int n) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_u128_check_bits(const rustsecp256k1_v0_11_uint128 *r, unsigned int n) { VERIFY_CHECK(n < 128); return (*r >> n == 0); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_load(rustsecp256k1_v0_10_0_int128 *r, int64_t hi, uint64_t lo) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_load(rustsecp256k1_v0_11_int128 *r, int64_t hi, uint64_t lo) { *r = (((uint128_t)(uint64_t)hi) << 64) + lo; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b) { *r = (int128_t)a * b; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_accum_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_accum_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b) { int128_t ab = (int128_t)a * b; VERIFY_CHECK(0 <= ab ? *r <= INT128_MAX - ab : INT128_MIN - ab <= *r); *r += ab; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_det(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_det(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { int128_t ad = (int128_t)a * d; int128_t bc = (int128_t)b * c; VERIFY_CHECK(0 <= bc ? INT128_MIN + bc <= ad : ad <= INT128_MAX + bc); *r = ad - bc; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_rshift(rustsecp256k1_v0_10_0_int128 *r, unsigned int n) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_rshift(rustsecp256k1_v0_11_int128 *r, unsigned int n) { VERIFY_CHECK(n < 128); *r >>= n; } -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_i128_to_u64(const rustsecp256k1_v0_10_0_int128 *a) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_i128_to_u64(const rustsecp256k1_v0_11_int128 *a) { return (uint64_t)*a; } -static SECP256K1_INLINE int64_t rustsecp256k1_v0_10_0_i128_to_i64(const rustsecp256k1_v0_10_0_int128 *a) { +static SECP256K1_INLINE int64_t rustsecp256k1_v0_11_i128_to_i64(const rustsecp256k1_v0_11_int128 *a) { VERIFY_CHECK(INT64_MIN <= *a && *a <= INT64_MAX); return *a; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_from_i64(rustsecp256k1_v0_10_0_int128 *r, int64_t a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_from_i64(rustsecp256k1_v0_11_int128 *r, int64_t a) { *r = a; } -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_i128_eq_var(const rustsecp256k1_v0_10_0_int128 *a, const rustsecp256k1_v0_10_0_int128 *b) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_i128_eq_var(const rustsecp256k1_v0_11_int128 *a, const rustsecp256k1_v0_11_int128 *b) { return *a == *b; } -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_i128_check_pow2(const rustsecp256k1_v0_10_0_int128 *r, unsigned int n, int sign) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_i128_check_pow2(const rustsecp256k1_v0_11_int128 *r, unsigned int n, int sign) { VERIFY_CHECK(n < 127); VERIFY_CHECK(sign == 1 || sign == -1); return (*r == (int128_t)((uint128_t)sign << n)); diff --git a/secp256k1-sys/depend/secp256k1/src/int128_struct.h b/secp256k1-sys/depend/secp256k1/src/int128_struct.h index 07d148360..d0b7d01c2 100644 --- a/secp256k1-sys/depend/secp256k1/src/int128_struct.h +++ b/secp256k1-sys/depend/secp256k1/src/int128_struct.h @@ -7,8 +7,8 @@ typedef struct { uint64_t lo; uint64_t hi; -} rustsecp256k1_v0_10_0_uint128; +} rustsecp256k1_v0_11_uint128; -typedef rustsecp256k1_v0_10_0_uint128 rustsecp256k1_v0_10_0_int128; +typedef rustsecp256k1_v0_11_uint128 rustsecp256k1_v0_11_int128; #endif diff --git a/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h b/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h index 22e8b982d..d89d74e94 100644 --- a/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/int128_struct_impl.h @@ -13,23 +13,23 @@ # if defined(SECP256K1_MSVC_MULH_TEST_OVERRIDE) # pragma message(__FILE__ ": SECP256K1_MSVC_MULH_TEST_OVERRIDE is defined, forcing use of __(u)mulh.") # endif -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_umul128(uint64_t a, uint64_t b, uint64_t* hi) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_umul128(uint64_t a, uint64_t b, uint64_t* hi) { *hi = __umulh(a, b); return a * b; } -static SECP256K1_INLINE int64_t rustsecp256k1_v0_10_0_mul128(int64_t a, int64_t b, int64_t* hi) { +static SECP256K1_INLINE int64_t rustsecp256k1_v0_11_mul128(int64_t a, int64_t b, int64_t* hi) { *hi = __mulh(a, b); return (uint64_t)a * (uint64_t)b; } # else /* On x84_64 MSVC, use native _(u)mul128 for 64x64->128 multiplications. */ -# define rustsecp256k1_v0_10_0_umul128 _umul128 -# define rustsecp256k1_v0_10_0_mul128 _mul128 +# define rustsecp256k1_v0_11_umul128 _umul128 +# define rustsecp256k1_v0_11_mul128 _mul128 # endif #else /* On other systems, emulate 64x64->128 multiplications using 32x32->64 multiplications. */ -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_umul128(uint64_t a, uint64_t b, uint64_t* hi) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_umul128(uint64_t a, uint64_t b, uint64_t* hi) { uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b; uint64_t lh = (uint32_t)a * (b >> 32); uint64_t hl = (a >> 32) * (uint32_t)b; @@ -39,7 +39,7 @@ static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_umul128(uint64_t a, uint6 return (mid34 << 32) + (uint32_t)ll; } -static SECP256K1_INLINE int64_t rustsecp256k1_v0_10_0_mul128(int64_t a, int64_t b, int64_t* hi) { +static SECP256K1_INLINE int64_t rustsecp256k1_v0_11_mul128(int64_t a, int64_t b, int64_t* hi) { uint64_t ll = (uint64_t)(uint32_t)a * (uint32_t)b; int64_t lh = (uint32_t)a * (b >> 32); int64_t hl = (a >> 32) * (uint32_t)b; @@ -50,23 +50,23 @@ static SECP256K1_INLINE int64_t rustsecp256k1_v0_10_0_mul128(int64_t a, int64_t } #endif -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_load(rustsecp256k1_v0_10_0_uint128 *r, uint64_t hi, uint64_t lo) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_load(rustsecp256k1_v0_11_uint128 *r, uint64_t hi, uint64_t lo) { r->hi = hi; r->lo = lo; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_mul(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a, uint64_t b) { - r->lo = rustsecp256k1_v0_10_0_umul128(a, b, &r->hi); +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_mul(rustsecp256k1_v0_11_uint128 *r, uint64_t a, uint64_t b) { + r->lo = rustsecp256k1_v0_11_umul128(a, b, &r->hi); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_mul(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a, uint64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_accum_mul(rustsecp256k1_v0_11_uint128 *r, uint64_t a, uint64_t b) { uint64_t lo, hi; - lo = rustsecp256k1_v0_10_0_umul128(a, b, &hi); + lo = rustsecp256k1_v0_11_umul128(a, b, &hi); r->lo += lo; r->hi += hi + (r->lo < lo); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_u64(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_accum_u64(rustsecp256k1_v0_11_uint128 *r, uint64_t a) { r->lo += a; r->hi += r->lo < a; } @@ -74,7 +74,7 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_accum_u64(rustsecp256k1_ /* Unsigned (logical) right shift. * Non-constant time in n. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_rshift(rustsecp256k1_v0_10_0_uint128 *r, unsigned int n) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_rshift(rustsecp256k1_v0_11_uint128 *r, unsigned int n) { VERIFY_CHECK(n < 128); if (n >= 64) { r->lo = r->hi >> (n-64); @@ -90,39 +90,39 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_rshift(rustsecp256k1_v0_ } } -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_u128_to_u64(const rustsecp256k1_v0_10_0_uint128 *a) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_u128_to_u64(const rustsecp256k1_v0_11_uint128 *a) { return a->lo; } -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_u128_hi_u64(const rustsecp256k1_v0_10_0_uint128 *a) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_u128_hi_u64(const rustsecp256k1_v0_11_uint128 *a) { return a->hi; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_u128_from_u64(rustsecp256k1_v0_10_0_uint128 *r, uint64_t a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_u128_from_u64(rustsecp256k1_v0_11_uint128 *r, uint64_t a) { r->hi = 0; r->lo = a; } -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_u128_check_bits(const rustsecp256k1_v0_10_0_uint128 *r, unsigned int n) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_u128_check_bits(const rustsecp256k1_v0_11_uint128 *r, unsigned int n) { VERIFY_CHECK(n < 128); return n >= 64 ? r->hi >> (n - 64) == 0 : r->hi == 0 && r->lo >> n == 0; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_load(rustsecp256k1_v0_10_0_int128 *r, int64_t hi, uint64_t lo) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_load(rustsecp256k1_v0_11_int128 *r, int64_t hi, uint64_t lo) { r->hi = hi; r->lo = lo; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b) { int64_t hi; - r->lo = (uint64_t)rustsecp256k1_v0_10_0_mul128(a, b, &hi); + r->lo = (uint64_t)rustsecp256k1_v0_11_mul128(a, b, &hi); r->hi = (uint64_t)hi; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_accum_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_accum_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b) { int64_t hi; - uint64_t lo = (uint64_t)rustsecp256k1_v0_10_0_mul128(a, b, &hi); + uint64_t lo = (uint64_t)rustsecp256k1_v0_11_mul128(a, b, &hi); r->lo += lo; hi += r->lo < lo; /* Verify no overflow. @@ -139,9 +139,9 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_accum_mul(rustsecp256k1_ r->hi += hi; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_dissip_mul(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_dissip_mul(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b) { int64_t hi; - uint64_t lo = (uint64_t)rustsecp256k1_v0_10_0_mul128(a, b, &hi); + uint64_t lo = (uint64_t)rustsecp256k1_v0_11_mul128(a, b, &hi); hi += r->lo < lo; /* Verify no overflow. * If r represents a positive value (the sign bit is not set) and the value we are subtracting is a negative value (the sign bit is set), @@ -157,15 +157,15 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_dissip_mul(rustsecp256k1 r->lo -= lo; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_det(rustsecp256k1_v0_10_0_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { - rustsecp256k1_v0_10_0_i128_mul(r, a, d); - rustsecp256k1_v0_10_0_i128_dissip_mul(r, b, c); +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_det(rustsecp256k1_v0_11_int128 *r, int64_t a, int64_t b, int64_t c, int64_t d) { + rustsecp256k1_v0_11_i128_mul(r, a, d); + rustsecp256k1_v0_11_i128_dissip_mul(r, b, c); } /* Signed (arithmetic) right shift. * Non-constant time in n. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_rshift(rustsecp256k1_v0_10_0_int128 *r, unsigned int n) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_rshift(rustsecp256k1_v0_11_int128 *r, unsigned int n) { VERIFY_CHECK(n < 128); if (n >= 64) { r->lo = (uint64_t)((int64_t)(r->hi) >> (n-64)); @@ -176,26 +176,26 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_rshift(rustsecp256k1_v0_ } } -static SECP256K1_INLINE uint64_t rustsecp256k1_v0_10_0_i128_to_u64(const rustsecp256k1_v0_10_0_int128 *a) { +static SECP256K1_INLINE uint64_t rustsecp256k1_v0_11_i128_to_u64(const rustsecp256k1_v0_11_int128 *a) { return a->lo; } -static SECP256K1_INLINE int64_t rustsecp256k1_v0_10_0_i128_to_i64(const rustsecp256k1_v0_10_0_int128 *a) { +static SECP256K1_INLINE int64_t rustsecp256k1_v0_11_i128_to_i64(const rustsecp256k1_v0_11_int128 *a) { /* Verify that a represents a 64 bit signed value by checking that the high bits are a sign extension of the low bits. */ VERIFY_CHECK(a->hi == -(a->lo >> 63)); - return (int64_t)rustsecp256k1_v0_10_0_i128_to_u64(a); + return (int64_t)rustsecp256k1_v0_11_i128_to_u64(a); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_i128_from_i64(rustsecp256k1_v0_10_0_int128 *r, int64_t a) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_i128_from_i64(rustsecp256k1_v0_11_int128 *r, int64_t a) { r->hi = (uint64_t)(a >> 63); r->lo = (uint64_t)a; } -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_i128_eq_var(const rustsecp256k1_v0_10_0_int128 *a, const rustsecp256k1_v0_10_0_int128 *b) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_i128_eq_var(const rustsecp256k1_v0_11_int128 *a, const rustsecp256k1_v0_11_int128 *b) { return a->hi == b->hi && a->lo == b->lo; } -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_i128_check_pow2(const rustsecp256k1_v0_10_0_int128 *r, unsigned int n, int sign) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_i128_check_pow2(const rustsecp256k1_v0_11_int128 *r, unsigned int n, int sign) { VERIFY_CHECK(n < 127); VERIFY_CHECK(sign == 1 || sign == -1); return n >= 64 ? r->hi == (uint64_t)sign << (n - 64) && r->lo == 0 diff --git a/secp256k1-sys/depend/secp256k1/src/modinv32.h b/secp256k1-sys/depend/secp256k1/src/modinv32.h index 769683585..269fbe8ef 100644 --- a/secp256k1-sys/depend/secp256k1/src/modinv32.h +++ b/secp256k1-sys/depend/secp256k1/src/modinv32.h @@ -14,15 +14,15 @@ * Its value is sum(v[i] * 2^(30*i), i=0..8). */ typedef struct { int32_t v[9]; -} rustsecp256k1_v0_10_0_modinv32_signed30; +} rustsecp256k1_v0_11_modinv32_signed30; typedef struct { /* The modulus in signed30 notation, must be odd and in [3, 2^256]. */ - rustsecp256k1_v0_10_0_modinv32_signed30 modulus; + rustsecp256k1_v0_11_modinv32_signed30 modulus; /* modulus^{-1} mod 2^30 */ uint32_t modulus_inv30; -} rustsecp256k1_v0_10_0_modinv32_modinfo; +} rustsecp256k1_v0_11_modinv32_modinfo; /* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of @@ -30,14 +30,14 @@ typedef struct { * * On output, all of x's limbs will be in [0, 2^30). */ -static void rustsecp256k1_v0_10_0_modinv32_var(rustsecp256k1_v0_10_0_modinv32_signed30 *x, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo); +static void rustsecp256k1_v0_11_modinv32_var(rustsecp256k1_v0_11_modinv32_signed30 *x, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo); -/* Same as rustsecp256k1_v0_10_0_modinv32_var, but constant time in x (not in the modulus). */ -static void rustsecp256k1_v0_10_0_modinv32(rustsecp256k1_v0_10_0_modinv32_signed30 *x, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo); +/* Same as rustsecp256k1_v0_11_modinv32_var, but constant time in x (not in the modulus). */ +static void rustsecp256k1_v0_11_modinv32(rustsecp256k1_v0_11_modinv32_signed30 *x, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo); /* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result * cannot be computed. */ -static int rustsecp256k1_v0_10_0_jacobi32_maybe_var(const rustsecp256k1_v0_10_0_modinv32_signed30 *x, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo); +static int rustsecp256k1_v0_11_jacobi32_maybe_var(const rustsecp256k1_v0_11_modinv32_signed30 *x, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo); #endif /* SECP256K1_MODINV32_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/modinv32_impl.h b/secp256k1-sys/depend/secp256k1/src/modinv32_impl.h index 6adb3087b..82eaec253 100644 --- a/secp256k1-sys/depend/secp256k1/src/modinv32_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modinv32_impl.h @@ -21,10 +21,10 @@ */ #ifdef VERIFY -static const rustsecp256k1_v0_10_0_modinv32_signed30 SECP256K1_SIGNED30_ONE = {{1}}; +static const rustsecp256k1_v0_11_modinv32_signed30 SECP256K1_SIGNED30_ONE = {{1}}; /* Compute a*factor and put it in r. All but the top limb in r will be in range [0,2^30). */ -static void rustsecp256k1_v0_10_0_modinv32_mul_30(rustsecp256k1_v0_10_0_modinv32_signed30 *r, const rustsecp256k1_v0_10_0_modinv32_signed30 *a, int alen, int32_t factor) { +static void rustsecp256k1_v0_11_modinv32_mul_30(rustsecp256k1_v0_11_modinv32_signed30 *r, const rustsecp256k1_v0_11_modinv32_signed30 *a, int alen, int32_t factor) { const int32_t M30 = (int32_t)(UINT32_MAX >> 2); int64_t c = 0; int i; @@ -38,11 +38,11 @@ static void rustsecp256k1_v0_10_0_modinv32_mul_30(rustsecp256k1_v0_10_0_modinv32 } /* Return -1 for ab*factor. A consists of alen limbs; b has 9. */ -static int rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(const rustsecp256k1_v0_10_0_modinv32_signed30 *a, int alen, const rustsecp256k1_v0_10_0_modinv32_signed30 *b, int32_t factor) { +static int rustsecp256k1_v0_11_modinv32_mul_cmp_30(const rustsecp256k1_v0_11_modinv32_signed30 *a, int alen, const rustsecp256k1_v0_11_modinv32_signed30 *b, int32_t factor) { int i; - rustsecp256k1_v0_10_0_modinv32_signed30 am, bm; - rustsecp256k1_v0_10_0_modinv32_mul_30(&am, a, alen, 1); /* Normalize all but the top limb of a. */ - rustsecp256k1_v0_10_0_modinv32_mul_30(&bm, b, 9, factor); + rustsecp256k1_v0_11_modinv32_signed30 am, bm; + rustsecp256k1_v0_11_modinv32_mul_30(&am, a, alen, 1); /* Normalize all but the top limb of a. */ + rustsecp256k1_v0_11_modinv32_mul_30(&bm, b, 9, factor); for (i = 0; i < 8; ++i) { /* Verify that all but the top limb of a and b are normalized. */ VERIFY_CHECK(am.v[i] >> 30 == 0); @@ -60,7 +60,7 @@ static int rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(const rustsecp256k1_v0_10_0 * to it to bring it to range [0,modulus). If sign < 0, the input will also be negated in the * process. The input must have limbs in range (-2^30,2^30). The output will have limbs in range * [0,2^30). */ -static void rustsecp256k1_v0_10_0_modinv32_normalize_30(rustsecp256k1_v0_10_0_modinv32_signed30 *r, int32_t sign, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo) { +static void rustsecp256k1_v0_11_modinv32_normalize_30(rustsecp256k1_v0_11_modinv32_signed30 *r, int32_t sign, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo) { const int32_t M30 = (int32_t)(UINT32_MAX >> 2); int32_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4], r5 = r->v[5], r6 = r->v[6], r7 = r->v[7], r8 = r->v[8]; @@ -73,8 +73,8 @@ static void rustsecp256k1_v0_10_0_modinv32_normalize_30(rustsecp256k1_v0_10_0_mo VERIFY_CHECK(r->v[i] >= -M30); VERIFY_CHECK(r->v[i] <= M30); } - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, -2) > 0); /* r > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 1) < 0); /* r < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, -2) > 0); /* r > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 1) < 0); /* r < modulus */ #endif /* In a first step, add the modulus if the input is negative, and then negate if requested. @@ -153,8 +153,8 @@ static void rustsecp256k1_v0_10_0_modinv32_normalize_30(rustsecp256k1_v0_10_0_mo VERIFY_CHECK(r6 >> 30 == 0); VERIFY_CHECK(r7 >> 30 == 0); VERIFY_CHECK(r8 >> 30 == 0); - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 0) >= 0); /* r >= 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 1) < 0); /* r < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 0) >= 0); /* r >= 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(r, 9, &modinfo->modulus, 1) < 0); /* r < modulus */ } /* Data type for transition matrices (see section 3 of explanation). @@ -164,7 +164,7 @@ static void rustsecp256k1_v0_10_0_modinv32_normalize_30(rustsecp256k1_v0_10_0_mo */ typedef struct { int32_t u, v, q, r; -} rustsecp256k1_v0_10_0_modinv32_trans2x2; +} rustsecp256k1_v0_11_modinv32_trans2x2; /* Compute the transition matrix and zeta for 30 divsteps. * @@ -176,7 +176,7 @@ typedef struct { * * Implements the divsteps_n_matrix function from the explanation. */ -static int32_t rustsecp256k1_v0_10_0_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_t g0, rustsecp256k1_v0_10_0_modinv32_trans2x2 *t) { +static int32_t rustsecp256k1_v0_11_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_t g0, rustsecp256k1_v0_11_modinv32_trans2x2 *t) { /* u,v,q,r are the elements of the transformation matrix being built up, * starting with the identity matrix. Semantically they are signed integers * in range [-2^30,2^30], but here represented as unsigned mod 2^32. This @@ -233,8 +233,8 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_divsteps_30(int32_t zeta, uint32_t return zeta; } -/* rustsecp256k1_v0_10_0_modinv32_inv256[i] = -(2*i+1)^-1 (mod 256) */ -static const uint8_t rustsecp256k1_v0_10_0_modinv32_inv256[128] = { +/* rustsecp256k1_v0_11_modinv32_inv256[i] = -(2*i+1)^-1 (mod 256) */ +static const uint8_t rustsecp256k1_v0_11_modinv32_inv256[128] = { 0xFF, 0x55, 0x33, 0x49, 0xC7, 0x5D, 0x3B, 0x11, 0x0F, 0xE5, 0xC3, 0x59, 0xD7, 0xED, 0xCB, 0x21, 0x1F, 0x75, 0x53, 0x69, 0xE7, 0x7D, 0x5B, 0x31, 0x2F, 0x05, 0xE3, 0x79, 0xF7, 0x0D, 0xEB, 0x41, 0x3F, 0x95, 0x73, 0x89, @@ -258,8 +258,8 @@ static const uint8_t rustsecp256k1_v0_10_0_modinv32_inv256[128] = { * * Implements the divsteps_n_matrix_var function from the explanation. */ -static int32_t rustsecp256k1_v0_10_0_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, rustsecp256k1_v0_10_0_modinv32_trans2x2 *t) { - /* Transformation matrix; see comments in rustsecp256k1_v0_10_0_modinv32_divsteps_30. */ +static int32_t rustsecp256k1_v0_11_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, rustsecp256k1_v0_11_modinv32_trans2x2 *t) { + /* Transformation matrix; see comments in rustsecp256k1_v0_11_modinv32_divsteps_30. */ uint32_t u = 1, v = 0, q = 0, r = 1; uint32_t f = f0, g = g0, m; uint16_t w; @@ -267,7 +267,7 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_divsteps_30_var(int32_t eta, uint3 for (;;) { /* Use a sentinel bit to count zeros only up to i. */ - zeros = rustsecp256k1_v0_10_0_ctz32_var(g | (UINT32_MAX << i)); + zeros = rustsecp256k1_v0_11_ctz32_var(g | (UINT32_MAX << i)); /* Perform zeros divsteps at once; they all just divide g by two. */ g >>= zeros; u <<= zeros; @@ -298,7 +298,7 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_divsteps_30_var(int32_t eta, uint3 VERIFY_CHECK(limit > 0 && limit <= 30); m = (UINT32_MAX >> (32 - limit)) & 255U; /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */ - w = (g * rustsecp256k1_v0_10_0_modinv32_inv256[(f >> 1) & 127]) & m; + w = (g * rustsecp256k1_v0_11_modinv32_inv256[(f >> 1) & 127]) & m; /* Do so. */ g += f * w; q += u * w; @@ -331,7 +331,7 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_divsteps_30_var(int32_t eta, uint3 * change, but are meaningless. * Return: final eta */ -static int32_t rustsecp256k1_v0_10_0_modinv32_posdivsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, rustsecp256k1_v0_10_0_modinv32_trans2x2 *t, int *jacp) { +static int32_t rustsecp256k1_v0_11_modinv32_posdivsteps_30_var(int32_t eta, uint32_t f0, uint32_t g0, rustsecp256k1_v0_11_modinv32_trans2x2 *t, int *jacp) { /* Transformation matrix. */ uint32_t u = 1, v = 0, q = 0, r = 1; uint32_t f = f0, g = g0, m; @@ -341,7 +341,7 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_posdivsteps_30_var(int32_t eta, ui for (;;) { /* Use a sentinel bit to count zeros only up to i. */ - zeros = rustsecp256k1_v0_10_0_ctz32_var(g | (UINT32_MAX << i)); + zeros = rustsecp256k1_v0_11_ctz32_var(g | (UINT32_MAX << i)); /* Perform zeros divsteps at once; they all just divide g by two. */ g >>= zeros; u <<= zeros; @@ -376,7 +376,7 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_posdivsteps_30_var(int32_t eta, ui VERIFY_CHECK(limit > 0 && limit <= 30); m = (UINT32_MAX >> (32 - limit)) & 255U; /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */ - w = (g * rustsecp256k1_v0_10_0_modinv32_inv256[(f >> 1) & 127]) & m; + w = (g * rustsecp256k1_v0_11_modinv32_inv256[(f >> 1) & 127]) & m; /* Do so. */ g += f * w; q += u * w; @@ -405,16 +405,16 @@ static int32_t rustsecp256k1_v0_10_0_modinv32_posdivsteps_30_var(int32_t eta, ui * * This implements the update_de function from the explanation. */ -static void rustsecp256k1_v0_10_0_modinv32_update_de_30(rustsecp256k1_v0_10_0_modinv32_signed30 *d, rustsecp256k1_v0_10_0_modinv32_signed30 *e, const rustsecp256k1_v0_10_0_modinv32_trans2x2 *t, const rustsecp256k1_v0_10_0_modinv32_modinfo* modinfo) { +static void rustsecp256k1_v0_11_modinv32_update_de_30(rustsecp256k1_v0_11_modinv32_signed30 *d, rustsecp256k1_v0_11_modinv32_signed30 *e, const rustsecp256k1_v0_11_modinv32_trans2x2 *t, const rustsecp256k1_v0_11_modinv32_modinfo* modinfo) { const int32_t M30 = (int32_t)(UINT32_MAX >> 2); const int32_t u = t->u, v = t->v, q = t->q, r = t->r; int32_t di, ei, md, me, sd, se; int64_t cd, ce; int i; - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ VERIFY_CHECK(labs(u) <= (M30 + 1 - labs(v))); /* |u|+|v| <= 2^30 */ VERIFY_CHECK(labs(q) <= (M30 + 1 - labs(r))); /* |q|+|r| <= 2^30 */ @@ -453,17 +453,17 @@ static void rustsecp256k1_v0_10_0_modinv32_update_de_30(rustsecp256k1_v0_10_0_mo d->v[8] = (int32_t)cd; e->v[8] = (int32_t)ce; - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(d, 9, &modinfo->modulus, 1) < 0); /* d < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(e, 9, &modinfo->modulus, 1) < 0); /* e < modulus */ } /* Compute (t/2^30) * [f, g], where t is a transition matrix for 30 divsteps. * * This implements the update_fg function from the explanation. */ -static void rustsecp256k1_v0_10_0_modinv32_update_fg_30(rustsecp256k1_v0_10_0_modinv32_signed30 *f, rustsecp256k1_v0_10_0_modinv32_signed30 *g, const rustsecp256k1_v0_10_0_modinv32_trans2x2 *t) { +static void rustsecp256k1_v0_11_modinv32_update_fg_30(rustsecp256k1_v0_11_modinv32_signed30 *f, rustsecp256k1_v0_11_modinv32_signed30 *g, const rustsecp256k1_v0_11_modinv32_trans2x2 *t) { const int32_t M30 = (int32_t)(UINT32_MAX >> 2); const int32_t u = t->u, v = t->v, q = t->q, r = t->r; int32_t fi, gi; @@ -498,7 +498,7 @@ static void rustsecp256k1_v0_10_0_modinv32_update_fg_30(rustsecp256k1_v0_10_0_mo * * This implements the update_fg function from the explanation in modinv64_impl.h. */ -static void rustsecp256k1_v0_10_0_modinv32_update_fg_30_var(int len, rustsecp256k1_v0_10_0_modinv32_signed30 *f, rustsecp256k1_v0_10_0_modinv32_signed30 *g, const rustsecp256k1_v0_10_0_modinv32_trans2x2 *t) { +static void rustsecp256k1_v0_11_modinv32_update_fg_30_var(int len, rustsecp256k1_v0_11_modinv32_signed30 *f, rustsecp256k1_v0_11_modinv32_signed30 *g, const rustsecp256k1_v0_11_modinv32_trans2x2 *t) { const int32_t M30 = (int32_t)(UINT32_MAX >> 2); const int32_t u = t->u, v = t->v, q = t->q, r = t->r; int32_t fi, gi; @@ -529,34 +529,34 @@ static void rustsecp256k1_v0_10_0_modinv32_update_fg_30_var(int len, rustsecp256 } /* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */ -static void rustsecp256k1_v0_10_0_modinv32(rustsecp256k1_v0_10_0_modinv32_signed30 *x, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo) { +static void rustsecp256k1_v0_11_modinv32(rustsecp256k1_v0_11_modinv32_signed30 *x, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo) { /* Start with d=0, e=1, f=modulus, g=x, zeta=-1. */ - rustsecp256k1_v0_10_0_modinv32_signed30 d = {{0}}; - rustsecp256k1_v0_10_0_modinv32_signed30 e = {{1}}; - rustsecp256k1_v0_10_0_modinv32_signed30 f = modinfo->modulus; - rustsecp256k1_v0_10_0_modinv32_signed30 g = *x; + rustsecp256k1_v0_11_modinv32_signed30 d = {{0}}; + rustsecp256k1_v0_11_modinv32_signed30 e = {{1}}; + rustsecp256k1_v0_11_modinv32_signed30 f = modinfo->modulus; + rustsecp256k1_v0_11_modinv32_signed30 g = *x; int i; int32_t zeta = -1; /* zeta = -(delta+1/2); delta is initially 1/2. */ /* Do 20 iterations of 30 divsteps each = 600 divsteps. 590 suffices for 256-bit inputs. */ for (i = 0; i < 20; ++i) { /* Compute transition matrix and new zeta after 30 divsteps. */ - rustsecp256k1_v0_10_0_modinv32_trans2x2 t; - zeta = rustsecp256k1_v0_10_0_modinv32_divsteps_30(zeta, f.v[0], g.v[0], &t); + rustsecp256k1_v0_11_modinv32_trans2x2 t; + zeta = rustsecp256k1_v0_11_modinv32_divsteps_30(zeta, f.v[0], g.v[0], &t); /* Update d,e using that transition matrix. */ - rustsecp256k1_v0_10_0_modinv32_update_de_30(&d, &e, &t, modinfo); + rustsecp256k1_v0_11_modinv32_update_de_30(&d, &e, &t, modinfo); /* Update f,g using that transition matrix. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, 1) < 0); /* g < modulus */ - rustsecp256k1_v0_10_0_modinv32_update_fg_30(&f, &g, &t); + rustsecp256k1_v0_11_modinv32_update_fg_30(&f, &g, &t); - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, 9, &modinfo->modulus, 1) < 0); /* g < modulus */ } /* At this point sufficient iterations have been performed that g must have reached 0 @@ -564,27 +564,26 @@ static void rustsecp256k1_v0_10_0_modinv32(rustsecp256k1_v0_10_0_modinv32_signed * values i.e. +/- 1, and d now contains +/- the modular inverse. */ /* g == 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, 9, &SECP256K1_SIGNED30_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, -1) == 0 || - rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, 1) == 0 || - (rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - (rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) == 0 || - rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, -1) == 0))); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, 9, &SECP256K1_SIGNED30_ONE, 0) == 0); + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, -1) == 0 || + rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &SECP256K1_SIGNED30_ONE, 1) == 0 || + (rustsecp256k1_v0_11_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, 9, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ - rustsecp256k1_v0_10_0_modinv32_normalize_30(&d, f.v[8], modinfo); + rustsecp256k1_v0_11_modinv32_normalize_30(&d, f.v[8], modinfo); *x = d; } /* Compute the inverse of x modulo modinfo->modulus, and replace x with it (variable time). */ -static void rustsecp256k1_v0_10_0_modinv32_var(rustsecp256k1_v0_10_0_modinv32_signed30 *x, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo) { +static void rustsecp256k1_v0_11_modinv32_var(rustsecp256k1_v0_11_modinv32_signed30 *x, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo) { /* Start with d=0, e=1, f=modulus, g=x, eta=-1. */ - rustsecp256k1_v0_10_0_modinv32_signed30 d = {{0, 0, 0, 0, 0, 0, 0, 0, 0}}; - rustsecp256k1_v0_10_0_modinv32_signed30 e = {{1, 0, 0, 0, 0, 0, 0, 0, 0}}; - rustsecp256k1_v0_10_0_modinv32_signed30 f = modinfo->modulus; - rustsecp256k1_v0_10_0_modinv32_signed30 g = *x; + rustsecp256k1_v0_11_modinv32_signed30 d = {{0, 0, 0, 0, 0, 0, 0, 0, 0}}; + rustsecp256k1_v0_11_modinv32_signed30 e = {{1, 0, 0, 0, 0, 0, 0, 0, 0}}; + rustsecp256k1_v0_11_modinv32_signed30 f = modinfo->modulus; + rustsecp256k1_v0_11_modinv32_signed30 g = *x; #ifdef VERIFY int i = 0; #endif @@ -595,18 +594,18 @@ static void rustsecp256k1_v0_10_0_modinv32_var(rustsecp256k1_v0_10_0_modinv32_si /* Do iterations of 30 divsteps each until g=0. */ while (1) { /* Compute transition matrix and new eta after 30 divsteps. */ - rustsecp256k1_v0_10_0_modinv32_trans2x2 t; - eta = rustsecp256k1_v0_10_0_modinv32_divsteps_30_var(eta, f.v[0], g.v[0], &t); + rustsecp256k1_v0_11_modinv32_trans2x2 t; + eta = rustsecp256k1_v0_11_modinv32_divsteps_30_var(eta, f.v[0], g.v[0], &t); /* Update d,e using that transition matrix. */ - rustsecp256k1_v0_10_0_modinv32_update_de_30(&d, &e, &t, modinfo); + rustsecp256k1_v0_11_modinv32_update_de_30(&d, &e, &t, modinfo); /* Update f,g using that transition matrix. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - rustsecp256k1_v0_10_0_modinv32_update_fg_30_var(len, &f, &g, &t); + rustsecp256k1_v0_11_modinv32_update_fg_30_var(len, &f, &g, &t); /* If the bottom limb of g is 0, there is a chance g=0. */ if (g.v[0] == 0) { cond = 0; @@ -632,27 +631,26 @@ static void rustsecp256k1_v0_10_0_modinv32_var(rustsecp256k1_v0_10_0_modinv32_si } VERIFY_CHECK(++i < 25); /* We should never need more than 25*30 = 750 divsteps */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ } /* At this point g is 0 and (if g was not originally 0) f must now equal +/- GCD of * the initial f, g values i.e. +/- 1, and d now contains +/- the modular inverse. */ /* g == 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &SECP256K1_SIGNED30_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, -1) == 0 || - rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, 1) == 0 || - (rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && - (rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) == 0 || - rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, -1) == 0))); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &SECP256K1_SIGNED30_ONE, 0) == 0); + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, -1) == 0 || + rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &SECP256K1_SIGNED30_ONE, 1) == 0 || + (rustsecp256k1_v0_11_modinv32_mul_cmp_30(x, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv32_mul_cmp_30(&d, 9, &SECP256K1_SIGNED30_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ - rustsecp256k1_v0_10_0_modinv32_normalize_30(&d, f.v[len - 1], modinfo); + rustsecp256k1_v0_11_modinv32_normalize_30(&d, f.v[len - 1], modinfo); *x = d; } @@ -665,10 +663,10 @@ static void rustsecp256k1_v0_10_0_modinv32_var(rustsecp256k1_v0_10_0_modinv32_si #endif /* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */ -static int rustsecp256k1_v0_10_0_jacobi32_maybe_var(const rustsecp256k1_v0_10_0_modinv32_signed30 *x, const rustsecp256k1_v0_10_0_modinv32_modinfo *modinfo) { +static int rustsecp256k1_v0_11_jacobi32_maybe_var(const rustsecp256k1_v0_11_modinv32_signed30 *x, const rustsecp256k1_v0_11_modinv32_modinfo *modinfo) { /* Start with f=modulus, g=x, eta=-1. */ - rustsecp256k1_v0_10_0_modinv32_signed30 f = modinfo->modulus; - rustsecp256k1_v0_10_0_modinv32_signed30 g = *x; + rustsecp256k1_v0_11_modinv32_signed30 f = modinfo->modulus; + rustsecp256k1_v0_11_modinv32_signed30 g = *x; int j, len = 9; int32_t eta = -1; /* eta = -delta; delta is initially 1 */ int32_t cond, fn, gn; @@ -685,15 +683,15 @@ static int rustsecp256k1_v0_10_0_jacobi32_maybe_var(const rustsecp256k1_v0_10_0_ for (count = 0; count < JACOBI32_ITERATIONS; ++count) { /* Compute transition matrix and new eta after 30 posdivsteps. */ - rustsecp256k1_v0_10_0_modinv32_trans2x2 t; - eta = rustsecp256k1_v0_10_0_modinv32_posdivsteps_30_var(eta, f.v[0] | ((uint32_t)f.v[1] << 30), g.v[0] | ((uint32_t)g.v[1] << 30), &t, &jac); + rustsecp256k1_v0_11_modinv32_trans2x2 t; + eta = rustsecp256k1_v0_11_modinv32_posdivsteps_30_var(eta, f.v[0] | ((uint32_t)f.v[1] << 30), g.v[0] | ((uint32_t)g.v[1] << 30), &t, &jac); /* Update f,g using that transition matrix. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - rustsecp256k1_v0_10_0_modinv32_update_fg_30_var(len, &f, &g, &t); + rustsecp256k1_v0_11_modinv32_update_fg_30_var(len, &f, &g, &t); /* If the bottom limb of f is 1, there is a chance that f=1. */ if (f.v[0] == 1) { cond = 0; @@ -714,10 +712,10 @@ static int rustsecp256k1_v0_10_0_jacobi32_maybe_var(const rustsecp256k1_v0_10_0_ /* If so, reduce length. */ if (cond == 0) --len; - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv32_mul_cmp_30(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ } /* The loop failed to converge to f=g after 1500 iterations. Return 0, indicating unknown result. */ diff --git a/secp256k1-sys/depend/secp256k1/src/modinv64.h b/secp256k1-sys/depend/secp256k1/src/modinv64.h index 0c6fa91d1..8ecb3835f 100644 --- a/secp256k1-sys/depend/secp256k1/src/modinv64.h +++ b/secp256k1-sys/depend/secp256k1/src/modinv64.h @@ -18,15 +18,15 @@ * Its value is sum(v[i] * 2^(62*i), i=0..4). */ typedef struct { int64_t v[5]; -} rustsecp256k1_v0_10_0_modinv64_signed62; +} rustsecp256k1_v0_11_modinv64_signed62; typedef struct { /* The modulus in signed62 notation, must be odd and in [3, 2^256]. */ - rustsecp256k1_v0_10_0_modinv64_signed62 modulus; + rustsecp256k1_v0_11_modinv64_signed62 modulus; /* modulus^{-1} mod 2^62 */ uint64_t modulus_inv62; -} rustsecp256k1_v0_10_0_modinv64_modinfo; +} rustsecp256k1_v0_11_modinv64_modinfo; /* Replace x with its modular inverse mod modinfo->modulus. x must be in range [0, modulus). * If x is zero, the result will be zero as well. If not, the inverse must exist (i.e., the gcd of @@ -34,14 +34,14 @@ typedef struct { * * On output, all of x's limbs will be in [0, 2^62). */ -static void rustsecp256k1_v0_10_0_modinv64_var(rustsecp256k1_v0_10_0_modinv64_signed62 *x, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo); +static void rustsecp256k1_v0_11_modinv64_var(rustsecp256k1_v0_11_modinv64_signed62 *x, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo); -/* Same as rustsecp256k1_v0_10_0_modinv64_var, but constant time in x (not in the modulus). */ -static void rustsecp256k1_v0_10_0_modinv64(rustsecp256k1_v0_10_0_modinv64_signed62 *x, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo); +/* Same as rustsecp256k1_v0_11_modinv64_var, but constant time in x (not in the modulus). */ +static void rustsecp256k1_v0_11_modinv64(rustsecp256k1_v0_11_modinv64_signed62 *x, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo); /* Compute the Jacobi symbol for (x | modinfo->modulus). x must be coprime with modulus (and thus * cannot be 0, as modulus >= 3). All limbs of x must be non-negative. Returns 0 if the result * cannot be computed. */ -static int rustsecp256k1_v0_10_0_jacobi64_maybe_var(const rustsecp256k1_v0_10_0_modinv64_signed62 *x, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo); +static int rustsecp256k1_v0_11_jacobi64_maybe_var(const rustsecp256k1_v0_11_modinv64_signed62 *x, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo); #endif /* SECP256K1_MODINV64_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/modinv64_impl.h b/secp256k1-sys/depend/secp256k1/src/modinv64_impl.h index 4ea806504..723cbc497 100644 --- a/secp256k1-sys/depend/secp256k1/src/modinv64_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modinv64_impl.h @@ -24,41 +24,41 @@ */ typedef struct { int64_t u, v, q, r; -} rustsecp256k1_v0_10_0_modinv64_trans2x2; +} rustsecp256k1_v0_11_modinv64_trans2x2; #ifdef VERIFY /* Helper function to compute the absolute value of an int64_t. * (we don't use abs/labs/llabs as it depends on the int sizes). */ -static int64_t rustsecp256k1_v0_10_0_modinv64_abs(int64_t v) { +static int64_t rustsecp256k1_v0_11_modinv64_abs(int64_t v) { VERIFY_CHECK(v > INT64_MIN); if (v < 0) return -v; return v; } -static const rustsecp256k1_v0_10_0_modinv64_signed62 SECP256K1_SIGNED62_ONE = {{1}}; +static const rustsecp256k1_v0_11_modinv64_signed62 SECP256K1_SIGNED62_ONE = {{1}}; /* Compute a*factor and put it in r. All but the top limb in r will be in range [0,2^62). */ -static void rustsecp256k1_v0_10_0_modinv64_mul_62(rustsecp256k1_v0_10_0_modinv64_signed62 *r, const rustsecp256k1_v0_10_0_modinv64_signed62 *a, int alen, int64_t factor) { +static void rustsecp256k1_v0_11_modinv64_mul_62(rustsecp256k1_v0_11_modinv64_signed62 *r, const rustsecp256k1_v0_11_modinv64_signed62 *a, int alen, int64_t factor) { const uint64_t M62 = UINT64_MAX >> 2; - rustsecp256k1_v0_10_0_int128 c, d; + rustsecp256k1_v0_11_int128 c, d; int i; - rustsecp256k1_v0_10_0_i128_from_i64(&c, 0); + rustsecp256k1_v0_11_i128_from_i64(&c, 0); for (i = 0; i < 4; ++i) { - if (i < alen) rustsecp256k1_v0_10_0_i128_accum_mul(&c, a->v[i], factor); - r->v[i] = rustsecp256k1_v0_10_0_i128_to_u64(&c) & M62; rustsecp256k1_v0_10_0_i128_rshift(&c, 62); + if (i < alen) rustsecp256k1_v0_11_i128_accum_mul(&c, a->v[i], factor); + r->v[i] = rustsecp256k1_v0_11_i128_to_u64(&c) & M62; rustsecp256k1_v0_11_i128_rshift(&c, 62); } - if (4 < alen) rustsecp256k1_v0_10_0_i128_accum_mul(&c, a->v[4], factor); - rustsecp256k1_v0_10_0_i128_from_i64(&d, rustsecp256k1_v0_10_0_i128_to_i64(&c)); - VERIFY_CHECK(rustsecp256k1_v0_10_0_i128_eq_var(&c, &d)); - r->v[4] = rustsecp256k1_v0_10_0_i128_to_i64(&c); + if (4 < alen) rustsecp256k1_v0_11_i128_accum_mul(&c, a->v[4], factor); + rustsecp256k1_v0_11_i128_from_i64(&d, rustsecp256k1_v0_11_i128_to_i64(&c)); + VERIFY_CHECK(rustsecp256k1_v0_11_i128_eq_var(&c, &d)); + r->v[4] = rustsecp256k1_v0_11_i128_to_i64(&c); } /* Return -1 for ab*factor. A has alen limbs; b has 5. */ -static int rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(const rustsecp256k1_v0_10_0_modinv64_signed62 *a, int alen, const rustsecp256k1_v0_10_0_modinv64_signed62 *b, int64_t factor) { +static int rustsecp256k1_v0_11_modinv64_mul_cmp_62(const rustsecp256k1_v0_11_modinv64_signed62 *a, int alen, const rustsecp256k1_v0_11_modinv64_signed62 *b, int64_t factor) { int i; - rustsecp256k1_v0_10_0_modinv64_signed62 am, bm; - rustsecp256k1_v0_10_0_modinv64_mul_62(&am, a, alen, 1); /* Normalize all but the top limb of a. */ - rustsecp256k1_v0_10_0_modinv64_mul_62(&bm, b, 5, factor); + rustsecp256k1_v0_11_modinv64_signed62 am, bm; + rustsecp256k1_v0_11_modinv64_mul_62(&am, a, alen, 1); /* Normalize all but the top limb of a. */ + rustsecp256k1_v0_11_modinv64_mul_62(&bm, b, 5, factor); for (i = 0; i < 4; ++i) { /* Verify that all but the top limb of a and b are normalized. */ VERIFY_CHECK(am.v[i] >> 62 == 0); @@ -72,11 +72,11 @@ static int rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(const rustsecp256k1_v0_10_0 } /* Check if the determinant of t is equal to 1 << n. If abs, check if |det t| == 1 << n. */ -static int rustsecp256k1_v0_10_0_modinv64_det_check_pow2(const rustsecp256k1_v0_10_0_modinv64_trans2x2 *t, unsigned int n, int abs) { - rustsecp256k1_v0_10_0_int128 a; - rustsecp256k1_v0_10_0_i128_det(&a, t->u, t->v, t->q, t->r); - if (rustsecp256k1_v0_10_0_i128_check_pow2(&a, n, 1)) return 1; - if (abs && rustsecp256k1_v0_10_0_i128_check_pow2(&a, n, -1)) return 1; +static int rustsecp256k1_v0_11_modinv64_det_check_pow2(const rustsecp256k1_v0_11_modinv64_trans2x2 *t, unsigned int n, int abs) { + rustsecp256k1_v0_11_int128 a; + rustsecp256k1_v0_11_i128_det(&a, t->u, t->v, t->q, t->r); + if (rustsecp256k1_v0_11_i128_check_pow2(&a, n, 1)) return 1; + if (abs && rustsecp256k1_v0_11_i128_check_pow2(&a, n, -1)) return 1; return 0; } #endif @@ -85,7 +85,7 @@ static int rustsecp256k1_v0_10_0_modinv64_det_check_pow2(const rustsecp256k1_v0_ * to it to bring it to range [0,modulus). If sign < 0, the input will also be negated in the * process. The input must have limbs in range (-2^62,2^62). The output will have limbs in range * [0,2^62). */ -static void rustsecp256k1_v0_10_0_modinv64_normalize_62(rustsecp256k1_v0_10_0_modinv64_signed62 *r, int64_t sign, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo) { +static void rustsecp256k1_v0_11_modinv64_normalize_62(rustsecp256k1_v0_11_modinv64_signed62 *r, int64_t sign, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo) { const int64_t M62 = (int64_t)(UINT64_MAX >> 2); int64_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4]; volatile int64_t cond_add, cond_negate; @@ -97,8 +97,8 @@ static void rustsecp256k1_v0_10_0_modinv64_normalize_62(rustsecp256k1_v0_10_0_mo VERIFY_CHECK(r->v[i] >= -M62); VERIFY_CHECK(r->v[i] <= M62); } - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, -2) > 0); /* r > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 1) < 0); /* r < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, -2) > 0); /* r > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 1) < 0); /* r < modulus */ #endif /* In a first step, add the modulus if the input is negative, and then negate if requested. @@ -149,8 +149,8 @@ static void rustsecp256k1_v0_10_0_modinv64_normalize_62(rustsecp256k1_v0_10_0_mo VERIFY_CHECK(r2 >> 62 == 0); VERIFY_CHECK(r3 >> 62 == 0); VERIFY_CHECK(r4 >> 62 == 0); - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 0) >= 0); /* r >= 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 1) < 0); /* r < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 0) >= 0); /* r >= 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(r, 5, &modinfo->modulus, 1) < 0); /* r < modulus */ } /* Compute the transition matrix and eta for 59 divsteps (where zeta=-(delta+1/2)). @@ -164,7 +164,7 @@ static void rustsecp256k1_v0_10_0_modinv64_normalize_62(rustsecp256k1_v0_10_0_mo * * Implements the divsteps_n_matrix function from the explanation. */ -static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_t g0, rustsecp256k1_v0_10_0_modinv64_trans2x2 *t) { +static int64_t rustsecp256k1_v0_11_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_t g0, rustsecp256k1_v0_11_modinv64_trans2x2 *t) { /* u,v,q,r are the elements of the transformation matrix being built up, * starting with the identity matrix times 8 (because the caller expects * a result scaled by 2^62). Semantically they are signed integers @@ -221,7 +221,7 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_59(int64_t zeta, uint64_t * aggregate of 59 of them will have determinant 2^59. Multiplying with the initial * 8*identity (which has determinant 2^6) means the overall outputs has determinant * 2^65. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_det_check_pow2(t, 65, 0)); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_det_check_pow2(t, 65, 0)); return zeta; } @@ -236,8 +236,8 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_59(int64_t zeta, uint64_t * * Implements the divsteps_n_matrix_var function from the explanation. */ -static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, rustsecp256k1_v0_10_0_modinv64_trans2x2 *t) { - /* Transformation matrix; see comments in rustsecp256k1_v0_10_0_modinv64_divsteps_62. */ +static int64_t rustsecp256k1_v0_11_modinv64_divsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, rustsecp256k1_v0_11_modinv64_trans2x2 *t) { + /* Transformation matrix; see comments in rustsecp256k1_v0_11_modinv64_divsteps_62. */ uint64_t u = 1, v = 0, q = 0, r = 1; uint64_t f = f0, g = g0, m; uint32_t w; @@ -245,7 +245,7 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_62_var(int64_t eta, uint6 for (;;) { /* Use a sentinel bit to count zeros only up to i. */ - zeros = rustsecp256k1_v0_10_0_ctz64_var(g | (UINT64_MAX << i)); + zeros = rustsecp256k1_v0_11_ctz64_var(g | (UINT64_MAX << i)); /* Perform zeros divsteps at once; they all just divide g by two. */ g >>= zeros; u <<= zeros; @@ -304,7 +304,7 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_62_var(int64_t eta, uint6 * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which * will be divided out again). As each divstep's individual matrix has determinant 2, the * aggregate of 62 of them will have determinant 2^62. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_det_check_pow2(t, 62, 0)); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_det_check_pow2(t, 62, 0)); return eta; } @@ -322,8 +322,8 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_divsteps_62_var(int64_t eta, uint6 * change, but are meaningless. * Return: final eta */ -static int64_t rustsecp256k1_v0_10_0_modinv64_posdivsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, rustsecp256k1_v0_10_0_modinv64_trans2x2 *t, int *jacp) { - /* Transformation matrix; see comments in rustsecp256k1_v0_10_0_modinv64_divsteps_62. */ +static int64_t rustsecp256k1_v0_11_modinv64_posdivsteps_62_var(int64_t eta, uint64_t f0, uint64_t g0, rustsecp256k1_v0_11_modinv64_trans2x2 *t, int *jacp) { + /* Transformation matrix; see comments in rustsecp256k1_v0_11_modinv64_divsteps_62. */ uint64_t u = 1, v = 0, q = 0, r = 1; uint64_t f = f0, g = g0, m; uint32_t w; @@ -332,7 +332,7 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_posdivsteps_62_var(int64_t eta, ui for (;;) { /* Use a sentinel bit to count zeros only up to i. */ - zeros = rustsecp256k1_v0_10_0_ctz64_var(g | (UINT64_MAX << i)); + zeros = rustsecp256k1_v0_11_ctz64_var(g | (UINT64_MAX << i)); /* Perform zeros divsteps at once; they all just divide g by two. */ g >>= zeros; u <<= zeros; @@ -395,7 +395,7 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_posdivsteps_62_var(int64_t eta, ui * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which * will be divided out again). As each divstep's individual matrix has determinant 2 or -2, * the aggregate of 62 of them will have determinant 2^62 or -2^62. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_det_check_pow2(t, 62, 1)); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_det_check_pow2(t, 62, 1)); *jacp = jac; return eta; @@ -408,19 +408,19 @@ static int64_t rustsecp256k1_v0_10_0_modinv64_posdivsteps_62_var(int64_t eta, ui * * This implements the update_de function from the explanation. */ -static void rustsecp256k1_v0_10_0_modinv64_update_de_62(rustsecp256k1_v0_10_0_modinv64_signed62 *d, rustsecp256k1_v0_10_0_modinv64_signed62 *e, const rustsecp256k1_v0_10_0_modinv64_trans2x2 *t, const rustsecp256k1_v0_10_0_modinv64_modinfo* modinfo) { +static void rustsecp256k1_v0_11_modinv64_update_de_62(rustsecp256k1_v0_11_modinv64_signed62 *d, rustsecp256k1_v0_11_modinv64_signed62 *e, const rustsecp256k1_v0_11_modinv64_trans2x2 *t, const rustsecp256k1_v0_11_modinv64_modinfo* modinfo) { const uint64_t M62 = UINT64_MAX >> 2; const int64_t d0 = d->v[0], d1 = d->v[1], d2 = d->v[2], d3 = d->v[3], d4 = d->v[4]; const int64_t e0 = e->v[0], e1 = e->v[1], e2 = e->v[2], e3 = e->v[3], e4 = e->v[4]; const int64_t u = t->u, v = t->v, q = t->q, r = t->r; int64_t md, me, sd, se; - rustsecp256k1_v0_10_0_int128 cd, ce; - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_abs(u) <= (((int64_t)1 << 62) - rustsecp256k1_v0_10_0_modinv64_abs(v))); /* |u|+|v| <= 2^62 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_abs(q) <= (((int64_t)1 << 62) - rustsecp256k1_v0_10_0_modinv64_abs(r))); /* |q|+|r| <= 2^62 */ + rustsecp256k1_v0_11_int128 cd, ce; + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_abs(u) <= (((int64_t)1 << 62) - rustsecp256k1_v0_11_modinv64_abs(v))); /* |u|+|v| <= 2^62 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_abs(q) <= (((int64_t)1 << 62) - rustsecp256k1_v0_11_modinv64_abs(r))); /* |q|+|r| <= 2^62 */ /* [md,me] start as zero; plus [u,q] if d is negative; plus [v,r] if e is negative. */ sd = d4 >> 63; @@ -428,120 +428,120 @@ static void rustsecp256k1_v0_10_0_modinv64_update_de_62(rustsecp256k1_v0_10_0_mo md = (u & sd) + (v & se); me = (q & sd) + (r & se); /* Begin computing t*[d,e]. */ - rustsecp256k1_v0_10_0_i128_mul(&cd, u, d0); - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, v, e0); - rustsecp256k1_v0_10_0_i128_mul(&ce, q, d0); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, r, e0); + rustsecp256k1_v0_11_i128_mul(&cd, u, d0); + rustsecp256k1_v0_11_i128_accum_mul(&cd, v, e0); + rustsecp256k1_v0_11_i128_mul(&ce, q, d0); + rustsecp256k1_v0_11_i128_accum_mul(&ce, r, e0); /* Correct md,me so that t*[d,e]+modulus*[md,me] has 62 zero bottom bits. */ - md -= (modinfo->modulus_inv62 * rustsecp256k1_v0_10_0_i128_to_u64(&cd) + md) & M62; - me -= (modinfo->modulus_inv62 * rustsecp256k1_v0_10_0_i128_to_u64(&ce) + me) & M62; + md -= (modinfo->modulus_inv62 * rustsecp256k1_v0_11_i128_to_u64(&cd) + md) & M62; + me -= (modinfo->modulus_inv62 * rustsecp256k1_v0_11_i128_to_u64(&ce) + me) & M62; /* Update the beginning of computation for t*[d,e]+modulus*[md,me] now md,me are known. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, modinfo->modulus.v[0], md); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, modinfo->modulus.v[0], me); + rustsecp256k1_v0_11_i128_accum_mul(&cd, modinfo->modulus.v[0], md); + rustsecp256k1_v0_11_i128_accum_mul(&ce, modinfo->modulus.v[0], me); /* Verify that the low 62 bits of the computation are indeed zero, and then throw them away. */ - VERIFY_CHECK((rustsecp256k1_v0_10_0_i128_to_u64(&cd) & M62) == 0); rustsecp256k1_v0_10_0_i128_rshift(&cd, 62); - VERIFY_CHECK((rustsecp256k1_v0_10_0_i128_to_u64(&ce) & M62) == 0); rustsecp256k1_v0_10_0_i128_rshift(&ce, 62); + VERIFY_CHECK((rustsecp256k1_v0_11_i128_to_u64(&cd) & M62) == 0); rustsecp256k1_v0_11_i128_rshift(&cd, 62); + VERIFY_CHECK((rustsecp256k1_v0_11_i128_to_u64(&ce) & M62) == 0); rustsecp256k1_v0_11_i128_rshift(&ce, 62); /* Compute limb 1 of t*[d,e]+modulus*[md,me], and store it as output limb 0 (= down shift). */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, u, d1); - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, v, e1); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, q, d1); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, r, e1); + rustsecp256k1_v0_11_i128_accum_mul(&cd, u, d1); + rustsecp256k1_v0_11_i128_accum_mul(&cd, v, e1); + rustsecp256k1_v0_11_i128_accum_mul(&ce, q, d1); + rustsecp256k1_v0_11_i128_accum_mul(&ce, r, e1); if (modinfo->modulus.v[1]) { /* Optimize for the case where limb of modulus is zero. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, modinfo->modulus.v[1], md); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, modinfo->modulus.v[1], me); + rustsecp256k1_v0_11_i128_accum_mul(&cd, modinfo->modulus.v[1], md); + rustsecp256k1_v0_11_i128_accum_mul(&ce, modinfo->modulus.v[1], me); } - d->v[0] = rustsecp256k1_v0_10_0_i128_to_u64(&cd) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cd, 62); - e->v[0] = rustsecp256k1_v0_10_0_i128_to_u64(&ce) & M62; rustsecp256k1_v0_10_0_i128_rshift(&ce, 62); + d->v[0] = rustsecp256k1_v0_11_i128_to_u64(&cd) & M62; rustsecp256k1_v0_11_i128_rshift(&cd, 62); + e->v[0] = rustsecp256k1_v0_11_i128_to_u64(&ce) & M62; rustsecp256k1_v0_11_i128_rshift(&ce, 62); /* Compute limb 2 of t*[d,e]+modulus*[md,me], and store it as output limb 1. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, u, d2); - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, v, e2); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, q, d2); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, r, e2); + rustsecp256k1_v0_11_i128_accum_mul(&cd, u, d2); + rustsecp256k1_v0_11_i128_accum_mul(&cd, v, e2); + rustsecp256k1_v0_11_i128_accum_mul(&ce, q, d2); + rustsecp256k1_v0_11_i128_accum_mul(&ce, r, e2); if (modinfo->modulus.v[2]) { /* Optimize for the case where limb of modulus is zero. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, modinfo->modulus.v[2], md); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, modinfo->modulus.v[2], me); + rustsecp256k1_v0_11_i128_accum_mul(&cd, modinfo->modulus.v[2], md); + rustsecp256k1_v0_11_i128_accum_mul(&ce, modinfo->modulus.v[2], me); } - d->v[1] = rustsecp256k1_v0_10_0_i128_to_u64(&cd) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cd, 62); - e->v[1] = rustsecp256k1_v0_10_0_i128_to_u64(&ce) & M62; rustsecp256k1_v0_10_0_i128_rshift(&ce, 62); + d->v[1] = rustsecp256k1_v0_11_i128_to_u64(&cd) & M62; rustsecp256k1_v0_11_i128_rshift(&cd, 62); + e->v[1] = rustsecp256k1_v0_11_i128_to_u64(&ce) & M62; rustsecp256k1_v0_11_i128_rshift(&ce, 62); /* Compute limb 3 of t*[d,e]+modulus*[md,me], and store it as output limb 2. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, u, d3); - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, v, e3); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, q, d3); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, r, e3); + rustsecp256k1_v0_11_i128_accum_mul(&cd, u, d3); + rustsecp256k1_v0_11_i128_accum_mul(&cd, v, e3); + rustsecp256k1_v0_11_i128_accum_mul(&ce, q, d3); + rustsecp256k1_v0_11_i128_accum_mul(&ce, r, e3); if (modinfo->modulus.v[3]) { /* Optimize for the case where limb of modulus is zero. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, modinfo->modulus.v[3], md); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, modinfo->modulus.v[3], me); + rustsecp256k1_v0_11_i128_accum_mul(&cd, modinfo->modulus.v[3], md); + rustsecp256k1_v0_11_i128_accum_mul(&ce, modinfo->modulus.v[3], me); } - d->v[2] = rustsecp256k1_v0_10_0_i128_to_u64(&cd) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cd, 62); - e->v[2] = rustsecp256k1_v0_10_0_i128_to_u64(&ce) & M62; rustsecp256k1_v0_10_0_i128_rshift(&ce, 62); + d->v[2] = rustsecp256k1_v0_11_i128_to_u64(&cd) & M62; rustsecp256k1_v0_11_i128_rshift(&cd, 62); + e->v[2] = rustsecp256k1_v0_11_i128_to_u64(&ce) & M62; rustsecp256k1_v0_11_i128_rshift(&ce, 62); /* Compute limb 4 of t*[d,e]+modulus*[md,me], and store it as output limb 3. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, u, d4); - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, v, e4); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, q, d4); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, r, e4); - rustsecp256k1_v0_10_0_i128_accum_mul(&cd, modinfo->modulus.v[4], md); - rustsecp256k1_v0_10_0_i128_accum_mul(&ce, modinfo->modulus.v[4], me); - d->v[3] = rustsecp256k1_v0_10_0_i128_to_u64(&cd) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cd, 62); - e->v[3] = rustsecp256k1_v0_10_0_i128_to_u64(&ce) & M62; rustsecp256k1_v0_10_0_i128_rshift(&ce, 62); + rustsecp256k1_v0_11_i128_accum_mul(&cd, u, d4); + rustsecp256k1_v0_11_i128_accum_mul(&cd, v, e4); + rustsecp256k1_v0_11_i128_accum_mul(&ce, q, d4); + rustsecp256k1_v0_11_i128_accum_mul(&ce, r, e4); + rustsecp256k1_v0_11_i128_accum_mul(&cd, modinfo->modulus.v[4], md); + rustsecp256k1_v0_11_i128_accum_mul(&ce, modinfo->modulus.v[4], me); + d->v[3] = rustsecp256k1_v0_11_i128_to_u64(&cd) & M62; rustsecp256k1_v0_11_i128_rshift(&cd, 62); + e->v[3] = rustsecp256k1_v0_11_i128_to_u64(&ce) & M62; rustsecp256k1_v0_11_i128_rshift(&ce, 62); /* What remains is limb 5 of t*[d,e]+modulus*[md,me]; store it as output limb 4. */ - d->v[4] = rustsecp256k1_v0_10_0_i128_to_i64(&cd); - e->v[4] = rustsecp256k1_v0_10_0_i128_to_i64(&ce); + d->v[4] = rustsecp256k1_v0_11_i128_to_i64(&cd); + e->v[4] = rustsecp256k1_v0_11_i128_to_i64(&ce); - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, -2) > 0); /* d > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(d, 5, &modinfo->modulus, 1) < 0); /* d < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, -2) > 0); /* e > -2*modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(e, 5, &modinfo->modulus, 1) < 0); /* e < modulus */ } /* Compute (t/2^62) * [f, g], where t is a transition matrix scaled by 2^62. * * This implements the update_fg function from the explanation. */ -static void rustsecp256k1_v0_10_0_modinv64_update_fg_62(rustsecp256k1_v0_10_0_modinv64_signed62 *f, rustsecp256k1_v0_10_0_modinv64_signed62 *g, const rustsecp256k1_v0_10_0_modinv64_trans2x2 *t) { +static void rustsecp256k1_v0_11_modinv64_update_fg_62(rustsecp256k1_v0_11_modinv64_signed62 *f, rustsecp256k1_v0_11_modinv64_signed62 *g, const rustsecp256k1_v0_11_modinv64_trans2x2 *t) { const uint64_t M62 = UINT64_MAX >> 2; const int64_t f0 = f->v[0], f1 = f->v[1], f2 = f->v[2], f3 = f->v[3], f4 = f->v[4]; const int64_t g0 = g->v[0], g1 = g->v[1], g2 = g->v[2], g3 = g->v[3], g4 = g->v[4]; const int64_t u = t->u, v = t->v, q = t->q, r = t->r; - rustsecp256k1_v0_10_0_int128 cf, cg; + rustsecp256k1_v0_11_int128 cf, cg; /* Start computing t*[f,g]. */ - rustsecp256k1_v0_10_0_i128_mul(&cf, u, f0); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, g0); - rustsecp256k1_v0_10_0_i128_mul(&cg, q, f0); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, g0); + rustsecp256k1_v0_11_i128_mul(&cf, u, f0); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, g0); + rustsecp256k1_v0_11_i128_mul(&cg, q, f0); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, g0); /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */ - VERIFY_CHECK((rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62) == 0); rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - VERIFY_CHECK((rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62) == 0); rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + VERIFY_CHECK((rustsecp256k1_v0_11_i128_to_u64(&cf) & M62) == 0); rustsecp256k1_v0_11_i128_rshift(&cf, 62); + VERIFY_CHECK((rustsecp256k1_v0_11_i128_to_u64(&cg) & M62) == 0); rustsecp256k1_v0_11_i128_rshift(&cg, 62); /* Compute limb 1 of t*[f,g], and store it as output limb 0 (= down shift). */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, u, f1); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, g1); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, q, f1); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, g1); - f->v[0] = rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - g->v[0] = rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + rustsecp256k1_v0_11_i128_accum_mul(&cf, u, f1); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, g1); + rustsecp256k1_v0_11_i128_accum_mul(&cg, q, f1); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, g1); + f->v[0] = rustsecp256k1_v0_11_i128_to_u64(&cf) & M62; rustsecp256k1_v0_11_i128_rshift(&cf, 62); + g->v[0] = rustsecp256k1_v0_11_i128_to_u64(&cg) & M62; rustsecp256k1_v0_11_i128_rshift(&cg, 62); /* Compute limb 2 of t*[f,g], and store it as output limb 1. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, u, f2); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, g2); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, q, f2); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, g2); - f->v[1] = rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - g->v[1] = rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + rustsecp256k1_v0_11_i128_accum_mul(&cf, u, f2); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, g2); + rustsecp256k1_v0_11_i128_accum_mul(&cg, q, f2); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, g2); + f->v[1] = rustsecp256k1_v0_11_i128_to_u64(&cf) & M62; rustsecp256k1_v0_11_i128_rshift(&cf, 62); + g->v[1] = rustsecp256k1_v0_11_i128_to_u64(&cg) & M62; rustsecp256k1_v0_11_i128_rshift(&cg, 62); /* Compute limb 3 of t*[f,g], and store it as output limb 2. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, u, f3); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, g3); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, q, f3); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, g3); - f->v[2] = rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - g->v[2] = rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + rustsecp256k1_v0_11_i128_accum_mul(&cf, u, f3); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, g3); + rustsecp256k1_v0_11_i128_accum_mul(&cg, q, f3); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, g3); + f->v[2] = rustsecp256k1_v0_11_i128_to_u64(&cf) & M62; rustsecp256k1_v0_11_i128_rshift(&cf, 62); + g->v[2] = rustsecp256k1_v0_11_i128_to_u64(&cg) & M62; rustsecp256k1_v0_11_i128_rshift(&cg, 62); /* Compute limb 4 of t*[f,g], and store it as output limb 3. */ - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, u, f4); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, g4); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, q, f4); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, g4); - f->v[3] = rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - g->v[3] = rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + rustsecp256k1_v0_11_i128_accum_mul(&cf, u, f4); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, g4); + rustsecp256k1_v0_11_i128_accum_mul(&cg, q, f4); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, g4); + f->v[3] = rustsecp256k1_v0_11_i128_to_u64(&cf) & M62; rustsecp256k1_v0_11_i128_rshift(&cf, 62); + g->v[3] = rustsecp256k1_v0_11_i128_to_u64(&cg) & M62; rustsecp256k1_v0_11_i128_rshift(&cg, 62); /* What remains is limb 5 of t*[f,g]; store it as output limb 4. */ - f->v[4] = rustsecp256k1_v0_10_0_i128_to_i64(&cf); - g->v[4] = rustsecp256k1_v0_10_0_i128_to_i64(&cg); + f->v[4] = rustsecp256k1_v0_11_i128_to_i64(&cf); + g->v[4] = rustsecp256k1_v0_11_i128_to_i64(&cg); } /* Compute (t/2^62) * [f, g], where t is a transition matrix for 62 divsteps. @@ -550,69 +550,69 @@ static void rustsecp256k1_v0_10_0_modinv64_update_fg_62(rustsecp256k1_v0_10_0_mo * * This implements the update_fg function from the explanation. */ -static void rustsecp256k1_v0_10_0_modinv64_update_fg_62_var(int len, rustsecp256k1_v0_10_0_modinv64_signed62 *f, rustsecp256k1_v0_10_0_modinv64_signed62 *g, const rustsecp256k1_v0_10_0_modinv64_trans2x2 *t) { +static void rustsecp256k1_v0_11_modinv64_update_fg_62_var(int len, rustsecp256k1_v0_11_modinv64_signed62 *f, rustsecp256k1_v0_11_modinv64_signed62 *g, const rustsecp256k1_v0_11_modinv64_trans2x2 *t) { const uint64_t M62 = UINT64_MAX >> 2; const int64_t u = t->u, v = t->v, q = t->q, r = t->r; int64_t fi, gi; - rustsecp256k1_v0_10_0_int128 cf, cg; + rustsecp256k1_v0_11_int128 cf, cg; int i; VERIFY_CHECK(len > 0); /* Start computing t*[f,g]. */ fi = f->v[0]; gi = g->v[0]; - rustsecp256k1_v0_10_0_i128_mul(&cf, u, fi); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, gi); - rustsecp256k1_v0_10_0_i128_mul(&cg, q, fi); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, gi); + rustsecp256k1_v0_11_i128_mul(&cf, u, fi); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, gi); + rustsecp256k1_v0_11_i128_mul(&cg, q, fi); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, gi); /* Verify that the bottom 62 bits of the result are zero, and then throw them away. */ - VERIFY_CHECK((rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62) == 0); rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - VERIFY_CHECK((rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62) == 0); rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + VERIFY_CHECK((rustsecp256k1_v0_11_i128_to_u64(&cf) & M62) == 0); rustsecp256k1_v0_11_i128_rshift(&cf, 62); + VERIFY_CHECK((rustsecp256k1_v0_11_i128_to_u64(&cg) & M62) == 0); rustsecp256k1_v0_11_i128_rshift(&cg, 62); /* Now iteratively compute limb i=1..len of t*[f,g], and store them in output limb i-1 (shifting * down by 62 bits). */ for (i = 1; i < len; ++i) { fi = f->v[i]; gi = g->v[i]; - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, u, fi); - rustsecp256k1_v0_10_0_i128_accum_mul(&cf, v, gi); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, q, fi); - rustsecp256k1_v0_10_0_i128_accum_mul(&cg, r, gi); - f->v[i - 1] = rustsecp256k1_v0_10_0_i128_to_u64(&cf) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cf, 62); - g->v[i - 1] = rustsecp256k1_v0_10_0_i128_to_u64(&cg) & M62; rustsecp256k1_v0_10_0_i128_rshift(&cg, 62); + rustsecp256k1_v0_11_i128_accum_mul(&cf, u, fi); + rustsecp256k1_v0_11_i128_accum_mul(&cf, v, gi); + rustsecp256k1_v0_11_i128_accum_mul(&cg, q, fi); + rustsecp256k1_v0_11_i128_accum_mul(&cg, r, gi); + f->v[i - 1] = rustsecp256k1_v0_11_i128_to_u64(&cf) & M62; rustsecp256k1_v0_11_i128_rshift(&cf, 62); + g->v[i - 1] = rustsecp256k1_v0_11_i128_to_u64(&cg) & M62; rustsecp256k1_v0_11_i128_rshift(&cg, 62); } /* What remains is limb (len) of t*[f,g]; store it as output limb (len-1). */ - f->v[len - 1] = rustsecp256k1_v0_10_0_i128_to_i64(&cf); - g->v[len - 1] = rustsecp256k1_v0_10_0_i128_to_i64(&cg); + f->v[len - 1] = rustsecp256k1_v0_11_i128_to_i64(&cf); + g->v[len - 1] = rustsecp256k1_v0_11_i128_to_i64(&cg); } /* Compute the inverse of x modulo modinfo->modulus, and replace x with it (constant time in x). */ -static void rustsecp256k1_v0_10_0_modinv64(rustsecp256k1_v0_10_0_modinv64_signed62 *x, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo) { +static void rustsecp256k1_v0_11_modinv64(rustsecp256k1_v0_11_modinv64_signed62 *x, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo) { /* Start with d=0, e=1, f=modulus, g=x, zeta=-1. */ - rustsecp256k1_v0_10_0_modinv64_signed62 d = {{0, 0, 0, 0, 0}}; - rustsecp256k1_v0_10_0_modinv64_signed62 e = {{1, 0, 0, 0, 0}}; - rustsecp256k1_v0_10_0_modinv64_signed62 f = modinfo->modulus; - rustsecp256k1_v0_10_0_modinv64_signed62 g = *x; + rustsecp256k1_v0_11_modinv64_signed62 d = {{0, 0, 0, 0, 0}}; + rustsecp256k1_v0_11_modinv64_signed62 e = {{1, 0, 0, 0, 0}}; + rustsecp256k1_v0_11_modinv64_signed62 f = modinfo->modulus; + rustsecp256k1_v0_11_modinv64_signed62 g = *x; int i; int64_t zeta = -1; /* zeta = -(delta+1/2); delta starts at 1/2. */ /* Do 10 iterations of 59 divsteps each = 590 divsteps. This suffices for 256-bit inputs. */ for (i = 0; i < 10; ++i) { /* Compute transition matrix and new zeta after 59 divsteps. */ - rustsecp256k1_v0_10_0_modinv64_trans2x2 t; - zeta = rustsecp256k1_v0_10_0_modinv64_divsteps_59(zeta, f.v[0], g.v[0], &t); + rustsecp256k1_v0_11_modinv64_trans2x2 t; + zeta = rustsecp256k1_v0_11_modinv64_divsteps_59(zeta, f.v[0], g.v[0], &t); /* Update d,e using that transition matrix. */ - rustsecp256k1_v0_10_0_modinv64_update_de_62(&d, &e, &t, modinfo); + rustsecp256k1_v0_11_modinv64_update_de_62(&d, &e, &t, modinfo); /* Update f,g using that transition matrix. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, 1) < 0); /* g < modulus */ - rustsecp256k1_v0_10_0_modinv64_update_fg_62(&f, &g, &t); + rustsecp256k1_v0_11_modinv64_update_fg_62(&f, &g, &t); - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, 5, &modinfo->modulus, 1) < 0); /* g < modulus */ } /* At this point sufficient iterations have been performed that g must have reached 0 @@ -620,27 +620,26 @@ static void rustsecp256k1_v0_10_0_modinv64(rustsecp256k1_v0_10_0_modinv64_signed * values i.e. +/- 1, and d now contains +/- the modular inverse. */ /* g == 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, 5, &SECP256K1_SIGNED62_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, -1) == 0 || - rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, 1) == 0 || - (rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - (rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) == 0 || - rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, -1) == 0))); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, 5, &SECP256K1_SIGNED62_ONE, 0) == 0); + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, -1) == 0 || + rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &SECP256K1_SIGNED62_ONE, 1) == 0 || + (rustsecp256k1_v0_11_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, 5, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ - rustsecp256k1_v0_10_0_modinv64_normalize_62(&d, f.v[4], modinfo); + rustsecp256k1_v0_11_modinv64_normalize_62(&d, f.v[4], modinfo); *x = d; } /* Compute the inverse of x modulo modinfo->modulus, and replace x with it (variable time). */ -static void rustsecp256k1_v0_10_0_modinv64_var(rustsecp256k1_v0_10_0_modinv64_signed62 *x, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo) { +static void rustsecp256k1_v0_11_modinv64_var(rustsecp256k1_v0_11_modinv64_signed62 *x, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo) { /* Start with d=0, e=1, f=modulus, g=x, eta=-1. */ - rustsecp256k1_v0_10_0_modinv64_signed62 d = {{0, 0, 0, 0, 0}}; - rustsecp256k1_v0_10_0_modinv64_signed62 e = {{1, 0, 0, 0, 0}}; - rustsecp256k1_v0_10_0_modinv64_signed62 f = modinfo->modulus; - rustsecp256k1_v0_10_0_modinv64_signed62 g = *x; + rustsecp256k1_v0_11_modinv64_signed62 d = {{0, 0, 0, 0, 0}}; + rustsecp256k1_v0_11_modinv64_signed62 e = {{1, 0, 0, 0, 0}}; + rustsecp256k1_v0_11_modinv64_signed62 f = modinfo->modulus; + rustsecp256k1_v0_11_modinv64_signed62 g = *x; #ifdef VERIFY int i = 0; #endif @@ -651,17 +650,17 @@ static void rustsecp256k1_v0_10_0_modinv64_var(rustsecp256k1_v0_10_0_modinv64_si /* Do iterations of 62 divsteps each until g=0. */ while (1) { /* Compute transition matrix and new eta after 62 divsteps. */ - rustsecp256k1_v0_10_0_modinv64_trans2x2 t; - eta = rustsecp256k1_v0_10_0_modinv64_divsteps_62_var(eta, f.v[0], g.v[0], &t); + rustsecp256k1_v0_11_modinv64_trans2x2 t; + eta = rustsecp256k1_v0_11_modinv64_divsteps_62_var(eta, f.v[0], g.v[0], &t); /* Update d,e using that transition matrix. */ - rustsecp256k1_v0_10_0_modinv64_update_de_62(&d, &e, &t, modinfo); + rustsecp256k1_v0_11_modinv64_update_de_62(&d, &e, &t, modinfo); /* Update f,g using that transition matrix. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - rustsecp256k1_v0_10_0_modinv64_update_fg_62_var(len, &f, &g, &t); + rustsecp256k1_v0_11_modinv64_update_fg_62_var(len, &f, &g, &t); /* If the bottom limb of g is zero, there is a chance that g=0. */ if (g.v[0] == 0) { cond = 0; @@ -687,27 +686,26 @@ static void rustsecp256k1_v0_10_0_modinv64_var(rustsecp256k1_v0_10_0_modinv64_si } VERIFY_CHECK(++i < 12); /* We should never need more than 12*62 = 744 divsteps */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) > 0); /* f > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, -1) > 0); /* g > -modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ } /* At this point g is 0 and (if g was not originally 0) f must now equal +/- GCD of * the initial f, g values i.e. +/- 1, and d now contains +/- the modular inverse. */ /* g == 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &SECP256K1_SIGNED62_ONE, 0) == 0); - /* |f| == 1, or (x == 0 and d == 0 and |f|=modulus) */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, -1) == 0 || - rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, 1) == 0 || - (rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && - (rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) == 0 || - rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, -1) == 0))); + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &SECP256K1_SIGNED62_ONE, 0) == 0); + /* |f| == 1, or (x == 0 and d == 0 and f == modulus) */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, -1) == 0 || + rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &SECP256K1_SIGNED62_ONE, 1) == 0 || + (rustsecp256k1_v0_11_modinv64_mul_cmp_62(x, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv64_mul_cmp_62(&d, 5, &SECP256K1_SIGNED62_ONE, 0) == 0 && + rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) == 0)); /* Optionally negate d, normalize to [0,modulus), and return it. */ - rustsecp256k1_v0_10_0_modinv64_normalize_62(&d, f.v[len - 1], modinfo); + rustsecp256k1_v0_11_modinv64_normalize_62(&d, f.v[len - 1], modinfo); *x = d; } @@ -720,10 +718,10 @@ static void rustsecp256k1_v0_10_0_modinv64_var(rustsecp256k1_v0_10_0_modinv64_si #endif /* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */ -static int rustsecp256k1_v0_10_0_jacobi64_maybe_var(const rustsecp256k1_v0_10_0_modinv64_signed62 *x, const rustsecp256k1_v0_10_0_modinv64_modinfo *modinfo) { +static int rustsecp256k1_v0_11_jacobi64_maybe_var(const rustsecp256k1_v0_11_modinv64_signed62 *x, const rustsecp256k1_v0_11_modinv64_modinfo *modinfo) { /* Start with f=modulus, g=x, eta=-1. */ - rustsecp256k1_v0_10_0_modinv64_signed62 f = modinfo->modulus; - rustsecp256k1_v0_10_0_modinv64_signed62 g = *x; + rustsecp256k1_v0_11_modinv64_signed62 f = modinfo->modulus; + rustsecp256k1_v0_11_modinv64_signed62 g = *x; int j, len = 5; int64_t eta = -1; /* eta = -delta; delta is initially 1 */ int64_t cond, fn, gn; @@ -740,15 +738,15 @@ static int rustsecp256k1_v0_10_0_jacobi64_maybe_var(const rustsecp256k1_v0_10_0_ for (count = 0; count < JACOBI64_ITERATIONS; ++count) { /* Compute transition matrix and new eta after 62 posdivsteps. */ - rustsecp256k1_v0_10_0_modinv64_trans2x2 t; - eta = rustsecp256k1_v0_10_0_modinv64_posdivsteps_62_var(eta, f.v[0] | ((uint64_t)f.v[1] << 62), g.v[0] | ((uint64_t)g.v[1] << 62), &t, &jac); + rustsecp256k1_v0_11_modinv64_trans2x2 t; + eta = rustsecp256k1_v0_11_modinv64_posdivsteps_62_var(eta, f.v[0] | ((uint64_t)f.v[1] << 62), g.v[0] | ((uint64_t)g.v[1] << 62), &t, &jac); /* Update f,g using that transition matrix. */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ - rustsecp256k1_v0_10_0_modinv64_update_fg_62_var(len, &f, &g, &t); + rustsecp256k1_v0_11_modinv64_update_fg_62_var(len, &f, &g, &t); /* If the bottom limb of f is 1, there is a chance that f=1. */ if (f.v[0] == 1) { cond = 0; @@ -769,10 +767,10 @@ static int rustsecp256k1_v0_10_0_jacobi64_maybe_var(const rustsecp256k1_v0_10_0_ /* If so, reduce length. */ if (cond == 0) --len; - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 0) > 0); /* f > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&f, len, &modinfo->modulus, 1) <= 0); /* f <= modulus */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 0) > 0); /* g > 0 */ + VERIFY_CHECK(rustsecp256k1_v0_11_modinv64_mul_cmp_62(&g, len, &modinfo->modulus, 1) < 0); /* g < modulus */ } /* The loop failed to converge to f=g after 1550 iterations. Return 0, indicating unknown result. */ diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include index bc75c44e8..1477c19c5 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/Makefile.am.include @@ -1,4 +1,4 @@ -include_HEADERS += include/rustsecp256k1_v0_10_0_ecdh.h +include_HEADERS += include/rustsecp256k1_v0_11_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 diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/bench_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/bench_impl.h index 62454b3d0..82d5a8b0d 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/bench_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/bench_impl.h @@ -10,8 +10,8 @@ #include "../../../include/secp256k1_ecdh.h" typedef struct { - rustsecp256k1_v0_10_0_context *ctx; - rustsecp256k1_v0_10_0_pubkey point; + rustsecp256k1_v0_11_context *ctx; + rustsecp256k1_v0_11_pubkey point; unsigned char scalar[32]; } bench_ecdh_data; @@ -29,7 +29,7 @@ static void bench_ecdh_setup(void* arg) { for (i = 0; i < 32; i++) { data->scalar[i] = i + 1; } - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); } static void bench_ecdh(void* arg, int iters) { @@ -38,7 +38,7 @@ static void bench_ecdh(void* arg, int iters) { bench_ecdh_data *data = (bench_ecdh_data*)arg; for (i = 0; i < iters; i++) { - CHECK(rustsecp256k1_v0_10_0_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(data->ctx, res, &data->point, data->scalar, NULL, NULL) == 1); } } @@ -47,11 +47,11 @@ static void run_ecdh_bench(int iters, int argc, char** argv) { int d = argc == 1; /* create a context with no capabilities */ - data.ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); + data.ctx = rustsecp256k1_v0_11_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); if (d || have_flag(argc, argv, "ecdh")) run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); - rustsecp256k1_v0_10_0_context_destroy(data.ctx); + rustsecp256k1_v0_11_context_destroy(data.ctx); } #endif /* SECP256K1_MODULE_ECDH_BENCH_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h index ff02af60c..fe055a2a0 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/main_impl.h @@ -12,26 +12,27 @@ static int ecdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { unsigned char version = (y32[31] & 0x01) | 0x02; - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; (void)data; - rustsecp256k1_v0_10_0_sha256_initialize(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, &version, 1); - rustsecp256k1_v0_10_0_sha256_write(&sha, x32, 32); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, output); + rustsecp256k1_v0_11_sha256_initialize(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, &version, 1); + rustsecp256k1_v0_11_sha256_write(&sha, x32, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, output); + rustsecp256k1_v0_11_sha256_clear(&sha); return 1; } -const rustsecp256k1_v0_10_0_ecdh_hash_function rustsecp256k1_v0_10_0_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; -const rustsecp256k1_v0_10_0_ecdh_hash_function rustsecp256k1_v0_10_0_ecdh_hash_function_default = ecdh_hash_function_sha256; +const rustsecp256k1_v0_11_ecdh_hash_function rustsecp256k1_v0_11_ecdh_hash_function_sha256 = ecdh_hash_function_sha256; +const rustsecp256k1_v0_11_ecdh_hash_function rustsecp256k1_v0_11_ecdh_hash_function_default = ecdh_hash_function_sha256; -int rustsecp256k1_v0_10_0_ecdh(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *output, const rustsecp256k1_v0_10_0_pubkey *point, const unsigned char *scalar, rustsecp256k1_v0_10_0_ecdh_hash_function hashfp, void *data) { +int rustsecp256k1_v0_11_ecdh(const rustsecp256k1_v0_11_context* ctx, unsigned char *output, const rustsecp256k1_v0_11_pubkey *point, const unsigned char *scalar, rustsecp256k1_v0_11_ecdh_hash_function hashfp, void *data) { int ret = 0; int overflow = 0; - rustsecp256k1_v0_10_0_gej res; - rustsecp256k1_v0_10_0_ge pt; - rustsecp256k1_v0_10_0_scalar s; + rustsecp256k1_v0_11_gej res; + rustsecp256k1_v0_11_ge pt; + rustsecp256k1_v0_11_scalar s; unsigned char x[32]; unsigned char y[32]; @@ -41,29 +42,31 @@ int rustsecp256k1_v0_10_0_ecdh(const rustsecp256k1_v0_10_0_context* ctx, unsigne ARG_CHECK(scalar != NULL); if (hashfp == NULL) { - hashfp = rustsecp256k1_v0_10_0_ecdh_hash_function_default; + hashfp = rustsecp256k1_v0_11_ecdh_hash_function_default; } - rustsecp256k1_v0_10_0_pubkey_load(ctx, &pt, point); - rustsecp256k1_v0_10_0_scalar_set_b32(&s, scalar, &overflow); + rustsecp256k1_v0_11_pubkey_load(ctx, &pt, point); + rustsecp256k1_v0_11_scalar_set_b32(&s, scalar, &overflow); - overflow |= rustsecp256k1_v0_10_0_scalar_is_zero(&s); - rustsecp256k1_v0_10_0_scalar_cmov(&s, &rustsecp256k1_v0_10_0_scalar_one, overflow); + overflow |= rustsecp256k1_v0_11_scalar_is_zero(&s); + rustsecp256k1_v0_11_scalar_cmov(&s, &rustsecp256k1_v0_11_scalar_one, overflow); - rustsecp256k1_v0_10_0_ecmult_const(&res, &pt, &s); - rustsecp256k1_v0_10_0_ge_set_gej(&pt, &res); + rustsecp256k1_v0_11_ecmult_const(&res, &pt, &s); + rustsecp256k1_v0_11_ge_set_gej(&pt, &res); /* Compute a hash of the point */ - rustsecp256k1_v0_10_0_fe_normalize(&pt.x); - rustsecp256k1_v0_10_0_fe_normalize(&pt.y); - rustsecp256k1_v0_10_0_fe_get_b32(x, &pt.x); - rustsecp256k1_v0_10_0_fe_get_b32(y, &pt.y); + rustsecp256k1_v0_11_fe_normalize(&pt.x); + rustsecp256k1_v0_11_fe_normalize(&pt.y); + rustsecp256k1_v0_11_fe_get_b32(x, &pt.x); + rustsecp256k1_v0_11_fe_get_b32(y, &pt.y); ret = hashfp(output, x, y, data); - memset(x, 0, 32); - memset(y, 0, 32); - rustsecp256k1_v0_10_0_scalar_clear(&s); + rustsecp256k1_v0_11_memclear(x, sizeof(x)); + rustsecp256k1_v0_11_memclear(y, sizeof(y)); + rustsecp256k1_v0_11_scalar_clear(&s); + rustsecp256k1_v0_11_ge_clear(&pt); + rustsecp256k1_v0_11_gej_clear(&res); return !!ret & !overflow; } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h index 1524a079d..8d2200d94 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ecdh/tests_impl.h @@ -25,59 +25,59 @@ static int ecdh_hash_function_custom(unsigned char *output, const unsigned char } static void test_ecdh_api(void) { - rustsecp256k1_v0_10_0_pubkey point; + rustsecp256k1_v0_11_pubkey point; unsigned char res[32]; unsigned char s_one[32] = { 0 }; s_one[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point, s_one) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point, s_one) == 1); /* Check all NULLs are detected */ - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdh(CTX, NULL, &point, s_one, NULL, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdh(CTX, res, NULL, s_one, NULL, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdh(CTX, res, &point, NULL, NULL, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdh(CTX, NULL, &point, s_one, NULL, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdh(CTX, res, NULL, s_one, NULL, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdh(CTX, res, &point, NULL, NULL, NULL)); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, res, &point, s_one, NULL, NULL) == 1); } static void test_ecdh_generator_basepoint(void) { unsigned char s_one[32] = { 0 }; - rustsecp256k1_v0_10_0_pubkey point[2]; + rustsecp256k1_v0_11_pubkey point[2]; int i; s_one[31] = 1; /* Check against pubkey creation when the basepoint is the generator */ for (i = 0; i < 2 * COUNT; ++i) { - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; unsigned char s_b32[32]; unsigned char output_ecdh[65]; unsigned char output_ser[32]; unsigned char point_ser[65]; size_t point_ser_len = sizeof(point_ser); - rustsecp256k1_v0_10_0_scalar s; + rustsecp256k1_v0_11_scalar s; - random_scalar_order(&s); - rustsecp256k1_v0_10_0_scalar_get_b32(s_b32, &s); + testutil_random_scalar_order(&s); + rustsecp256k1_v0_11_scalar_get_b32(s_b32, &s); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point[0], s_one) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point[1], s_b32) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point[0], s_one) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point[1], s_b32) == 1); /* compute using ECDH function with custom hash function */ - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, output_ecdh, &point[0], s_b32, ecdh_hash_function_custom, NULL) == 1); /* compute "explicitly" */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_UNCOMPRESSED) == 1); /* compare */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(output_ecdh, point_ser, 65) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(output_ecdh, point_ser, 65) == 0); /* compute using ECDH function with default hash function */ - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, output_ecdh, &point[0], s_b32, NULL, NULL) == 1); /* compute "explicitly" */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); - rustsecp256k1_v0_10_0_sha256_initialize(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, point_ser, point_ser_len); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, output_ser); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); + rustsecp256k1_v0_11_sha256_initialize(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, point_ser, point_ser_len); + rustsecp256k1_v0_11_sha256_finalize(&sha, output_ser); /* compare */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(output_ecdh, output_ser, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(output_ecdh, output_ser, 32) == 0); } } @@ -91,29 +91,29 @@ static void test_bad_scalar(void) { }; unsigned char s_rand[32] = { 0 }; unsigned char output[32]; - rustsecp256k1_v0_10_0_scalar rand; - rustsecp256k1_v0_10_0_pubkey point; + rustsecp256k1_v0_11_scalar rand; + rustsecp256k1_v0_11_pubkey point; /* Create random point */ - random_scalar_order(&rand); - rustsecp256k1_v0_10_0_scalar_get_b32(s_rand, &rand); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point, s_rand) == 1); + testutil_random_scalar_order(&rand); + rustsecp256k1_v0_11_scalar_get_b32(s_rand, &rand); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point, s_rand) == 1); /* Try to multiply it by bad values */ - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, output, &point, s_zero, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 0); /* ...and a good one */ s_overflow[31] -= 1; - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, output, &point, s_overflow, NULL, NULL) == 1); /* Hash function failure results in ecdh failure */ - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, output, &point, s_overflow, ecdh_hash_function_test_fail, NULL) == 0); } /** Test that ECDH(sG, 1/s) == ECDH((1/s)G, s) == ECDH(G, 1) for a few random s. */ static void test_result_basepoint(void) { - rustsecp256k1_v0_10_0_pubkey point; - rustsecp256k1_v0_10_0_scalar rand; + rustsecp256k1_v0_11_pubkey point; + rustsecp256k1_v0_11_scalar rand; unsigned char s[32]; unsigned char s_inv[32]; unsigned char out[32]; @@ -123,22 +123,22 @@ static void test_result_basepoint(void) { unsigned char s_one[32] = { 0 }; s_one[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point, s_one) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point, s_one) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, out_base, &point, s_one, NULL, NULL) == 1); for (i = 0; i < 2 * COUNT; i++) { - random_scalar_order(&rand); - rustsecp256k1_v0_10_0_scalar_get_b32(s, &rand); - rustsecp256k1_v0_10_0_scalar_inverse(&rand, &rand); - rustsecp256k1_v0_10_0_scalar_get_b32(s_inv, &rand); - - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point, s) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, out_base, 32) == 0); - - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &point, s_inv) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out_inv, out_base, 32) == 0); + testutil_random_scalar_order(&rand); + rustsecp256k1_v0_11_scalar_get_b32(s, &rand); + rustsecp256k1_v0_11_scalar_inverse(&rand, &rand); + rustsecp256k1_v0_11_scalar_get_b32(s_inv, &rand); + + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point, s) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, out, &point, s_inv, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, out_base, 32) == 0); + + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &point, s_inv) == 1); + CHECK(rustsecp256k1_v0_11_ecdh(CTX, out_inv, &point, s, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(out_inv, out_base, 32) == 0); } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include index 819f26b0e..9e77d0693 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/Makefile.am.include @@ -1,4 +1,4 @@ -include_HEADERS += include/rustsecp256k1_v0_10_0_ellswift.h +include_HEADERS += include/rustsecp256k1_v0_11_ellswift.h noinst_HEADERS += src/modules/ellswift/bench_impl.h noinst_HEADERS += src/modules/ellswift/main_impl.h noinst_HEADERS += src/modules/ellswift/tests_impl.h diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h index c90ba194a..59f4e52d0 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/bench_impl.h @@ -9,8 +9,8 @@ #include "../../../include/secp256k1_ellswift.h" typedef struct { - rustsecp256k1_v0_10_0_context *ctx; - rustsecp256k1_v0_10_0_pubkey point[256]; + rustsecp256k1_v0_11_context *ctx; + rustsecp256k1_v0_11_pubkey point[256]; unsigned char rnd64[64]; } bench_ellswift_data; @@ -30,12 +30,12 @@ static void bench_ellswift_setup(void *arg) { memcpy(data->rnd64, init, 64); for (i = 0; i < 256; ++i) { int j; - CHECK(rustsecp256k1_v0_10_0_ellswift_decode(data->ctx, &data->point[i], data->rnd64)); + CHECK(rustsecp256k1_v0_11_ellswift_decode(data->ctx, &data->point[i], data->rnd64)); for (j = 0; j < 64; ++j) { data->rnd64[j] += 1; } } - CHECK(rustsecp256k1_v0_10_0_ellswift_encode(data->ctx, data->rnd64, &data->point[255], init + 16)); + CHECK(rustsecp256k1_v0_11_ellswift_encode(data->ctx, data->rnd64, &data->point[255], init + 16)); } static void bench_ellswift_encode(void *arg, int iters) { @@ -43,7 +43,7 @@ static void bench_ellswift_encode(void *arg, int iters) { bench_ellswift_data *data = (bench_ellswift_data*)arg; for (i = 0; i < iters; i++) { - CHECK(rustsecp256k1_v0_10_0_ellswift_encode(data->ctx, data->rnd64, &data->point[i & 255], data->rnd64 + 16)); + CHECK(rustsecp256k1_v0_11_ellswift_encode(data->ctx, data->rnd64, &data->point[i & 255], data->rnd64 + 16)); } } @@ -53,21 +53,21 @@ static void bench_ellswift_create(void *arg, int iters) { for (i = 0; i < iters; i++) { unsigned char buf[64]; - CHECK(rustsecp256k1_v0_10_0_ellswift_create(data->ctx, buf, data->rnd64, data->rnd64 + 32)); + CHECK(rustsecp256k1_v0_11_ellswift_create(data->ctx, buf, data->rnd64, data->rnd64 + 32)); memcpy(data->rnd64, buf, 64); } } static void bench_ellswift_decode(void *arg, int iters) { int i; - rustsecp256k1_v0_10_0_pubkey out; + rustsecp256k1_v0_11_pubkey out; size_t len; bench_ellswift_data *data = (bench_ellswift_data*)arg; for (i = 0; i < iters; i++) { - CHECK(rustsecp256k1_v0_10_0_ellswift_decode(data->ctx, &out, data->rnd64) == 1); + CHECK(rustsecp256k1_v0_11_ellswift_decode(data->ctx, &out, data->rnd64) == 1); len = 33; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(data->ctx, data->rnd64 + (i % 32), &len, &out, SECP256K1_EC_COMPRESSED)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(data->ctx, data->rnd64 + (i % 32), &len, &out, SECP256K1_EC_COMPRESSED)); } } @@ -77,13 +77,13 @@ static void bench_ellswift_xdh(void *arg, int iters) { for (i = 0; i < iters; i++) { int party = i & 1; - CHECK(rustsecp256k1_v0_10_0_ellswift_xdh(data->ctx, + CHECK(rustsecp256k1_v0_11_ellswift_xdh(data->ctx, data->rnd64 + (i % 33), data->rnd64, data->rnd64, data->rnd64 + ((i + 16) % 33), party, - rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324, + rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324, NULL) == 1); } } @@ -93,14 +93,14 @@ void run_ellswift_bench(int iters, int argc, char **argv) { int d = argc == 1; /* create a context with signing capabilities */ - data.ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + data.ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "encode") || have_flag(argc, argv, "ellswift_encode")) run_benchmark("ellswift_encode", bench_ellswift_encode, bench_ellswift_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "decode") || have_flag(argc, argv, "ellswift_decode")) run_benchmark("ellswift_decode", bench_ellswift_decode, bench_ellswift_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "keygen") || have_flag(argc, argv, "ellswift_keygen")) run_benchmark("ellswift_keygen", bench_ellswift_create, bench_ellswift_setup, NULL, &data, 10, iters); if (d || have_flag(argc, argv, "ellswift") || have_flag(argc, argv, "ecdh") || have_flag(argc, argv, "ellswift_ecdh")) run_benchmark("ellswift_ecdh", bench_ellswift_xdh, bench_ellswift_setup, NULL, &data, 10, iters); - rustsecp256k1_v0_10_0_context_destroy(data.ctx); + rustsecp256k1_v0_11_context_destroy(data.ctx); } #endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h index ea61fa6df..b778ecdff 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/main_impl.h @@ -12,16 +12,16 @@ #include "../../hash.h" /** c1 = (sqrt(-3)-1)/2 */ -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_ellswift_c1 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40); +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_ellswift_c1 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40); /** c2 = (-sqrt(-3)-1)/2 = -(c1+1) */ -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_ellswift_c2 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ee); +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_ellswift_c2 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ee); /** c3 = (-sqrt(-3)+1)/2 = -c1 = c2+1 */ -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_ellswift_c3 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ef); +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_ellswift_c3 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ef); /** c4 = (sqrt(-3)+1)/2 = -c2 = c1+1 */ -static const rustsecp256k1_v0_10_0_fe rustsecp256k1_v0_10_0_ellswift_c4 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa41); +static const rustsecp256k1_v0_11_fe rustsecp256k1_v0_11_ellswift_c4 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa41); /** Decode ElligatorSwift encoding (u, t) to a fraction xn/xd representing a curve X coordinate. */ -static void rustsecp256k1_v0_10_0_ellswift_xswiftec_frac_var(rustsecp256k1_v0_10_0_fe *xn, rustsecp256k1_v0_10_0_fe *xd, const rustsecp256k1_v0_10_0_fe *u, const rustsecp256k1_v0_10_0_fe *t) { +static void rustsecp256k1_v0_11_ellswift_xswiftec_frac_var(rustsecp256k1_v0_11_fe *xn, rustsecp256k1_v0_11_fe *xd, const rustsecp256k1_v0_11_fe *u, const rustsecp256k1_v0_11_fe *t) { /* The implemented algorithm is the following (all operations in GF(p)): * * - Let c0 = sqrt(-3) = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852. @@ -83,67 +83,67 @@ static void rustsecp256k1_v0_10_0_ellswift_xswiftec_frac_var(rustsecp256k1_v0_10 * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it. * - Return x1 = -(x2+u). */ - rustsecp256k1_v0_10_0_fe u1, s, g, p, d, n, l; + rustsecp256k1_v0_11_fe u1, s, g, p, d, n, l; u1 = *u; - if (EXPECT(rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&u1), 0)) u1 = rustsecp256k1_v0_10_0_fe_one; - rustsecp256k1_v0_10_0_fe_sqr(&s, t); - if (EXPECT(rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(t), 0)) s = rustsecp256k1_v0_10_0_fe_one; - rustsecp256k1_v0_10_0_fe_sqr(&l, &u1); /* l = u^2 */ - rustsecp256k1_v0_10_0_fe_mul(&g, &l, &u1); /* g = u^3 */ - rustsecp256k1_v0_10_0_fe_add_int(&g, SECP256K1_B); /* g = u^3 + 7 */ + if (EXPECT(rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&u1), 0)) u1 = rustsecp256k1_v0_11_fe_one; + rustsecp256k1_v0_11_fe_sqr(&s, t); + if (EXPECT(rustsecp256k1_v0_11_fe_normalizes_to_zero_var(t), 0)) s = rustsecp256k1_v0_11_fe_one; + rustsecp256k1_v0_11_fe_sqr(&l, &u1); /* l = u^2 */ + rustsecp256k1_v0_11_fe_mul(&g, &l, &u1); /* g = u^3 */ + rustsecp256k1_v0_11_fe_add_int(&g, SECP256K1_B); /* g = u^3 + 7 */ p = g; /* p = g */ - rustsecp256k1_v0_10_0_fe_add(&p, &s); /* p = g+s */ - if (EXPECT(rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&p), 0)) { - rustsecp256k1_v0_10_0_fe_mul_int(&s, 4); + rustsecp256k1_v0_11_fe_add(&p, &s); /* p = g+s */ + if (EXPECT(rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&p), 0)) { + rustsecp256k1_v0_11_fe_mul_int(&s, 4); /* Recompute p = g+s */ p = g; /* p = g */ - rustsecp256k1_v0_10_0_fe_add(&p, &s); /* p = g+s */ + rustsecp256k1_v0_11_fe_add(&p, &s); /* p = g+s */ } - rustsecp256k1_v0_10_0_fe_mul(&d, &s, &l); /* d = s*u^2 */ - rustsecp256k1_v0_10_0_fe_mul_int(&d, 3); /* d = 3*s*u^2 */ - rustsecp256k1_v0_10_0_fe_sqr(&l, &p); /* l = (g+s)^2 */ - rustsecp256k1_v0_10_0_fe_negate(&l, &l, 1); /* l = -(g+s)^2 */ - rustsecp256k1_v0_10_0_fe_mul(&n, &d, &u1); /* n = 3*s*u^3 */ - rustsecp256k1_v0_10_0_fe_add(&n, &l); /* n = 3*s*u^3-(g+s)^2 */ - if (rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(&n, &d)) { + rustsecp256k1_v0_11_fe_mul(&d, &s, &l); /* d = s*u^2 */ + rustsecp256k1_v0_11_fe_mul_int(&d, 3); /* d = 3*s*u^2 */ + rustsecp256k1_v0_11_fe_sqr(&l, &p); /* l = (g+s)^2 */ + rustsecp256k1_v0_11_fe_negate(&l, &l, 1); /* l = -(g+s)^2 */ + rustsecp256k1_v0_11_fe_mul(&n, &d, &u1); /* n = 3*s*u^3 */ + rustsecp256k1_v0_11_fe_add(&n, &l); /* n = 3*s*u^3-(g+s)^2 */ + if (rustsecp256k1_v0_11_ge_x_frac_on_curve_var(&n, &d)) { /* Return x3 = n/d = (3*s*u^3-(g+s)^2)/(3*s*u^2) */ *xn = n; *xd = d; return; } *xd = p; - rustsecp256k1_v0_10_0_fe_mul(&l, &rustsecp256k1_v0_10_0_ellswift_c1, &s); /* l = c1*s */ - rustsecp256k1_v0_10_0_fe_mul(&n, &rustsecp256k1_v0_10_0_ellswift_c2, &g); /* n = c2*g */ - rustsecp256k1_v0_10_0_fe_add(&n, &l); /* n = c1*s+c2*g */ - rustsecp256k1_v0_10_0_fe_mul(&n, &n, &u1); /* n = u*(c1*s+c2*g) */ + rustsecp256k1_v0_11_fe_mul(&l, &rustsecp256k1_v0_11_ellswift_c1, &s); /* l = c1*s */ + rustsecp256k1_v0_11_fe_mul(&n, &rustsecp256k1_v0_11_ellswift_c2, &g); /* n = c2*g */ + rustsecp256k1_v0_11_fe_add(&n, &l); /* n = c1*s+c2*g */ + rustsecp256k1_v0_11_fe_mul(&n, &n, &u1); /* n = u*(c1*s+c2*g) */ /* Possible optimization: in the invocation below, p^2 = (g+s)^2 is computed, * which we already have computed above. This could be deduplicated. */ - if (rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(&n, &p)) { + if (rustsecp256k1_v0_11_ge_x_frac_on_curve_var(&n, &p)) { /* Return x2 = n/p = u*(c1*s+c2*g)/(g+s) */ *xn = n; return; } - rustsecp256k1_v0_10_0_fe_mul(&l, &p, &u1); /* l = u*(g+s) */ - rustsecp256k1_v0_10_0_fe_add(&n, &l); /* n = u*(c1*s+c2*g)+u*(g+s) */ - rustsecp256k1_v0_10_0_fe_negate(xn, &n, 2); /* n = -u*(c1*s+c2*g)-u*(g+s) */ + rustsecp256k1_v0_11_fe_mul(&l, &p, &u1); /* l = u*(g+s) */ + rustsecp256k1_v0_11_fe_add(&n, &l); /* n = u*(c1*s+c2*g)+u*(g+s) */ + rustsecp256k1_v0_11_fe_negate(xn, &n, 2); /* n = -u*(c1*s+c2*g)-u*(g+s) */ - VERIFY_CHECK(rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(xn, &p)); + VERIFY_CHECK(rustsecp256k1_v0_11_ge_x_frac_on_curve_var(xn, &p)); /* Return x3 = n/p = -(u*(c1*s+c2*g)/(g+s)+u) */ } /** Decode ElligatorSwift encoding (u, t) to X coordinate. */ -static void rustsecp256k1_v0_10_0_ellswift_xswiftec_var(rustsecp256k1_v0_10_0_fe *x, const rustsecp256k1_v0_10_0_fe *u, const rustsecp256k1_v0_10_0_fe *t) { - rustsecp256k1_v0_10_0_fe xn, xd; - rustsecp256k1_v0_10_0_ellswift_xswiftec_frac_var(&xn, &xd, u, t); - rustsecp256k1_v0_10_0_fe_inv_var(&xd, &xd); - rustsecp256k1_v0_10_0_fe_mul(x, &xn, &xd); +static void rustsecp256k1_v0_11_ellswift_xswiftec_var(rustsecp256k1_v0_11_fe *x, const rustsecp256k1_v0_11_fe *u, const rustsecp256k1_v0_11_fe *t) { + rustsecp256k1_v0_11_fe xn, xd; + rustsecp256k1_v0_11_ellswift_xswiftec_frac_var(&xn, &xd, u, t); + rustsecp256k1_v0_11_fe_inv_var(&xd, &xd); + rustsecp256k1_v0_11_fe_mul(x, &xn, &xd); } /** Decode ElligatorSwift encoding (u, t) to point P. */ -static void rustsecp256k1_v0_10_0_ellswift_swiftec_var(rustsecp256k1_v0_10_0_ge *p, const rustsecp256k1_v0_10_0_fe *u, const rustsecp256k1_v0_10_0_fe *t) { - rustsecp256k1_v0_10_0_fe x; - rustsecp256k1_v0_10_0_ellswift_xswiftec_var(&x, u, t); - rustsecp256k1_v0_10_0_ge_set_xo_var(p, &x, rustsecp256k1_v0_10_0_fe_is_odd(t)); +static void rustsecp256k1_v0_11_ellswift_swiftec_var(rustsecp256k1_v0_11_ge *p, const rustsecp256k1_v0_11_fe *u, const rustsecp256k1_v0_11_fe *t) { + rustsecp256k1_v0_11_fe x; + rustsecp256k1_v0_11_ellswift_xswiftec_var(&x, u, t); + rustsecp256k1_v0_11_ge_set_xo_var(p, &x, rustsecp256k1_v0_11_fe_is_odd(t)); } /* Try to complete an ElligatorSwift encoding (u, t) for X coordinate x, given u and x. @@ -153,7 +153,7 @@ static void rustsecp256k1_v0_10_0_ellswift_swiftec_var(rustsecp256k1_v0_10_0_ge * distinct input argument c (in range 0-7), and some or all of these may return failure. * The following guarantees exist: * - Given (x, u), no two distinct c values give the same successful result t. - * - Every successful result maps back to x through rustsecp256k1_v0_10_0_ellswift_xswiftec_var. + * - Every successful result maps back to x through rustsecp256k1_v0_11_ellswift_xswiftec_var. * - Given (x, u), all t values that map back to x can be reached by combining the * successful results from this function over all c values, with the exception of: * - this function cannot be called with u=0 @@ -165,7 +165,7 @@ static void rustsecp256k1_v0_10_0_ellswift_swiftec_var(rustsecp256k1_v0_10_0_ge * encoding more closely: c=0 through c=3 match branches 1..4 in the paper, while c=4 through * c=7 are copies of those with an additional negation of sqrt(w). */ -static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0_fe *t, const rustsecp256k1_v0_10_0_fe *x_in, const rustsecp256k1_v0_10_0_fe *u_in, int c) { +static int rustsecp256k1_v0_11_ellswift_xswiftec_inv_var(rustsecp256k1_v0_11_fe *t, const rustsecp256k1_v0_11_fe *x_in, const rustsecp256k1_v0_11_fe *u_in, int c) { /* The implemented algorithm is this (all arithmetic, except involving c, is mod p): * * - If (c & 2) = 0: @@ -186,14 +186,14 @@ static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0 * - If (c & 5) = 4: return w*(c3*u + v). * - If (c & 5) = 5: return -w*(c4*u + v). */ - rustsecp256k1_v0_10_0_fe x = *x_in, u = *u_in, g, v, s, m, r, q; + rustsecp256k1_v0_11_fe x = *x_in, u = *u_in, g, v, s, m, r, q; int ret; - rustsecp256k1_v0_10_0_fe_normalize_weak(&x); - rustsecp256k1_v0_10_0_fe_normalize_weak(&u); + rustsecp256k1_v0_11_fe_normalize_weak(&x); + rustsecp256k1_v0_11_fe_normalize_weak(&u); VERIFY_CHECK(c >= 0 && c < 8); - VERIFY_CHECK(rustsecp256k1_v0_10_0_ge_x_on_curve_var(&x)); + VERIFY_CHECK(rustsecp256k1_v0_11_ge_x_on_curve_var(&x)); if (!(c & 2)) { /* c is in {0, 1, 4, 5}. In this case we look for an inverse under the x1 (if c=0 or @@ -203,16 +203,16 @@ static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0 * back under the x3 formula instead (which has priority over x1 and x2, so the decoding * would not match x). */ m = x; /* m = x */ - rustsecp256k1_v0_10_0_fe_add(&m, &u); /* m = u+x */ - rustsecp256k1_v0_10_0_fe_negate(&m, &m, 2); /* m = -u-x */ + rustsecp256k1_v0_11_fe_add(&m, &u); /* m = u+x */ + rustsecp256k1_v0_11_fe_negate(&m, &m, 2); /* m = -u-x */ /* Test if (-u-x) is a valid X coordinate. If so, fail. */ - if (rustsecp256k1_v0_10_0_ge_x_on_curve_var(&m)) return 0; + if (rustsecp256k1_v0_11_ge_x_on_curve_var(&m)) return 0; /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [first part] */ - rustsecp256k1_v0_10_0_fe_sqr(&s, &m); /* s = (u+x)^2 */ - rustsecp256k1_v0_10_0_fe_negate(&s, &s, 1); /* s = -(u+x)^2 */ - rustsecp256k1_v0_10_0_fe_mul(&m, &u, &x); /* m = u*x */ - rustsecp256k1_v0_10_0_fe_add(&s, &m); /* s = -(u^2 + u*x + x^2) */ + rustsecp256k1_v0_11_fe_sqr(&s, &m); /* s = (u+x)^2 */ + rustsecp256k1_v0_11_fe_negate(&s, &s, 1); /* s = -(u+x)^2 */ + rustsecp256k1_v0_11_fe_mul(&m, &u, &x); /* m = u*x */ + rustsecp256k1_v0_11_fe_add(&s, &m); /* s = -(u^2 + u*x + x^2) */ /* Note that at this point, s = 0 is impossible. If it were the case: * s = -(u^2 + u*x + x^2) = 0 @@ -224,23 +224,23 @@ static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0 * => x^3 + B = (-u - x)^3 + B * * However, we know x^3 + B is square (because x is on the curve) and - * that (-u-x)^3 + B is not square (the rustsecp256k1_v0_10_0_ge_x_on_curve_var(&m) + * that (-u-x)^3 + B is not square (the rustsecp256k1_v0_11_ge_x_on_curve_var(&m) * test above would have failed). This is a contradiction, and thus the * assumption s=0 is false. */ - VERIFY_CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&s)); + VERIFY_CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&s)); /* If s is not square, fail. We have not fully computed s yet, but s is square iff * -(u^3+7)*(u^2+u*x+x^2) is square (because a/b is square iff a*b is square and b is * nonzero). */ - rustsecp256k1_v0_10_0_fe_sqr(&g, &u); /* g = u^2 */ - rustsecp256k1_v0_10_0_fe_mul(&g, &g, &u); /* g = u^3 */ - rustsecp256k1_v0_10_0_fe_add_int(&g, SECP256K1_B); /* g = u^3+7 */ - rustsecp256k1_v0_10_0_fe_mul(&m, &s, &g); /* m = -(u^3 + 7)*(u^2 + u*x + x^2) */ - if (!rustsecp256k1_v0_10_0_fe_is_square_var(&m)) return 0; + rustsecp256k1_v0_11_fe_sqr(&g, &u); /* g = u^2 */ + rustsecp256k1_v0_11_fe_mul(&g, &g, &u); /* g = u^3 */ + rustsecp256k1_v0_11_fe_add_int(&g, SECP256K1_B); /* g = u^3+7 */ + rustsecp256k1_v0_11_fe_mul(&m, &s, &g); /* m = -(u^3 + 7)*(u^2 + u*x + x^2) */ + if (!rustsecp256k1_v0_11_fe_is_square_var(&m)) return 0; /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [second part] */ - rustsecp256k1_v0_10_0_fe_inv_var(&s, &s); /* s = -1/(u^2 + u*x + x^2) [no div by 0] */ - rustsecp256k1_v0_10_0_fe_mul(&s, &s, &g); /* s = -(u^3 + 7)/(u^2 + u*x + x^2) */ + rustsecp256k1_v0_11_fe_inv_var(&s, &s); /* s = -1/(u^2 + u*x + x^2) [no div by 0] */ + rustsecp256k1_v0_11_fe_mul(&s, &s, &g); /* s = -(u^3 + 7)/(u^2 + u*x + x^2) */ /* Let v = x. */ v = x; @@ -248,25 +248,25 @@ static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0 /* c is in {2, 3, 6, 7}. In this case we look for an inverse under the x3 formula. */ /* Let s = x-u. */ - rustsecp256k1_v0_10_0_fe_negate(&m, &u, 1); /* m = -u */ + rustsecp256k1_v0_11_fe_negate(&m, &u, 1); /* m = -u */ s = m; /* s = -u */ - rustsecp256k1_v0_10_0_fe_add(&s, &x); /* s = x-u */ + rustsecp256k1_v0_11_fe_add(&s, &x); /* s = x-u */ /* If s is not square, fail. */ - if (!rustsecp256k1_v0_10_0_fe_is_square_var(&s)) return 0; + if (!rustsecp256k1_v0_11_fe_is_square_var(&s)) return 0; /* Let r = sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. */ - rustsecp256k1_v0_10_0_fe_sqr(&g, &u); /* g = u^2 */ - rustsecp256k1_v0_10_0_fe_mul(&q, &s, &g); /* q = s*u^2 */ - rustsecp256k1_v0_10_0_fe_mul_int(&q, 3); /* q = 3*s*u^2 */ - rustsecp256k1_v0_10_0_fe_mul(&g, &g, &u); /* g = u^3 */ - rustsecp256k1_v0_10_0_fe_mul_int(&g, 4); /* g = 4*u^3 */ - rustsecp256k1_v0_10_0_fe_add_int(&g, 4 * SECP256K1_B); /* g = 4*(u^3+7) */ - rustsecp256k1_v0_10_0_fe_add(&q, &g); /* q = 4*(u^3+7)+3*s*u^2 */ - rustsecp256k1_v0_10_0_fe_mul(&q, &q, &s); /* q = s*(4*(u^3+7)+3*u^2*s) */ - rustsecp256k1_v0_10_0_fe_negate(&q, &q, 1); /* q = -s*(4*(u^3+7)+3*u^2*s) */ - if (!rustsecp256k1_v0_10_0_fe_is_square_var(&q)) return 0; - ret = rustsecp256k1_v0_10_0_fe_sqrt(&r, &q); /* r = sqrt(-s*(4*(u^3+7)+3*u^2*s)) */ + rustsecp256k1_v0_11_fe_sqr(&g, &u); /* g = u^2 */ + rustsecp256k1_v0_11_fe_mul(&q, &s, &g); /* q = s*u^2 */ + rustsecp256k1_v0_11_fe_mul_int(&q, 3); /* q = 3*s*u^2 */ + rustsecp256k1_v0_11_fe_mul(&g, &g, &u); /* g = u^3 */ + rustsecp256k1_v0_11_fe_mul_int(&g, 4); /* g = 4*u^3 */ + rustsecp256k1_v0_11_fe_add_int(&g, 4 * SECP256K1_B); /* g = 4*(u^3+7) */ + rustsecp256k1_v0_11_fe_add(&q, &g); /* q = 4*(u^3+7)+3*s*u^2 */ + rustsecp256k1_v0_11_fe_mul(&q, &q, &s); /* q = s*(4*(u^3+7)+3*u^2*s) */ + rustsecp256k1_v0_11_fe_negate(&q, &q, 1); /* q = -s*(4*(u^3+7)+3*u^2*s) */ + if (!rustsecp256k1_v0_11_fe_is_square_var(&q)) return 0; + ret = rustsecp256k1_v0_11_fe_sqrt(&r, &q); /* r = sqrt(-s*(4*(u^3+7)+3*u^2*s)) */ #ifdef VERIFY VERIFY_CHECK(ret); #else @@ -274,31 +274,31 @@ static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0 #endif /* If (c & 1) = 1 and r = 0, fail. */ - if (EXPECT((c & 1) && rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&r), 0)) return 0; + if (EXPECT((c & 1) && rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&r), 0)) return 0; /* If s = 0, fail. */ - if (EXPECT(rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&s), 0)) return 0; + if (EXPECT(rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&s), 0)) return 0; /* Let v = (r/s-u)/2. */ - rustsecp256k1_v0_10_0_fe_inv_var(&v, &s); /* v = 1/s [no div by 0] */ - rustsecp256k1_v0_10_0_fe_mul(&v, &v, &r); /* v = r/s */ - rustsecp256k1_v0_10_0_fe_add(&v, &m); /* v = r/s-u */ - rustsecp256k1_v0_10_0_fe_half(&v); /* v = (r/s-u)/2 */ + rustsecp256k1_v0_11_fe_inv_var(&v, &s); /* v = 1/s [no div by 0] */ + rustsecp256k1_v0_11_fe_mul(&v, &v, &r); /* v = r/s */ + rustsecp256k1_v0_11_fe_add(&v, &m); /* v = r/s-u */ + rustsecp256k1_v0_11_fe_half(&v); /* v = (r/s-u)/2 */ } /* Let w = sqrt(s). */ - ret = rustsecp256k1_v0_10_0_fe_sqrt(&m, &s); /* m = sqrt(s) = w */ + ret = rustsecp256k1_v0_11_fe_sqrt(&m, &s); /* m = sqrt(s) = w */ VERIFY_CHECK(ret); /* Return logic. */ if ((c & 5) == 0 || (c & 5) == 5) { - rustsecp256k1_v0_10_0_fe_negate(&m, &m, 1); /* m = -w */ + rustsecp256k1_v0_11_fe_negate(&m, &m, 1); /* m = -w */ } /* Now m = {-w if c&5=0 or c&5=5; w otherwise}. */ - rustsecp256k1_v0_10_0_fe_mul(&u, &u, c&1 ? &rustsecp256k1_v0_10_0_ellswift_c4 : &rustsecp256k1_v0_10_0_ellswift_c3); + rustsecp256k1_v0_11_fe_mul(&u, &u, c&1 ? &rustsecp256k1_v0_11_ellswift_c4 : &rustsecp256k1_v0_11_ellswift_c3); /* u = {c4 if c&1=1; c3 otherwise}*u */ - rustsecp256k1_v0_10_0_fe_add(&u, &v); /* u = {c4 if c&1=1; c3 otherwise}*u + v */ - rustsecp256k1_v0_10_0_fe_mul(t, &m, &u); + rustsecp256k1_v0_11_fe_add(&u, &v); /* u = {c4 if c&1=1; c3 otherwise}*u + v */ + rustsecp256k1_v0_11_fe_mul(t, &m, &u); return 1; } @@ -307,8 +307,8 @@ static int rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(rustsecp256k1_v0_10_0 * 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 rustsecp256k1_v0_10_0_ellswift_prng(unsigned char* out32, const rustsecp256k1_v0_10_0_sha256 *hasher, uint32_t cnt) { - rustsecp256k1_v0_10_0_sha256 hash = *hasher; +static void rustsecp256k1_v0_11_ellswift_prng(unsigned char* out32, const rustsecp256k1_v0_11_sha256 *hasher, uint32_t cnt) { + rustsecp256k1_v0_11_sha256 hash = *hasher; unsigned char buf4[4]; #ifdef VERIFY size_t blocks = hash.bytes >> 6; @@ -317,8 +317,8 @@ static void rustsecp256k1_v0_10_0_ellswift_prng(unsigned char* out32, const rust buf4[1] = cnt >> 8; buf4[2] = cnt >> 16; buf4[3] = cnt >> 24; - rustsecp256k1_v0_10_0_sha256_write(&hash, buf4, 4); - rustsecp256k1_v0_10_0_sha256_finalize(&hash, out32); + rustsecp256k1_v0_11_sha256_write(&hash, buf4, 4); + rustsecp256k1_v0_11_sha256_finalize(&hash, out32); /* Writing and finalizing together should trigger exactly one SHA256 compression. */ VERIFY_CHECK(((hash.bytes) >> 6) == (blocks + 1)); @@ -329,8 +329,8 @@ static void rustsecp256k1_v0_10_0_ellswift_prng(unsigned char* out32, const rust * u32 is the 32-byte big endian encoding of u; t is the output field element t that still * needs encoding. * - * hasher is a hasher in the rustsecp256k1_v0_10_0_ellswift_prng sense, with the same restrictions. */ -static void rustsecp256k1_v0_10_0_ellswift_xelligatorswift_var(unsigned char *u32, rustsecp256k1_v0_10_0_fe *t, const rustsecp256k1_v0_10_0_fe *x, const rustsecp256k1_v0_10_0_sha256 *hasher) { + * hasher is a hasher in the rustsecp256k1_v0_11_ellswift_prng sense, with the same restrictions. */ +static void rustsecp256k1_v0_11_ellswift_xelligatorswift_var(unsigned char *u32, rustsecp256k1_v0_11_fe *t, const rustsecp256k1_v0_11_fe *x, const rustsecp256k1_v0_11_sha256 *hasher) { /* Pool of 3-bit branch values. */ unsigned char branch_hash[32]; /* Number of 3-bit values in branch_hash left. */ @@ -343,47 +343,47 @@ static void rustsecp256k1_v0_10_0_ellswift_xelligatorswift_var(unsigned char *u3 uint32_t cnt = 0; while (1) { int branch; - rustsecp256k1_v0_10_0_fe u; + rustsecp256k1_v0_11_fe u; /* If the pool of branch values is empty, populate it. */ if (branches_left == 0) { - rustsecp256k1_v0_10_0_ellswift_prng(branch_hash, hasher, cnt++); + rustsecp256k1_v0_11_ellswift_prng(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. */ - rustsecp256k1_v0_10_0_ellswift_prng(u32, hasher, cnt++); + rustsecp256k1_v0_11_ellswift_prng(u32, hasher, cnt++); /* overflow is not a problem (we prefer uniform u32 over uniform u). */ - rustsecp256k1_v0_10_0_fe_set_b32_mod(&u, u32); + rustsecp256k1_v0_11_fe_set_b32_mod(&u, u32); /* Since u is the output of a hash, it should practically never be 0. We could apply the * u=0 to u=1 correction here too to deal with that case still, but it's such a low * probability event that we do not bother. */ - VERIFY_CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&u)); + VERIFY_CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&u)); /* Find a remainder t, and return it if found. */ - if (EXPECT(rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(t, x, &u, branch), 0)) break; + if (EXPECT(rustsecp256k1_v0_11_ellswift_xswiftec_inv_var(t, x, &u, branch), 0)) break; } } /** Find an ElligatorSwift encoding (u, t) for point P. * - * This is similar rustsecp256k1_v0_10_0_ellswift_xelligatorswift_var, except it takes a full group element p + * This is similar rustsecp256k1_v0_11_ellswift_xelligatorswift_var, except it takes a full group element p * as input, and returns an encoding that matches the provided Y coordinate rather than a random * one. */ -static void rustsecp256k1_v0_10_0_ellswift_elligatorswift_var(unsigned char *u32, rustsecp256k1_v0_10_0_fe *t, const rustsecp256k1_v0_10_0_ge *p, const rustsecp256k1_v0_10_0_sha256 *hasher) { - rustsecp256k1_v0_10_0_ellswift_xelligatorswift_var(u32, t, &p->x, hasher); - rustsecp256k1_v0_10_0_fe_normalize_var(t); - if (rustsecp256k1_v0_10_0_fe_is_odd(t) != rustsecp256k1_v0_10_0_fe_is_odd(&p->y)) { - rustsecp256k1_v0_10_0_fe_negate(t, t, 1); - rustsecp256k1_v0_10_0_fe_normalize_var(t); +static void rustsecp256k1_v0_11_ellswift_elligatorswift_var(unsigned char *u32, rustsecp256k1_v0_11_fe *t, const rustsecp256k1_v0_11_ge *p, const rustsecp256k1_v0_11_sha256 *hasher) { + rustsecp256k1_v0_11_ellswift_xelligatorswift_var(u32, t, &p->x, hasher); + rustsecp256k1_v0_11_fe_normalize_var(t); + if (rustsecp256k1_v0_11_fe_is_odd(t) != rustsecp256k1_v0_11_fe_is_odd(&p->y)) { + rustsecp256k1_v0_11_fe_negate(t, t, 1); + rustsecp256k1_v0_11_fe_normalize_var(t); } } -/** Set hash state to the BIP340 tagged hash midstate for "rustsecp256k1_v0_10_0_ellswift_encode". */ -static void rustsecp256k1_v0_10_0_ellswift_sha256_init_encode(rustsecp256k1_v0_10_0_sha256* hash) { - rustsecp256k1_v0_10_0_sha256_initialize(hash); +/** Set hash state to the BIP340 tagged hash midstate for "rustsecp256k1_v0_11_ellswift_encode". */ +static void rustsecp256k1_v0_11_ellswift_sha256_init_encode(rustsecp256k1_v0_11_sha256* hash) { + rustsecp256k1_v0_11_sha256_initialize(hash); hash->s[0] = 0xd1a6524bul; hash->s[1] = 0x028594b3ul; hash->s[2] = 0x96e42f4eul; @@ -396,35 +396,35 @@ static void rustsecp256k1_v0_10_0_ellswift_sha256_init_encode(rustsecp256k1_v0_1 hash->bytes = 64; } -int rustsecp256k1_v0_10_0_ellswift_encode(const rustsecp256k1_v0_10_0_context *ctx, unsigned char *ell64, const rustsecp256k1_v0_10_0_pubkey *pubkey, const unsigned char *rnd32) { - rustsecp256k1_v0_10_0_ge p; +int rustsecp256k1_v0_11_ellswift_encode(const rustsecp256k1_v0_11_context *ctx, unsigned char *ell64, const rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *rnd32) { + rustsecp256k1_v0_11_ge p; VERIFY_CHECK(ctx != NULL); ARG_CHECK(ell64 != NULL); ARG_CHECK(pubkey != NULL); ARG_CHECK(rnd32 != NULL); - if (rustsecp256k1_v0_10_0_pubkey_load(ctx, &p, pubkey)) { - rustsecp256k1_v0_10_0_fe t; + if (rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey)) { + rustsecp256k1_v0_11_fe t; unsigned char p64[64] = {0}; size_t ser_size; int ser_ret; - rustsecp256k1_v0_10_0_sha256 hash; + rustsecp256k1_v0_11_sha256 hash; /* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using - * BIP340 tagged hash with tag "rustsecp256k1_v0_10_0_ellswift_encode". */ - rustsecp256k1_v0_10_0_ellswift_sha256_init_encode(&hash); - ser_ret = rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&p, p64, &ser_size, 1); + * BIP340 tagged hash with tag "rustsecp256k1_v0_11_ellswift_encode". */ + rustsecp256k1_v0_11_ellswift_sha256_init_encode(&hash); + ser_ret = rustsecp256k1_v0_11_eckey_pubkey_serialize(&p, p64, &ser_size, 1); #ifdef VERIFY VERIFY_CHECK(ser_ret && ser_size == 33); #else (void)ser_ret; #endif - rustsecp256k1_v0_10_0_sha256_write(&hash, p64, sizeof(p64)); - rustsecp256k1_v0_10_0_sha256_write(&hash, rnd32, 32); + rustsecp256k1_v0_11_sha256_write(&hash, p64, sizeof(p64)); + rustsecp256k1_v0_11_sha256_write(&hash, rnd32, 32); /* Compute ElligatorSwift encoding and construct output. */ - rustsecp256k1_v0_10_0_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ - rustsecp256k1_v0_10_0_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ + rustsecp256k1_v0_11_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ + rustsecp256k1_v0_11_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ return 1; } /* Only reached in case the provided pubkey is invalid. */ @@ -432,9 +432,9 @@ int rustsecp256k1_v0_10_0_ellswift_encode(const rustsecp256k1_v0_10_0_context *c return 0; } -/** Set hash state to the BIP340 tagged hash midstate for "rustsecp256k1_v0_10_0_ellswift_create". */ -static void rustsecp256k1_v0_10_0_ellswift_sha256_init_create(rustsecp256k1_v0_10_0_sha256* hash) { - rustsecp256k1_v0_10_0_sha256_initialize(hash); +/** Set hash state to the BIP340 tagged hash midstate for "rustsecp256k1_v0_11_ellswift_create". */ +static void rustsecp256k1_v0_11_ellswift_sha256_init_create(rustsecp256k1_v0_11_sha256* hash) { + rustsecp256k1_v0_11_sha256_initialize(hash); hash->s[0] = 0xd29e1bf5ul; hash->s[1] = 0xf7025f42ul; hash->s[2] = 0x9b024773ul; @@ -447,11 +447,11 @@ static void rustsecp256k1_v0_10_0_ellswift_sha256_init_create(rustsecp256k1_v0_1 hash->bytes = 64; } -int rustsecp256k1_v0_10_0_ellswift_create(const rustsecp256k1_v0_10_0_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) { - rustsecp256k1_v0_10_0_ge p; - rustsecp256k1_v0_10_0_fe t; - rustsecp256k1_v0_10_0_sha256 hash; - rustsecp256k1_v0_10_0_scalar seckey_scalar; +int rustsecp256k1_v0_11_ellswift_create(const rustsecp256k1_v0_11_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) { + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_fe t; + rustsecp256k1_v0_11_sha256 hash; + rustsecp256k1_v0_11_scalar seckey_scalar; int ret; static const unsigned char zero32[32] = {0}; @@ -459,64 +459,65 @@ int rustsecp256k1_v0_10_0_ellswift_create(const rustsecp256k1_v0_10_0_context *c VERIFY_CHECK(ctx != NULL); ARG_CHECK(ell64 != NULL); memset(ell64, 0, 64); - ARG_CHECK(rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey32 != NULL); /* Compute (affine) public key */ - ret = rustsecp256k1_v0_10_0_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey32); - rustsecp256k1_v0_10_0_declassify(ctx, &p, sizeof(p)); /* not constant time in produced pubkey */ - rustsecp256k1_v0_10_0_fe_normalize_var(&p.x); - rustsecp256k1_v0_10_0_fe_normalize_var(&p.y); + ret = rustsecp256k1_v0_11_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey32); + rustsecp256k1_v0_11_declassify(ctx, &p, sizeof(p)); /* not constant time in produced pubkey */ + rustsecp256k1_v0_11_fe_normalize_var(&p.x); + rustsecp256k1_v0_11_fe_normalize_var(&p.y); /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++), - * using BIP340 tagged hash with tag "rustsecp256k1_v0_10_0_ellswift_create". */ - rustsecp256k1_v0_10_0_ellswift_sha256_init_create(&hash); - rustsecp256k1_v0_10_0_sha256_write(&hash, seckey32, 32); - rustsecp256k1_v0_10_0_sha256_write(&hash, zero32, sizeof(zero32)); - rustsecp256k1_v0_10_0_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */ - if (auxrnd32) rustsecp256k1_v0_10_0_sha256_write(&hash, auxrnd32, 32); + * using BIP340 tagged hash with tag "rustsecp256k1_v0_11_ellswift_create". */ + rustsecp256k1_v0_11_ellswift_sha256_init_create(&hash); + rustsecp256k1_v0_11_sha256_write(&hash, seckey32, 32); + rustsecp256k1_v0_11_sha256_write(&hash, zero32, sizeof(zero32)); + rustsecp256k1_v0_11_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */ + if (auxrnd32) rustsecp256k1_v0_11_sha256_write(&hash, auxrnd32, 32); /* Compute ElligatorSwift encoding and construct output. */ - rustsecp256k1_v0_10_0_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ - rustsecp256k1_v0_10_0_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ + rustsecp256k1_v0_11_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */ + rustsecp256k1_v0_11_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */ - rustsecp256k1_v0_10_0_memczero(ell64, 64, !ret); - rustsecp256k1_v0_10_0_scalar_clear(&seckey_scalar); + rustsecp256k1_v0_11_memczero(ell64, 64, !ret); + rustsecp256k1_v0_11_scalar_clear(&seckey_scalar); return ret; } -int rustsecp256k1_v0_10_0_ellswift_decode(const rustsecp256k1_v0_10_0_context *ctx, rustsecp256k1_v0_10_0_pubkey *pubkey, const unsigned char *ell64) { - rustsecp256k1_v0_10_0_fe u, t; - rustsecp256k1_v0_10_0_ge p; +int rustsecp256k1_v0_11_ellswift_decode(const rustsecp256k1_v0_11_context *ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *ell64) { + rustsecp256k1_v0_11_fe u, t; + rustsecp256k1_v0_11_ge p; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); ARG_CHECK(ell64 != NULL); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&u, ell64); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&t, ell64 + 32); - rustsecp256k1_v0_10_0_fe_normalize_var(&t); - rustsecp256k1_v0_10_0_ellswift_swiftec_var(&p, &u, &t); - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &p); + rustsecp256k1_v0_11_fe_set_b32_mod(&u, ell64); + rustsecp256k1_v0_11_fe_set_b32_mod(&t, ell64 + 32); + rustsecp256k1_v0_11_fe_normalize_var(&t); + rustsecp256k1_v0_11_ellswift_swiftec_var(&p, &u, &t); + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); 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) { - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; - rustsecp256k1_v0_10_0_sha256_initialize(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, data, 64); - rustsecp256k1_v0_10_0_sha256_write(&sha, ell_a64, 64); - rustsecp256k1_v0_10_0_sha256_write(&sha, ell_b64, 64); - rustsecp256k1_v0_10_0_sha256_write(&sha, x32, 32); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, output); + rustsecp256k1_v0_11_sha256_initialize(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, data, 64); + rustsecp256k1_v0_11_sha256_write(&sha, ell_a64, 64); + rustsecp256k1_v0_11_sha256_write(&sha, ell_b64, 64); + rustsecp256k1_v0_11_sha256_write(&sha, x32, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, output); + rustsecp256k1_v0_11_sha256_clear(&sha); return 1; } /** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */ -static void rustsecp256k1_v0_10_0_ellswift_sha256_init_bip324(rustsecp256k1_v0_10_0_sha256* hash) { - rustsecp256k1_v0_10_0_sha256_initialize(hash); +static void rustsecp256k1_v0_11_ellswift_sha256_init_bip324(rustsecp256k1_v0_11_sha256* hash) { + rustsecp256k1_v0_11_sha256_initialize(hash); hash->s[0] = 0x8c12d730ul; hash->s[1] = 0x827bd392ul; hash->s[2] = 0x9e4fb2eeul; @@ -530,27 +531,28 @@ static void rustsecp256k1_v0_10_0_ellswift_sha256_init_bip324(rustsecp256k1_v0_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) { - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; (void)data; - rustsecp256k1_v0_10_0_ellswift_sha256_init_bip324(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, ell_a64, 64); - rustsecp256k1_v0_10_0_sha256_write(&sha, ell_b64, 64); - rustsecp256k1_v0_10_0_sha256_write(&sha, x32, 32); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, output); + rustsecp256k1_v0_11_ellswift_sha256_init_bip324(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, ell_a64, 64); + rustsecp256k1_v0_11_sha256_write(&sha, ell_b64, 64); + rustsecp256k1_v0_11_sha256_write(&sha, x32, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, output); + rustsecp256k1_v0_11_sha256_clear(&sha); return 1; } -const rustsecp256k1_v0_10_0_ellswift_xdh_hash_function rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix; -const rustsecp256k1_v0_10_0_ellswift_xdh_hash_function rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324; +const rustsecp256k1_v0_11_ellswift_xdh_hash_function rustsecp256k1_v0_11_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix; +const rustsecp256k1_v0_11_ellswift_xdh_hash_function rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324; -int rustsecp256k1_v0_10_0_ellswift_xdh(const rustsecp256k1_v0_10_0_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, rustsecp256k1_v0_10_0_ellswift_xdh_hash_function hashfp, void *data) { +int rustsecp256k1_v0_11_ellswift_xdh(const rustsecp256k1_v0_11_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, rustsecp256k1_v0_11_ellswift_xdh_hash_function hashfp, void *data) { int ret = 0; int overflow; - rustsecp256k1_v0_10_0_scalar s; - rustsecp256k1_v0_10_0_fe xn, xd, px, u, t; + rustsecp256k1_v0_11_scalar s; + rustsecp256k1_v0_11_fe xn, xd, px, u, t; unsigned char sx[32]; const unsigned char* theirs64; @@ -563,26 +565,26 @@ int rustsecp256k1_v0_10_0_ellswift_xdh(const rustsecp256k1_v0_10_0_context *ctx, /* Load remote public key (as fraction). */ theirs64 = party ? ell_a64 : ell_b64; - rustsecp256k1_v0_10_0_fe_set_b32_mod(&u, theirs64); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&t, theirs64 + 32); - rustsecp256k1_v0_10_0_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t); + rustsecp256k1_v0_11_fe_set_b32_mod(&u, theirs64); + rustsecp256k1_v0_11_fe_set_b32_mod(&t, theirs64 + 32); + rustsecp256k1_v0_11_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t); /* Load private key (using one if invalid). */ - rustsecp256k1_v0_10_0_scalar_set_b32(&s, seckey32, &overflow); - overflow = rustsecp256k1_v0_10_0_scalar_is_zero(&s); - rustsecp256k1_v0_10_0_scalar_cmov(&s, &rustsecp256k1_v0_10_0_scalar_one, overflow); + rustsecp256k1_v0_11_scalar_set_b32(&s, seckey32, &overflow); + overflow = rustsecp256k1_v0_11_scalar_is_zero(&s); + rustsecp256k1_v0_11_scalar_cmov(&s, &rustsecp256k1_v0_11_scalar_one, overflow); /* Compute shared X coordinate. */ - rustsecp256k1_v0_10_0_ecmult_const_xonly(&px, &xn, &xd, &s, 1); - rustsecp256k1_v0_10_0_fe_normalize(&px); - rustsecp256k1_v0_10_0_fe_get_b32(sx, &px); + rustsecp256k1_v0_11_ecmult_const_xonly(&px, &xn, &xd, &s, 1); + rustsecp256k1_v0_11_fe_normalize(&px); + rustsecp256k1_v0_11_fe_get_b32(sx, &px); /* Invoke hasher */ ret = hashfp(output, sx, ell_a64, ell_b64, data); - memset(sx, 0, 32); - rustsecp256k1_v0_10_0_fe_clear(&px); - rustsecp256k1_v0_10_0_scalar_clear(&s); + rustsecp256k1_v0_11_memclear(sx, sizeof(sx)); + rustsecp256k1_v0_11_fe_clear(&px); + rustsecp256k1_v0_11_scalar_clear(&s); return !!ret & !overflow; } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h index f6f023861..1c6e5e4e7 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_exhaustive_impl.h @@ -9,7 +9,7 @@ #include "../../../include/secp256k1_ellswift.h" #include "main_impl.h" -static void test_exhaustive_ellswift(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_ellswift(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { int i; /* Note that SwiftEC/ElligatorSwift are inherently curve operations, not @@ -18,21 +18,21 @@ static void test_exhaustive_ellswift(const rustsecp256k1_v0_10_0_context *ctx, c * it doesn't (and for computational reasons obviously cannot) test the * entire domain ellswift operates under. */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_scalar scalar_i; + rustsecp256k1_v0_11_scalar scalar_i; unsigned char sec32[32]; unsigned char ell64[64]; - rustsecp256k1_v0_10_0_pubkey pub_decoded; - rustsecp256k1_v0_10_0_ge ge_decoded; + rustsecp256k1_v0_11_pubkey pub_decoded; + rustsecp256k1_v0_11_ge ge_decoded; /* Construct ellswift pubkey from exhaustive loop scalar i. */ - rustsecp256k1_v0_10_0_scalar_set_int(&scalar_i, i); - rustsecp256k1_v0_10_0_scalar_get_b32(sec32, &scalar_i); - CHECK(rustsecp256k1_v0_10_0_ellswift_create(ctx, ell64, sec32, NULL)); + rustsecp256k1_v0_11_scalar_set_int(&scalar_i, i); + rustsecp256k1_v0_11_scalar_get_b32(sec32, &scalar_i); + CHECK(rustsecp256k1_v0_11_ellswift_create(ctx, ell64, sec32, NULL)); /* Decode ellswift pubkey and check that it matches the precomputed group element. */ - rustsecp256k1_v0_10_0_ellswift_decode(ctx, &pub_decoded, ell64); - rustsecp256k1_v0_10_0_pubkey_load(ctx, &ge_decoded, &pub_decoded); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&ge_decoded, &group[i])); + rustsecp256k1_v0_11_ellswift_decode(ctx, &pub_decoded, ell64); + rustsecp256k1_v0_11_pubkey_load(ctx, &ge_decoded, &pub_decoded); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&ge_decoded, &group[i])); } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h index 53ec88d39..67b590970 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/ellswift/tests_impl.h @@ -10,14 +10,14 @@ struct ellswift_xswiftec_inv_test { int enc_bitmap; - rustsecp256k1_v0_10_0_fe u; - rustsecp256k1_v0_10_0_fe x; - rustsecp256k1_v0_10_0_fe encs[8]; + rustsecp256k1_v0_11_fe u; + rustsecp256k1_v0_11_fe x; + rustsecp256k1_v0_11_fe encs[8]; }; struct ellswift_decode_test { unsigned char enc[64]; - rustsecp256k1_v0_10_0_fe x; + rustsecp256k1_v0_11_fe x; int odd_y; }; @@ -183,28 +183,28 @@ void run_ellswift_tests(void) { const struct ellswift_xswiftec_inv_test *testcase = &ellswift_xswiftec_inv_tests[i]; int c; for (c = 0; c < 8; ++c) { - rustsecp256k1_v0_10_0_fe t; - int ret = rustsecp256k1_v0_10_0_ellswift_xswiftec_inv_var(&t, &testcase->x, &testcase->u, c); + rustsecp256k1_v0_11_fe t; + int ret = rustsecp256k1_v0_11_ellswift_xswiftec_inv_var(&t, &testcase->x, &testcase->u, c); CHECK(ret == ((testcase->enc_bitmap >> c) & 1)); if (ret) { - rustsecp256k1_v0_10_0_fe x2; - CHECK(check_fe_equal(&t, &testcase->encs[c])); - rustsecp256k1_v0_10_0_ellswift_xswiftec_var(&x2, &testcase->u, &testcase->encs[c]); - CHECK(check_fe_equal(&testcase->x, &x2)); + rustsecp256k1_v0_11_fe x2; + CHECK(fe_equal(&t, &testcase->encs[c])); + rustsecp256k1_v0_11_ellswift_xswiftec_var(&x2, &testcase->u, &testcase->encs[c]); + CHECK(fe_equal(&testcase->x, &x2)); } } } 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]; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_ge ge; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_ge ge; int ret; - ret = rustsecp256k1_v0_10_0_ellswift_decode(CTX, &pubkey, testcase->enc); + ret = rustsecp256k1_v0_11_ellswift_decode(CTX, &pubkey, testcase->enc); CHECK(ret); - ret = rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey); + ret = rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey); CHECK(ret); - CHECK(check_fe_equal(&testcase->x, &ge.x)); - CHECK(rustsecp256k1_v0_10_0_fe_is_odd(&ge.y) == testcase->odd_y); + CHECK(fe_equal(&testcase->x, &ge.x)); + CHECK(rustsecp256k1_v0_11_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) { const struct ellswift_xdh_test *test = &ellswift_xdh_tests_bip324[i]; @@ -213,94 +213,94 @@ void run_ellswift_tests(void) { int party = !test->initiating; const unsigned char* ell_a64 = party ? test->ellswift_theirs : test->ellswift_ours; const unsigned char* ell_b64 = party ? test->ellswift_ours : test->ellswift_theirs; - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, shared_secret, + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, shared_secret, ell_a64, ell_b64, test->priv_ours, party, - rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324, + rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324, NULL); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(shared_secret, test->shared_secret, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(shared_secret, test->shared_secret, 32) == 0); } - /* Verify that rustsecp256k1_v0_10_0_ellswift_encode + decode roundtrips. */ + /* Verify that rustsecp256k1_v0_11_ellswift_encode + decode roundtrips. */ for (i = 0; i < 1000 * COUNT; i++) { unsigned char rnd32[32]; unsigned char ell64[64]; - rustsecp256k1_v0_10_0_ge g, g2; - rustsecp256k1_v0_10_0_pubkey pubkey, pubkey2; + rustsecp256k1_v0_11_ge g, g2; + rustsecp256k1_v0_11_pubkey pubkey, pubkey2; /* Generate random public key and random randomizer. */ - random_group_element_test(&g); - rustsecp256k1_v0_10_0_pubkey_save(&pubkey, &g); - rustsecp256k1_v0_10_0_testrand256(rnd32); + testutil_random_ge_test(&g); + rustsecp256k1_v0_11_pubkey_save(&pubkey, &g); + testrand256(rnd32); /* Convert the public key to ElligatorSwift and back. */ - rustsecp256k1_v0_10_0_ellswift_encode(CTX, ell64, &pubkey, rnd32); - rustsecp256k1_v0_10_0_ellswift_decode(CTX, &pubkey2, ell64); - rustsecp256k1_v0_10_0_pubkey_load(CTX, &g2, &pubkey2); + rustsecp256k1_v0_11_ellswift_encode(CTX, ell64, &pubkey, rnd32); + rustsecp256k1_v0_11_ellswift_decode(CTX, &pubkey2, ell64); + rustsecp256k1_v0_11_pubkey_load(CTX, &g2, &pubkey2); /* Compare with original. */ - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&g, &g2)); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&g, &g2)); } - /* Verify the behavior of rustsecp256k1_v0_10_0_ellswift_create */ + /* Verify the behavior of rustsecp256k1_v0_11_ellswift_create */ for (i = 0; i < 400 * COUNT; i++) { unsigned char auxrnd32[32], sec32[32]; - rustsecp256k1_v0_10_0_scalar sec; - rustsecp256k1_v0_10_0_gej res; - rustsecp256k1_v0_10_0_ge dec; - rustsecp256k1_v0_10_0_pubkey pub; + rustsecp256k1_v0_11_scalar sec; + rustsecp256k1_v0_11_gej res; + rustsecp256k1_v0_11_ge dec; + rustsecp256k1_v0_11_pubkey pub; unsigned char ell64[64]; int ret; /* Generate random secret key and random randomizer. */ - if (i & 1) rustsecp256k1_v0_10_0_testrand256_test(auxrnd32); - random_scalar_order_test(&sec); - rustsecp256k1_v0_10_0_scalar_get_b32(sec32, &sec); + if (i & 1) testrand256_test(auxrnd32); + testutil_random_scalar_order_test(&sec); + rustsecp256k1_v0_11_scalar_get_b32(sec32, &sec); /* Construct ElligatorSwift-encoded public keys for that key. */ - ret = rustsecp256k1_v0_10_0_ellswift_create(CTX, ell64, sec32, (i & 1) ? auxrnd32 : NULL); + ret = rustsecp256k1_v0_11_ellswift_create(CTX, ell64, sec32, (i & 1) ? auxrnd32 : NULL); CHECK(ret); /* Decode it, and compare with traditionally-computed public key. */ - rustsecp256k1_v0_10_0_ellswift_decode(CTX, &pub, ell64); - rustsecp256k1_v0_10_0_pubkey_load(CTX, &dec, &pub); - rustsecp256k1_v0_10_0_ecmult(&res, NULL, &rustsecp256k1_v0_10_0_scalar_zero, &sec); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&res, &dec)); + rustsecp256k1_v0_11_ellswift_decode(CTX, &pub, ell64); + rustsecp256k1_v0_11_pubkey_load(CTX, &dec, &pub); + rustsecp256k1_v0_11_ecmult(&res, NULL, &rustsecp256k1_v0_11_scalar_zero, &sec); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&res, &dec)); } - /* Verify that rustsecp256k1_v0_10_0_ellswift_xdh computes the right shared X coordinate. */ + /* Verify that rustsecp256k1_v0_11_ellswift_xdh computes the right shared X coordinate. */ for (i = 0; i < 800 * COUNT; i++) { unsigned char ell64[64], sec32[32], share32[32]; - rustsecp256k1_v0_10_0_scalar sec; - rustsecp256k1_v0_10_0_ge dec, res; - rustsecp256k1_v0_10_0_fe share_x; - rustsecp256k1_v0_10_0_gej decj, resj; - rustsecp256k1_v0_10_0_pubkey pub; + rustsecp256k1_v0_11_scalar sec; + rustsecp256k1_v0_11_ge dec, res; + rustsecp256k1_v0_11_fe share_x; + rustsecp256k1_v0_11_gej decj, resj; + rustsecp256k1_v0_11_pubkey pub; int ret; /* Generate random secret key. */ - random_scalar_order_test(&sec); - rustsecp256k1_v0_10_0_scalar_get_b32(sec32, &sec); + testutil_random_scalar_order_test(&sec); + rustsecp256k1_v0_11_scalar_get_b32(sec32, &sec); /* Generate random ElligatorSwift encoding for the remote key and decode it. */ - rustsecp256k1_v0_10_0_testrand256_test(ell64); - rustsecp256k1_v0_10_0_testrand256_test(ell64 + 32); - rustsecp256k1_v0_10_0_ellswift_decode(CTX, &pub, ell64); - rustsecp256k1_v0_10_0_pubkey_load(CTX, &dec, &pub); - rustsecp256k1_v0_10_0_gej_set_ge(&decj, &dec); + testrand256_test(ell64); + testrand256_test(ell64 + 32); + rustsecp256k1_v0_11_ellswift_decode(CTX, &pub, ell64); + rustsecp256k1_v0_11_pubkey_load(CTX, &dec, &pub); + rustsecp256k1_v0_11_gej_set_ge(&decj, &dec); /* Compute the X coordinate of seckey*pubkey using ellswift_xdh. Note that we * pass ell64 as claimed (but incorrect) encoding for sec32 here; this works * because the "hasher" function we use here ignores the ell64 arguments. */ - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32, ell64, ell64, sec32, i & 1, &ellswift_xdh_hash_x32, NULL); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32, ell64, ell64, sec32, i & 1, &ellswift_xdh_hash_x32, NULL); CHECK(ret); - (void)rustsecp256k1_v0_10_0_fe_set_b32_limit(&share_x, share32); /* no overflow is possible */ + (void)rustsecp256k1_v0_11_fe_set_b32_limit(&share_x, share32); /* no overflow is possible */ SECP256K1_FE_VERIFY(&share_x); /* Compute seckey*pubkey directly. */ - rustsecp256k1_v0_10_0_ecmult(&resj, &decj, &sec, NULL); - rustsecp256k1_v0_10_0_ge_set_gej(&res, &resj); + rustsecp256k1_v0_11_ecmult(&resj, &decj, &sec, NULL); + rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_ellswift_xdh */ + /* Verify the joint behavior of rustsecp256k1_v0_11_ellswift_xdh */ for (i = 0; i < 200 * COUNT; i++) { unsigned char auxrnd32a[32], auxrnd32b[32], auxrnd32a_bad[32], auxrnd32b_bad[32]; unsigned char sec32a[32], sec32b[32], sec32a_bad[32], sec32b_bad[32]; - rustsecp256k1_v0_10_0_scalar seca, secb; + rustsecp256k1_v0_11_scalar seca, secb; unsigned char ell64a[64], ell64b[64], ell64a_bad[64], ell64b_bad[64]; unsigned char share32a[32], share32b[32], share32_bad[32]; unsigned char prefix64[64]; - rustsecp256k1_v0_10_0_ellswift_xdh_hash_function hash_function; + rustsecp256k1_v0_11_ellswift_xdh_hash_function hash_function; void* data; int ret; @@ -309,126 +309,126 @@ void run_ellswift_tests(void) { hash_function = ellswift_xdh_hash_x32; data = NULL; } else if ((i % 3) == 1) { - hash_function = rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324; + hash_function = rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324; data = NULL; } else { - hash_function = rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_prefix; - rustsecp256k1_v0_10_0_testrand256_test(prefix64); - rustsecp256k1_v0_10_0_testrand256_test(prefix64 + 32); + hash_function = rustsecp256k1_v0_11_ellswift_xdh_hash_function_prefix; + testrand256_test(prefix64); + testrand256_test(prefix64 + 32); data = prefix64; } /* Generate random secret keys and random randomizers. */ - rustsecp256k1_v0_10_0_testrand256_test(auxrnd32a); - rustsecp256k1_v0_10_0_testrand256_test(auxrnd32b); - random_scalar_order_test(&seca); + 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 */ - random_scalar_order(&secb); - rustsecp256k1_v0_10_0_scalar_get_b32(sec32a, &seca); - rustsecp256k1_v0_10_0_scalar_get_b32(sec32b, &secb); + testutil_random_scalar_order(&secb); + rustsecp256k1_v0_11_scalar_get_b32(sec32a, &seca); + rustsecp256k1_v0_11_scalar_get_b32(sec32b, &secb); /* Construct ElligatorSwift-encoded public keys for those keys. */ /* For A: */ - ret = rustsecp256k1_v0_10_0_ellswift_create(CTX, ell64a, sec32a, auxrnd32a); + ret = rustsecp256k1_v0_11_ellswift_create(CTX, ell64a, sec32a, auxrnd32a); CHECK(ret); /* For B: */ - ret = rustsecp256k1_v0_10_0_ellswift_create(CTX, ell64b, sec32b, auxrnd32b); + ret = rustsecp256k1_v0_11_ellswift_create(CTX, ell64b, sec32b, auxrnd32b); CHECK(ret); /* Compute the shared secret both ways and compare with each other. */ /* For A: */ - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32a, ell64a, ell64b, sec32a, 0, hash_function, data); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32a, ell64a, ell64b, sec32a, 0, hash_function, data); CHECK(ret); /* For B: */ - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32b, ell64a, ell64b, sec32b, 1, hash_function, data); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32b, ell64a, ell64b, sec32b, 1, hash_function, data); CHECK(ret); /* And compare: */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32a, share32b, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(share32a, share32b, 32) == 0); /* 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)); - rustsecp256k1_v0_10_0_testrand_flip(ell64b_bad, sizeof(ell64b_bad)); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); - CHECK(ret); /* Mismatching encodings don't get detected by rustsecp256k1_v0_10_0_ellswift_xdh. */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32a, 32) != 0); + testrand_flip(ell64b_bad, sizeof(ell64b_bad)); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); + CHECK(ret); /* Mismatching encodings don't get detected by rustsecp256k1_v0_11_ellswift_xdh. */ + CHECK(rustsecp256k1_v0_11_memcmp_var(share32_bad, share32a, 32) != 0); /* For B (using a bad public key for A): */ memcpy(ell64a_bad, ell64a, sizeof(ell64a_bad)); - rustsecp256k1_v0_10_0_testrand_flip(ell64a_bad, sizeof(ell64a_bad)); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); + testrand_flip(ell64a_bad, sizeof(ell64a_bad)); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32b, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(share32_bad, share32b, 32) != 0); /* Verify that the shared secret doesn't match if the private key is incorrect. */ /* For A: */ memcpy(sec32a_bad, sec32a, sizeof(sec32a_bad)); - rustsecp256k1_v0_10_0_testrand_flip(sec32a_bad, sizeof(sec32a_bad)); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a_bad, 0, hash_function, data); - CHECK(!ret || rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32a, 32) != 0); + testrand_flip(sec32a_bad, sizeof(sec32a_bad)); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a_bad, 0, hash_function, data); + CHECK(!ret || rustsecp256k1_v0_11_memcmp_var(share32_bad, share32a, 32) != 0); /* For B: */ memcpy(sec32b_bad, sec32b, sizeof(sec32b_bad)); - rustsecp256k1_v0_10_0_testrand_flip(sec32b_bad, sizeof(sec32b_bad)); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b_bad, 1, hash_function, data); - CHECK(!ret || rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32b, 32) != 0); + testrand_flip(sec32b_bad, sizeof(sec32b_bad)); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b_bad, 1, hash_function, data); + CHECK(!ret || rustsecp256k1_v0_11_memcmp_var(share32_bad, share32b, 32) != 0); if (hash_function != ellswift_xdh_hash_x32) { /* 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)); - rustsecp256k1_v0_10_0_testrand_flip(auxrnd32b_bad, sizeof(auxrnd32b_bad)); - ret = rustsecp256k1_v0_10_0_ellswift_create(CTX, ell64b_bad, sec32b, auxrnd32b_bad); + testrand_flip(auxrnd32b_bad, sizeof(auxrnd32b_bad)); + ret = rustsecp256k1_v0_11_ellswift_create(CTX, ell64b_bad, sec32b, auxrnd32b_bad); CHECK(ret); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a, ell64b_bad, sec32a, 0, hash_function, data); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32a, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(share32_bad, share32a, 32) != 0); /* For B (changing A's public key): */ memcpy(auxrnd32a_bad, auxrnd32a, sizeof(auxrnd32a_bad)); - rustsecp256k1_v0_10_0_testrand_flip(auxrnd32a_bad, sizeof(auxrnd32a_bad)); - ret = rustsecp256k1_v0_10_0_ellswift_create(CTX, ell64a_bad, sec32a, auxrnd32a_bad); + testrand_flip(auxrnd32a_bad, sizeof(auxrnd32a_bad)); + ret = rustsecp256k1_v0_11_ellswift_create(CTX, ell64a_bad, sec32a, auxrnd32a_bad); CHECK(ret); - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a_bad, ell64b, sec32b, 1, hash_function, data); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32b, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(share32_bad, share32b, 32) != 0); /* Verify that swapping sides changes the shared secret. */ /* For A (claiming to be B): */ - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a, 1, hash_function, data); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32a, 1, hash_function, data); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32a, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(share32_bad, share32a, 32) != 0); /* For B (claiming to be A): */ - ret = rustsecp256k1_v0_10_0_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b, 0, hash_function, data); + ret = rustsecp256k1_v0_11_ellswift_xdh(CTX, share32_bad, ell64a, ell64b, sec32b, 0, hash_function, data); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(share32_bad, share32b, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(share32_bad, share32b, 32) != 0); } } /* Test hash initializers. */ { - rustsecp256k1_v0_10_0_sha256 sha, sha_optimized; - static const unsigned char encode_tag[25] = "rustsecp256k1_v0_10_0_ellswift_encode"; - static const unsigned char create_tag[25] = "rustsecp256k1_v0_10_0_ellswift_create"; - static const unsigned char bip324_tag[26] = "bip324_ellswift_xonly_ecdh"; + rustsecp256k1_v0_11_sha256 sha, sha_optimized; + 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 - * rustsecp256k1_v0_10_0_ellswift_sha256_init_encode has the expected + * rustsecp256k1_v0_11_ellswift_sha256_init_encode has the expected * state. */ - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, encode_tag, sizeof(encode_tag)); - rustsecp256k1_v0_10_0_ellswift_sha256_init_encode(&sha_optimized); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, encode_tag, sizeof(encode_tag)); + rustsecp256k1_v0_11_ellswift_sha256_init_encode(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); /* Check that hash initialized by - * rustsecp256k1_v0_10_0_ellswift_sha256_init_create has the expected + * rustsecp256k1_v0_11_ellswift_sha256_init_create has the expected * state. */ - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, create_tag, sizeof(create_tag)); - rustsecp256k1_v0_10_0_ellswift_sha256_init_create(&sha_optimized); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, create_tag, sizeof(create_tag)); + rustsecp256k1_v0_11_ellswift_sha256_init_create(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); /* Check that hash initialized by - * rustsecp256k1_v0_10_0_ellswift_sha256_init_bip324 has the expected + * rustsecp256k1_v0_11_ellswift_sha256_init_bip324 has the expected * state. */ - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, bip324_tag, sizeof(bip324_tag)); - rustsecp256k1_v0_10_0_ellswift_sha256_init_bip324(&sha_optimized); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, bip324_tag, sizeof(bip324_tag)); + rustsecp256k1_v0_11_ellswift_sha256_init_bip324(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/Makefile.am.include index 7893e24bb..dcfade508 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/Makefile.am.include @@ -1,4 +1,4 @@ -include_HEADERS += include/rustsecp256k1_v0_10_0_extrakeys.h +include_HEADERS += include/rustsecp256k1_v0_11_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 diff --git a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/main_impl.h index ab5692cd0..3b18ca1f7 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/main_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/main_impl.h @@ -11,54 +11,54 @@ #include "../../../include/secp256k1_extrakeys.h" #include "../../util.h" -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_xonly_pubkey_load(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ge *ge, const rustsecp256k1_v0_10_0_xonly_pubkey *pubkey) { - return rustsecp256k1_v0_10_0_pubkey_load(ctx, ge, (const rustsecp256k1_v0_10_0_pubkey *) pubkey); +static SECP256K1_INLINE int rustsecp256k1_v0_11_xonly_pubkey_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ge *ge, const rustsecp256k1_v0_11_xonly_pubkey *pubkey) { + return rustsecp256k1_v0_11_pubkey_load(ctx, ge, (const rustsecp256k1_v0_11_pubkey *) pubkey); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_xonly_pubkey_save(rustsecp256k1_v0_10_0_xonly_pubkey *pubkey, rustsecp256k1_v0_10_0_ge *ge) { - rustsecp256k1_v0_10_0_pubkey_save((rustsecp256k1_v0_10_0_pubkey *) pubkey, ge); +static SECP256K1_INLINE void rustsecp256k1_v0_11_xonly_pubkey_save(rustsecp256k1_v0_11_xonly_pubkey *pubkey, rustsecp256k1_v0_11_ge *ge) { + rustsecp256k1_v0_11_pubkey_save((rustsecp256k1_v0_11_pubkey *) pubkey, ge); } -int rustsecp256k1_v0_10_0_xonly_pubkey_parse(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_xonly_pubkey *pubkey, const unsigned char *input32) { - rustsecp256k1_v0_10_0_ge pk; - rustsecp256k1_v0_10_0_fe x; +int rustsecp256k1_v0_11_xonly_pubkey_parse(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_xonly_pubkey *pubkey, const unsigned char *input32) { + rustsecp256k1_v0_11_ge pk; + rustsecp256k1_v0_11_fe x; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(input32 != NULL); - if (!rustsecp256k1_v0_10_0_fe_set_b32_limit(&x, input32)) { + if (!rustsecp256k1_v0_11_fe_set_b32_limit(&x, input32)) { return 0; } - if (!rustsecp256k1_v0_10_0_ge_set_xo_var(&pk, &x, 0)) { + if (!rustsecp256k1_v0_11_ge_set_xo_var(&pk, &x, 0)) { return 0; } - if (!rustsecp256k1_v0_10_0_ge_is_in_correct_subgroup(&pk)) { + if (!rustsecp256k1_v0_11_ge_is_in_correct_subgroup(&pk)) { return 0; } - rustsecp256k1_v0_10_0_xonly_pubkey_save(pubkey, &pk); + rustsecp256k1_v0_11_xonly_pubkey_save(pubkey, &pk); return 1; } -int rustsecp256k1_v0_10_0_xonly_pubkey_serialize(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *output32, const rustsecp256k1_v0_10_0_xonly_pubkey *pubkey) { - rustsecp256k1_v0_10_0_ge pk; +int rustsecp256k1_v0_11_xonly_pubkey_serialize(const rustsecp256k1_v0_11_context* ctx, unsigned char *output32, const rustsecp256k1_v0_11_xonly_pubkey *pubkey) { + rustsecp256k1_v0_11_ge pk; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output32 != NULL); memset(output32, 0, 32); ARG_CHECK(pubkey != NULL); - if (!rustsecp256k1_v0_10_0_xonly_pubkey_load(ctx, &pk, pubkey)) { + if (!rustsecp256k1_v0_11_xonly_pubkey_load(ctx, &pk, pubkey)) { return 0; } - rustsecp256k1_v0_10_0_fe_get_b32(output32, &pk.x); + rustsecp256k1_v0_11_fe_get_b32(output32, &pk.x); return 1; } -int rustsecp256k1_v0_10_0_xonly_pubkey_cmp(const rustsecp256k1_v0_10_0_context* ctx, const rustsecp256k1_v0_10_0_xonly_pubkey* pk0, const rustsecp256k1_v0_10_0_xonly_pubkey* pk1) { +int rustsecp256k1_v0_11_xonly_pubkey_cmp(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_xonly_pubkey* pk0, const rustsecp256k1_v0_11_xonly_pubkey* pk1) { unsigned char out[2][32]; - const rustsecp256k1_v0_10_0_xonly_pubkey* pk[2]; + const rustsecp256k1_v0_11_xonly_pubkey* pk[2]; int i; VERIFY_CHECK(ctx != NULL); @@ -71,7 +71,7 @@ int rustsecp256k1_v0_10_0_xonly_pubkey_cmp(const rustsecp256k1_v0_10_0_context* * pubkeys are involved and prevents edge cases such as sorting * algorithms that use this function and do not terminate as a * result. */ - if (!rustsecp256k1_v0_10_0_xonly_pubkey_serialize(ctx, out[i], pk[i])) { + if (!rustsecp256k1_v0_11_xonly_pubkey_serialize(ctx, out[i], pk[i])) { /* Note that xonly_pubkey_serialize should already set the output to * zero in that case, but it's not guaranteed by the API, we can't * test it and writing a VERIFY_CHECK is more complex than @@ -79,44 +79,44 @@ int rustsecp256k1_v0_10_0_xonly_pubkey_cmp(const rustsecp256k1_v0_10_0_context* memset(out[i], 0, sizeof(out[i])); } } - return rustsecp256k1_v0_10_0_memcmp_var(out[0], out[1], sizeof(out[1])); + return rustsecp256k1_v0_11_memcmp_var(out[0], out[1], sizeof(out[1])); } /** Keeps a group element as is if it has an even Y and otherwise negates it. * y_parity is set to 0 in the former case and to 1 in the latter case. * Requires that the coordinates of r are normalized. */ -static int rustsecp256k1_v0_10_0_extrakeys_ge_even_y(rustsecp256k1_v0_10_0_ge *r) { +static int rustsecp256k1_v0_11_extrakeys_ge_even_y(rustsecp256k1_v0_11_ge *r) { int y_parity = 0; - VERIFY_CHECK(!rustsecp256k1_v0_10_0_ge_is_infinity(r)); + VERIFY_CHECK(!rustsecp256k1_v0_11_ge_is_infinity(r)); - if (rustsecp256k1_v0_10_0_fe_is_odd(&r->y)) { - rustsecp256k1_v0_10_0_fe_negate(&r->y, &r->y, 1); + if (rustsecp256k1_v0_11_fe_is_odd(&r->y)) { + rustsecp256k1_v0_11_fe_negate(&r->y, &r->y, 1); y_parity = 1; } return y_parity; } -int rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_xonly_pubkey *xonly_pubkey, int *pk_parity, const rustsecp256k1_v0_10_0_pubkey *pubkey) { - rustsecp256k1_v0_10_0_ge pk; +int rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_xonly_pubkey *xonly_pubkey, int *pk_parity, const rustsecp256k1_v0_11_pubkey *pubkey) { + rustsecp256k1_v0_11_ge pk; int tmp; VERIFY_CHECK(ctx != NULL); ARG_CHECK(xonly_pubkey != NULL); ARG_CHECK(pubkey != NULL); - if (!rustsecp256k1_v0_10_0_pubkey_load(ctx, &pk, pubkey)) { + if (!rustsecp256k1_v0_11_pubkey_load(ctx, &pk, pubkey)) { return 0; } - tmp = rustsecp256k1_v0_10_0_extrakeys_ge_even_y(&pk); + tmp = rustsecp256k1_v0_11_extrakeys_ge_even_y(&pk); if (pk_parity != NULL) { *pk_parity = tmp; } - rustsecp256k1_v0_10_0_xonly_pubkey_save(xonly_pubkey, &pk); + rustsecp256k1_v0_11_xonly_pubkey_save(xonly_pubkey, &pk); return 1; } -int rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *output_pubkey, const rustsecp256k1_v0_10_0_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_ge pk; +int rustsecp256k1_v0_11_xonly_pubkey_tweak_add(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *output_pubkey, const rustsecp256k1_v0_11_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge pk; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output_pubkey != NULL); @@ -124,16 +124,16 @@ int rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(const rustsecp256k1_v0_10_0_con ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(tweak32 != NULL); - if (!rustsecp256k1_v0_10_0_xonly_pubkey_load(ctx, &pk, internal_pubkey) - || !rustsecp256k1_v0_10_0_ec_pubkey_tweak_add_helper(&pk, tweak32)) { + if (!rustsecp256k1_v0_11_xonly_pubkey_load(ctx, &pk, internal_pubkey) + || !rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(&pk, tweak32)) { return 0; } - rustsecp256k1_v0_10_0_pubkey_save(output_pubkey, &pk); + rustsecp256k1_v0_11_pubkey_save(output_pubkey, &pk); return 1; } -int rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(const rustsecp256k1_v0_10_0_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const rustsecp256k1_v0_10_0_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_ge pk; +int rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(const rustsecp256k1_v0_11_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const rustsecp256k1_v0_11_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge pk; unsigned char pk_expected32[32]; VERIFY_CHECK(ctx != NULL); @@ -141,31 +141,31 @@ int rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(const rustsecp256k1_v0_10 ARG_CHECK(tweaked_pubkey32 != NULL); ARG_CHECK(tweak32 != NULL); - if (!rustsecp256k1_v0_10_0_xonly_pubkey_load(ctx, &pk, internal_pubkey) - || !rustsecp256k1_v0_10_0_ec_pubkey_tweak_add_helper(&pk, tweak32)) { + if (!rustsecp256k1_v0_11_xonly_pubkey_load(ctx, &pk, internal_pubkey) + || !rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(&pk, tweak32)) { return 0; } - rustsecp256k1_v0_10_0_fe_normalize_var(&pk.x); - rustsecp256k1_v0_10_0_fe_normalize_var(&pk.y); - rustsecp256k1_v0_10_0_fe_get_b32(pk_expected32, &pk.x); + rustsecp256k1_v0_11_fe_normalize_var(&pk.x); + rustsecp256k1_v0_11_fe_normalize_var(&pk.y); + rustsecp256k1_v0_11_fe_get_b32(pk_expected32, &pk.x); - return rustsecp256k1_v0_10_0_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0 - && rustsecp256k1_v0_10_0_fe_is_odd(&pk.y) == tweaked_pk_parity; + return rustsecp256k1_v0_11_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0 + && rustsecp256k1_v0_11_fe_is_odd(&pk.y) == tweaked_pk_parity; } -static void rustsecp256k1_v0_10_0_keypair_save(rustsecp256k1_v0_10_0_keypair *keypair, const rustsecp256k1_v0_10_0_scalar *sk, rustsecp256k1_v0_10_0_ge *pk) { - rustsecp256k1_v0_10_0_scalar_get_b32(&keypair->data[0], sk); - rustsecp256k1_v0_10_0_pubkey_save((rustsecp256k1_v0_10_0_pubkey *)&keypair->data[32], pk); +static void rustsecp256k1_v0_11_keypair_save(rustsecp256k1_v0_11_keypair *keypair, const rustsecp256k1_v0_11_scalar *sk, rustsecp256k1_v0_11_ge *pk) { + rustsecp256k1_v0_11_scalar_get_b32(&keypair->data[0], sk); + rustsecp256k1_v0_11_pubkey_save((rustsecp256k1_v0_11_pubkey *)&keypair->data[32], pk); } -static int rustsecp256k1_v0_10_0_keypair_seckey_load(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_scalar *sk, const rustsecp256k1_v0_10_0_keypair *keypair) { +static int rustsecp256k1_v0_11_keypair_seckey_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar *sk, const rustsecp256k1_v0_11_keypair *keypair) { int ret; - ret = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(sk, &keypair->data[0]); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(sk, &keypair->data[0]); /* We can declassify ret here because sk is only zero if a keypair function * failed (which zeroes the keypair) and its return value is ignored. */ - rustsecp256k1_v0_10_0_declassify(ctx, &ret, sizeof(ret)); + rustsecp256k1_v0_11_declassify(ctx, &ret, sizeof(ret)); ARG_CHECK(ret); return ret; } @@ -173,45 +173,45 @@ static int rustsecp256k1_v0_10_0_keypair_seckey_load(const rustsecp256k1_v0_10_0 /* Load a keypair into pk and sk (if non-NULL). This function declassifies pk * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and * pk with dummy values. */ -static int rustsecp256k1_v0_10_0_keypair_load(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_scalar *sk, rustsecp256k1_v0_10_0_ge *pk, const rustsecp256k1_v0_10_0_keypair *keypair) { +static int rustsecp256k1_v0_11_keypair_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar *sk, rustsecp256k1_v0_11_ge *pk, const rustsecp256k1_v0_11_keypair *keypair) { int ret; - const rustsecp256k1_v0_10_0_pubkey *pubkey = (const rustsecp256k1_v0_10_0_pubkey *)&keypair->data[32]; + const rustsecp256k1_v0_11_pubkey *pubkey = (const rustsecp256k1_v0_11_pubkey *)&keypair->data[32]; /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's * invalid. */ - rustsecp256k1_v0_10_0_declassify(ctx, pubkey, sizeof(*pubkey)); - ret = rustsecp256k1_v0_10_0_pubkey_load(ctx, pk, pubkey); + rustsecp256k1_v0_11_declassify(ctx, pubkey, sizeof(*pubkey)); + ret = rustsecp256k1_v0_11_pubkey_load(ctx, pk, pubkey); if (sk != NULL) { - ret = ret && rustsecp256k1_v0_10_0_keypair_seckey_load(ctx, sk, keypair); + ret = ret && rustsecp256k1_v0_11_keypair_seckey_load(ctx, sk, keypair); } if (!ret) { - *pk = rustsecp256k1_v0_10_0_ge_const_g; + *pk = rustsecp256k1_v0_11_ge_const_g; if (sk != NULL) { - *sk = rustsecp256k1_v0_10_0_scalar_one; + *sk = rustsecp256k1_v0_11_scalar_one; } } return ret; } -int rustsecp256k1_v0_10_0_keypair_create(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_keypair *keypair, const unsigned char *seckey32) { - rustsecp256k1_v0_10_0_scalar sk; - rustsecp256k1_v0_10_0_ge pk; +int rustsecp256k1_v0_11_keypair_create(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_keypair *keypair, const unsigned char *seckey32) { + rustsecp256k1_v0_11_scalar sk; + rustsecp256k1_v0_11_ge pk; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(keypair != NULL); memset(keypair, 0, sizeof(*keypair)); - ARG_CHECK(rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey32 != NULL); - ret = rustsecp256k1_v0_10_0_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32); - rustsecp256k1_v0_10_0_keypair_save(keypair, &sk, &pk); - rustsecp256k1_v0_10_0_memczero(keypair, sizeof(*keypair), !ret); + ret = rustsecp256k1_v0_11_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32); + rustsecp256k1_v0_11_keypair_save(keypair, &sk, &pk); + rustsecp256k1_v0_11_memczero(keypair, sizeof(*keypair), !ret); - rustsecp256k1_v0_10_0_scalar_clear(&sk); + rustsecp256k1_v0_11_scalar_clear(&sk); return ret; } -int rustsecp256k1_v0_10_0_keypair_sec(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey, const rustsecp256k1_v0_10_0_keypair *keypair) { +int rustsecp256k1_v0_11_keypair_sec(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const rustsecp256k1_v0_11_keypair *keypair) { VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); memset(seckey, 0, 32); @@ -221,7 +221,7 @@ int rustsecp256k1_v0_10_0_keypair_sec(const rustsecp256k1_v0_10_0_context* ctx, return 1; } -int rustsecp256k1_v0_10_0_keypair_pub(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubkey, const rustsecp256k1_v0_10_0_keypair *keypair) { +int rustsecp256k1_v0_11_keypair_pub(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const rustsecp256k1_v0_11_keypair *keypair) { VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); @@ -231,8 +231,8 @@ int rustsecp256k1_v0_10_0_keypair_pub(const rustsecp256k1_v0_10_0_context* ctx, return 1; } -int rustsecp256k1_v0_10_0_keypair_xonly_pub(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_xonly_pubkey *pubkey, int *pk_parity, const rustsecp256k1_v0_10_0_keypair *keypair) { - rustsecp256k1_v0_10_0_ge pk; +int rustsecp256k1_v0_11_keypair_xonly_pub(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_xonly_pubkey *pubkey, int *pk_parity, const rustsecp256k1_v0_11_keypair *keypair) { + rustsecp256k1_v0_11_ge pk; int tmp; VERIFY_CHECK(ctx != NULL); @@ -240,21 +240,21 @@ int rustsecp256k1_v0_10_0_keypair_xonly_pub(const rustsecp256k1_v0_10_0_context* memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(keypair != NULL); - if (!rustsecp256k1_v0_10_0_keypair_load(ctx, NULL, &pk, keypair)) { + if (!rustsecp256k1_v0_11_keypair_load(ctx, NULL, &pk, keypair)) { return 0; } - tmp = rustsecp256k1_v0_10_0_extrakeys_ge_even_y(&pk); + tmp = rustsecp256k1_v0_11_extrakeys_ge_even_y(&pk); if (pk_parity != NULL) { *pk_parity = tmp; } - rustsecp256k1_v0_10_0_xonly_pubkey_save(pubkey, &pk); + rustsecp256k1_v0_11_xonly_pubkey_save(pubkey, &pk); return 1; } -int rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_keypair *keypair, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_ge pk; - rustsecp256k1_v0_10_0_scalar sk; +int rustsecp256k1_v0_11_keypair_xonly_tweak_add(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_keypair *keypair, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge pk; + rustsecp256k1_v0_11_scalar sk; int y_parity; int ret; @@ -262,23 +262,23 @@ int rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(const rustsecp256k1_v0_10_0_co ARG_CHECK(keypair != NULL); ARG_CHECK(tweak32 != NULL); - ret = rustsecp256k1_v0_10_0_keypair_load(ctx, &sk, &pk, keypair); + ret = rustsecp256k1_v0_11_keypair_load(ctx, &sk, &pk, keypair); memset(keypair, 0, sizeof(*keypair)); - y_parity = rustsecp256k1_v0_10_0_extrakeys_ge_even_y(&pk); + y_parity = rustsecp256k1_v0_11_extrakeys_ge_even_y(&pk); if (y_parity == 1) { - rustsecp256k1_v0_10_0_scalar_negate(&sk, &sk); + rustsecp256k1_v0_11_scalar_negate(&sk, &sk); } - ret &= rustsecp256k1_v0_10_0_ec_seckey_tweak_add_helper(&sk, tweak32); - ret &= rustsecp256k1_v0_10_0_ec_pubkey_tweak_add_helper(&pk, tweak32); + ret &= rustsecp256k1_v0_11_ec_seckey_tweak_add_helper(&sk, tweak32); + ret &= rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(&pk, tweak32); - rustsecp256k1_v0_10_0_declassify(ctx, &ret, sizeof(ret)); + rustsecp256k1_v0_11_declassify(ctx, &ret, sizeof(ret)); if (ret) { - rustsecp256k1_v0_10_0_keypair_save(keypair, &sk, &pk); + rustsecp256k1_v0_11_keypair_save(keypair, &sk, &pk); } - rustsecp256k1_v0_10_0_scalar_clear(&sk); + rustsecp256k1_v0_11_scalar_clear(&sk); return ret; } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h index 1612cd521..54dccce70 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h @@ -10,54 +10,54 @@ #include "../../../include/secp256k1_extrakeys.h" #include "main_impl.h" -static void test_exhaustive_extrakeys(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge* group) { - rustsecp256k1_v0_10_0_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; - rustsecp256k1_v0_10_0_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; - rustsecp256k1_v0_10_0_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; +static void test_exhaustive_extrakeys(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge* group) { + rustsecp256k1_v0_11_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; + rustsecp256k1_v0_11_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; + rustsecp256k1_v0_11_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; int parities[EXHAUSTIVE_TEST_ORDER - 1]; unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; int i; for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_fe fe; - rustsecp256k1_v0_10_0_scalar scalar_i; + rustsecp256k1_v0_11_fe fe; + rustsecp256k1_v0_11_scalar scalar_i; unsigned char buf[33]; int parity; - rustsecp256k1_v0_10_0_scalar_set_int(&scalar_i, i); - rustsecp256k1_v0_10_0_scalar_get_b32(buf, &scalar_i); + rustsecp256k1_v0_11_scalar_set_int(&scalar_i, i); + rustsecp256k1_v0_11_scalar_get_b32(buf, &scalar_i); /* Construct pubkey and keypair. */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(ctx, &keypair[i - 1], buf)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); + CHECK(rustsecp256k1_v0_11_keypair_create(ctx, &keypair[i - 1], buf)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); /* Construct serialized xonly_pubkey from keypair. */ - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); + CHECK(rustsecp256k1_v0_11_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); CHECK(parity == parities[i - 1]); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); + CHECK(rustsecp256k1_v0_11_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); /* Compare the xonly_pubkey bytes against the precomputed group. */ - rustsecp256k1_v0_10_0_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&fe, &group[i].x)); + rustsecp256k1_v0_11_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]); + CHECK(rustsecp256k1_v0_11_fe_equal(&fe, &group[i].x)); /* Check the parity against the precomputed group. */ fe = group[i].y; - rustsecp256k1_v0_10_0_fe_normalize_var(&fe); - CHECK(rustsecp256k1_v0_10_0_fe_is_odd(&fe) == parities[i - 1]); + rustsecp256k1_v0_11_fe_normalize_var(&fe); + CHECK(rustsecp256k1_v0_11_fe_is_odd(&fe) == parities[i - 1]); /* Verify that the higher half is identical to the lower half mirrored. */ if (i > EXHAUSTIVE_TEST_ORDER / 2) { - CHECK(rustsecp256k1_v0_10_0_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_impl.h index e5143dec2..544ce31b9 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/extrakeys/tests_impl.h @@ -10,11 +10,11 @@ #include "../../../include/secp256k1_extrakeys.h" static void test_xonly_pubkey(void) { - rustsecp256k1_v0_10_0_pubkey pk; - rustsecp256k1_v0_10_0_xonly_pubkey xonly_pk, xonly_pk_tmp; - rustsecp256k1_v0_10_0_ge pk1; - rustsecp256k1_v0_10_0_ge pk2; - rustsecp256k1_v0_10_0_fe y; + rustsecp256k1_v0_11_pubkey pk; + rustsecp256k1_v0_11_xonly_pubkey xonly_pk, xonly_pk_tmp; + rustsecp256k1_v0_11_ge pk1; + rustsecp256k1_v0_11_ge pk2; + rustsecp256k1_v0_11_fe y; unsigned char sk[32]; unsigned char xy_sk[32]; unsigned char buf32[32]; @@ -23,86 +23,86 @@ static void test_xonly_pubkey(void) { int pk_parity; int i; - rustsecp256k1_v0_10_0_testrand256(sk); + testrand256(sk); memset(ones32, 0xFF, 32); - rustsecp256k1_v0_10_0_testrand256(xy_sk); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); + testrand256(xy_sk); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); /* Test xonly_pubkey_from_pubkey */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, NULL, &pk_parity, &pk)); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, NULL)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, NULL, &pk_parity, &pk)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, NULL)); memset(&pk, 0, sizeof(pk)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk)); /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */ memset(sk, 0, sizeof(sk)); sk[0] = 1; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0); CHECK(pk_parity == 0); /* Choose a secret key such that pubkey and xonly_pubkey are each others * negation. */ sk[0] = 2; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); CHECK(pk_parity == 1); - rustsecp256k1_v0_10_0_pubkey_load(CTX, &pk1, &pk); - rustsecp256k1_v0_10_0_pubkey_load(CTX, &pk2, (rustsecp256k1_v0_10_0_pubkey *) &xonly_pk); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&pk1.x, &pk2.x) == 1); - rustsecp256k1_v0_10_0_fe_negate(&y, &pk2.y, 1); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&pk1.y, &y) == 1); + rustsecp256k1_v0_11_pubkey_load(CTX, &pk1, &pk); + rustsecp256k1_v0_11_pubkey_load(CTX, &pk2, (rustsecp256k1_v0_11_pubkey *) &xonly_pk); + CHECK(rustsecp256k1_v0_11_fe_equal(&pk1.x, &pk2.x) == 1); + rustsecp256k1_v0_11_fe_negate(&y, &pk2.y, 1); + CHECK(rustsecp256k1_v0_11_fe_equal(&pk1.y, &y) == 1); /* Test xonly_pubkey_serialize and xonly_pubkey_parse */ - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, NULL, &xonly_pk)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, buf32, NULL)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf32, zeros64, 32) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, NULL, &xonly_pk)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, buf32, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(buf32, zeros64, 32) == 0); { /* A pubkey filled with 0s will fail to serialize due to pubkey_load * special casing. */ - rustsecp256k1_v0_10_0_xonly_pubkey pk_tmp; + rustsecp256k1_v0_11_xonly_pubkey pk_tmp; memset(&pk_tmp, 0, sizeof(pk_tmp)); /* pubkey_load calls illegal callback */ - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, buf32, &pk_tmp)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, buf32, &pk_tmp)); } - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, buf32, &xonly_pk) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, NULL, buf32)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &xonly_pk, NULL)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, buf32, &xonly_pk) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, NULL, buf32)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &xonly_pk, NULL)); /* Serialization and parse roundtrip */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, buf32, &xonly_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &xonly_pk_tmp, buf32) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, buf32, &xonly_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &xonly_pk_tmp, buf32) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); /* Test parsing invalid field elements */ memset(&xonly_pk, 1, sizeof(xonly_pk)); /* Overflowing field element */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &xonly_pk, ones32) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &xonly_pk, ones32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); memset(&xonly_pk, 1, sizeof(xonly_pk)); /* There's no point with x-coordinate 0 on secp256k1 */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &xonly_pk, zeros64) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &xonly_pk, zeros64) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); /* If a random 32-byte string can not be parsed with ec_pubkey_parse * (because interpreted as X coordinate it does not correspond to a point on * the curve) then xonly_pubkey_parse should fail as well. */ for (i = 0; i < COUNT; i++) { unsigned char rand33[33]; - rustsecp256k1_v0_10_0_testrand256(&rand33[1]); + testrand256(&rand33[1]); rand33[0] = SECP256K1_TAG_PUBKEY_EVEN; - if (!rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pk, rand33, 33)) { + if (!rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pk, rand33, 33)) { memset(&xonly_pk, 1, sizeof(xonly_pk)); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &xonly_pk, &rand33[1]) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &xonly_pk, &rand33[1]) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); } else { - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &xonly_pk, &rand33[1]) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &xonly_pk, &rand33[1]) == 1); } } } @@ -116,133 +116,133 @@ static void test_xonly_pubkey_comparison(void) { 0xde, 0x36, 0x0e, 0x87, 0x59, 0x8f, 0x3c, 0x01, 0x36, 0x2a, 0x2a, 0xb8, 0xc6, 0xf4, 0x5e, 0x4d, 0xb2, 0xc2, 0xd5, 0x03, 0xa7, 0xf9, 0xf1, 0x4f, 0xa8, 0xfa, 0x95, 0xa8, 0xe9, 0x69, 0x76, 0x1c }; - rustsecp256k1_v0_10_0_xonly_pubkey pk1; - rustsecp256k1_v0_10_0_xonly_pubkey pk2; - - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &pk1, pk1_ser) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &pk2, pk2_ser) == 1); - - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, NULL, &pk2) < 0)); - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk1, NULL) > 0)); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk1, &pk2) < 0); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk2, &pk1) > 0); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk1, &pk1) == 0); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk2, &pk2) == 0); + rustsecp256k1_v0_11_xonly_pubkey pk1; + rustsecp256k1_v0_11_xonly_pubkey pk2; + + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &pk1, pk1_ser) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &pk2, pk2_ser) == 1); + + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, NULL, &pk2) < 0)); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk1, NULL) > 0)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk1, &pk2) < 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk2, &pk1) > 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk1, &pk1) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk2, &pk2) == 0); memset(&pk1, 0, sizeof(pk1)); /* illegal pubkey */ - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk1, &pk2) < 0)); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk1, &pk2) < 0)); { int32_t ecount = 0; - rustsecp256k1_v0_10_0_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk1, &pk1) == 0); + rustsecp256k1_v0_11_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk1, &pk1) == 0); CHECK(ecount == 2); - rustsecp256k1_v0_10_0_context_set_illegal_callback(CTX, NULL, NULL); + rustsecp256k1_v0_11_context_set_illegal_callback(CTX, NULL, NULL); } - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_cmp(CTX, &pk2, &pk1) > 0)); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_xonly_pubkey_cmp(CTX, &pk2, &pk1) > 0)); } static void test_xonly_pubkey_tweak(void) { unsigned char zeros64[64] = { 0 }; unsigned char overflows[32]; unsigned char sk[32]; - rustsecp256k1_v0_10_0_pubkey internal_pk; - rustsecp256k1_v0_10_0_xonly_pubkey internal_xonly_pk; - rustsecp256k1_v0_10_0_pubkey output_pk; + rustsecp256k1_v0_11_pubkey internal_pk; + rustsecp256k1_v0_11_xonly_pubkey internal_xonly_pk; + rustsecp256k1_v0_11_pubkey output_pk; int pk_parity; unsigned char tweak[32]; int i; memset(overflows, 0xff, sizeof(overflows)); - rustsecp256k1_v0_10_0_testrand256(tweak); - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &internal_pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); - - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, NULL, &internal_xonly_pk, tweak)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, NULL, tweak)); + testrand256(tweak); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &internal_pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); + + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, NULL, &internal_xonly_pk, tweak)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, NULL, tweak)); /* NULL internal_xonly_pk zeroes the output_pk */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, NULL)); /* NULL tweak zeroes the output_pk */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); /* Invalid tweak zeroes the output_pk */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, overflows) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, overflows) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); /* A zero tweak is fine */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, zeros64) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, zeros64) == 1); /* Fails if the resulting key was infinity */ for (i = 0; i < COUNT; i++) { - rustsecp256k1_v0_10_0_scalar scalar_tweak; + rustsecp256k1_v0_11_scalar scalar_tweak; /* Because sk may be negated before adding, we need to try with tweak = * sk as well as tweak = -sk. */ - rustsecp256k1_v0_10_0_scalar_set_b32(&scalar_tweak, sk, NULL); - rustsecp256k1_v0_10_0_scalar_negate(&scalar_tweak, &scalar_tweak); - rustsecp256k1_v0_10_0_scalar_get_b32(tweak, &scalar_tweak); - CHECK((rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, sk) == 0) - || (rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 0)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); + rustsecp256k1_v0_11_scalar_set_b32(&scalar_tweak, sk, NULL); + rustsecp256k1_v0_11_scalar_negate(&scalar_tweak, &scalar_tweak); + rustsecp256k1_v0_11_scalar_get_b32(tweak, &scalar_tweak); + CHECK((rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, sk) == 0) + || (rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 0)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); } /* Invalid pk with a valid tweak */ memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); - rustsecp256k1_v0_10_0_testrand256(tweak); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); + testrand256(tweak); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); } static void test_xonly_pubkey_tweak_check(void) { unsigned char zeros64[64] = { 0 }; unsigned char overflows[32]; unsigned char sk[32]; - rustsecp256k1_v0_10_0_pubkey internal_pk; - rustsecp256k1_v0_10_0_xonly_pubkey internal_xonly_pk; - rustsecp256k1_v0_10_0_pubkey output_pk; - rustsecp256k1_v0_10_0_xonly_pubkey output_xonly_pk; + rustsecp256k1_v0_11_pubkey internal_pk; + rustsecp256k1_v0_11_xonly_pubkey internal_xonly_pk; + rustsecp256k1_v0_11_pubkey output_pk; + rustsecp256k1_v0_11_xonly_pubkey output_xonly_pk; unsigned char output_pk32[32]; unsigned char buf32[32]; int pk_parity; unsigned char tweak[32]; memset(overflows, 0xff, sizeof(overflows)); - rustsecp256k1_v0_10_0_testrand256(tweak); - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &internal_pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); - - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &output_xonly_pk, &pk_parity, &output_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, buf32, &output_xonly_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, NULL, pk_parity, &internal_xonly_pk, tweak)); + testrand256(tweak); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &internal_pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); + + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &output_xonly_pk, &pk_parity, &output_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, buf32, &output_xonly_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, NULL, pk_parity, &internal_xonly_pk, tweak)); /* invalid pk_parity value */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, 2, &internal_xonly_pk, tweak) == 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, NULL, tweak)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, NULL)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, 2, &internal_xonly_pk, tweak) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, NULL, tweak)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, NULL)); memset(tweak, 1, sizeof(tweak)); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, NULL, &internal_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &output_xonly_pk, &pk_parity, &output_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, output_pk32, &output_xonly_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &internal_xonly_pk, NULL, &internal_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &output_xonly_pk, &pk_parity, &output_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, output_pk32, &output_xonly_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); /* Wrong pk_parity */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); /* Wrong public key */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, buf32, &internal_xonly_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, buf32, &internal_xonly_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); /* Overflowing tweak not allowed */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, overflows) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk, &internal_xonly_pk, overflows) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); } /* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1 @@ -251,29 +251,29 @@ static void test_xonly_pubkey_tweak_check(void) { #define N_PUBKEYS 32 static void test_xonly_pubkey_tweak_recursive(void) { unsigned char sk[32]; - rustsecp256k1_v0_10_0_pubkey pk[N_PUBKEYS]; + rustsecp256k1_v0_11_pubkey pk[N_PUBKEYS]; unsigned char pk_serialized[32]; unsigned char tweak[N_PUBKEYS - 1][32]; int i; - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pk[0], sk) == 1); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pk[0], sk) == 1); /* Add tweaks */ for (i = 0; i < N_PUBKEYS - 1; i++) { - rustsecp256k1_v0_10_0_xonly_pubkey xonly_pk; + rustsecp256k1_v0_11_xonly_pubkey xonly_pk; memset(tweak[i], i + 1, sizeof(tweak[i])); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk[i]) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &pk[i + 1], &xonly_pk, tweak[i]) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk[i]) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &pk[i + 1], &xonly_pk, tweak[i]) == 1); } /* Verify tweaks */ for (i = N_PUBKEYS - 1; i > 0; i--) { - rustsecp256k1_v0_10_0_xonly_pubkey xonly_pk; + rustsecp256k1_v0_11_xonly_pubkey xonly_pk; int pk_parity; - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk[i]) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, pk_serialized, &xonly_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk[i - 1]) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk[i]) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, pk_serialized, &xonly_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, NULL, &pk[i - 1]) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); } } #undef N_PUBKEYS @@ -283,187 +283,187 @@ static void test_keypair(void) { unsigned char sk_tmp[32]; unsigned char zeros96[96] = { 0 }; unsigned char overflows[32]; - rustsecp256k1_v0_10_0_keypair keypair; - rustsecp256k1_v0_10_0_pubkey pk, pk_tmp; - rustsecp256k1_v0_10_0_xonly_pubkey xonly_pk, xonly_pk_tmp; + rustsecp256k1_v0_11_keypair keypair; + rustsecp256k1_v0_11_pubkey pk, pk_tmp; + rustsecp256k1_v0_11_xonly_pubkey xonly_pk, xonly_pk_tmp; int pk_parity, pk_parity_tmp; CHECK(sizeof(zeros96) == sizeof(keypair)); memset(overflows, 0xFF, sizeof(overflows)); /* Test keypair_create */ - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_create(CTX, NULL, sk)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, NULL)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_keypair_create(STATIC_CTX, &keypair, sk)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &keypair, sizeof(keypair)) != 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_create(CTX, NULL, sk)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_create(CTX, &keypair, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_keypair_create(STATIC_CTX, &keypair, sk)); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); /* Invalid secret key */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, zeros96) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, overflows) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, zeros96) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, overflows) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); /* Test keypair_pub */ - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_pub(CTX, &pk, &keypair) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_pub(CTX, NULL, &keypair)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_pub(CTX, &pk, NULL)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_pub(CTX, &pk, &keypair) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_pub(CTX, NULL, &keypair)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_pub(CTX, &pk, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); /* Using an invalid keypair is fine for keypair_pub */ memset(&keypair, 0, sizeof(keypair)); - CHECK(rustsecp256k1_v0_10_0_keypair_pub(CTX, &pk, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_pub(CTX, &pk, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); /* keypair holds the same pubkey as pubkey_create */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_pub(CTX, &pk_tmp, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_pub(CTX, &pk_tmp, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); /** Test keypair_xonly_pub **/ - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, NULL, &pk_parity, &keypair)); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &xonly_pk, NULL, &keypair) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, NULL)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_pub(CTX, NULL, &pk_parity, &keypair)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &xonly_pk, NULL, &keypair) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); /* Using an invalid keypair will set the xonly_pk to 0 (first reset * xonly_pk). */ - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair) == 1); memset(&keypair, 0, sizeof(keypair)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &xonly_pk, &pk_parity, &keypair)); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); /** keypair holds the same xonly pubkey as pubkey_create **/ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pk, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pk, sk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &xonly_pk, &pk_parity, &pk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); CHECK(pk_parity == pk_parity_tmp); /* Test keypair_seckey */ - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_sec(CTX, sk_tmp, &keypair) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_sec(CTX, NULL, &keypair)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_sec(CTX, sk_tmp, NULL)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_sec(CTX, sk_tmp, &keypair) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_sec(CTX, NULL, &keypair)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_sec(CTX, sk_tmp, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); /* keypair returns the same seckey it got */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_sec(CTX, sk_tmp, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_sec(CTX, sk_tmp, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0); /* Using an invalid keypair is fine for keypair_seckey */ memset(&keypair, 0, sizeof(keypair)); - CHECK(rustsecp256k1_v0_10_0_keypair_sec(CTX, sk_tmp, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_sec(CTX, sk_tmp, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); } static void test_keypair_add(void) { unsigned char sk[32]; - rustsecp256k1_v0_10_0_keypair keypair; + rustsecp256k1_v0_11_keypair keypair; unsigned char overflows[32]; unsigned char zeros96[96] = { 0 }; unsigned char tweak[32]; int i; CHECK(sizeof(zeros96) == sizeof(keypair)); - rustsecp256k1_v0_10_0_testrand256(sk); - rustsecp256k1_v0_10_0_testrand256(tweak); + testrand256(sk); + testrand256(tweak); memset(overflows, 0xFF, 32); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, NULL, tweak)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, NULL)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, NULL, tweak)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, NULL)); /* This does not set the keypair to zeroes */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); /* Invalid tweak zeroes the keypair */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, overflows) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, overflows) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* A zero tweak is fine */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, zeros96) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, zeros96) == 1); /* Fails if the resulting keypair was (sk=0, pk=infinity) */ for (i = 0; i < COUNT; i++) { - rustsecp256k1_v0_10_0_scalar scalar_tweak; - rustsecp256k1_v0_10_0_keypair keypair_tmp; - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); + rustsecp256k1_v0_11_scalar scalar_tweak; + rustsecp256k1_v0_11_keypair keypair_tmp; + testrand256(sk); + CHECK(rustsecp256k1_v0_11_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 = * sk as well as tweak = -sk. */ - rustsecp256k1_v0_10_0_scalar_set_b32(&scalar_tweak, sk, NULL); - rustsecp256k1_v0_10_0_scalar_negate(&scalar_tweak, &scalar_tweak); - rustsecp256k1_v0_10_0_scalar_get_b32(tweak, &scalar_tweak); - CHECK((rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, sk) == 0) - || (rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair_tmp, tweak) == 0)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0 - || rustsecp256k1_v0_10_0_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); + rustsecp256k1_v0_11_scalar_set_b32(&scalar_tweak, sk, NULL); + rustsecp256k1_v0_11_scalar_negate(&scalar_tweak, &scalar_tweak); + rustsecp256k1_v0_11_scalar_get_b32(tweak, &scalar_tweak); + CHECK((rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, sk) == 0) + || (rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair_tmp, tweak) == 0)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0 + || rustsecp256k1_v0_11_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); } /* Invalid keypair with a valid tweak */ memset(&keypair, 0, sizeof(keypair)); - rustsecp256k1_v0_10_0_testrand256(tweak); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); + testrand256(tweak); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* Only seckey part of keypair invalid */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); memset(&keypair, 0, 32); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak)); /* Only pubkey part of keypair invalid */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); memset(&keypair.data[32], 0, 64); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak)); /* Check that the keypair_tweak_add implementation is correct */ - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); for (i = 0; i < COUNT; i++) { - rustsecp256k1_v0_10_0_xonly_pubkey internal_pk; - rustsecp256k1_v0_10_0_xonly_pubkey output_pk; - rustsecp256k1_v0_10_0_pubkey output_pk_xy; - rustsecp256k1_v0_10_0_pubkey output_pk_expected; + rustsecp256k1_v0_11_xonly_pubkey internal_pk; + rustsecp256k1_v0_11_xonly_pubkey output_pk; + rustsecp256k1_v0_11_pubkey output_pk_xy; + rustsecp256k1_v0_11_pubkey output_pk_expected; unsigned char pk32[32]; unsigned char sk32[32]; int pk_parity; - rustsecp256k1_v0_10_0_testrand256(tweak); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); + testrand256(tweak); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); /* Check that it passes xonly_pubkey_tweak_add_check */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, pk32, &output_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, pk32, pk_parity, &internal_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, pk32, &output_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, pk32, pk_parity, &internal_pk, tweak) == 1); /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ - CHECK(rustsecp256k1_v0_10_0_keypair_pub(CTX, &output_pk_xy, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add(CTX, &output_pk_expected, &internal_pk, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_pub(CTX, &output_pk_xy, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add(CTX, &output_pk_expected, &internal_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); /* Check that the secret key in the keypair is tweaked correctly */ - CHECK(rustsecp256k1_v0_10_0_keypair_sec(CTX, sk32, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &output_pk_expected, sk32) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); + CHECK(rustsecp256k1_v0_11_keypair_sec(CTX, sk32, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &output_pk_expected, sk32) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/musig/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/musig/Makefile.am.include new file mode 100644 index 000000000..d478ec751 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/musig/Makefile.am.include @@ -0,0 +1,8 @@ +include_HEADERS += include/rustsecp256k1_v0_11_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/secp256k1-sys/depend/secp256k1/src/modules/musig/keyagg.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/keyagg.h new file mode 100644 index 000000000..bee2a322d --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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 { + rustsecp256k1_v0_11_ge pk; + /* If there is no "second" public key, second_pk is set to the point at + * infinity */ + rustsecp256k1_v0_11_ge second_pk; + unsigned char pks_hash[32]; + /* tweak is identical to value tacc[v] in the specification. */ + rustsecp256k1_v0_11_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; +} rustsecp256k1_v0_11_keyagg_cache_internal; + +static int rustsecp256k1_v0_11_keyagg_cache_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_keyagg_cache_internal *cache_i, const rustsecp256k1_v0_11_musig_keyagg_cache *cache); + +static void rustsecp256k1_v0_11_musig_keyaggcoef(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_keyagg_cache_internal *cache_i, rustsecp256k1_v0_11_ge *pk); + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/musig/keyagg_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/keyagg_impl.h new file mode 100644 index 000000000..c21b45d89 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_keyagg_cache_save(rustsecp256k1_v0_11_musig_keyagg_cache *cache, const rustsecp256k1_v0_11_keyagg_cache_internal *cache_i) { + unsigned char *ptr = cache->data; + memcpy(ptr, rustsecp256k1_v0_11_musig_keyagg_cache_magic, 4); + ptr += 4; + rustsecp256k1_v0_11_ge_to_bytes(ptr, &cache_i->pk); + ptr += 64; + rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_scalar_get_b32(ptr, &cache_i->tweak); +} + +static int rustsecp256k1_v0_11_keyagg_cache_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_keyagg_cache_internal *cache_i, const rustsecp256k1_v0_11_musig_keyagg_cache *cache) { + const unsigned char *ptr = cache->data; + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(ptr, rustsecp256k1_v0_11_musig_keyagg_cache_magic, 4) == 0); + ptr += 4; + rustsecp256k1_v0_11_ge_from_bytes(&cache_i->pk, ptr); + ptr += 64; + rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_keyagglist_sha256(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_compute_pks_hash(const rustsecp256k1_v0_11_context *ctx, unsigned char *pks_hash, const rustsecp256k1_v0_11_pubkey * const* pks, size_t np) { + rustsecp256k1_v0_11_sha256 sha; + size_t i; + + rustsecp256k1_v0_11_musig_keyagglist_sha256(&sha); + for (i = 0; i < np; i++) { + unsigned char ser[33]; + size_t ser_len = sizeof(ser); + if (!rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, ser, &ser_len, pks[i], SECP256K1_EC_COMPRESSED)) { + return 0; + } + VERIFY_CHECK(ser_len == sizeof(ser)); + rustsecp256k1_v0_11_sha256_write(&sha, ser, sizeof(ser)); + } + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_keyaggcoef_sha256(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_keyaggcoef_internal(rustsecp256k1_v0_11_scalar *r, const unsigned char *pks_hash, rustsecp256k1_v0_11_ge *pk, const rustsecp256k1_v0_11_ge *second_pk) { + VERIFY_CHECK(!rustsecp256k1_v0_11_ge_is_infinity(pk)); + + if (!rustsecp256k1_v0_11_ge_is_infinity(second_pk) + && rustsecp256k1_v0_11_ge_eq_var(pk, second_pk)) { + rustsecp256k1_v0_11_scalar_set_int(r, 1); + } else { + rustsecp256k1_v0_11_sha256 sha; + unsigned char buf[33]; + size_t buflen = sizeof(buf); + int ret; + rustsecp256k1_v0_11_musig_keyaggcoef_sha256(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, pks_hash, 32); + ret = rustsecp256k1_v0_11_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 + rustsecp256k1_v0_11_sha256_write(&sha, buf, sizeof(buf)); + rustsecp256k1_v0_11_sha256_finalize(&sha, buf); + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_keyaggcoef(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_keyagg_cache_internal *cache_i, rustsecp256k1_v0_11_ge *pk) { + rustsecp256k1_v0_11_musig_keyaggcoef_internal(r, cache_i->pks_hash, pk, &cache_i->second_pk); +} + +typedef struct { + const rustsecp256k1_v0_11_context *ctx; + /* pks_hash is the hash of the public keys */ + unsigned char pks_hash[32]; + const rustsecp256k1_v0_11_pubkey * const* pks; + rustsecp256k1_v0_11_ge second_pk; +} rustsecp256k1_v0_11_musig_pubkey_agg_ecmult_data; + +/* Callback for batch EC multiplication to compute keyaggcoef_0*P0 + keyaggcoef_1*P1 + ... */ +static int rustsecp256k1_v0_11_musig_pubkey_agg_callback(rustsecp256k1_v0_11_scalar *sc, rustsecp256k1_v0_11_ge *pt, size_t idx, void *data) { + rustsecp256k1_v0_11_musig_pubkey_agg_ecmult_data *ctx = (rustsecp256k1_v0_11_musig_pubkey_agg_ecmult_data *) data; + int ret; + ret = rustsecp256k1_v0_11_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 + rustsecp256k1_v0_11_musig_keyaggcoef_internal(sc, ctx->pks_hash, pt, &ctx->second_pk); + return 1; +} + +int rustsecp256k1_v0_11_musig_pubkey_agg(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_xonly_pubkey *agg_pk, rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const rustsecp256k1_v0_11_pubkey * const* pubkeys, size_t n_pubkeys) { + rustsecp256k1_v0_11_musig_pubkey_agg_ecmult_data ecmult_data; + rustsecp256k1_v0_11_gej pkj; + rustsecp256k1_v0_11_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; + + rustsecp256k1_v0_11_ge_set_infinity(&ecmult_data.second_pk); + for (i = 1; i < n_pubkeys; i++) { + if (rustsecp256k1_v0_11_memcmp_var(pubkeys[0], pubkeys[i], sizeof(*pubkeys[0])) != 0) { + rustsecp256k1_v0_11_ge pk; + if (!rustsecp256k1_v0_11_pubkey_load(ctx, &pk, pubkeys[i])) { + return 0; + } + ecmult_data.second_pk = pk; + break; + } + } + + if (!rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_ecmult_multi_var(&ctx->error_callback, NULL, &pkj, NULL, rustsecp256k1_v0_11_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; + } + rustsecp256k1_v0_11_ge_set_gej(&pkp, &pkj); + rustsecp256k1_v0_11_fe_normalize_var(&pkp.y); + /* The resulting public key is infinity with negligible probability */ + VERIFY_CHECK(!rustsecp256k1_v0_11_ge_is_infinity(&pkp)); + if (keyagg_cache != NULL) { + rustsecp256k1_v0_11_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)); + rustsecp256k1_v0_11_keyagg_cache_save(keyagg_cache, &cache_i); + } + + if (agg_pk != NULL) { + rustsecp256k1_v0_11_extrakeys_ge_even_y(&pkp); + rustsecp256k1_v0_11_xonly_pubkey_save(agg_pk, &pkp); + } + return 1; +} + +int rustsecp256k1_v0_11_musig_pubkey_get(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *agg_pk, const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache) { + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + rustsecp256k1_v0_11_pubkey_save(agg_pk, &cache_i.pk); + return 1; +} + +static int rustsecp256k1_v0_11_musig_pubkey_tweak_add_internal(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *output_pubkey, rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32, int xonly) { + rustsecp256k1_v0_11_keyagg_cache_internal cache_i; + int overflow = 0; + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + rustsecp256k1_v0_11_scalar_set_b32(&tweak, tweak32, &overflow); + if (overflow) { + return 0; + } + if (xonly && rustsecp256k1_v0_11_extrakeys_ge_even_y(&cache_i.pk)) { + cache_i.parity_acc ^= 1; + rustsecp256k1_v0_11_scalar_negate(&cache_i.tweak, &cache_i.tweak); + } + rustsecp256k1_v0_11_scalar_add(&cache_i.tweak, &cache_i.tweak, &tweak); + if (!rustsecp256k1_v0_11_eckey_pubkey_tweak_add(&cache_i.pk, &tweak)) { + return 0; + } + /* eckey_pubkey_tweak_add fails if cache_i.pk is infinity */ + VERIFY_CHECK(!rustsecp256k1_v0_11_ge_is_infinity(&cache_i.pk)); + rustsecp256k1_v0_11_keyagg_cache_save(keyagg_cache, &cache_i); + if (output_pubkey != NULL) { + rustsecp256k1_v0_11_pubkey_save(output_pubkey, &cache_i.pk); + } + return 1; +} + +int rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *output_pubkey, rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { + return rustsecp256k1_v0_11_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 0); +} + +int rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *output_pubkey, rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32) { + return rustsecp256k1_v0_11_musig_pubkey_tweak_add_internal(ctx, output_pubkey, keyagg_cache, tweak32, 1); +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/musig/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/main_impl.h new file mode 100644 index 000000000..a1311e419 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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/secp256k1-sys/depend/secp256k1/src/modules/musig/session.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/session.h new file mode 100644 index 000000000..d010a9b86 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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]; + rustsecp256k1_v0_11_scalar noncecoef; + rustsecp256k1_v0_11_scalar challenge; + rustsecp256k1_v0_11_scalar s_part; +} rustsecp256k1_v0_11_musig_session_internal; + +static int rustsecp256k1_v0_11_musig_session_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_session_internal *session_i, const rustsecp256k1_v0_11_musig_session *session); + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/musig/session_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/session_impl.h new file mode 100644 index 000000000..418910240 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/modules/musig/session_impl.h @@ -0,0 +1,816 @@ +/*********************************************************************** + * 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 rustsecp256k1_v0_11_musig_ge_serialize_ext(unsigned char *out33, rustsecp256k1_v0_11_ge* ge) { + if (rustsecp256k1_v0_11_ge_is_infinity(ge)) { + memset(out33, 0, 33); + } else { + int ret; + size_t size = 33; + ret = rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_ge_parse_ext(rustsecp256k1_v0_11_ge* ge, const unsigned char *in33) { + unsigned char zeros[33] = { 0 }; + + if (rustsecp256k1_v0_11_memcmp_var(in33, zeros, sizeof(zeros)) == 0) { + rustsecp256k1_v0_11_ge_set_infinity(ge); + return 1; + } + if (!rustsecp256k1_v0_11_eckey_pubkey_parse(ge, in33, 33)) { + return 0; + } + return rustsecp256k1_v0_11_ge_is_in_correct_subgroup(ge); +} + +static const unsigned char rustsecp256k1_v0_11_musig_secnonce_magic[4] = { 0x22, 0x0e, 0xdc, 0xf1 }; + +static void rustsecp256k1_v0_11_musig_secnonce_save(rustsecp256k1_v0_11_musig_secnonce *secnonce, const rustsecp256k1_v0_11_scalar *k, const rustsecp256k1_v0_11_ge *pk) { + memcpy(&secnonce->data[0], rustsecp256k1_v0_11_musig_secnonce_magic, 4); + rustsecp256k1_v0_11_scalar_get_b32(&secnonce->data[4], &k[0]); + rustsecp256k1_v0_11_scalar_get_b32(&secnonce->data[36], &k[1]); + rustsecp256k1_v0_11_ge_to_bytes(&secnonce->data[68], pk); +} + +static int rustsecp256k1_v0_11_musig_secnonce_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar *k, rustsecp256k1_v0_11_ge *pk, const rustsecp256k1_v0_11_musig_secnonce *secnonce) { + int is_zero; + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(&secnonce->data[0], rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_is_zero_array(&secnonce->data[4], 2 * 32); + rustsecp256k1_v0_11_declassify(ctx, &is_zero, sizeof(is_zero)); + ARG_CHECK(!is_zero); + + rustsecp256k1_v0_11_scalar_set_b32(&k[0], &secnonce->data[4], NULL); + rustsecp256k1_v0_11_scalar_set_b32(&k[1], &secnonce->data[36], NULL); + rustsecp256k1_v0_11_ge_from_bytes(pk, &secnonce->data[68]); + return 1; +} + +/* If flag is true, invalidate the secnonce; otherwise leave it. Constant-time. */ +static void rustsecp256k1_v0_11_musig_secnonce_invalidate(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_secnonce *secnonce, int flag) { + rustsecp256k1_v0_11_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. */ + rustsecp256k1_v0_11_declassify(ctx, secnonce->data, sizeof(rustsecp256k1_v0_11_musig_secnonce_magic)); + rustsecp256k1_v0_11_declassify(ctx, &secnonce->data[68], 64); +} + +static const unsigned char rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubnonce_save(rustsecp256k1_v0_11_musig_pubnonce* nonce, const rustsecp256k1_v0_11_ge* ges) { + int i; + memcpy(&nonce->data[0], rustsecp256k1_v0_11_musig_pubnonce_magic, 4); + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_pubnonce_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ge* ges, const rustsecp256k1_v0_11_musig_pubnonce* nonce) { + int i; + + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(&nonce->data[0], rustsecp256k1_v0_11_musig_pubnonce_magic, 4) == 0); + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_ge_from_bytes(&ges[i], nonce->data + 4 + 64*i); + } + return 1; +} + +static const unsigned char rustsecp256k1_v0_11_musig_aggnonce_magic[4] = { 0xa8, 0xb7, 0xe4, 0x67 }; + +static void rustsecp256k1_v0_11_musig_aggnonce_save(rustsecp256k1_v0_11_musig_aggnonce* nonce, const rustsecp256k1_v0_11_ge* ges) { + int i; + memcpy(&nonce->data[0], rustsecp256k1_v0_11_musig_aggnonce_magic, 4); + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_ge_to_bytes_ext(&nonce->data[4 + 64*i], &ges[i]); + } +} + +static int rustsecp256k1_v0_11_musig_aggnonce_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ge* ges, const rustsecp256k1_v0_11_musig_aggnonce* nonce) { + int i; + + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(&nonce->data[0], rustsecp256k1_v0_11_musig_aggnonce_magic, 4) == 0); + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_ge_from_bytes_ext(&ges[i], &nonce->data[4 + 64*i]); + } + return 1; +} + +static const unsigned char rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_session_save(rustsecp256k1_v0_11_musig_session *session, const rustsecp256k1_v0_11_musig_session_internal *session_i) { + unsigned char *ptr = session->data; + + memcpy(ptr, rustsecp256k1_v0_11_musig_session_cache_magic, 4); + ptr += 4; + *ptr = session_i->fin_nonce_parity; + ptr += 1; + memcpy(ptr, session_i->fin_nonce, 32); + ptr += 32; + rustsecp256k1_v0_11_scalar_get_b32(ptr, &session_i->noncecoef); + ptr += 32; + rustsecp256k1_v0_11_scalar_get_b32(ptr, &session_i->challenge); + ptr += 32; + rustsecp256k1_v0_11_scalar_get_b32(ptr, &session_i->s_part); +} + +static int rustsecp256k1_v0_11_musig_session_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_session_internal *session_i, const rustsecp256k1_v0_11_musig_session *session) { + const unsigned char *ptr = session->data; + + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(ptr, rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_scalar_set_b32(&session_i->noncecoef, ptr, NULL); + ptr += 32; + rustsecp256k1_v0_11_scalar_set_b32(&session_i->challenge, ptr, NULL); + ptr += 32; + rustsecp256k1_v0_11_scalar_set_b32(&session_i->s_part, ptr, NULL); + return 1; +} + +static const unsigned char rustsecp256k1_v0_11_musig_partial_sig_magic[4] = { 0xeb, 0xfb, 0x1a, 0x32 }; + +static void rustsecp256k1_v0_11_musig_partial_sig_save(rustsecp256k1_v0_11_musig_partial_sig* sig, rustsecp256k1_v0_11_scalar *s) { + memcpy(&sig->data[0], rustsecp256k1_v0_11_musig_partial_sig_magic, 4); + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[4], s); +} + +static int rustsecp256k1_v0_11_musig_partial_sig_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar *s, const rustsecp256k1_v0_11_musig_partial_sig* sig) { + int overflow; + + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(&sig->data[0], rustsecp256k1_v0_11_musig_partial_sig_magic, 4) == 0); + rustsecp256k1_v0_11_scalar_set_b32(s, &sig->data[4], &overflow); + /* Parsed signatures can not overflow */ + VERIFY_CHECK(!overflow); + return 1; +} + +int rustsecp256k1_v0_11_musig_pubnonce_parse(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_pubnonce* nonce, const unsigned char *in66) { + rustsecp256k1_v0_11_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(nonce != NULL); + ARG_CHECK(in66 != NULL); + + for (i = 0; i < 2; i++) { + if (!rustsecp256k1_v0_11_eckey_pubkey_parse(&ges[i], &in66[33*i], 33)) { + return 0; + } + if (!rustsecp256k1_v0_11_ge_is_in_correct_subgroup(&ges[i])) { + return 0; + } + } + rustsecp256k1_v0_11_musig_pubnonce_save(nonce, ges); + return 1; +} + +int rustsecp256k1_v0_11_musig_pubnonce_serialize(const rustsecp256k1_v0_11_context* ctx, unsigned char *out66, const rustsecp256k1_v0_11_musig_pubnonce* nonce) { + rustsecp256k1_v0_11_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(out66 != NULL); + memset(out66, 0, 66); + ARG_CHECK(nonce != NULL); + + if (!rustsecp256k1_v0_11_musig_pubnonce_load(ctx, ges, nonce)) { + return 0; + } + for (i = 0; i < 2; i++) { + int ret; + size_t size = 33; + ret = rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_aggnonce_parse(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_aggnonce* nonce, const unsigned char *in66) { + rustsecp256k1_v0_11_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(nonce != NULL); + ARG_CHECK(in66 != NULL); + + for (i = 0; i < 2; i++) { + if (!rustsecp256k1_v0_11_musig_ge_parse_ext(&ges[i], &in66[33*i])) { + return 0; + } + } + rustsecp256k1_v0_11_musig_aggnonce_save(nonce, ges); + return 1; +} + +int rustsecp256k1_v0_11_musig_aggnonce_serialize(const rustsecp256k1_v0_11_context* ctx, unsigned char *out66, const rustsecp256k1_v0_11_musig_aggnonce* nonce) { + rustsecp256k1_v0_11_ge ges[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(out66 != NULL); + memset(out66, 0, 66); + ARG_CHECK(nonce != NULL); + + if (!rustsecp256k1_v0_11_musig_aggnonce_load(ctx, ges, nonce)) { + return 0; + } + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_musig_ge_serialize_ext(&out66[33*i], &ges[i]); + } + return 1; +} + +int rustsecp256k1_v0_11_musig_partial_sig_parse(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_partial_sig* sig, const unsigned char *in32) { + rustsecp256k1_v0_11_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)); + + rustsecp256k1_v0_11_scalar_set_b32(&tmp, in32, &overflow); + if (overflow) { + return 0; + } + rustsecp256k1_v0_11_musig_partial_sig_save(sig, &tmp); + return 1; +} + +int rustsecp256k1_v0_11_musig_partial_sig_serialize(const rustsecp256k1_v0_11_context* ctx, unsigned char *out32, const rustsecp256k1_v0_11_musig_partial_sig* sig) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(out32 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(&sig->data[0], rustsecp256k1_v0_11_musig_partial_sig_magic, 4) == 0); + + memcpy(out32, &sig->data[4], 32); + return 1; +} + +/* Write optional inputs into the hash */ +static void rustsecp256k1_v0_11_nonce_function_musig_helper(rustsecp256k1_v0_11_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. */ + rustsecp256k1_v0_11_sha256_write(sha, zero, prefix_size - 1); + if (data != NULL) { + rustsecp256k1_v0_11_sha256_write(sha, &len, 1); + rustsecp256k1_v0_11_sha256_write(sha, data, len); + } else { + len = 0; + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_nonce_function_musig_sha256_tagged_aux(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_nonce_function_musig_sha256_tagged(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_nonce_function_musig(rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_sha256 sha; + unsigned char rand[32]; + unsigned char i; + unsigned char msg_present; + + if (seckey32 != NULL) { + rustsecp256k1_v0_11_nonce_function_musig_sha256_tagged_aux(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, session_secrand, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, rand); + for (i = 0; i < 32; i++) { + rand[i] ^= seckey32[i]; + } + } else { + memcpy(rand, session_secrand, sizeof(rand)); + } + + rustsecp256k1_v0_11_nonce_function_musig_sha256_tagged(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, rand, sizeof(rand)); + rustsecp256k1_v0_11_nonce_function_musig_helper(&sha, 1, pk33, 33); + rustsecp256k1_v0_11_nonce_function_musig_helper(&sha, 1, agg_pk32, 32); + msg_present = msg32 != NULL; + rustsecp256k1_v0_11_sha256_write(&sha, &msg_present, 1); + if (msg_present) { + rustsecp256k1_v0_11_nonce_function_musig_helper(&sha, 8, msg32, 32); + } + rustsecp256k1_v0_11_nonce_function_musig_helper(&sha, 4, extra_input32, 32); + + for (i = 0; i < 2; i++) { + unsigned char buf[32]; + rustsecp256k1_v0_11_sha256 sha_tmp = sha; + rustsecp256k1_v0_11_sha256_write(&sha_tmp, &i, 1); + rustsecp256k1_v0_11_sha256_finalize(&sha_tmp, buf); + rustsecp256k1_v0_11_scalar_set_b32(&k[i], buf, NULL); + + /* Attempt to erase secret data */ + rustsecp256k1_v0_11_memclear(buf, sizeof(buf)); + rustsecp256k1_v0_11_sha256_clear(&sha_tmp); + } + rustsecp256k1_v0_11_memclear(rand, sizeof(rand)); + rustsecp256k1_v0_11_sha256_clear(&sha); +} + +static int rustsecp256k1_v0_11_musig_nonce_gen_internal(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_secnonce *secnonce, rustsecp256k1_v0_11_musig_pubnonce *pubnonce, const unsigned char *input_nonce, const unsigned char *seckey, const rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *msg32, const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { + rustsecp256k1_v0_11_scalar k[2]; + rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_ge pk; + int pk_serialize_success; + int ret = 1; + + ARG_CHECK(pubnonce != NULL); + memset(pubnonce, 0, sizeof(*pubnonce)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_scalar sk; + ret &= rustsecp256k1_v0_11_scalar_set_b32_seckey(&sk, seckey); + rustsecp256k1_v0_11_scalar_clear(&sk); + } + + if (keyagg_cache != NULL) { + rustsecp256k1_v0_11_keyagg_cache_internal cache_i; + if (!rustsecp256k1_v0_11_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + /* The loaded point cache_i.pk can not be the point at infinity. */ + rustsecp256k1_v0_11_fe_get_b32(aggpk_ser, &cache_i.pk.x); + aggpk_ser_ptr = aggpk_ser; + } + if (!rustsecp256k1_v0_11_pubkey_load(ctx, &pk, pubkey)) { + return 0; + } + pk_serialize_success = rustsecp256k1_v0_11_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 + + rustsecp256k1_v0_11_nonce_function_musig(k, input_nonce, msg32, seckey, pk_ser, aggpk_ser_ptr, extra_input32); + VERIFY_CHECK(!rustsecp256k1_v0_11_scalar_is_zero(&k[0])); + VERIFY_CHECK(!rustsecp256k1_v0_11_scalar_is_zero(&k[1])); + rustsecp256k1_v0_11_musig_secnonce_save(secnonce, k, &pk); + rustsecp256k1_v0_11_musig_secnonce_invalidate(ctx, secnonce, !ret); + + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_gej nonce_ptj; + rustsecp256k1_v0_11_ecmult_gen(&ctx->ecmult_gen_ctx, &nonce_ptj, &k[i]); + rustsecp256k1_v0_11_ge_set_gej(&nonce_pts[i], &nonce_ptj); + rustsecp256k1_v0_11_declassify(ctx, &nonce_pts[i], sizeof(nonce_pts[i])); + rustsecp256k1_v0_11_scalar_clear(&k[i]); + rustsecp256k1_v0_11_gej_clear(&nonce_ptj); + } + /* None of the nonce_pts will be infinity because k != 0 with overwhelming + * probability */ + rustsecp256k1_v0_11_musig_pubnonce_save(pubnonce, nonce_pts); + return ret; +} + +int rustsecp256k1_v0_11_musig_nonce_gen(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_secnonce *secnonce, rustsecp256k1_v0_11_musig_pubnonce *pubnonce, unsigned char *session_secrand32, const unsigned char *seckey, const rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *msg32, const rustsecp256k1_v0_11_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 &= !rustsecp256k1_v0_11_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 */ + rustsecp256k1_v0_11_declassify(ctx, &ret, sizeof(ret)); + if (ret == 0) { + rustsecp256k1_v0_11_musig_secnonce_invalidate(ctx, secnonce, 1); + return 0; + } + + ret &= rustsecp256k1_v0_11_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. */ + rustsecp256k1_v0_11_memczero(session_secrand32, 32, ret); + return ret; +} + +int rustsecp256k1_v0_11_musig_nonce_gen_counter(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_secnonce *secnonce, rustsecp256k1_v0_11_musig_pubnonce *pubnonce, uint64_t nonrepeating_cnt, const rustsecp256k1_v0_11_keypair *keypair, const unsigned char *msg32, const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const unsigned char *extra_input32) { + unsigned char buf[32] = { 0 }; + unsigned char seckey[32]; + rustsecp256k1_v0_11_pubkey pubkey; + int ret; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secnonce != NULL); + memset(secnonce, 0, sizeof(*secnonce)); + ARG_CHECK(keypair != NULL); + + rustsecp256k1_v0_11_write_be64(buf, nonrepeating_cnt); + /* keypair_sec and keypair_pub do not fail if the arguments are not NULL */ + ret = rustsecp256k1_v0_11_keypair_sec(ctx, seckey, keypair); + VERIFY_CHECK(ret); + ret = rustsecp256k1_v0_11_keypair_pub(ctx, &pubkey, keypair); + VERIFY_CHECK(ret); +#ifndef VERIFY + (void) ret; +#endif + + if (!rustsecp256k1_v0_11_musig_nonce_gen_internal(ctx, secnonce, pubnonce, buf, seckey, &pubkey, msg32, keyagg_cache, extra_input32)) { + return 0; + } + rustsecp256k1_v0_11_memclear(seckey, sizeof(seckey)); + return 1; +} + +static int rustsecp256k1_v0_11_musig_sum_pubnonces(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_gej *summed_pubnonces, const rustsecp256k1_v0_11_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { + size_t i; + int j; + + rustsecp256k1_v0_11_gej_set_infinity(&summed_pubnonces[0]); + rustsecp256k1_v0_11_gej_set_infinity(&summed_pubnonces[1]); + + for (i = 0; i < n_pubnonces; i++) { + rustsecp256k1_v0_11_ge nonce_pts[2]; + if (!rustsecp256k1_v0_11_musig_pubnonce_load(ctx, nonce_pts, pubnonces[i])) { + return 0; + } + for (j = 0; j < 2; j++) { + rustsecp256k1_v0_11_gej_add_ge_var(&summed_pubnonces[j], &summed_pubnonces[j], &nonce_pts[j], NULL); + } + } + return 1; +} + +int rustsecp256k1_v0_11_musig_nonce_agg(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_aggnonce *aggnonce, const rustsecp256k1_v0_11_musig_pubnonce * const* pubnonces, size_t n_pubnonces) { + rustsecp256k1_v0_11_gej aggnonce_ptsj[2]; + rustsecp256k1_v0_11_ge aggnonce_pts[2]; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(aggnonce != NULL); + ARG_CHECK(pubnonces != NULL); + ARG_CHECK(n_pubnonces > 0); + + if (!rustsecp256k1_v0_11_musig_sum_pubnonces(ctx, aggnonce_ptsj, pubnonces, n_pubnonces)) { + return 0; + } + rustsecp256k1_v0_11_ge_set_all_gej_var(aggnonce_pts, aggnonce_ptsj, 2); + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_compute_noncehash_sha256_tagged(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_musig_compute_noncehash(unsigned char *noncehash, rustsecp256k1_v0_11_ge *aggnonce, const unsigned char *agg_pk32, const unsigned char *msg) { + unsigned char buf[33]; + rustsecp256k1_v0_11_sha256 sha; + int i; + + rustsecp256k1_v0_11_musig_compute_noncehash_sha256_tagged(&sha); + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_musig_ge_serialize_ext(buf, &aggnonce[i]); + rustsecp256k1_v0_11_sha256_write(&sha, buf, sizeof(buf)); + } + rustsecp256k1_v0_11_sha256_write(&sha, agg_pk32, 32); + rustsecp256k1_v0_11_sha256_write(&sha, msg, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, noncehash); +} + +/* out_nonce = nonce_pts[0] + b*nonce_pts[1] */ +static void rustsecp256k1_v0_11_effective_nonce(rustsecp256k1_v0_11_gej *out_nonce, const rustsecp256k1_v0_11_ge *nonce_pts, const rustsecp256k1_v0_11_scalar *b) { + rustsecp256k1_v0_11_gej tmp; + + rustsecp256k1_v0_11_gej_set_ge(&tmp, &nonce_pts[1]); + rustsecp256k1_v0_11_ecmult(out_nonce, &tmp, b, NULL); + rustsecp256k1_v0_11_gej_add_ge_var(out_nonce, out_nonce, &nonce_pts[0], NULL); +} + +static void rustsecp256k1_v0_11_musig_nonce_process_internal(int *fin_nonce_parity, unsigned char *fin_nonce, rustsecp256k1_v0_11_scalar *b, rustsecp256k1_v0_11_ge *aggnonce_pts, const unsigned char *agg_pk32, const unsigned char *msg) { + unsigned char noncehash[32]; + rustsecp256k1_v0_11_ge fin_nonce_pt; + rustsecp256k1_v0_11_gej fin_nonce_ptj; + + rustsecp256k1_v0_11_musig_compute_noncehash(noncehash, aggnonce_pts, agg_pk32, msg); + rustsecp256k1_v0_11_scalar_set_b32(b, noncehash, NULL); + /* fin_nonce = aggnonce_pts[0] + b*aggnonce_pts[1] */ + rustsecp256k1_v0_11_effective_nonce(&fin_nonce_ptj, aggnonce_pts, b); + rustsecp256k1_v0_11_ge_set_gej(&fin_nonce_pt, &fin_nonce_ptj); + if (rustsecp256k1_v0_11_ge_is_infinity(&fin_nonce_pt)) { + fin_nonce_pt = rustsecp256k1_v0_11_ge_const_g; + } + /* fin_nonce_pt is not the point at infinity */ + rustsecp256k1_v0_11_fe_normalize_var(&fin_nonce_pt.x); + rustsecp256k1_v0_11_fe_get_b32(fin_nonce, &fin_nonce_pt.x); + rustsecp256k1_v0_11_fe_normalize_var(&fin_nonce_pt.y); + *fin_nonce_parity = rustsecp256k1_v0_11_fe_is_odd(&fin_nonce_pt.y); +} + +int rustsecp256k1_v0_11_musig_nonce_process(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_session *session, const rustsecp256k1_v0_11_musig_aggnonce *aggnonce, const unsigned char *msg32, const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache) { + rustsecp256k1_v0_11_keyagg_cache_internal cache_i; + rustsecp256k1_v0_11_ge aggnonce_pts[2]; + unsigned char fin_nonce[32]; + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + return 0; + } + rustsecp256k1_v0_11_fe_get_b32(agg_pk32, &cache_i.pk.x); + + if (!rustsecp256k1_v0_11_musig_aggnonce_load(ctx, aggnonce_pts, aggnonce)) { + return 0; + } + + rustsecp256k1_v0_11_musig_nonce_process_internal(&session_i.fin_nonce_parity, fin_nonce, &session_i.noncecoef, aggnonce_pts, agg_pk32, msg32); + rustsecp256k1_v0_11_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.*/ + rustsecp256k1_v0_11_scalar_set_int(&session_i.s_part, 0); + if (!rustsecp256k1_v0_11_scalar_is_zero(&cache_i.tweak)) { + rustsecp256k1_v0_11_scalar e_tmp; + rustsecp256k1_v0_11_scalar_mul(&e_tmp, &session_i.challenge, &cache_i.tweak); + if (rustsecp256k1_v0_11_fe_is_odd(&cache_i.pk.y)) { + rustsecp256k1_v0_11_scalar_negate(&e_tmp, &e_tmp); + } + session_i.s_part = e_tmp; + } + memcpy(session_i.fin_nonce, fin_nonce, sizeof(session_i.fin_nonce)); + rustsecp256k1_v0_11_musig_session_save(session, &session_i); + return 1; +} + +static void rustsecp256k1_v0_11_musig_partial_sign_clear(rustsecp256k1_v0_11_scalar *sk, rustsecp256k1_v0_11_scalar *k) { + rustsecp256k1_v0_11_scalar_clear(sk); + rustsecp256k1_v0_11_scalar_clear(&k[0]); + rustsecp256k1_v0_11_scalar_clear(&k[1]); +} + +int rustsecp256k1_v0_11_musig_partial_sign(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_musig_partial_sig *partial_sig, rustsecp256k1_v0_11_musig_secnonce *secnonce, const rustsecp256k1_v0_11_keypair *keypair, const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const rustsecp256k1_v0_11_musig_session *session) { + rustsecp256k1_v0_11_scalar sk; + rustsecp256k1_v0_11_ge pk, keypair_pk; + rustsecp256k1_v0_11_scalar k[2]; + rustsecp256k1_v0_11_scalar mu, s; + rustsecp256k1_v0_11_keyagg_cache_internal cache_i; + rustsecp256k1_v0_11_musig_session_internal session_i; + int ret; + + VERIFY_CHECK(ctx != NULL); + + ARG_CHECK(secnonce != NULL); + /* Fails if the magic doesn't match */ + ret = rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_keypair_load(ctx, &sk, &keypair_pk, keypair)) { + rustsecp256k1_v0_11_musig_partial_sign_clear(&sk, k); + return 0; + } + ARG_CHECK(rustsecp256k1_v0_11_fe_equal(&pk.x, &keypair_pk.x) + && rustsecp256k1_v0_11_fe_equal(&pk.y, &keypair_pk.y)); + if (!rustsecp256k1_v0_11_keyagg_cache_load(ctx, &cache_i, keyagg_cache)) { + rustsecp256k1_v0_11_musig_partial_sign_clear(&sk, k); + return 0; + } + + /* Negate sk if rustsecp256k1_v0_11_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 ((rustsecp256k1_v0_11_fe_is_odd(&cache_i.pk.y) + != cache_i.parity_acc)) { + rustsecp256k1_v0_11_scalar_negate(&sk, &sk); + } + + /* Multiply KeyAgg coefficient */ + rustsecp256k1_v0_11_musig_keyaggcoef(&mu, &cache_i, &pk); + rustsecp256k1_v0_11_scalar_mul(&sk, &sk, &mu); + + if (!rustsecp256k1_v0_11_musig_session_load(ctx, &session_i, session)) { + rustsecp256k1_v0_11_musig_partial_sign_clear(&sk, k); + return 0; + } + + if (session_i.fin_nonce_parity) { + rustsecp256k1_v0_11_scalar_negate(&k[0], &k[0]); + rustsecp256k1_v0_11_scalar_negate(&k[1], &k[1]); + } + + /* Sign */ + rustsecp256k1_v0_11_scalar_mul(&s, &session_i.challenge, &sk); + rustsecp256k1_v0_11_scalar_mul(&k[1], &session_i.noncecoef, &k[1]); + rustsecp256k1_v0_11_scalar_add(&k[0], &k[0], &k[1]); + rustsecp256k1_v0_11_scalar_add(&s, &s, &k[0]); + rustsecp256k1_v0_11_musig_partial_sig_save(partial_sig, &s); + rustsecp256k1_v0_11_musig_partial_sign_clear(&sk, k); + return 1; +} + +int rustsecp256k1_v0_11_musig_partial_sig_verify(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_musig_partial_sig *partial_sig, const rustsecp256k1_v0_11_musig_pubnonce *pubnonce, const rustsecp256k1_v0_11_pubkey *pubkey, const rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const rustsecp256k1_v0_11_musig_session *session) { + rustsecp256k1_v0_11_keyagg_cache_internal cache_i; + rustsecp256k1_v0_11_musig_session_internal session_i; + rustsecp256k1_v0_11_scalar mu, e, s; + rustsecp256k1_v0_11_gej pkj; + rustsecp256k1_v0_11_ge nonce_pts[2]; + rustsecp256k1_v0_11_gej rj; + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_musig_session_load(ctx, &session_i, session)) { + return 0; + } + + if (!rustsecp256k1_v0_11_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] */ + rustsecp256k1_v0_11_effective_nonce(&rj, nonce_pts, &session_i.noncecoef); + + if (!rustsecp256k1_v0_11_pubkey_load(ctx, &pkp, pubkey)) { + return 0; + } + if (!rustsecp256k1_v0_11_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. */ + rustsecp256k1_v0_11_musig_keyaggcoef(&mu, &cache_i, &pkp); + rustsecp256k1_v0_11_scalar_mul(&e, &session_i.challenge, &mu); + + /* Negate e if rustsecp256k1_v0_11_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 (rustsecp256k1_v0_11_fe_is_odd(&cache_i.pk.y) + != cache_i.parity_acc) { + rustsecp256k1_v0_11_scalar_negate(&e, &e); + } + + if (!rustsecp256k1_v0_11_musig_partial_sig_load(ctx, &s, partial_sig)) { + return 0; + } + /* Compute -s*G + e*pkj + rj (e already includes the keyagg coefficient mu) */ + rustsecp256k1_v0_11_scalar_negate(&s, &s); + rustsecp256k1_v0_11_gej_set_ge(&pkj, &pkp); + rustsecp256k1_v0_11_ecmult(&tmp, &pkj, &e, &s); + if (session_i.fin_nonce_parity) { + rustsecp256k1_v0_11_gej_neg(&rj, &rj); + } + rustsecp256k1_v0_11_gej_add_var(&tmp, &tmp, &rj, NULL); + + return rustsecp256k1_v0_11_gej_is_infinity(&tmp); +} + +int rustsecp256k1_v0_11_musig_partial_sig_agg(const rustsecp256k1_v0_11_context* ctx, unsigned char *sig64, const rustsecp256k1_v0_11_musig_session *session, const rustsecp256k1_v0_11_musig_partial_sig * const* partial_sigs, size_t n_sigs) { + size_t i; + rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_musig_session_load(ctx, &session_i, session)) { + return 0; + } + for (i = 0; i < n_sigs; i++) { + rustsecp256k1_v0_11_scalar term; + if (!rustsecp256k1_v0_11_musig_partial_sig_load(ctx, &term, partial_sigs[i])) { + return 0; + } + rustsecp256k1_v0_11_scalar_add(&session_i.s_part, &session_i.s_part, &term); + } + rustsecp256k1_v0_11_scalar_get_b32(&sig64[32], &session_i.s_part); + memcpy(&sig64[0], session_i.fin_nonce, 32); + return 1; +} + +#endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/musig/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/tests_impl.h new file mode 100644 index 000000000..853011ba7 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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(rustsecp256k1_v0_11_keypair *keypair, rustsecp256k1_v0_11_pubkey *pk, const unsigned char *sk) { + int ret; + rustsecp256k1_v0_11_keypair keypair_tmp; + ret = rustsecp256k1_v0_11_keypair_create(CTX, &keypair_tmp, sk); + ret &= rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_keypair keypair[2]; + rustsecp256k1_v0_11_musig_pubnonce pubnonce[2]; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[2]; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + unsigned char msg[32]; + rustsecp256k1_v0_11_xonly_pubkey agg_pk; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + unsigned char session_secrand[2][32]; + rustsecp256k1_v0_11_musig_secnonce secnonce[2]; + rustsecp256k1_v0_11_pubkey pk[2]; + const rustsecp256k1_v0_11_pubkey *pk_ptr[2]; + rustsecp256k1_v0_11_musig_partial_sig partial_sig[2]; + const rustsecp256k1_v0_11_musig_partial_sig *partial_sig_ptr[2]; + unsigned char final_sig[64]; + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, &secnonce[i], &pubnonce[i], nonrepeating_cnt, &keypair[i], NULL, NULL, NULL) == 1); + } + } + + CHECK(rustsecp256k1_v0_11_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + + for (i = 0; i < 2; i++) { + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[i], &secnonce[i], &keypair[i], &keyagg_cache, &session) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[i], &pubnonce[i], &pk[i], &keyagg_cache, &session) == 1); + } + + CHECK(rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, final_sig, msg, sizeof(msg), &agg_pk) == 1); +} + +/* Generate two pubnonces such that both group elements of their sum (calculated + * with rustsecp256k1_v0_11_musig_sum_pubnonces) are infinity. */ +static void pubnonce_summing_to_inf(rustsecp256k1_v0_11_musig_pubnonce *pubnonce) { + rustsecp256k1_v0_11_ge ge[2]; + int i; + rustsecp256k1_v0_11_gej summed_pubnonces[2]; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[2]; + + testutil_random_ge_test(&ge[0]); + testutil_random_ge_test(&ge[1]); + + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_musig_pubnonce_save(&pubnonce[i], ge); + pubnonce_ptr[i] = &pubnonce[i]; + rustsecp256k1_v0_11_ge_neg(&ge[0], &ge[0]); + rustsecp256k1_v0_11_ge_neg(&ge[1], &ge[1]); + } + + rustsecp256k1_v0_11_musig_sum_pubnonces(CTX, summed_pubnonces, pubnonce_ptr, 2); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&summed_pubnonces[0])); + CHECK(rustsecp256k1_v0_11_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 = rustsecp256k1_v0_11_memcmp_var(value, expected, len); + for (i = 0; i < len; i++) { + value[i] = testrand_bits(8); + } + return ret; +} + +static void musig_api_tests(void) { + rustsecp256k1_v0_11_musig_partial_sig partial_sig[2]; + const rustsecp256k1_v0_11_musig_partial_sig *partial_sig_ptr[2]; + rustsecp256k1_v0_11_musig_partial_sig invalid_partial_sig; + const rustsecp256k1_v0_11_musig_partial_sig *invalid_partial_sig_ptr[2]; + unsigned char pre_sig[64]; + unsigned char buf[32]; + unsigned char sk[2][32]; + rustsecp256k1_v0_11_keypair keypair[2]; + rustsecp256k1_v0_11_keypair invalid_keypair; + unsigned char max64[64]; + unsigned char zeros132[132] = { 0 }; + unsigned char session_secrand[2][32]; + unsigned char nonrepeating_cnt = 0; + rustsecp256k1_v0_11_musig_secnonce secnonce[2]; + rustsecp256k1_v0_11_musig_secnonce secnonce_tmp; + rustsecp256k1_v0_11_musig_secnonce invalid_secnonce; + rustsecp256k1_v0_11_musig_pubnonce pubnonce[2]; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[2]; + unsigned char pubnonce_ser[66]; + rustsecp256k1_v0_11_musig_pubnonce inf_pubnonce[2]; + const rustsecp256k1_v0_11_musig_pubnonce *inf_pubnonce_ptr[2]; + rustsecp256k1_v0_11_musig_pubnonce invalid_pubnonce; + const rustsecp256k1_v0_11_musig_pubnonce *invalid_pubnonce_ptr[1]; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + unsigned char aggnonce_ser[66]; + unsigned char msg[32]; + rustsecp256k1_v0_11_xonly_pubkey agg_pk; + rustsecp256k1_v0_11_pubkey full_agg_pk; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_musig_keyagg_cache invalid_keyagg_cache; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_session invalid_session; + rustsecp256k1_v0_11_pubkey pk[2]; + const rustsecp256k1_v0_11_pubkey *pk_ptr[2]; + rustsecp256k1_v0_11_pubkey invalid_pk; + const rustsecp256k1_v0_11_pubkey *invalid_pk_ptr2[2]; + const rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_musig_pubkey_agg(CTX, NULL, &keyagg_cache, pk_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_musig_pubkey_agg(CTX, &agg_pk, NULL, pk_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, NULL, 0)); + CHECK(memcmp_and_randomize(agg_pk.data, zeros132, sizeof(agg_pk.data)) == 0); + + CHECK(rustsecp256k1_v0_11_musig_pubkey_agg(CTX, &agg_pk, &keyagg_cache, pk_ptr, 2) == 1); + + /* pubkey_get */ + CHECK(rustsecp256k1_v0_11_musig_pubkey_get(CTX, &full_agg_pk, &keyagg_cache) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_pubkey_get(CTX, NULL, &keyagg_cache)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_pubkey_get(CTX, &full_agg_pk, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&full_agg_pk, zeros132, sizeof(full_agg_pk)) == 0); + + /** Tweaking **/ + { + int (*tweak_func[2]) (const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *output_pubkey, rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache, const unsigned char *tweak32); + tweak_func[0] = rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add; + tweak_func[1] = rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add; + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_pubkey tmp_output_pk; + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_nonce_gen(CTX, NULL, &pubnonce[0], session_secrand[0], sk[0], &pk[0], msg, &keyagg_cache, max64)); + + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], NULL, &pk[0], NULL, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64) == 1); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, NULL, &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, &keyagg_cache, max64)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], NULL, &keyagg_cache, max64) == 1); + CHECK(rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], msg, NULL, max64) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, &secnonce[0], &pubnonce[0], nonrepeating_cnt, &keypair[0], NULL, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, NULL, &pubnonce[0])); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, pubnonce_ser, NULL)); + CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, pubnonce_ser, &invalid_pubnonce)); + CHECK(memcmp_and_randomize(pubnonce_ser, zeros132, sizeof(pubnonce_ser)) == 0); + CHECK(rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); + + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, NULL, pubnonce_ser)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce[0], NULL)); + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce[0], zeros132) == 0); + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce[0], pubnonce_ser) == 1); + + { + /* Check that serialize and parse results in the same value */ + rustsecp256k1_v0_11_musig_pubnonce tmp; + CHECK(rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, pubnonce_ser, &pubnonce[0]) == 1); + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &tmp, pubnonce_ser) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&tmp, &pubnonce[0], sizeof(tmp)) == 0); + } + + /** Receive nonces and aggregate **/ + CHECK(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_agg(CTX, NULL, pubnonce_ptr, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, NULL, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 0)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, invalid_pubnonce_ptr, 1)); + CHECK(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, inf_pubnonce_ptr, 2) == 1); + { + /* Check that the aggnonce encodes two points at infinity */ + rustsecp256k1_v0_11_ge aggnonce_pt[2]; + rustsecp256k1_v0_11_musig_aggnonce_load(CTX, aggnonce_pt, &aggnonce); + for (i = 0; i < 2; i++) { + rustsecp256k1_v0_11_ge_is_infinity(&aggnonce_pt[i]); + } + } + CHECK(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + + /** Serialize and parse aggregate nonces **/ + CHECK(rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, NULL, &aggnonce)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, aggnonce_ser, NULL)); + CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, aggnonce_ser, (rustsecp256k1_v0_11_musig_aggnonce*) &invalid_pubnonce)); + CHECK(memcmp_and_randomize(aggnonce_ser, zeros132, sizeof(aggnonce_ser)) == 0); + CHECK(rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); + + CHECK(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, NULL, aggnonce_ser)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, NULL)); + CHECK(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, zeros132) == 1); + CHECK(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, aggnonce_ser) == 1); + + { + /* Check that serialize and parse results in the same value */ + rustsecp256k1_v0_11_musig_aggnonce tmp; + CHECK(rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, aggnonce_ser, &aggnonce) == 1); + CHECK(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &tmp, aggnonce_ser) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&tmp, &aggnonce, sizeof(tmp)) == 0); + } + + /** Process nonces **/ + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_process(CTX, NULL, &aggnonce, msg, &keyagg_cache)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, NULL, msg, &keyagg_cache)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, (rustsecp256k1_v0_11_musig_aggnonce*) &invalid_pubnonce, msg, &keyagg_cache)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, NULL, &keyagg_cache)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, msg, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, msg, &invalid_keyagg_cache)); + + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, msg, &keyagg_cache) == 1); + + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_memcmp_var(&secnonce_tmp, zeros132, sizeof(secnonce_tmp)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_partial_sign(CTX, NULL, &secnonce_tmp, &keypair[0], &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], NULL, &keypair[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], &invalid_secnonce, &keypair[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, NULL, &keyagg_cache, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_keypair keypair_tmp; + testrand256(sk_tmp); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair_tmp, sk_tmp)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], NULL, &session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_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, rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], &secnonce_tmp, &keypair[0], &keyagg_cache, &invalid_session)); + memcpy(&secnonce_tmp, &secnonce[0], sizeof(secnonce_tmp)); + + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], &keyagg_cache, &session) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], &keyagg_cache, &session) == 1); + + CHECK(rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, NULL, &partial_sig[0])); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, buf, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, buf, &invalid_partial_sig)); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, &partial_sig[0], buf) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, NULL, buf)); + { + /* Check that parsing failure results in an invalid sig */ + rustsecp256k1_v0_11_musig_partial_sig tmp; + CHECK(rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, &tmp, max64) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&tmp, zeros132, sizeof(partial_sig[0])) == 0); + } + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, &partial_sig[0], NULL)); + + { + /* Check that serialize and parse results in the same value */ + rustsecp256k1_v0_11_musig_partial_sig tmp; + CHECK(rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, buf, &partial_sig[0]) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, &tmp, buf) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&tmp, &partial_sig[0], sizeof(tmp)) == 0); + } + + /** Partial signature verification */ + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, NULL, &pubnonce[0], &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &invalid_partial_sig, &pubnonce[0], &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], NULL, &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &invalid_pubnonce, &pk[0], &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], NULL, &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &invalid_pk, &keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], NULL, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &invalid_keyagg_cache, &session)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &invalid_session)); + + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], &keyagg_cache, &session) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], &keyagg_cache, &session) == 1); + + /** Signature aggregation and verification */ + CHECK(rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, NULL, &session, partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, NULL, partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, &invalid_session, partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, &session, NULL, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, &session, invalid_partial_sig_ptr, 2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 0)); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, pre_sig, &session, partial_sig_ptr, 1) == 1); + CHECK(rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_scalar k1[2], k2[2]; + + rustsecp256k1_v0_11_nonce_function_musig(k1, args[0], args[1], args[2], args[3], args[4], args[5]); + testrand_flip(args[n_flip], n_bytes); + rustsecp256k1_v0_11_nonce_function_musig(k2, args[0], args[1], args[2], args[3], args[4], args[5]); + CHECK(rustsecp256k1_v0_11_scalar_eq(&k1[0], &k2[0]) == 0); + CHECK(rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_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)); + rustsecp256k1_v0_11_nonce_function_musig(k[0], args[0], args[1], args[2], args[3], args[4], args[5]); + rustsecp256k1_v0_11_nonce_function_musig(k[1], args[0], NULL, args[2], args[3], args[4], args[5]); + rustsecp256k1_v0_11_nonce_function_musig(k[2], args[0], args[1], NULL, args[3], args[4], args[5]); + rustsecp256k1_v0_11_nonce_function_musig(k[3], args[0], args[1], args[2], NULL, args[4], args[5]); + rustsecp256k1_v0_11_nonce_function_musig(k[4], args[0], args[1], args[2], args[3], NULL, args[5]); + rustsecp256k1_v0_11_nonce_function_musig(k[5], args[0], args[1], args[2], args[3], args[4], NULL); + for (i = 0; i < 6; i++) { + CHECK(!rustsecp256k1_v0_11_scalar_eq(&k[i][0], &k[i][1])); + for (j = i+1; j < 6; j++) { + CHECK(!rustsecp256k1_v0_11_scalar_eq(&k[i][0], &k[j][0])); + CHECK(!rustsecp256k1_v0_11_scalar_eq(&k[i][1], &k[j][1])); + } + } +} + +static void sha256_tag_test_internal(rustsecp256k1_v0_11_sha256 *sha_tagged, unsigned char *tag, size_t taglen) { + rustsecp256k1_v0_11_sha256 sha; + rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_sha256 sha; + { + char tag[] = "KeyAgg list"; + rustsecp256k1_v0_11_musig_keyagglist_sha256(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + char tag[] = "KeyAgg coefficient"; + rustsecp256k1_v0_11_musig_keyaggcoef_sha256(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + unsigned char tag[] = "MuSig/aux"; + rustsecp256k1_v0_11_nonce_function_musig_sha256_tagged_aux(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + unsigned char tag[] = "MuSig/nonce"; + rustsecp256k1_v0_11_nonce_function_musig_sha256_tagged(&sha); + sha256_tag_test_internal(&sha, (unsigned char*)tag, sizeof(tag) - 1); + } + { + unsigned char tag[] = "MuSig/noncecoef"; + rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_xonly_pubkey* agg_pk, const unsigned char *sk0, const unsigned char *sk1, rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache) { + rustsecp256k1_v0_11_pubkey pk[2]; + unsigned char session_secrand[2][32]; + unsigned char msg[32]; + rustsecp256k1_v0_11_musig_secnonce secnonce[2]; + rustsecp256k1_v0_11_musig_pubnonce pubnonce[2]; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[2]; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_keypair keypair[2]; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_partial_sig partial_sig[2]; + const rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_gen(CTX, &secnonce[0], &pubnonce[0], session_secrand[0], sk0, &pk[0], NULL, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_musig_nonce_gen(CTX, &secnonce[1], &pubnonce[1], session_secrand[1], sk1, &pk[1], NULL, NULL, NULL) == 1); + + CHECK(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, msg, keyagg_cache) == 1); + + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[0], &secnonce[0], &keypair[0], keyagg_cache, &session) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig[1], &secnonce[1], &keypair[1], keyagg_cache, &session) == 1); + + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[0], &pubnonce[0], &pk[0], keyagg_cache, &session) == 1); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_verify(CTX, &partial_sig[1], &pubnonce[1], &pk[1], keyagg_cache, &session) == 1); + + CHECK(rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, 2) == 1); + CHECK(rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_pubkey pk[2]; + const rustsecp256k1_v0_11_pubkey *pk_ptr[2]; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + enum { N_TWEAKS = 8 }; + rustsecp256k1_v0_11_pubkey P[N_TWEAKS + 1]; + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); + } else { + CHECK(rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add(CTX, &P[i], &keyagg_cache, tweak) == 1); + } + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, P_serialized, &P_xonly[i])); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, P_serialized, P_parity, &P_xonly[i-1], tweak) == 1); + } else { + rustsecp256k1_v0_11_pubkey tmp_key = P[i-1]; + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &tmp_key, tweak)); + CHECK(rustsecp256k1_v0_11_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, + rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_pubkey pubkeys[MUSIG_VECTORS_MAX_PUBKEYS]; + const rustsecp256k1_v0_11_pubkey *pk_ptr[MUSIG_VECTORS_MAX_PUBKEYS]; + int i; + rustsecp256k1_v0_11_pubkey agg_pk; + rustsecp256k1_v0_11_xonly_pubkey agg_pk_xonly; + + for (i = 0; i < (int)key_indices_len; i++) { + if (!rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkeys[i], pubkeys33[key_indices[i]], 33)) { + *error = MUSIG_PUBKEY; + return 0; + } + pk_ptr[i] = &pubkeys[i]; + } + if (!rustsecp256k1_v0_11_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 (!rustsecp256k1_v0_11_musig_pubkey_xonly_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { + *error = MUSIG_TWEAK; + return 0; + } + } else { + if (!rustsecp256k1_v0_11_musig_pubkey_ec_tweak_add(CTX, NULL, keyagg_cache, tweaks32[tweak_indices[i]])) { + *error = MUSIG_TWEAK; + return 0; + } + } + } + if (!rustsecp256k1_v0_11_musig_pubkey_get(CTX, &agg_pk, keyagg_cache)) { + *error = MUSIG_OTHER; + return 0; + } + + if (!rustsecp256k1_v0_11_xonly_pubkey_from_pubkey(CTX, &agg_pk_xonly, NULL, &agg_pk)) { + *error = MUSIG_OTHER; + return 0; + } + + if (agg_pk_ser != NULL) { + if (!rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_musig_keyagg_cache *keyagg_cache_ptr = NULL; + unsigned char session_secrand32[32]; + rustsecp256k1_v0_11_musig_secnonce secnonce; + rustsecp256k1_v0_11_musig_pubnonce pubnonce; + const unsigned char *sk = NULL; + const unsigned char *msg = NULL; + const unsigned char *extra_in = NULL; + rustsecp256k1_v0_11_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 */ + rustsecp256k1_v0_11_keyagg_cache_internal cache_i; + rustsecp256k1_v0_11_xonly_pubkey aggpk; + memset(&cache_i, 0, sizeof(cache_i)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &aggpk, c->aggpk)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_load(CTX, &cache_i.pk, &aggpk)); + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pk, c->pk, sizeof(c->pk))); + CHECK(rustsecp256k1_v0_11_musig_nonce_gen(CTX, &secnonce, &pubnonce, session_secrand32, sk, &pk, msg, keyagg_cache_ptr, extra_in) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&secnonce.data[4], c->expected_secnonce, 2*32) == 0); + /* The last element of the secnonce is the public key (uncompressed in + * rustsecp256k1_v0_11_musig_secnonce, compressed in the test vector secnonce). */ + CHECK(rustsecp256k1_v0_11_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&c->expected_secnonce[2*32], c->pk, sizeof(c->pk)) == 0); + + CHECK(rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); + CHECK(sizeof(c->expected_pubnonce) == sizeof(pubnonce66)); + CHECK(rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_musig_pubnonce pubnonce[2]; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[2]; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + unsigned char aggnonce66[66]; + + for (j = 0; j < 2; j++) { + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]]) == 1); + pubnonce_ptr[j] = &pubnonce[j]; + } + CHECK(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, 2)); + CHECK(rustsecp256k1_v0_11_musig_aggnonce_serialize(CTX, aggnonce66, &aggnonce)); + CHECK(rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_musig_pubnonce pubnonce[2]; + for (j = 0; j < 2; j++) { + int expected = c->invalid_nonce_idx != j; + CHECK(expected == rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce[j], vector->pnonces[c->pnonce_indices[j]])); + } + } +} + +static void musig_test_set_secnonce(rustsecp256k1_v0_11_musig_secnonce *secnonce, const unsigned char *secnonce64, const rustsecp256k1_v0_11_pubkey *pubkey) { + rustsecp256k1_v0_11_ge pk; + rustsecp256k1_v0_11_scalar k[2]; + + rustsecp256k1_v0_11_scalar_set_b32(&k[0], &secnonce64[0], NULL); + rustsecp256k1_v0_11_scalar_set_b32(&k[1], &secnonce64[32], NULL); + CHECK(rustsecp256k1_v0_11_pubkey_load(CTX, &pk, pubkey)); + rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_musig_pubnonce pubnonce; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_partial_sig partial_sig; + rustsecp256k1_v0_11_musig_secnonce secnonce; + rustsecp256k1_v0_11_keypair keypair; + unsigned char partial_sig32[32]; + + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[0], sizeof(vector->pubkeys[0]))); + musig_test_set_secnonce(&secnonce, vector->secnonces[0], &pubkey); + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); + CHECK(rustsecp256k1_v0_11_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); + + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[0])); + CHECK(rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_partial_sig partial_sig; + rustsecp256k1_v0_11_musig_secnonce secnonce; + rustsecp256k1_v0_11_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 == rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonces[c->aggnonce_index])); + if (!expected) { + continue; + } + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + } else { + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_partial_sig partial_sig; + enum { NUM_PUBNONCES = 3 }; + rustsecp256k1_v0_11_musig_pubnonce pubnonce[NUM_PUBNONCES]; + const rustsecp256k1_v0_11_musig_pubnonce *pubnonce_ptr[NUM_PUBNONCES]; + rustsecp256k1_v0_11_pubkey pubkey; + int expected; + size_t j; + + CHECK(NUM_PUBNONCES <= c->nonce_indices_len); + for (j = 0; j < c->nonce_indices_len; j++) { + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_agg(CTX, &aggnonce, pubnonce_ptr, c->nonce_indices_len) == 1); + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, vector->msgs[c->msg_index], &keyagg_cache)); + + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, vector->pubkeys[c->signer_index], sizeof(vector->pubkeys[0]))); + + expected = c->error != MUSIG_SIG; + CHECK(expected == rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, &partial_sig, c->sig)); + if (!expected) { + continue; + } + expected = c->error != MUSIG_SIG_VERIFY; + CHECK(expected == rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_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 == rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_musig_secnonce secnonce; + + CHECK(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, vector->aggnonce)); + CHECK(rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + rustsecp256k1_v0_11_musig_pubnonce pubnonce; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_partial_sig partial_sig; + rustsecp256k1_v0_11_keypair keypair; + unsigned char partial_sig32[32]; + + musig_test_set_secnonce(&secnonce, vector->secnonce, &pubkey); + + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); + + CHECK(rustsecp256k1_v0_11_musig_partial_sign(CTX, &partial_sig, &secnonce, &keypair, &keyagg_cache, &session)); + CHECK(rustsecp256k1_v0_11_musig_partial_sig_serialize(CTX, partial_sig32, &partial_sig)); + CHECK(rustsecp256k1_v0_11_memcmp_var(partial_sig32, c->expected, sizeof(partial_sig32)) == 0); + + CHECK(rustsecp256k1_v0_11_musig_pubnonce_parse(CTX, &pubnonce, vector->pubnonces[c->nonce_indices[c->signer_index]])); + CHECK(rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_musig_keyagg_cache keyagg_cache; + unsigned char agg_pk32[32]; + rustsecp256k1_v0_11_xonly_pubkey agg_pk; + rustsecp256k1_v0_11_musig_aggnonce aggnonce; + rustsecp256k1_v0_11_musig_session session; + rustsecp256k1_v0_11_musig_partial_sig partial_sig[(sizeof(vector->psigs)/sizeof(vector->psigs[0]))]; + const rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_musig_aggnonce_parse(CTX, &aggnonce, c->aggnonce)); + CHECK(rustsecp256k1_v0_11_musig_nonce_process(CTX, &session, &aggnonce, vector->msg, &keyagg_cache)); + for (j = 0; j < c->psig_indices_len; j++) { + CHECK(rustsecp256k1_v0_11_musig_partial_sig_parse(CTX, &partial_sig[j], vector->psigs[c->psig_indices[j]])); + partial_sig_ptr[j] = &partial_sig[j]; + } + + CHECK(rustsecp256k1_v0_11_musig_partial_sig_agg(CTX, final_sig, &session, partial_sig_ptr, c->psig_indices_len) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(final_sig, c->expected, sizeof(final_sig)) == 0); + + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &agg_pk, agg_pk32)); + CHECK(rustsecp256k1_v0_11_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]; + rustsecp256k1_v0_11_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 == rustsecp256k1_v0_11_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) { + rustsecp256k1_v0_11_musig_secnonce secnonce; + rustsecp256k1_v0_11_musig_pubnonce pubnonce; + unsigned char pubnonce66[66]; + rustsecp256k1_v0_11_pubkey pk; + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk)); + CHECK(rustsecp256k1_v0_11_keypair_pub(CTX, &pk, &keypair)); + CHECK(rustsecp256k1_v0_11_musig_nonce_gen_counter(CTX, &secnonce, &pubnonce, nonrepeating_cnt, &keypair, NULL, NULL, NULL) == 1); + + CHECK(rustsecp256k1_v0_11_memcmp_var(&secnonce.data[4], expected_secnonce, 2*32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&secnonce.data[4+2*32], &pk, sizeof(pk)) == 0); + + CHECK(rustsecp256k1_v0_11_musig_pubnonce_serialize(CTX, pubnonce66, &pubnonce) == 1); + CHECK(rustsecp256k1_v0_11_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/secp256k1-sys/depend/secp256k1/src/modules/musig/vectors.h b/secp256k1-sys/depend/secp256k1/src/modules/musig/vectors.h new file mode 100644 index 000000000..8407c2a69 --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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/secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include index 328f1e12b..4ea04f800 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/Makefile.am.include @@ -1,4 +1,4 @@ -include_HEADERS += include/rustsecp256k1_v0_10_0_recovery.h +include_HEADERS += include/rustsecp256k1_v0_11_recovery.h noinst_HEADERS += src/modules/recovery/main_impl.h noinst_HEADERS += src/modules/recovery/tests_impl.h noinst_HEADERS += src/modules/recovery/tests_exhaustive_impl.h diff --git a/secp256k1-sys/depend/secp256k1/src/modules/recovery/bench_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/recovery/bench_impl.h index 610e938f6..defd82f6e 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/recovery/bench_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/bench_impl.h @@ -10,7 +10,7 @@ #include "../../../include/secp256k1_recovery.h" typedef struct { - rustsecp256k1_v0_10_0_context *ctx; + rustsecp256k1_v0_11_context *ctx; unsigned char msg[32]; unsigned char sig[64]; } bench_recover_data; @@ -18,16 +18,16 @@ typedef struct { static void bench_recover(void* arg, int iters) { int i; bench_recover_data *data = (bench_recover_data*)arg; - rustsecp256k1_v0_10_0_pubkey pubkey; + rustsecp256k1_v0_11_pubkey pubkey; unsigned char pubkeyc[33]; for (i = 0; i < iters; i++) { int j; size_t pubkeylen = 33; - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature sig; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); + rustsecp256k1_v0_11_ecdsa_recoverable_signature sig; + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); for (j = 0; j < 32; j++) { data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ data->msg[j] = data->sig[j]; /* Move former R to message. */ @@ -52,11 +52,11 @@ static void run_recovery_bench(int iters, int argc, char** argv) { bench_recover_data data; int d = argc == 1; - data.ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + data.ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); if (d || have_flag(argc, argv, "ecdsa") || have_flag(argc, argv, "recover") || have_flag(argc, argv, "ecdsa_recover")) run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters); - rustsecp256k1_v0_10_0_context_destroy(data.ctx); + rustsecp256k1_v0_11_context_destroy(data.ctx); } #endif /* SECP256K1_MODULE_RECOVERY_BENCH_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h index 9d7a0d486..32f182a3c 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/main_impl.h @@ -9,34 +9,34 @@ #include "../../../include/secp256k1_recovery.h" -static void rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_load(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_scalar* r, rustsecp256k1_v0_10_0_scalar* s, int* recid, const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature* sig) { +static void rustsecp256k1_v0_11_ecdsa_recoverable_signature_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar* r, rustsecp256k1_v0_11_scalar* s, int* recid, const rustsecp256k1_v0_11_ecdsa_recoverable_signature* sig) { (void)ctx; - if (sizeof(rustsecp256k1_v0_10_0_scalar) == 32) { - /* When the rustsecp256k1_v0_10_0_scalar type is exactly 32 byte, use its - * representation inside rustsecp256k1_v0_10_0_ecdsa_signature, as conversion is very fast. - * Note that rustsecp256k1_v0_10_0_ecdsa_signature_save must use the same representation. */ + if (sizeof(rustsecp256k1_v0_11_scalar) == 32) { + /* When the rustsecp256k1_v0_11_scalar type is exactly 32 byte, use its + * representation inside rustsecp256k1_v0_11_ecdsa_signature, as conversion is very fast. + * Note that rustsecp256k1_v0_11_ecdsa_signature_save must use the same representation. */ memcpy(r, &sig->data[0], 32); memcpy(s, &sig->data[32], 32); } else { - rustsecp256k1_v0_10_0_scalar_set_b32(r, &sig->data[0], NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(s, &sig->data[32], NULL); + rustsecp256k1_v0_11_scalar_set_b32(r, &sig->data[0], NULL); + rustsecp256k1_v0_11_scalar_set_b32(s, &sig->data[32], NULL); } *recid = sig->data[64]; } -static void rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_save(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature* sig, const rustsecp256k1_v0_10_0_scalar* r, const rustsecp256k1_v0_10_0_scalar* s, int recid) { - if (sizeof(rustsecp256k1_v0_10_0_scalar) == 32) { +static void rustsecp256k1_v0_11_ecdsa_recoverable_signature_save(rustsecp256k1_v0_11_ecdsa_recoverable_signature* sig, const rustsecp256k1_v0_11_scalar* r, const rustsecp256k1_v0_11_scalar* s, int recid) { + if (sizeof(rustsecp256k1_v0_11_scalar) == 32) { memcpy(&sig->data[0], r, 32); memcpy(&sig->data[32], s, 32); } else { - rustsecp256k1_v0_10_0_scalar_get_b32(&sig->data[0], r); - rustsecp256k1_v0_10_0_scalar_get_b32(&sig->data[32], s); + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[0], r); + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[32], s); } sig->data[64] = recid; } -int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { + rustsecp256k1_v0_11_scalar r, s; int ret = 1; int overflow = 0; @@ -45,110 +45,110 @@ int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(const rustse ARG_CHECK(input64 != NULL); ARG_CHECK(recid >= 0 && recid <= 3); - rustsecp256k1_v0_10_0_scalar_set_b32(&r, &input64[0], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&r, &input64[0], &overflow); ret &= !overflow; - rustsecp256k1_v0_10_0_scalar_set_b32(&s, &input64[32], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&s, &input64[32], &overflow); ret &= !overflow; if (ret) { - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_save(sig, &r, &s, recid); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_save(sig, &r, &s, recid); } else { memset(sig, 0, sizeof(*sig)); } return ret; } -int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *output64, int *recid, const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature* sig) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(const rustsecp256k1_v0_11_context* ctx, unsigned char *output64, int *recid, const rustsecp256k1_v0_11_ecdsa_recoverable_signature* sig) { + rustsecp256k1_v0_11_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output64 != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(recid != NULL); - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); - rustsecp256k1_v0_10_0_scalar_get_b32(&output64[0], &r); - rustsecp256k1_v0_10_0_scalar_get_b32(&output64[32], &s); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); + rustsecp256k1_v0_11_scalar_get_b32(&output64[0], &r); + rustsecp256k1_v0_11_scalar_get_b32(&output64[32], &s); return 1; } -int rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_signature* sig, const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature* sigin) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature* sig, const rustsecp256k1_v0_11_ecdsa_recoverable_signature* sigin) { + rustsecp256k1_v0_11_scalar r, s; int recid; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(sigin != NULL); - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); - rustsecp256k1_v0_10_0_ecdsa_signature_save(sig, &r, &s); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); + rustsecp256k1_v0_11_ecdsa_signature_save(sig, &r, &s); return 1; } -static int rustsecp256k1_v0_10_0_ecdsa_sig_recover(const rustsecp256k1_v0_10_0_scalar *sigr, const rustsecp256k1_v0_10_0_scalar* sigs, rustsecp256k1_v0_10_0_ge *pubkey, const rustsecp256k1_v0_10_0_scalar *message, int recid) { +static int rustsecp256k1_v0_11_ecdsa_sig_recover(const rustsecp256k1_v0_11_scalar *sigr, const rustsecp256k1_v0_11_scalar* sigs, rustsecp256k1_v0_11_ge *pubkey, const rustsecp256k1_v0_11_scalar *message, int recid) { unsigned char brx[32]; - rustsecp256k1_v0_10_0_fe fx; - rustsecp256k1_v0_10_0_ge x; - rustsecp256k1_v0_10_0_gej xj; - rustsecp256k1_v0_10_0_scalar rn, u1, u2; - rustsecp256k1_v0_10_0_gej qj; + rustsecp256k1_v0_11_fe fx; + rustsecp256k1_v0_11_ge x; + rustsecp256k1_v0_11_gej xj; + rustsecp256k1_v0_11_scalar rn, u1, u2; + rustsecp256k1_v0_11_gej qj; int r; - if (rustsecp256k1_v0_10_0_scalar_is_zero(sigr) || rustsecp256k1_v0_10_0_scalar_is_zero(sigs)) { + if (rustsecp256k1_v0_11_scalar_is_zero(sigr) || rustsecp256k1_v0_11_scalar_is_zero(sigs)) { return 0; } - rustsecp256k1_v0_10_0_scalar_get_b32(brx, sigr); - r = rustsecp256k1_v0_10_0_fe_set_b32_limit(&fx, brx); + rustsecp256k1_v0_11_scalar_get_b32(brx, sigr); + r = rustsecp256k1_v0_11_fe_set_b32_limit(&fx, brx); (void)r; VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ if (recid & 2) { - if (rustsecp256k1_v0_10_0_fe_cmp_var(&fx, &rustsecp256k1_v0_10_0_ecdsa_const_p_minus_order) >= 0) { + if (rustsecp256k1_v0_11_fe_cmp_var(&fx, &rustsecp256k1_v0_11_ecdsa_const_p_minus_order) >= 0) { return 0; } - rustsecp256k1_v0_10_0_fe_add(&fx, &rustsecp256k1_v0_10_0_ecdsa_const_order_as_fe); + rustsecp256k1_v0_11_fe_add(&fx, &rustsecp256k1_v0_11_ecdsa_const_order_as_fe); } - if (!rustsecp256k1_v0_10_0_ge_set_xo_var(&x, &fx, recid & 1)) { + if (!rustsecp256k1_v0_11_ge_set_xo_var(&x, &fx, recid & 1)) { return 0; } - rustsecp256k1_v0_10_0_gej_set_ge(&xj, &x); - rustsecp256k1_v0_10_0_scalar_inverse_var(&rn, sigr); - rustsecp256k1_v0_10_0_scalar_mul(&u1, &rn, message); - rustsecp256k1_v0_10_0_scalar_negate(&u1, &u1); - rustsecp256k1_v0_10_0_scalar_mul(&u2, &rn, sigs); - rustsecp256k1_v0_10_0_ecmult(&qj, &xj, &u2, &u1); - rustsecp256k1_v0_10_0_ge_set_gej_var(pubkey, &qj); - return !rustsecp256k1_v0_10_0_gej_is_infinity(&qj); + rustsecp256k1_v0_11_gej_set_ge(&xj, &x); + rustsecp256k1_v0_11_scalar_inverse_var(&rn, sigr); + rustsecp256k1_v0_11_scalar_mul(&u1, &rn, message); + rustsecp256k1_v0_11_scalar_negate(&u1, &u1); + rustsecp256k1_v0_11_scalar_mul(&u2, &rn, sigs); + rustsecp256k1_v0_11_ecmult(&qj, &xj, &u2, &u1); + rustsecp256k1_v0_11_ge_set_gej_var(pubkey, &qj); + return !rustsecp256k1_v0_11_gej_is_infinity(&qj); } -int rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, rustsecp256k1_v0_10_0_nonce_function noncefp, const void* noncedata) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_sign_recoverable(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_recoverable_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, rustsecp256k1_v0_11_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_11_scalar r, s; int ret, recid; VERIFY_CHECK(ctx != NULL); - ARG_CHECK(rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(seckey != NULL); - ret = rustsecp256k1_v0_10_0_ecdsa_sign_inner(ctx, &r, &s, &recid, msghash32, seckey, noncefp, noncedata); - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_save(signature, &r, &s, recid); + ret = rustsecp256k1_v0_11_ecdsa_sign_inner(ctx, &r, &s, &recid, msghash32, seckey, noncefp, noncedata); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_save(signature, &r, &s, recid); return ret; } -int rustsecp256k1_v0_10_0_ecdsa_recover(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubkey, const rustsecp256k1_v0_10_0_ecdsa_recoverable_signature *signature, const unsigned char *msghash32) { - rustsecp256k1_v0_10_0_ge q; - rustsecp256k1_v0_10_0_scalar r, s; - rustsecp256k1_v0_10_0_scalar m; +int rustsecp256k1_v0_11_ecdsa_recover(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const rustsecp256k1_v0_11_ecdsa_recoverable_signature *signature, const unsigned char *msghash32) { + rustsecp256k1_v0_11_ge q; + rustsecp256k1_v0_11_scalar r, s; + rustsecp256k1_v0_11_scalar m; int recid; VERIFY_CHECK(ctx != NULL); ARG_CHECK(msghash32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(pubkey != NULL); - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ - rustsecp256k1_v0_10_0_scalar_set_b32(&m, msghash32, NULL); - if (rustsecp256k1_v0_10_0_ecdsa_sig_recover(&r, &s, &q, &m, recid)) { - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &q); + rustsecp256k1_v0_11_scalar_set_b32(&m, msghash32, NULL); + if (rustsecp256k1_v0_11_ecdsa_sig_recover(&r, &s, &q, &m, recid)) { + rustsecp256k1_v0_11_pubkey_save(pubkey, &q); return 1; } else { memset(pubkey, 0, sizeof(*pubkey)); diff --git a/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_exhaustive_impl.h index 716153b8f..30876a008 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_exhaustive_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_exhaustive_impl.h @@ -10,7 +10,7 @@ #include "main_impl.h" #include "../../../include/secp256k1_recovery.h" -static void test_exhaustive_recovery_sign(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_recovery_sign(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { int i, j, k; uint64_t iter = 0; @@ -20,23 +20,23 @@ static void test_exhaustive_recovery_sign(const rustsecp256k1_v0_10_0_context *c if (skip_section(&iter)) continue; for (k = 1; k < EXHAUSTIVE_TEST_ORDER; k++) { /* nonce */ const int starting_k = k; - rustsecp256k1_v0_10_0_fe r_dot_y_normalized; - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature rsig; - rustsecp256k1_v0_10_0_ecdsa_signature sig; - rustsecp256k1_v0_10_0_scalar sk, msg, r, s, expected_r; + rustsecp256k1_v0_11_fe r_dot_y_normalized; + rustsecp256k1_v0_11_ecdsa_recoverable_signature rsig; + rustsecp256k1_v0_11_ecdsa_signature sig; + rustsecp256k1_v0_11_scalar sk, msg, r, s, expected_r; unsigned char sk32[32], msg32[32]; int expected_recid; int recid; int overflow; - rustsecp256k1_v0_10_0_scalar_set_int(&msg, i); - rustsecp256k1_v0_10_0_scalar_set_int(&sk, j); - rustsecp256k1_v0_10_0_scalar_get_b32(sk32, &sk); - rustsecp256k1_v0_10_0_scalar_get_b32(msg32, &msg); + rustsecp256k1_v0_11_scalar_set_int(&msg, i); + rustsecp256k1_v0_11_scalar_set_int(&sk, j); + rustsecp256k1_v0_11_scalar_get_b32(sk32, &sk); + rustsecp256k1_v0_11_scalar_get_b32(msg32, &msg); - rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, rustsecp256k1_v0_10_0_nonce_function_smallint, &k); + rustsecp256k1_v0_11_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, rustsecp256k1_v0_11_nonce_function_smallint, &k); /* Check directly */ - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); r_from_k(&expected_r, group, k, &overflow); CHECK(r == expected_r); CHECK((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER || @@ -49,18 +49,18 @@ static void test_exhaustive_recovery_sign(const rustsecp256k1_v0_10_0_context *c * in the real group. */ expected_recid = overflow ? 2 : 0; r_dot_y_normalized = group[k].y; - rustsecp256k1_v0_10_0_fe_normalize(&r_dot_y_normalized); + rustsecp256k1_v0_11_fe_normalize(&r_dot_y_normalized); /* Also the recovery id is flipped depending if we hit the low-s branch */ if ((k * s) % EXHAUSTIVE_TEST_ORDER == (i + r * j) % EXHAUSTIVE_TEST_ORDER) { - expected_recid |= rustsecp256k1_v0_10_0_fe_is_odd(&r_dot_y_normalized); + expected_recid |= rustsecp256k1_v0_11_fe_is_odd(&r_dot_y_normalized); } else { - expected_recid |= !rustsecp256k1_v0_10_0_fe_is_odd(&r_dot_y_normalized); + expected_recid |= !rustsecp256k1_v0_11_fe_is_odd(&r_dot_y_normalized); } CHECK(recid == expected_recid); /* Convert to a standard sig then check */ - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); - rustsecp256k1_v0_10_0_ecdsa_signature_load(ctx, &r, &s, &sig); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, &sig); /* Note that we compute expected_r *after* signing -- this is important * because our nonce-computing function function might change k during * signing. */ @@ -78,7 +78,7 @@ static void test_exhaustive_recovery_sign(const rustsecp256k1_v0_10_0_context *c } } -static void test_exhaustive_recovery_verify(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_recovery_verify(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { /* This is essentially a copy of test_exhaustive_verify, with recovery added */ int s, r, msg, key; uint64_t iter = 0; @@ -86,41 +86,41 @@ static void test_exhaustive_recovery_verify(const rustsecp256k1_v0_10_0_context for (r = 1; r < EXHAUSTIVE_TEST_ORDER; r++) { for (msg = 1; msg < EXHAUSTIVE_TEST_ORDER; msg++) { for (key = 1; key < EXHAUSTIVE_TEST_ORDER; key++) { - rustsecp256k1_v0_10_0_ge nonconst_ge; - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature rsig; - rustsecp256k1_v0_10_0_ecdsa_signature sig; - rustsecp256k1_v0_10_0_pubkey pk; - rustsecp256k1_v0_10_0_scalar sk_s, msg_s, r_s, s_s; - rustsecp256k1_v0_10_0_scalar s_times_k_s, msg_plus_r_times_sk_s; + rustsecp256k1_v0_11_ge nonconst_ge; + rustsecp256k1_v0_11_ecdsa_recoverable_signature rsig; + rustsecp256k1_v0_11_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pk; + rustsecp256k1_v0_11_scalar sk_s, msg_s, r_s, s_s; + rustsecp256k1_v0_11_scalar s_times_k_s, msg_plus_r_times_sk_s; int recid = 0; int k, should_verify; unsigned char msg32[32]; if (skip_section(&iter)) continue; - rustsecp256k1_v0_10_0_scalar_set_int(&s_s, s); - rustsecp256k1_v0_10_0_scalar_set_int(&r_s, r); - rustsecp256k1_v0_10_0_scalar_set_int(&msg_s, msg); - rustsecp256k1_v0_10_0_scalar_set_int(&sk_s, key); - rustsecp256k1_v0_10_0_scalar_get_b32(msg32, &msg_s); + rustsecp256k1_v0_11_scalar_set_int(&s_s, s); + rustsecp256k1_v0_11_scalar_set_int(&r_s, r); + rustsecp256k1_v0_11_scalar_set_int(&msg_s, msg); + rustsecp256k1_v0_11_scalar_set_int(&sk_s, key); + rustsecp256k1_v0_11_scalar_get_b32(msg32, &msg_s); /* Verify by hand */ /* Run through every k value that gives us this r and check that *one* works. * Note there could be none, there could be multiple, ECDSA is weird. */ should_verify = 0; for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { - rustsecp256k1_v0_10_0_scalar check_x_s; + rustsecp256k1_v0_11_scalar check_x_s; r_from_k(&check_x_s, group, k, NULL); if (r_s == check_x_s) { - rustsecp256k1_v0_10_0_scalar_set_int(&s_times_k_s, k); - rustsecp256k1_v0_10_0_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - rustsecp256k1_v0_10_0_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - rustsecp256k1_v0_10_0_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= rustsecp256k1_v0_10_0_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + rustsecp256k1_v0_11_scalar_set_int(&s_times_k_s, k); + rustsecp256k1_v0_11_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + rustsecp256k1_v0_11_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + rustsecp256k1_v0_11_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= rustsecp256k1_v0_11_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); } } /* nb we have a "high s" rule */ - should_verify &= !rustsecp256k1_v0_10_0_scalar_is_high(&s_s); + should_verify &= !rustsecp256k1_v0_11_scalar_is_high(&s_s); /* We would like to try recovering the pubkey and checking that it matches, * but pubkey recovery is impossible in the exhaustive tests (the reason @@ -128,19 +128,19 @@ static void test_exhaustive_recovery_verify(const rustsecp256k1_v0_10_0_context * overlap between the sets, so there are no valid signatures). */ /* Verify by converting to a standard signature and calling verify */ - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); + rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - rustsecp256k1_v0_10_0_pubkey_save(&pk, &nonconst_ge); + rustsecp256k1_v0_11_pubkey_save(&pk, &nonconst_ge); CHECK(should_verify == - rustsecp256k1_v0_10_0_ecdsa_verify(ctx, &sig, msg32, &pk)); + rustsecp256k1_v0_11_ecdsa_verify(ctx, &sig, msg32, &pk)); } } } } } -static void test_exhaustive_recovery(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_recovery(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { test_exhaustive_recovery_sign(ctx, group); test_exhaustive_recovery_verify(ctx, group); } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h index 9143f9ba7..96a2a1cca 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/recovery/tests_impl.h @@ -25,15 +25,15 @@ 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 rustsecp256k1_v0_10_0_testrand_bits(1); + return testrand_bits(1); } static void test_ecdsa_recovery_api(void) { /* Setup contexts that just count errors */ - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_pubkey recpubkey; - rustsecp256k1_v0_10_0_ecdsa_signature normal_sig; - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature recsig; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_pubkey recpubkey; + rustsecp256k1_v0_11_ecdsa_signature normal_sig; + rustsecp256k1_v0_11_ecdsa_recoverable_signature recsig; unsigned char privkey[32] = { 1 }; unsigned char message[32] = { 2 }; int recid = 0; @@ -45,109 +45,109 @@ static void test_ecdsa_recovery_api(void) { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /* Construct and verify corresponding public key. */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, privkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, privkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, privkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, privkey) == 1); /* Check bad contexts and NULLs for signing */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, NULL, message, privkey, NULL, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, NULL, privkey, NULL, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, NULL, NULL, NULL)); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(STATIC_CTX, &recsig, message, privkey, NULL, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, NULL, message, privkey, NULL, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, NULL, privkey, NULL, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, NULL, NULL, NULL)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_ecdsa_sign_recoverable(STATIC_CTX, &recsig, message, privkey, NULL, NULL)); /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ - rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, recovery_test_nonce_function, NULL); + rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, recovery_test_nonce_function, NULL); /* These will all fail, but not in ARG_CHECK way */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, zero_privkey, NULL, NULL) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, over_privkey, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, zero_privkey, NULL, NULL) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, over_privkey, NULL, NULL) == 0); /* This one will succeed. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); /* Check signing with a goofy nonce function */ /* Check bad contexts and NULLs for recovery */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &recpubkey, &recsig, message) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recover(CTX, NULL, &recsig, message)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &recpubkey, NULL, message)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &recpubkey, &recsig, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &recpubkey, &recsig, message) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recover(CTX, NULL, &recsig, message)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recover(CTX, &recpubkey, NULL, message)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recover(CTX, &recpubkey, &recsig, NULL)); /* Check NULLs for conversion */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &normal_sig, message, privkey, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(CTX, NULL, &recsig)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(CTX, &normal_sig, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(CTX, &normal_sig, &recsig) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &normal_sig, message, privkey, NULL, NULL) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(CTX, NULL, &recsig)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(CTX, &normal_sig, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(CTX, &normal_sig, &recsig) == 1); /* Check NULLs for de/serialization */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(CTX, NULL, &recid, &recsig)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, NULL, &recsig)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &recsig) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &recsig, message, privkey, NULL, NULL) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(CTX, NULL, &recid, &recsig)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(CTX, sig, NULL, &recsig)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &recsig) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, NULL, sig, recid)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, NULL, recid)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, -1)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, 5)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, NULL, sig, recid)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, NULL, recid)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, -1)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, 5)); /* overflow in signature will not result in calling illegal_callback */ memcpy(sig, over_privkey, 32); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, recid) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &recsig, sig, recid) == 0); } static void test_ecdsa_recovery_end_to_end(void) { unsigned char extra[32] = {0x00}; unsigned char privkey[32]; unsigned char message[32]; - rustsecp256k1_v0_10_0_ecdsa_signature signature[5]; - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature rsignature[5]; + rustsecp256k1_v0_11_ecdsa_signature signature[5]; + rustsecp256k1_v0_11_ecdsa_recoverable_signature rsignature[5]; unsigned char sig[74]; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_pubkey recpubkey; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_pubkey recpubkey; int recid = 0; /* Generate a random key and message. */ { - rustsecp256k1_v0_10_0_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - rustsecp256k1_v0_10_0_scalar_get_b32(privkey, &key); - rustsecp256k1_v0_10_0_scalar_get_b32(message, &msg); + rustsecp256k1_v0_11_scalar msg, key; + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); + rustsecp256k1_v0_11_scalar_get_b32(privkey, &key); + rustsecp256k1_v0_11_scalar_get_b32(message, &msg); } /* Construct and verify corresponding public key. */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, privkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, privkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, privkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, privkey) == 1); /* Serialize/parse compact and verify/recover. */ extra[0] = 0; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &rsignature[0], message, privkey, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &rsignature[4], message, privkey, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &rsignature[1], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &rsignature[0], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &rsignature[4], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &rsignature[1], message, privkey, NULL, extra) == 1); extra[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &rsignature[2], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &rsignature[2], message, privkey, NULL, extra) == 1); extra[31] = 0; extra[0] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign_recoverable(CTX, &rsignature[3], message, privkey, NULL, extra) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[4], &signature[0], 64) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign_recoverable(CTX, &rsignature[3], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[4], &signature[0], 64) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1); memset(&rsignature[4], 0, sizeof(rsignature[4])); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 1); /* Parse compact (with recovery id) and recover. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) == 0); /* Serialize/destroy/parse signature and verify again. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); - sig[rustsecp256k1_v0_10_0_testrand_bits(6)] += 1 + rustsecp256k1_v0_10_0_testrand_int(255); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact(CTX, sig, &recid, &rsignature[4]) == 1); + sig[testrand_bits(6)] += 1 + testrand_int(255); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsignature[4], sig, recid) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert(CTX, &signature[4], &rsignature[4]) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[4], message, &pubkey) == 0); /* Recover again */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 0 || - rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) != 0); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &recpubkey, &rsignature[4], message) == 0 || + rustsecp256k1_v0_11_memcmp_var(&pubkey, &recpubkey, sizeof(pubkey)) != 0); } /* Tests several edge cases. */ @@ -170,7 +170,7 @@ static void test_ecdsa_recovery_edge_cases(void) { 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 }; - rustsecp256k1_v0_10_0_pubkey pubkey; + rustsecp256k1_v0_11_pubkey pubkey; /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ const unsigned char sigb64[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -182,19 +182,19 @@ static void test_ecdsa_recovery_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, }; - rustsecp256k1_v0_10_0_pubkey pubkeyb; - rustsecp256k1_v0_10_0_ecdsa_recoverable_signature rsig; - rustsecp256k1_v0_10_0_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pubkeyb; + rustsecp256k1_v0_11_ecdsa_recoverable_signature rsig; + rustsecp256k1_v0_11_ecdsa_signature sig; int recid; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 0)); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 1)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 2)); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 3)); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 0)); + CHECK(!rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 1)); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 2)); + CHECK(!rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sig64, 3)); + CHECK(!rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkey, &rsig, msg32)); for (recid = 0; recid < 4; recid++) { int i; @@ -239,40 +239,40 @@ static void test_ecdsa_recovery_edge_cases(void) { 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 }; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 1); for (recid2 = 0; recid2 < 4; recid2++) { - rustsecp256k1_v0_10_0_pubkey pubkey2b; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid2) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkey2b, &rsig, msg32) == 1); + rustsecp256k1_v0_11_pubkey pubkey2b; + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigb64, recid2) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkey2b, &rsig, msg32) == 1); /* Verifying with (order + r,4) should always fail. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderlong, sizeof(sigbderlong)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderlong, sizeof(sigbderlong)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); } /* DER parsing tests. */ /* Zero length r/s. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); /* Leading zeros. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); sigbderalt3[4] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); sigbderalt4[7] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); /* Damage signature. */ sigbder[7]++; - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); sigbder[7]--; - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, 6) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder) - 1) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbder, 6) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder) - 1) == 0); for(i = 0; i < 8; i++) { int c; unsigned char orig = sigbder[i]; @@ -282,7 +282,7 @@ static void test_ecdsa_recovery_edge_cases(void) { continue; } sigbder[i] = c; - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 0 || rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigbder, sizeof(sigbder)) == 0 || rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyb) == 0); } sigbder[i] = orig; } @@ -302,25 +302,25 @@ static void test_ecdsa_recovery_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; - rustsecp256k1_v0_10_0_pubkey pubkeyc; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkeyc, &rsig, msg32) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 1); + rustsecp256k1_v0_11_pubkey pubkeyc; + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkeyc, &rsig, msg32) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 1); sigcder[4] = 0; sigc64[31] = 0; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0); sigcder[4] = 1; sigcder[7] = 0; sigc64[31] = 1; sigc64[63] = 0; - CHECK(rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact(CTX, &rsig, sigc64, 0) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_recover(CTX, &pubkeyb, &rsig, msg32) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg32, &pubkeyc) == 0); } } diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/Makefile.am.include b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/Makefile.am.include index 77d9bcffa..829ccdf69 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/Makefile.am.include +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/Makefile.am.include @@ -1,4 +1,4 @@ -include_HEADERS += include/rustsecp256k1_v0_10_0_schnorrsig.h +include_HEADERS += include/rustsecp256k1_v0_11_schnorrsig.h noinst_HEADERS += src/modules/schnorrsig/main_impl.h noinst_HEADERS += src/modules/schnorrsig/tests_impl.h noinst_HEADERS += src/modules/schnorrsig/tests_exhaustive_impl.h diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/bench_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/bench_impl.h index 1140bb167..f37e24bc4 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/bench_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/bench_impl.h @@ -12,10 +12,10 @@ #define MSGLEN 32 typedef struct { - rustsecp256k1_v0_10_0_context *ctx; + rustsecp256k1_v0_11_context *ctx; int n; - const rustsecp256k1_v0_10_0_keypair **keypairs; + const rustsecp256k1_v0_11_keypair **keypairs; const unsigned char **pk; const unsigned char **sigs; const unsigned char **msgs; @@ -30,7 +30,7 @@ static void bench_schnorrsig_sign(void* arg, int iters) { for (i = 0; i < iters; i++) { msg[0] = i; msg[1] = i >> 8; - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(data->ctx, sig, msg, MSGLEN, data->keypairs[i], NULL)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(data->ctx, sig, msg, MSGLEN, data->keypairs[i], NULL)); } } @@ -39,9 +39,9 @@ static void bench_schnorrsig_verify(void* arg, int iters) { int i; for (i = 0; i < iters; i++) { - rustsecp256k1_v0_10_0_xonly_pubkey pk; - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], MSGLEN, &pk)); + rustsecp256k1_v0_11_xonly_pubkey pk; + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], MSGLEN, &pk)); } } @@ -50,8 +50,8 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) { bench_schnorrsig_data data; int d = argc == 1; - data.ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); - data.keypairs = (const rustsecp256k1_v0_10_0_keypair **)malloc(iters * sizeof(rustsecp256k1_v0_10_0_keypair *)); + data.ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); + data.keypairs = (const rustsecp256k1_v0_11_keypair **)malloc(iters * sizeof(rustsecp256k1_v0_11_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 *)); @@ -61,9 +61,9 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) { unsigned char sk[32]; unsigned char *msg = (unsigned char *)malloc(MSGLEN); unsigned char *sig = (unsigned char *)malloc(64); - rustsecp256k1_v0_10_0_keypair *keypair = (rustsecp256k1_v0_10_0_keypair *)malloc(sizeof(*keypair)); + rustsecp256k1_v0_11_keypair *keypair = (rustsecp256k1_v0_11_keypair *)malloc(sizeof(*keypair)); unsigned char *pk_char = (unsigned char *)malloc(32); - rustsecp256k1_v0_10_0_xonly_pubkey pk; + rustsecp256k1_v0_11_xonly_pubkey pk; msg[0] = sk[0] = i; msg[1] = sk[1] = i >> 8; msg[2] = sk[2] = i >> 16; @@ -76,10 +76,10 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) { data.msgs[i] = msg; data.sigs[i] = sig; - CHECK(rustsecp256k1_v0_10_0_keypair_create(data.ctx, keypair, sk)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(data.ctx, sig, msg, MSGLEN, keypair, NULL)); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(data.ctx, &pk, NULL, keypair)); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(data.ctx, keypair, sk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(data.ctx, sig, msg, MSGLEN, keypair, NULL)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(data.ctx, &pk, NULL, keypair)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); } if (d || have_flag(argc, argv, "schnorrsig") || have_flag(argc, argv, "sign") || have_flag(argc, argv, "schnorrsig_sign")) run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters); @@ -98,7 +98,7 @@ static void run_schnorrsig_bench(int iters, int argc, char** argv) { free((void *)data.msgs); free((void *)data.sigs); - rustsecp256k1_v0_10_0_context_destroy(data.ctx); + rustsecp256k1_v0_11_context_destroy(data.ctx); } #endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h index 9df11af32..0fee9b54d 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/main_impl.h @@ -13,8 +13,8 @@ /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ -static void rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged(rustsecp256k1_v0_10_0_sha256 *sha) { - rustsecp256k1_v0_10_0_sha256_initialize(sha); +static void rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_sha256_initialize(sha); sha->s[0] = 0x46615b35ul; sha->s[1] = 0xf4bfbff7ul; sha->s[2] = 0x9f8dc671ul; @@ -29,8 +29,8 @@ static void rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged(rustsecp25 /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ -static void rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged_aux(rustsecp256k1_v0_10_0_sha256 *sha) { - rustsecp256k1_v0_10_0_sha256_initialize(sha); +static void rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged_aux(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_sha256_initialize(sha); sha->s[0] = 0x24dd3219ul; sha->s[1] = 0x4eba7e70ul; sha->s[2] = 0xca0fabb9ul; @@ -45,12 +45,12 @@ static void rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged_aux(rustse /* 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; 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) { - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; unsigned char masked_key[32]; int i; @@ -59,9 +59,9 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms } if (data != NULL) { - rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged_aux(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, data, 32); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, masked_key); + rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged_aux(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, data, 32); + rustsecp256k1_v0_11_sha256_finalize(&sha, masked_key); for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; } @@ -82,26 +82,27 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms * algorithms. If this nonce function is used in BIP-340 signing as defined * in the spec, an optimized tagging implementation is used. */ if (algolen == sizeof(bip340_algo) - && rustsecp256k1_v0_10_0_memcmp_var(algo, bip340_algo, algolen) == 0) { - rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged(&sha); + && rustsecp256k1_v0_11_memcmp_var(algo, bip340_algo, algolen) == 0) { + rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged(&sha); } else { - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, algo, algolen); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, algo, algolen); } /* Hash masked-key||pk||msg using the tagged hash as per the spec */ - rustsecp256k1_v0_10_0_sha256_write(&sha, masked_key, 32); - rustsecp256k1_v0_10_0_sha256_write(&sha, xonly_pk32, 32); - rustsecp256k1_v0_10_0_sha256_write(&sha, msg, msglen); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, nonce32); + rustsecp256k1_v0_11_sha256_write(&sha, masked_key, 32); + rustsecp256k1_v0_11_sha256_write(&sha, xonly_pk32, 32); + rustsecp256k1_v0_11_sha256_write(&sha, msg, msglen); + rustsecp256k1_v0_11_sha256_finalize(&sha, nonce32); + rustsecp256k1_v0_11_sha256_clear(&sha); return 1; } -const rustsecp256k1_v0_10_0_nonce_function_hardened rustsecp256k1_v0_10_0_nonce_function_bip340 = nonce_function_bip340; +const rustsecp256k1_v0_11_nonce_function_hardened rustsecp256k1_v0_11_nonce_function_bip340 = nonce_function_bip340; /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ -static void rustsecp256k1_v0_10_0_schnorrsig_sha256_tagged(rustsecp256k1_v0_10_0_sha256 *sha) { - rustsecp256k1_v0_10_0_sha256_initialize(sha); +static void rustsecp256k1_v0_11_schnorrsig_sha256_tagged(rustsecp256k1_v0_11_sha256 *sha) { + rustsecp256k1_v0_11_sha256_initialize(sha); sha->s[0] = 0x9cecba11ul; sha->s[1] = 0x23925381ul; sha->s[2] = 0x11679112ul; @@ -113,117 +114,118 @@ static void rustsecp256k1_v0_10_0_schnorrsig_sha256_tagged(rustsecp256k1_v0_10_0 sha->bytes = 64; } -static void rustsecp256k1_v0_10_0_schnorrsig_challenge(rustsecp256k1_v0_10_0_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) +static void rustsecp256k1_v0_11_schnorrsig_challenge(rustsecp256k1_v0_11_scalar* e, const unsigned char *r32, const unsigned char *msg, size_t msglen, const unsigned char *pubkey32) { unsigned char buf[32]; - rustsecp256k1_v0_10_0_sha256 sha; + rustsecp256k1_v0_11_sha256 sha; /* tagged hash(r.x, pk.x, msg) */ - rustsecp256k1_v0_10_0_schnorrsig_sha256_tagged(&sha); - rustsecp256k1_v0_10_0_sha256_write(&sha, r32, 32); - rustsecp256k1_v0_10_0_sha256_write(&sha, pubkey32, 32); - rustsecp256k1_v0_10_0_sha256_write(&sha, msg, msglen); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, buf); + rustsecp256k1_v0_11_schnorrsig_sha256_tagged(&sha); + rustsecp256k1_v0_11_sha256_write(&sha, r32, 32); + rustsecp256k1_v0_11_sha256_write(&sha, pubkey32, 32); + rustsecp256k1_v0_11_sha256_write(&sha, msg, msglen); + rustsecp256k1_v0_11_sha256_finalize(&sha, buf); /* Set scalar e to the challenge hash modulo the curve order as per * BIP340. */ - rustsecp256k1_v0_10_0_scalar_set_b32(e, buf, NULL); + rustsecp256k1_v0_11_scalar_set_b32(e, buf, NULL); } -static int rustsecp256k1_v0_10_0_schnorrsig_sign_internal(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const rustsecp256k1_v0_10_0_keypair *keypair, rustsecp256k1_v0_10_0_nonce_function_hardened noncefp, void *ndata) { - rustsecp256k1_v0_10_0_scalar sk; - rustsecp256k1_v0_10_0_scalar e; - rustsecp256k1_v0_10_0_scalar k; - rustsecp256k1_v0_10_0_gej rj; - rustsecp256k1_v0_10_0_ge pk; - rustsecp256k1_v0_10_0_ge r; +static int rustsecp256k1_v0_11_schnorrsig_sign_internal(const rustsecp256k1_v0_11_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const rustsecp256k1_v0_11_keypair *keypair, rustsecp256k1_v0_11_nonce_function_hardened noncefp, void *ndata) { + rustsecp256k1_v0_11_scalar sk; + rustsecp256k1_v0_11_scalar e; + rustsecp256k1_v0_11_scalar k; + rustsecp256k1_v0_11_gej rj; + rustsecp256k1_v0_11_ge pk; + rustsecp256k1_v0_11_ge r; unsigned char buf[32] = { 0 }; unsigned char pk_buf[32]; unsigned char seckey[32]; int ret = 1; VERIFY_CHECK(ctx != NULL); - ARG_CHECK(rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(sig64 != NULL); ARG_CHECK(msg != NULL || msglen == 0); ARG_CHECK(keypair != NULL); if (noncefp == NULL) { - noncefp = rustsecp256k1_v0_10_0_nonce_function_bip340; + noncefp = rustsecp256k1_v0_11_nonce_function_bip340; } - ret &= rustsecp256k1_v0_10_0_keypair_load(ctx, &sk, &pk, keypair); + ret &= rustsecp256k1_v0_11_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 * have an even Y. */ - if (rustsecp256k1_v0_10_0_fe_is_odd(&pk.y)) { - rustsecp256k1_v0_10_0_scalar_negate(&sk, &sk); + if (rustsecp256k1_v0_11_fe_is_odd(&pk.y)) { + rustsecp256k1_v0_11_scalar_negate(&sk, &sk); } - rustsecp256k1_v0_10_0_scalar_get_b32(seckey, &sk); - rustsecp256k1_v0_10_0_fe_get_b32(pk_buf, &pk.x); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sk); + rustsecp256k1_v0_11_fe_get_b32(pk_buf, &pk.x); ret &= !!noncefp(buf, msg, msglen, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata); - rustsecp256k1_v0_10_0_scalar_set_b32(&k, buf, NULL); - ret &= !rustsecp256k1_v0_10_0_scalar_is_zero(&k); - rustsecp256k1_v0_10_0_scalar_cmov(&k, &rustsecp256k1_v0_10_0_scalar_one, !ret); + rustsecp256k1_v0_11_scalar_set_b32(&k, buf, NULL); + ret &= !rustsecp256k1_v0_11_scalar_is_zero(&k); + rustsecp256k1_v0_11_scalar_cmov(&k, &rustsecp256k1_v0_11_scalar_one, !ret); - rustsecp256k1_v0_10_0_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); - rustsecp256k1_v0_10_0_ge_set_gej(&r, &rj); + rustsecp256k1_v0_11_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); + rustsecp256k1_v0_11_ge_set_gej(&r, &rj); /* We declassify r to allow using it as a branch point. This is fine * because r is not a secret. */ - rustsecp256k1_v0_10_0_declassify(ctx, &r, sizeof(r)); - rustsecp256k1_v0_10_0_fe_normalize_var(&r.y); - if (rustsecp256k1_v0_10_0_fe_is_odd(&r.y)) { - rustsecp256k1_v0_10_0_scalar_negate(&k, &k); + rustsecp256k1_v0_11_declassify(ctx, &r, sizeof(r)); + rustsecp256k1_v0_11_fe_normalize_var(&r.y); + if (rustsecp256k1_v0_11_fe_is_odd(&r.y)) { + rustsecp256k1_v0_11_scalar_negate(&k, &k); } - rustsecp256k1_v0_10_0_fe_normalize_var(&r.x); - rustsecp256k1_v0_10_0_fe_get_b32(&sig64[0], &r.x); + rustsecp256k1_v0_11_fe_normalize_var(&r.x); + rustsecp256k1_v0_11_fe_get_b32(&sig64[0], &r.x); - rustsecp256k1_v0_10_0_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf); - rustsecp256k1_v0_10_0_scalar_mul(&e, &e, &sk); - rustsecp256k1_v0_10_0_scalar_add(&e, &e, &k); - rustsecp256k1_v0_10_0_scalar_get_b32(&sig64[32], &e); + rustsecp256k1_v0_11_schnorrsig_challenge(&e, &sig64[0], msg, msglen, pk_buf); + rustsecp256k1_v0_11_scalar_mul(&e, &e, &sk); + rustsecp256k1_v0_11_scalar_add(&e, &e, &k); + rustsecp256k1_v0_11_scalar_get_b32(&sig64[32], &e); - rustsecp256k1_v0_10_0_memczero(sig64, 64, !ret); - rustsecp256k1_v0_10_0_scalar_clear(&k); - rustsecp256k1_v0_10_0_scalar_clear(&sk); - memset(seckey, 0, sizeof(seckey)); + rustsecp256k1_v0_11_memczero(sig64, 64, !ret); + rustsecp256k1_v0_11_scalar_clear(&k); + rustsecp256k1_v0_11_scalar_clear(&sk); + rustsecp256k1_v0_11_memclear(seckey, sizeof(seckey)); + rustsecp256k1_v0_11_gej_clear(&rj); return ret; } -int rustsecp256k1_v0_10_0_schnorrsig_sign32(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *sig64, const unsigned char *msg32, const rustsecp256k1_v0_10_0_keypair *keypair, const unsigned char *aux_rand32) { +int rustsecp256k1_v0_11_schnorrsig_sign32(const rustsecp256k1_v0_11_context* ctx, unsigned char *sig64, const unsigned char *msg32, const rustsecp256k1_v0_11_keypair *keypair, const unsigned char *aux_rand32) { /* We cast away const from the passed aux_rand32 argument since we know the default nonce function does not modify it. */ - return rustsecp256k1_v0_10_0_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, rustsecp256k1_v0_10_0_nonce_function_bip340, (unsigned char*)aux_rand32); + return rustsecp256k1_v0_11_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, rustsecp256k1_v0_11_nonce_function_bip340, (unsigned char*)aux_rand32); } -int rustsecp256k1_v0_10_0_schnorrsig_sign(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *sig64, const unsigned char *msg32, const rustsecp256k1_v0_10_0_keypair *keypair, const unsigned char *aux_rand32) { - return rustsecp256k1_v0_10_0_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32); +int rustsecp256k1_v0_11_schnorrsig_sign(const rustsecp256k1_v0_11_context* ctx, unsigned char *sig64, const unsigned char *msg32, const rustsecp256k1_v0_11_keypair *keypair, const unsigned char *aux_rand32) { + return rustsecp256k1_v0_11_schnorrsig_sign32(ctx, sig64, msg32, keypair, aux_rand32); } -int rustsecp256k1_v0_10_0_schnorrsig_sign_custom(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const rustsecp256k1_v0_10_0_keypair *keypair, rustsecp256k1_v0_10_0_schnorrsig_extraparams *extraparams) { - rustsecp256k1_v0_10_0_nonce_function_hardened noncefp = NULL; +int rustsecp256k1_v0_11_schnorrsig_sign_custom(const rustsecp256k1_v0_11_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const rustsecp256k1_v0_11_keypair *keypair, rustsecp256k1_v0_11_schnorrsig_extraparams *extraparams) { + rustsecp256k1_v0_11_nonce_function_hardened noncefp = NULL; void *ndata = NULL; VERIFY_CHECK(ctx != NULL); if (extraparams != NULL) { - ARG_CHECK(rustsecp256k1_v0_10_0_memcmp_var(extraparams->magic, + ARG_CHECK(rustsecp256k1_v0_11_memcmp_var(extraparams->magic, schnorrsig_extraparams_magic, sizeof(extraparams->magic)) == 0); noncefp = extraparams->noncefp; ndata = extraparams->ndata; } - return rustsecp256k1_v0_10_0_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata); + return rustsecp256k1_v0_11_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata); } -int rustsecp256k1_v0_10_0_schnorrsig_verify(const rustsecp256k1_v0_10_0_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const rustsecp256k1_v0_10_0_xonly_pubkey *pubkey) { - rustsecp256k1_v0_10_0_scalar s; - rustsecp256k1_v0_10_0_scalar e; - rustsecp256k1_v0_10_0_gej rj; - rustsecp256k1_v0_10_0_ge pk; - rustsecp256k1_v0_10_0_gej pkj; - rustsecp256k1_v0_10_0_fe rx; - rustsecp256k1_v0_10_0_ge r; +int rustsecp256k1_v0_11_schnorrsig_verify(const rustsecp256k1_v0_11_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const rustsecp256k1_v0_11_xonly_pubkey *pubkey) { + rustsecp256k1_v0_11_scalar s; + rustsecp256k1_v0_11_scalar e; + rustsecp256k1_v0_11_gej rj; + rustsecp256k1_v0_11_ge pk; + rustsecp256k1_v0_11_gej pkj; + rustsecp256k1_v0_11_fe rx; + rustsecp256k1_v0_11_ge r; unsigned char buf[32]; int overflow; @@ -232,36 +234,36 @@ int rustsecp256k1_v0_10_0_schnorrsig_verify(const rustsecp256k1_v0_10_0_context* ARG_CHECK(msg != NULL || msglen == 0); ARG_CHECK(pubkey != NULL); - if (!rustsecp256k1_v0_10_0_fe_set_b32_limit(&rx, &sig64[0])) { + if (!rustsecp256k1_v0_11_fe_set_b32_limit(&rx, &sig64[0])) { return 0; } - rustsecp256k1_v0_10_0_scalar_set_b32(&s, &sig64[32], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&s, &sig64[32], &overflow); if (overflow) { return 0; } - if (!rustsecp256k1_v0_10_0_xonly_pubkey_load(ctx, &pk, pubkey)) { + if (!rustsecp256k1_v0_11_xonly_pubkey_load(ctx, &pk, pubkey)) { return 0; } /* Compute e. */ - rustsecp256k1_v0_10_0_fe_get_b32(buf, &pk.x); - rustsecp256k1_v0_10_0_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf); + rustsecp256k1_v0_11_fe_get_b32(buf, &pk.x); + rustsecp256k1_v0_11_schnorrsig_challenge(&e, &sig64[0], msg, msglen, buf); /* Compute rj = s*G + (-e)*pkj */ - rustsecp256k1_v0_10_0_scalar_negate(&e, &e); - rustsecp256k1_v0_10_0_gej_set_ge(&pkj, &pk); - rustsecp256k1_v0_10_0_ecmult(&rj, &pkj, &e, &s); + rustsecp256k1_v0_11_scalar_negate(&e, &e); + rustsecp256k1_v0_11_gej_set_ge(&pkj, &pk); + rustsecp256k1_v0_11_ecmult(&rj, &pkj, &e, &s); - rustsecp256k1_v0_10_0_ge_set_gej_var(&r, &rj); - if (rustsecp256k1_v0_10_0_ge_is_infinity(&r)) { + rustsecp256k1_v0_11_ge_set_gej_var(&r, &rj); + if (rustsecp256k1_v0_11_ge_is_infinity(&r)) { return 0; } - rustsecp256k1_v0_10_0_fe_normalize_var(&r.y); - return !rustsecp256k1_v0_10_0_fe_is_odd(&r.y) && - rustsecp256k1_v0_10_0_fe_equal(&rx, &r.x); + rustsecp256k1_v0_11_fe_normalize_var(&r.y); + return !rustsecp256k1_v0_11_fe_is_odd(&r.y) && + rustsecp256k1_v0_11_fe_equal(&rx, &r.x); } #endif diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h index 6906786e9..b8a4a90e7 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -58,12 +58,12 @@ static const unsigned char invalid_pubkey_bytes[][32] = { #define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) -static int rustsecp256k1_v0_10_0_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg, +static int rustsecp256k1_v0_11_hardened_nonce_function_smallint(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) { - rustsecp256k1_v0_10_0_scalar s; + rustsecp256k1_v0_11_scalar s; int *idata = data; (void)msg; (void)msglen; @@ -71,12 +71,12 @@ static int rustsecp256k1_v0_10_0_hardened_nonce_function_smallint(unsigned char (void)xonly_pk32; (void)algo; (void)algolen; - rustsecp256k1_v0_10_0_scalar_set_int(&s, *idata); - rustsecp256k1_v0_10_0_scalar_get_b32(nonce32, &s); + rustsecp256k1_v0_11_scalar_set_int(&s, *idata); + rustsecp256k1_v0_11_scalar_get_b32(nonce32, &s); return 1; } -static void test_exhaustive_schnorrsig_verify(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_xonly_pubkey* pubkeys, unsigned char (*xonly_pubkey_bytes)[32], const int* parities) { +static void test_exhaustive_schnorrsig_verify(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_xonly_pubkey* pubkeys, unsigned char (*xonly_pubkey_bytes)[32], const int* parities) { int d; uint64_t iter = 0; /* Iterate over the possible public keys to verify against (through their corresponding DL d). */ @@ -102,10 +102,10 @@ static void test_exhaustive_schnorrsig_verify(const rustsecp256k1_v0_10_0_contex } /* Randomly generate messages until all challenges have been hit. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { - rustsecp256k1_v0_10_0_scalar e; + rustsecp256k1_v0_11_scalar e; unsigned char msg32[32]; - rustsecp256k1_v0_10_0_testrand256(msg32); - rustsecp256k1_v0_10_0_schnorrsig_challenge(&e, sig64, msg32, sizeof(msg32), pk32); + testrand256(msg32); + rustsecp256k1_v0_11_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]) { /* Iterate over the possible valid last 32 bytes in the signature. @@ -116,14 +116,14 @@ static void test_exhaustive_schnorrsig_verify(const rustsecp256k1_v0_10_0_contex int expect_valid, valid; if (s <= EXHAUSTIVE_TEST_ORDER) { memset(sig64 + 32, 0, 32); - rustsecp256k1_v0_10_0_write_be32(sig64 + 60, s); + rustsecp256k1_v0_11_write_be32(sig64 + 60, s); expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && (s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); } else { - rustsecp256k1_v0_10_0_testrand256(sig64 + 32); + testrand256(sig64 + 32); expect_valid = 0; } - valid = rustsecp256k1_v0_10_0_schnorrsig_verify(ctx, sig64, msg32, sizeof(msg32), &pubkeys[d - 1]); + valid = rustsecp256k1_v0_11_schnorrsig_verify(ctx, sig64, msg32, sizeof(msg32), &pubkeys[d - 1]); CHECK(valid == expect_valid); count_valid += valid; } @@ -138,10 +138,10 @@ static void test_exhaustive_schnorrsig_verify(const rustsecp256k1_v0_10_0_contex } } -static void test_exhaustive_schnorrsig_sign(const rustsecp256k1_v0_10_0_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const rustsecp256k1_v0_10_0_keypair* keypairs, const int* parities) { +static void test_exhaustive_schnorrsig_sign(const rustsecp256k1_v0_11_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const rustsecp256k1_v0_11_keypair* keypairs, const int* parities) { int d, k; uint64_t iter = 0; - rustsecp256k1_v0_10_0_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; + rustsecp256k1_v0_11_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; /* Loop over keys. */ for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) { @@ -155,25 +155,25 @@ static void test_exhaustive_schnorrsig_sign(const rustsecp256k1_v0_10_0_context unsigned char sig64[64]; int actual_k = k; if (skip_section(&iter)) continue; - extraparams.noncefp = rustsecp256k1_v0_10_0_hardened_nonce_function_smallint; + extraparams.noncefp = rustsecp256k1_v0_11_hardened_nonce_function_smallint; extraparams.ndata = &k; if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k; /* Generate random messages until all challenges have been tried. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { - rustsecp256k1_v0_10_0_scalar e; - rustsecp256k1_v0_10_0_testrand256(msg32); - rustsecp256k1_v0_10_0_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, sizeof(msg32), xonly_pubkey_bytes[d - 1]); + rustsecp256k1_v0_11_scalar e; + testrand256(msg32); + rustsecp256k1_v0_11_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]) { - rustsecp256k1_v0_10_0_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; + rustsecp256k1_v0_11_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; unsigned char expected_s_bytes[32]; - rustsecp256k1_v0_10_0_scalar_get_b32(expected_s_bytes, &expected_s); + rustsecp256k1_v0_11_scalar_get_b32(expected_s_bytes, &expected_s); /* Invoke the real function to construct a signature. */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], &extraparams)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], &extraparams)); /* The first 32 bytes must match the xonly pubkey for the specified k. */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); /* The last 32 bytes must match the expected s value. */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0); /* Don't retry other messages that result in the same challenge. */ e_done[e] = 1; ++e_count_done; @@ -183,28 +183,28 @@ static void test_exhaustive_schnorrsig_sign(const rustsecp256k1_v0_10_0_context } } -static void test_exhaustive_schnorrsig(const rustsecp256k1_v0_10_0_context *ctx) { - rustsecp256k1_v0_10_0_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; - rustsecp256k1_v0_10_0_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; +static void test_exhaustive_schnorrsig(const rustsecp256k1_v0_11_context *ctx) { + rustsecp256k1_v0_11_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; + rustsecp256k1_v0_11_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; int parity[EXHAUSTIVE_TEST_ORDER - 1]; unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; unsigned i; /* Verify that all invalid_pubkey_bytes are actually invalid. */ for (i = 0; i < NUM_INVALID_KEYS; ++i) { - rustsecp256k1_v0_10_0_xonly_pubkey pk; - CHECK(!rustsecp256k1_v0_10_0_xonly_pubkey_parse(ctx, &pk, invalid_pubkey_bytes[i])); + rustsecp256k1_v0_11_xonly_pubkey pk; + CHECK(!rustsecp256k1_v0_11_xonly_pubkey_parse(ctx, &pk, invalid_pubkey_bytes[i])); } /* Construct keypairs and xonly-pubkeys for the entire group. */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; ++i) { - rustsecp256k1_v0_10_0_scalar scalar_i; + rustsecp256k1_v0_11_scalar scalar_i; unsigned char buf[32]; - rustsecp256k1_v0_10_0_scalar_set_int(&scalar_i, i); - rustsecp256k1_v0_10_0_scalar_get_b32(buf, &scalar_i); - CHECK(rustsecp256k1_v0_10_0_keypair_create(ctx, &keypair[i - 1], buf)); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1])); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); + rustsecp256k1_v0_11_scalar_set_int(&scalar_i, i); + rustsecp256k1_v0_11_scalar_get_b32(buf, &scalar_i); + CHECK(rustsecp256k1_v0_11_keypair_create(ctx, &keypair[i - 1], buf)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1])); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); } test_exhaustive_schnorrsig_sign(ctx, xonly_pubkey_bytes, keypair, parity); diff --git a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h index e29a1dfd4..ff40eff5f 100644 --- a/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/modules/schnorrsig/tests_impl.h @@ -15,18 +15,18 @@ 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); - rustsecp256k1_v0_10_0_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(rustsecp256k1_v0_10_0_memcmp_var(nonces[0], nonces[1], 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonces[0], nonces[1], 32) != 0); } 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); - rustsecp256k1_v0_10_0_sha256 sha; - rustsecp256k1_v0_10_0_sha256 sha_optimized; + rustsecp256k1_v0_11_sha256 sha; + rustsecp256k1_v0_11_sha256 sha_optimized; unsigned char nonce[32], nonce_z[32]; unsigned char msg[32]; size_t msglen = sizeof(msg); @@ -37,23 +37,23 @@ static void run_nonce_function_bip340_tests(void) { int i; /* Check that hash initialized by - * rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged has the expected + * rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged has the expected * state. */ - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, tag, sizeof(tag)); - rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged(&sha_optimized); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, tag, sizeof(tag)); + rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); /* Check that hash initialized by - * rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged_aux has the expected + * rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged_aux has the expected * state. */ - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); - rustsecp256k1_v0_10_0_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); + rustsecp256k1_v0_11_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); - rustsecp256k1_v0_10_0_testrand256(msg); - rustsecp256k1_v0_10_0_testrand256(key); - rustsecp256k1_v0_10_0_testrand256(pk); - rustsecp256k1_v0_10_0_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,31 +76,31 @@ 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 */ - rustsecp256k1_v0_10_0_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 = rustsecp256k1_v0_10_0_testrand_int(msglen - 1); + uint32_t offset = testrand_int(msglen - 1); size_t msglen_tmp = (msglen + offset) % msglen; size_t algolen_tmp; /* Different msglen gives different nonce */ CHECK(nonce_function_bip340(nonce2, msg, msglen_tmp, key, pk, algo, algolen, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce, nonce2, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce, nonce2, 32) != 0); /* Different algolen gives different nonce */ - offset = rustsecp256k1_v0_10_0_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(rustsecp256k1_v0_10_0_memcmp_var(nonce, nonce2, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce, nonce2, 32) != 0); } /* NULL aux_rand argument is allowed, and identical to passing all zero aux_rand. */ memset(aux_rand, 0, 32); CHECK(nonce_function_bip340(nonce_z, msg, msglen, key, pk, algo, algolen, &aux_rand) == 1); CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce_z, nonce, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce_z, nonce, 32) == 0); } static void test_schnorrsig_api(void) { @@ -108,62 +108,62 @@ static void test_schnorrsig_api(void) { unsigned char sk2[32]; unsigned char sk3[32]; unsigned char msg[32]; - rustsecp256k1_v0_10_0_keypair keypairs[3]; - rustsecp256k1_v0_10_0_keypair invalid_keypair = {{ 0 }}; - rustsecp256k1_v0_10_0_xonly_pubkey pk[3]; - rustsecp256k1_v0_10_0_xonly_pubkey zero_pk; + rustsecp256k1_v0_11_keypair keypairs[3]; + rustsecp256k1_v0_11_keypair invalid_keypair = {{ 0 }}; + rustsecp256k1_v0_11_xonly_pubkey pk[3]; + rustsecp256k1_v0_11_xonly_pubkey zero_pk; unsigned char sig[64]; - rustsecp256k1_v0_10_0_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; - rustsecp256k1_v0_10_0_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL}; - - rustsecp256k1_v0_10_0_testrand256(sk1); - rustsecp256k1_v0_10_0_testrand256(sk2); - rustsecp256k1_v0_10_0_testrand256(sk3); - rustsecp256k1_v0_10_0_testrand256(msg); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypairs[0], sk1) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypairs[1], sk2) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypairs[2], sk3) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &pk[0], NULL, &keypairs[0]) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &pk[1], NULL, &keypairs[1]) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &pk[2], NULL, &keypairs[2]) == 1); + rustsecp256k1_v0_11_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; + rustsecp256k1_v0_11_schnorrsig_extraparams invalid_extraparams = {{ 0 }, NULL, NULL}; + + testrand256(sk1); + testrand256(sk2); + testrand256(sk3); + testrand256(msg); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypairs[0], sk1) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypairs[1], sk2) == 1); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypairs[2], sk3) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &pk[0], NULL, &keypairs[0]) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &pk[1], NULL, &keypairs[1]) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &pk[2], NULL, &keypairs[2]) == 1); memset(&zero_pk, 0, sizeof(zero_pk)); /** main test body **/ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, &keypairs[0], NULL) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, NULL, msg, &keypairs[0], NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, NULL, &keypairs[0], NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, NULL, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, &invalid_keypair, NULL)); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_schnorrsig_sign32(STATIC_CTX, sig, msg, &keypairs[0], NULL)); - - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, NULL, msg, sizeof(msg), &keypairs[0], &extraparams)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, NULL, sizeof(msg), &keypairs[0], &extraparams)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, NULL, 0, &keypairs[0], &extraparams) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), NULL, &extraparams)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &invalid_keypair, &extraparams)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams)); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_schnorrsig_sign_custom(STATIC_CTX, sig, msg, sizeof(msg), &keypairs[0], &extraparams)); - - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, &keypairs[0], NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk[0]) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, NULL, msg, sizeof(msg), &pk[0])); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, NULL, sizeof(msg), &pk[0])); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, NULL, 0, &pk[0]) == 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &zero_pk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, &keypairs[0], NULL) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign32(CTX, NULL, msg, &keypairs[0], NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, NULL, &keypairs[0], NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, NULL, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, &invalid_keypair, NULL)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_schnorrsig_sign32(STATIC_CTX, sig, msg, &keypairs[0], NULL)); + + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], &extraparams) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, NULL, msg, sizeof(msg), &keypairs[0], &extraparams)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, NULL, sizeof(msg), &keypairs[0], &extraparams)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, NULL, 0, &keypairs[0], &extraparams) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), NULL, &extraparams)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &invalid_keypair, &extraparams)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], NULL) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypairs[0], &invalid_extraparams)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_schnorrsig_sign_custom(STATIC_CTX, sig, msg, sizeof(msg), &keypairs[0], &extraparams)); + + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, &keypairs[0], NULL) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk[0]) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_verify(CTX, NULL, msg, sizeof(msg), &pk[0])); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, NULL, sizeof(msg), &pk[0])); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, NULL, 0, &pk[0]) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &zero_pk)); } -/* Checks that hash initialized by rustsecp256k1_v0_10_0_schnorrsig_sha256_tagged has the +/* Checks that hash initialized by rustsecp256k1_v0_11_schnorrsig_sha256_tagged has the * expected state. */ static void test_schnorrsig_sha256_tagged(void) { - unsigned char tag[17] = "BIP0340/challenge"; - rustsecp256k1_v0_10_0_sha256 sha; - rustsecp256k1_v0_10_0_sha256 sha_optimized; + unsigned char tag[] = {'B', 'I', 'P', '0', '3', '4', '0', '/', 'c', 'h', 'a', 'l', 'l', 'e', 'n', 'g', 'e'}; + rustsecp256k1_v0_11_sha256 sha; + rustsecp256k1_v0_11_sha256 sha_optimized; - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); - rustsecp256k1_v0_10_0_schnorrsig_sha256_tagged(&sha_optimized); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); + rustsecp256k1_v0_11_schnorrsig_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); } @@ -171,34 +171,34 @@ static void test_schnorrsig_sha256_tagged(void) { * Signs the message and checks that it's the same as expected_sig. */ static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg, size_t msglen, const unsigned char *expected_sig) { unsigned char sig[64]; - rustsecp256k1_v0_10_0_keypair keypair; - rustsecp256k1_v0_10_0_xonly_pubkey pk, pk_expected; + rustsecp256k1_v0_11_keypair keypair; + rustsecp256k1_v0_11_xonly_pubkey pk, pk_expected; - rustsecp256k1_v0_10_0_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; + rustsecp256k1_v0_11_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; extraparams.ndata = (unsigned char*)aux_rand; - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, msglen, &keypair, &extraparams)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig, expected_sig, 64) == 0); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, msglen, &keypair, &extraparams)); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig, expected_sig, 64) == 0); if (msglen == 32) { memset(sig, 0, 64); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, &keypair, aux_rand)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig, expected_sig, 64) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, &keypair, aux_rand)); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig, expected_sig, 64) == 0); } - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &pk_expected, pk_serialized)); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, msglen, &pk)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &pk_expected, pk_serialized)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, msglen, &pk)); } /* Helper function for schnorrsig_bip_vectors * Checks that both verify and verify_batch (TODO) return the same value as expected. */ static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg, size_t msglen, const unsigned char *sig, int expected) { - rustsecp256k1_v0_10_0_xonly_pubkey pk; + rustsecp256k1_v0_11_xonly_pubkey pk; - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &pk, pk_serialized)); - CHECK(expected == rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, msglen, &pk)); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &pk, pk_serialized)); + CHECK(expected == rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, msglen, &pk)); } /* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See @@ -394,9 +394,9 @@ static void test_schnorrsig_bip_vectors(void) { 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87, 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34 }; - rustsecp256k1_v0_10_0_xonly_pubkey pk_parsed; + rustsecp256k1_v0_11_xonly_pubkey pk_parsed; /* No need to check the signature of the test vector as parsing the pubkey already fails */ - CHECK(!rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &pk_parsed, pk)); + CHECK(!rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &pk_parsed, pk)); } { /* Test vector 6 */ @@ -614,9 +614,9 @@ static void test_schnorrsig_bip_vectors(void) { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 }; - rustsecp256k1_v0_10_0_xonly_pubkey pk_parsed; + rustsecp256k1_v0_11_xonly_pubkey pk_parsed; /* No need to check the signature of the test vector as parsing the pubkey already fails */ - CHECK(!rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &pk_parsed, pk)); + CHECK(!rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &pk_parsed, pk)); } { /* Test vector 15 */ @@ -804,48 +804,48 @@ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned cha static void test_schnorrsig_sign(void) { unsigned char sk[32]; - rustsecp256k1_v0_10_0_xonly_pubkey pk; - rustsecp256k1_v0_10_0_keypair keypair; - const unsigned char msg[32] = "this is a msg for a schnorrsig.."; + rustsecp256k1_v0_11_xonly_pubkey pk; + rustsecp256k1_v0_11_keypair keypair; + 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 }; - rustsecp256k1_v0_10_0_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; + rustsecp256k1_v0_11_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; unsigned char aux_rand[32]; - rustsecp256k1_v0_10_0_testrand256(sk); - rustsecp256k1_v0_10_0_testrand256(aux_rand); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk)); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); + testrand256(sk); + testrand256(aux_rand); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); /* Check that deprecated alias gives the same result */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign(CTX, sig2, msg, &keypair, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig, sig2, sizeof(sig)) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign(CTX, sig2, msg, &keypair, NULL) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig, sig2, sizeof(sig)) == 0); /* Test different nonce functions */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); memset(sig, 1, sizeof(sig)); extraparams.noncefp = nonce_function_failing; - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig, zeros64, sizeof(sig)) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig, zeros64, sizeof(sig)) == 0); memset(&sig, 1, sizeof(sig)); extraparams.noncefp = nonce_function_0; - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig, zeros64, sizeof(sig)) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig, zeros64, sizeof(sig)) == 0); memset(&sig, 1, sizeof(sig)); extraparams.noncefp = nonce_function_overflowing; - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk)); /* When using the default nonce function, schnorrsig_sign_custom produces * the same result as schnorrsig_sign with aux_rand = extraparams.ndata */ extraparams.noncefp = NULL; extraparams.ndata = aux_rand; - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig2, msg, &keypair, extraparams.ndata) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sig, sig2, sizeof(sig)) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig2, msg, &keypair, extraparams.ndata) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(sig, sig2, sizeof(sig)) == 0); } #define N_SIGS 3 @@ -857,84 +857,84 @@ static void test_schnorrsig_sign_verify(void) { unsigned char msg[N_SIGS][32]; unsigned char sig[N_SIGS][64]; size_t i; - rustsecp256k1_v0_10_0_keypair keypair; - rustsecp256k1_v0_10_0_xonly_pubkey pk; - rustsecp256k1_v0_10_0_scalar s; + rustsecp256k1_v0_11_keypair keypair; + rustsecp256k1_v0_11_xonly_pubkey pk; + rustsecp256k1_v0_11_scalar s; - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk)); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk)); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &pk, NULL, &keypair)); for (i = 0; i < N_SIGS; i++) { - rustsecp256k1_v0_10_0_testrand256(msg[i]); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig[i], msg[i], &keypair, NULL)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[i], msg[i], sizeof(msg[i]), &pk)); + testrand256(msg[i]); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig[i], msg[i], &keypair, NULL)); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[i], msg[i], sizeof(msg[i]), &pk)); } { /* Flip a few bits in the signature and in the message and check that * verify and verify_batch (TODO) fail */ - size_t sig_idx = rustsecp256k1_v0_10_0_testrand_int(N_SIGS); - size_t byte_idx = rustsecp256k1_v0_10_0_testrand_bits(5); - unsigned char xorbyte = rustsecp256k1_v0_10_0_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(!rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); + CHECK(!rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); sig[sig_idx][byte_idx] ^= xorbyte; - byte_idx = rustsecp256k1_v0_10_0_testrand_bits(5); + byte_idx = testrand_bits(5); sig[sig_idx][32+byte_idx] ^= xorbyte; - CHECK(!rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); + CHECK(!rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); sig[sig_idx][32+byte_idx] ^= xorbyte; - byte_idx = rustsecp256k1_v0_10_0_testrand_bits(5); + byte_idx = testrand_bits(5); msg[sig_idx][byte_idx] ^= xorbyte; - CHECK(!rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); + CHECK(!rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); msg[sig_idx][byte_idx] ^= xorbyte; /* Check that above bitflips have been reversed correctly */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[sig_idx], msg[sig_idx], sizeof(msg[sig_idx]), &pk)); } /* Test overflowing s */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig[0], msg[0], &keypair, NULL)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig[0], msg[0], &keypair, NULL)); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); memset(&sig[0][32], 0xFF, 32); - CHECK(!rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); + CHECK(!rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); /* Test negative s */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig[0], msg[0], &keypair, NULL)); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); - rustsecp256k1_v0_10_0_scalar_set_b32(&s, &sig[0][32], NULL); - rustsecp256k1_v0_10_0_scalar_negate(&s, &s); - rustsecp256k1_v0_10_0_scalar_get_b32(&sig[0][32], &s); - CHECK(!rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig[0], msg[0], &keypair, NULL)); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); + rustsecp256k1_v0_11_scalar_set_b32(&s, &sig[0][32], NULL); + rustsecp256k1_v0_11_scalar_negate(&s, &s); + rustsecp256k1_v0_11_scalar_get_b32(&sig[0][32], &s); + CHECK(!rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], msg[0], sizeof(msg[0]), &pk)); /* The empty message can be signed & verified */ - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig[0], NULL, 0, &keypair, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], NULL, 0, &pk) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig[0], NULL, 0, &keypair, NULL) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], NULL, 0, &pk) == 1); { /* Test varying message lengths */ unsigned char msg_large[32 * 8]; - uint32_t msglen = rustsecp256k1_v0_10_0_testrand_int(sizeof(msg_large)); + uint32_t msglen = testrand_int(sizeof(msg_large)); for (i = 0; i < sizeof(msg_large); i += 32) { - rustsecp256k1_v0_10_0_testrand256(&msg_large[i]); + testrand256(&msg_large[i]); } - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign_custom(CTX, sig[0], msg_large, msglen, &keypair, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign_custom(CTX, sig[0], msg_large, msglen, &keypair, NULL) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 1); /* Verification for a random wrong message length fails */ msglen = (msglen + (sizeof(msg_large) - 1)) % sizeof(msg_large); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 0); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig[0], msg_large, msglen, &pk) == 0); } } #undef N_SIGS static void test_schnorrsig_taproot(void) { unsigned char sk[32]; - rustsecp256k1_v0_10_0_keypair keypair; - rustsecp256k1_v0_10_0_xonly_pubkey internal_pk; + rustsecp256k1_v0_11_keypair keypair; + rustsecp256k1_v0_11_xonly_pubkey internal_pk; unsigned char internal_pk_bytes[32]; - rustsecp256k1_v0_10_0_xonly_pubkey output_pk; + rustsecp256k1_v0_11_xonly_pubkey output_pk; unsigned char output_pk_bytes[32]; unsigned char tweak[32]; int pk_parity; @@ -942,27 +942,27 @@ static void test_schnorrsig_taproot(void) { unsigned char sig[64]; /* Create output key */ - rustsecp256k1_v0_10_0_testrand256(sk); - CHECK(rustsecp256k1_v0_10_0_keypair_create(CTX, &keypair, sk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); + testrand256(sk); + CHECK(rustsecp256k1_v0_11_keypair_create(CTX, &keypair, sk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &internal_pk, NULL, &keypair) == 1); /* In actual taproot the tweak would be hash of internal_pk */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, tweak, &internal_pk) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); - CHECK(rustsecp256k1_v0_10_0_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, output_pk_bytes, &output_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, tweak, &internal_pk) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_tweak_add(CTX, &keypair, tweak) == 1); + CHECK(rustsecp256k1_v0_11_keypair_xonly_pub(CTX, &output_pk, &pk_parity, &keypair) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, output_pk_bytes, &output_pk) == 1); /* Key spend */ - rustsecp256k1_v0_10_0_testrand256(msg); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); + testrand256(msg); + CHECK(rustsecp256k1_v0_11_schnorrsig_sign32(CTX, sig, msg, &keypair, NULL) == 1); /* Verify key spend */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &output_pk, output_pk_bytes) == 1); - CHECK(rustsecp256k1_v0_10_0_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &output_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &output_pk, output_pk_bytes) == 1); + CHECK(rustsecp256k1_v0_11_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &output_pk) == 1); /* Script spend */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_serialize(CTX, internal_pk_bytes, &internal_pk) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_serialize(CTX, internal_pk_bytes, &internal_pk) == 1); /* Verify script spend */ - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_parse(CTX, &internal_pk, internal_pk_bytes) == 1); - CHECK(rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check(CTX, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_parse(CTX, &internal_pk, internal_pk_bytes) == 1); + CHECK(rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check(CTX, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); } static void run_schnorrsig_tests(void) { diff --git a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c index b460cbe51..b4370e2c4 100644 --- a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c +++ b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult.c @@ -18,11 +18,11 @@ #include "ecmult.h" #include "ecmult_compute_table_impl.h" -static void print_table(FILE *fp, const char *name, int window_g, const rustsecp256k1_v0_10_0_ge_storage* table) { +static void print_table(FILE *fp, const char *name, int window_g, const rustsecp256k1_v0_11_ge_storage* table) { int j; int i; - fprintf(fp, "const rustsecp256k1_v0_10_0_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); + fprintf(fp, "const rustsecp256k1_v0_11_ge_storage %s[ECMULT_TABLE_SIZE(WINDOW_G)] = {\n", name); fprintf(fp, " S(%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32 ",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32")\n", SECP256K1_GE_STORAGE_CONST_GET(table[0])); @@ -41,13 +41,13 @@ static void print_table(FILE *fp, const char *name, int window_g, const rustsecp } static void print_two_tables(FILE *fp, int window_g) { - rustsecp256k1_v0_10_0_ge_storage* table = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(rustsecp256k1_v0_10_0_ge_storage)); - rustsecp256k1_v0_10_0_ge_storage* table_128 = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(rustsecp256k1_v0_10_0_ge_storage)); + rustsecp256k1_v0_11_ge_storage* table = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(rustsecp256k1_v0_11_ge_storage)); + rustsecp256k1_v0_11_ge_storage* table_128 = malloc(ECMULT_TABLE_SIZE(window_g) * sizeof(rustsecp256k1_v0_11_ge_storage)); - rustsecp256k1_v0_10_0_ecmult_compute_two_tables(table, table_128, window_g, &rustsecp256k1_v0_10_0_ge_const_g); + rustsecp256k1_v0_11_ecmult_compute_two_tables(table, table_128, window_g, &rustsecp256k1_v0_11_ge_const_g); - print_table(fp, "rustsecp256k1_v0_10_0_pre_g", window_g, table); - print_table(fp, "rustsecp256k1_v0_10_0_pre_g_128", window_g, table_128); + print_table(fp, "rustsecp256k1_v0_11_pre_g", window_g, table); + print_table(fp, "rustsecp256k1_v0_11_pre_g_128", window_g, table_128); free(table); free(table_128); @@ -66,8 +66,8 @@ int main(void) { } fprintf(fp, "/* This file was automatically generated by precompute_ecmult. */\n"); - fprintf(fp, "/* This file contains an array rustsecp256k1_v0_10_0_pre_g with odd multiples of the base point G and\n"); - fprintf(fp, " * an array rustsecp256k1_v0_10_0_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n"); + fprintf(fp, "/* This file contains an array rustsecp256k1_v0_11_pre_g with odd multiples of the base point G and\n"); + fprintf(fp, " * an array rustsecp256k1_v0_11_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G.\n"); fprintf(fp, " */\n"); fprintf(fp, "#include \"group.h\"\n"); fprintf(fp, "#include \"ecmult.h\"\n"); diff --git a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c index 05097c7ae..467c61b59 100644 --- a/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c +++ b/secp256k1-sys/depend/secp256k1/src/precompute_ecmult_gen.c @@ -17,10 +17,46 @@ #include "ecmult_gen.h" #include "ecmult_gen_compute_table_impl.h" +static const int CONFIGS[][2] = { + {2, 5}, + {11, 6}, + {43, 6} +}; + +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; + + rustsecp256k1_v0_11_ge_storage* table = checked_malloc(&default_error_callback, blocks * points * sizeof(rustsecp256k1_v0_11_ge_storage)); + rustsecp256k1_v0_11_ecmult_gen_compute_table(table, &rustsecp256k1_v0_11_ge_const_g, blocks, teeth, spacing); + + 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++) { + 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; + int did_current_config = 0; (void)argc; (void)argv; @@ -40,36 +76,21 @@ 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 rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_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; - - rustsecp256k1_v0_10_0_ge_storage* table = checked_malloc(&default_error_callback, n * g * sizeof(rustsecp256k1_v0_10_0_ge_storage)); - rustsecp256k1_v0_10_0_ecmult_gen_compute_table(table, &rustsecp256k1_v0_10_0_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, "const rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_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]); + if (CONFIGS[config][0] == COMB_BLOCKS && CONFIGS[config][1] == COMB_TEETH) { + did_current_config = 1; } - fprintf(fp, "#endif\n"); - free(table); } + 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"); + fprintf(fp, "#endif\n"); fprintf(fp, "};\n"); fprintf(fp, "#undef S\n"); diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c index 9dd2ca25d..68b7ebffb 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.c @@ -1,6 +1,6 @@ /* This file was automatically generated by precompute_ecmult. */ -/* This file contains an array rustsecp256k1_v0_10_0_pre_g with odd multiples of the base point G and - * an array rustsecp256k1_v0_10_0_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G. +/* This file contains an array rustsecp256k1_v0_11_pre_g with odd multiples of the base point G and + * an array rustsecp256k1_v0_11_pre_g_128 with odd multiples of 2^128*G for accelerating the computation of a*P + b*G. */ #include "group.h" #include "ecmult.h" @@ -13,7 +13,7 @@ # error Cannot compile precomputed_ecmult.c in exhaustive test mode #endif /* EXHAUSTIVE_TEST_ORDER */ #define WINDOW_G ECMULT_WINDOW_SIZE -const rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = { +const rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)] = { S(79be667e,f9dcbbac,55a06295,ce870b07,29bfcdb,2dce28d9,59f2815b,16f81798,483ada77,26a3c465,5da4fbfc,e1108a8,fd17b448,a6855419,9c47d08f,fb10d4b8) #if WINDOW_G > 2 ,S(f9308a01,9258c310,49344f85,f89d5229,b531c845,836f99b0,8601f113,bce036f9,388f7b0f,632de814,fe337e6,2a37f356,6500a999,34c2231b,6cb9fd75,84b8e672) @@ -8233,7 +8233,7 @@ const rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g[ECMULT_TABLE_ ,S(1e70619c,381a6adc,e5d925e0,c9c74f97,3c02ff64,ff2662d7,34efc485,d2bce895,c923f771,f543ffed,42935c28,8474aaaf,80a46ad4,3c579ce0,bb5e663d,668b24b3) #endif }; -const rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = { +const rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)] = { S(8f68b9d2,f63b5f33,9239c1ad,981f162e,e88c5678,723ea335,1b7b444c,9ec4c0da,662a9f2d,ba063986,de1d90c2,b6be215d,bbea2cfe,95510bfd,f23cbf79,501fff82) #if WINDOW_G > 2 ,S(38381dbe,2e509f22,8ba93363,f2451f08,fd845cb3,51d954be,18e2b8ed,d23809fa,e4a32d0a,fb917dc,b09405a5,520eb1cc,3681fccb,32d8f24d,bd707518,331fed52) diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h index 6da106e8a..6b6ded95b 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult.h @@ -23,12 +23,12 @@ extern "C" { # else # error No known generator for the specified exhaustive test group order. # endif -static rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; -static rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; +static rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; +static rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; #else /* !defined(EXHAUSTIVE_TEST_ORDER) */ # define WINDOW_G ECMULT_WINDOW_SIZE -extern const rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; -extern const rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; +extern const rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; +extern const rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ #ifdef __cplusplus diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c index 9e2f33958..2d8fabc90 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.c @@ -7,9740 +7,1773 @@ # 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 rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS] = { +#if 0 +#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), +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) && (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), +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)} +#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), +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 }; #undef S diff --git a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.h b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.h index 37094a19b..a548cdce1 100644 --- a/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.h +++ b/secp256k1-sys/depend/secp256k1/src/precomputed_ecmult_gen.h @@ -14,9 +14,9 @@ extern "C" { #include "group.h" #include "ecmult_gen.h" #ifdef EXHAUSTIVE_TEST_ORDER -static rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)]; +static rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; #else -extern const rustsecp256k1_v0_10_0_ge_storage rustsecp256k1_v0_10_0_ecmult_gen_prec_table[ECMULT_GEN_PREC_N(ECMULT_GEN_PREC_BITS)][ECMULT_GEN_PREC_G(ECMULT_GEN_PREC_BITS)]; +extern const rustsecp256k1_v0_11_ge_storage rustsecp256k1_v0_11_ecmult_gen_prec_table[COMB_BLOCKS][COMB_POINTS]; #endif /* defined(EXHAUSTIVE_TEST_ORDER) */ #ifdef __cplusplus diff --git a/secp256k1-sys/depend/secp256k1/src/scalar.h b/secp256k1-sys/depend/secp256k1/src/scalar.h index 28c01d6c1..a1347d843 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar.h @@ -20,86 +20,86 @@ #endif /** Clear a scalar to prevent the leak of sensitive data. */ -static void rustsecp256k1_v0_10_0_scalar_clear(rustsecp256k1_v0_10_0_scalar *r); +static void rustsecp256k1_v0_11_scalar_clear(rustsecp256k1_v0_11_scalar *r); -/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ -static unsigned int rustsecp256k1_v0_10_0_scalar_get_bits(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count); +/** Access bits (1 < count <= 32) from a scalar. All requested bits must belong to the same 32-bit limb. */ +static uint32_t rustsecp256k1_v0_11_scalar_get_bits_limb32(const rustsecp256k1_v0_11_scalar *a, unsigned int offset, unsigned int count); -/** Access bits from a scalar. Not constant time in offset and count. */ -static unsigned int rustsecp256k1_v0_10_0_scalar_get_bits_var(const rustsecp256k1_v0_10_0_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. */ +static uint32_t rustsecp256k1_v0_11_scalar_get_bits_var(const rustsecp256k1_v0_11_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. * Out: r: scalar to be set. * overflow: non-zero if the scalar was bigger or equal to `n` before reduction, zero otherwise (can be NULL). */ -static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r, const unsigned char *bin, int *overflow); +static void rustsecp256k1_v0_11_scalar_set_b32(rustsecp256k1_v0_11_scalar *r, const unsigned char *bin, int *overflow); /** Set a scalar from a big endian byte array and returns 1 if it is a valid * seckey and 0 otherwise. */ -static int rustsecp256k1_v0_10_0_scalar_set_b32_seckey(rustsecp256k1_v0_10_0_scalar *r, const unsigned char *bin); +static int rustsecp256k1_v0_11_scalar_set_b32_seckey(rustsecp256k1_v0_11_scalar *r, const unsigned char *bin); /** Set a scalar to an unsigned integer. */ -static void rustsecp256k1_v0_10_0_scalar_set_int(rustsecp256k1_v0_10_0_scalar *r, unsigned int v); +static void rustsecp256k1_v0_11_scalar_set_int(rustsecp256k1_v0_11_scalar *r, unsigned int v); /** Convert a scalar to a byte array. */ -static void rustsecp256k1_v0_10_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_10_0_scalar* a); +static void rustsecp256k1_v0_11_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_11_scalar* a); /** Add two scalars together (modulo the group order). Returns whether it overflowed. */ -static int rustsecp256k1_v0_10_0_scalar_add(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b); +static int rustsecp256k1_v0_11_scalar_add(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b); /** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ -static void rustsecp256k1_v0_10_0_scalar_cadd_bit(rustsecp256k1_v0_10_0_scalar *r, unsigned int bit, int flag); +static void rustsecp256k1_v0_11_scalar_cadd_bit(rustsecp256k1_v0_11_scalar *r, unsigned int bit, int flag); /** Multiply two scalars (modulo the group order). */ -static void rustsecp256k1_v0_10_0_scalar_mul(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b); +static void rustsecp256k1_v0_11_scalar_mul(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b); /** Compute the inverse of a scalar (modulo the group order). */ -static void rustsecp256k1_v0_10_0_scalar_inverse(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a); +static void rustsecp256k1_v0_11_scalar_inverse(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a); /** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ -static void rustsecp256k1_v0_10_0_scalar_inverse_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a); +static void rustsecp256k1_v0_11_scalar_inverse_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a); /** Compute the complement of a scalar (modulo the group order). */ -static void rustsecp256k1_v0_10_0_scalar_negate(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a); +static void rustsecp256k1_v0_11_scalar_negate(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a); /** Multiply a scalar with the multiplicative inverse of 2. */ -static void rustsecp256k1_v0_10_0_scalar_half(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a); +static void rustsecp256k1_v0_11_scalar_half(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a); /** Check whether a scalar equals zero. */ -static int rustsecp256k1_v0_10_0_scalar_is_zero(const rustsecp256k1_v0_10_0_scalar *a); +static int rustsecp256k1_v0_11_scalar_is_zero(const rustsecp256k1_v0_11_scalar *a); /** Check whether a scalar equals one. */ -static int rustsecp256k1_v0_10_0_scalar_is_one(const rustsecp256k1_v0_10_0_scalar *a); +static int rustsecp256k1_v0_11_scalar_is_one(const rustsecp256k1_v0_11_scalar *a); /** Check whether a scalar, considered as an nonnegative integer, is even. */ -static int rustsecp256k1_v0_10_0_scalar_is_even(const rustsecp256k1_v0_10_0_scalar *a); +static int rustsecp256k1_v0_11_scalar_is_even(const rustsecp256k1_v0_11_scalar *a); /** Check whether a scalar is higher than the group order divided by 2. */ -static int rustsecp256k1_v0_10_0_scalar_is_high(const rustsecp256k1_v0_10_0_scalar *a); +static int rustsecp256k1_v0_11_scalar_is_high(const rustsecp256k1_v0_11_scalar *a); /** Conditionally negate a number, in constant time. * Returns -1 if the number was negated, 1 otherwise */ -static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar *a, int flag); +static int rustsecp256k1_v0_11_scalar_cond_negate(rustsecp256k1_v0_11_scalar *a, int flag); /** Compare two scalars. */ -static int rustsecp256k1_v0_10_0_scalar_eq(const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b); +static int rustsecp256k1_v0_11_scalar_eq(const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b); /** Find r1 and r2 such that r1+r2*2^128 = k. */ -static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar *r1, rustsecp256k1_v0_10_0_scalar *r2, const rustsecp256k1_v0_10_0_scalar *k); +static void rustsecp256k1_v0_11_scalar_split_128(rustsecp256k1_v0_11_scalar *r1, rustsecp256k1_v0_11_scalar *r2, const rustsecp256k1_v0_11_scalar *k); /** Find r1 and r2 such that r1+r2*lambda = k, where r1 and r2 or their - * negations are maximum 128 bits long (see rustsecp256k1_v0_10_0_ge_mul_lambda). It is + * negations are maximum 128 bits long (see rustsecp256k1_v0_11_ge_mul_lambda). It is * required that r1, r2, and k all point to different objects. */ -static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT k); +static void rustsecp256k1_v0_11_scalar_split_lambda(rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT k); /** 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 rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b, unsigned int shift); +static void rustsecp256k1_v0_11_scalar_mul_shift_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_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.*/ -static void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, int flag); +static void rustsecp256k1_v0_11_scalar_cmov(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, int flag); /** Check invariants on a scalar (no-op unless VERIFY is enabled). */ -static void rustsecp256k1_v0_10_0_scalar_verify(const rustsecp256k1_v0_10_0_scalar *r); -#define SECP256K1_SCALAR_VERIFY(r) rustsecp256k1_v0_10_0_scalar_verify(r) +static void rustsecp256k1_v0_11_scalar_verify(const rustsecp256k1_v0_11_scalar *r); +#define SECP256K1_SCALAR_VERIFY(r) rustsecp256k1_v0_11_scalar_verify(r) #endif /* SECP256K1_SCALAR_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_4x64.h b/secp256k1-sys/depend/secp256k1/src/scalar_4x64.h index cee6d188b..5be54acd0 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_4x64.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_4x64.h @@ -12,7 +12,7 @@ /** A scalar modulo the group order of the secp256k1 curve. */ typedef struct { uint64_t d[4]; -} rustsecp256k1_v0_10_0_scalar; +} rustsecp256k1_v0_11_scalar; #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h index c6eba307f..4a147c6ae 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_4x64_impl.h @@ -29,14 +29,7 @@ #define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) #define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_clear(rustsecp256k1_v0_10_0_scalar *r) { - r->d[0] = 0; - r->d[1] = 0; - r->d[2] = 0; - r->d[3] = 0; -} - -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_set_int(rustsecp256k1_v0_10_0_scalar *r, unsigned int v) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_scalar_set_int(rustsecp256k1_v0_11_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; r->d[2] = 0; @@ -45,27 +38,28 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_set_int(rustsecp256k1_ SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static unsigned int rustsecp256k1_v0_10_0_scalar_get_bits(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_scalar_get_bits_limb32(const rustsecp256k1_v0_11_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 unsigned int rustsecp256k1_v0_10_0_scalar_get_bits_var(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_scalar_get_bits_var(const rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_scalar_get_bits(a, offset, count); + return rustsecp256k1_v0_11_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)); } } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_check_overflow(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_check_overflow(const rustsecp256k1_v0_11_scalar *a) { int yes = 0; int no = 0; no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ @@ -77,83 +71,83 @@ SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_check_overflow(const ru return yes; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_reduce(rustsecp256k1_v0_10_0_scalar *r, unsigned int overflow) { - rustsecp256k1_v0_10_0_uint128 t; +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_reduce(rustsecp256k1_v0_11_scalar *r, unsigned int overflow) { + rustsecp256k1_v0_11_uint128 t; VERIFY_CHECK(overflow <= 1); - rustsecp256k1_v0_10_0_u128_from_u64(&t, r->d[0]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, overflow * SECP256K1_N_C_0); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[1]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, overflow * SECP256K1_N_C_1); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[2]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, overflow * SECP256K1_N_C_2); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[3]); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&t); + rustsecp256k1_v0_11_u128_from_u64(&t, r->d[0]); + rustsecp256k1_v0_11_u128_accum_u64(&t, overflow * SECP256K1_N_C_0); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[1]); + rustsecp256k1_v0_11_u128_accum_u64(&t, overflow * SECP256K1_N_C_1); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[2]); + rustsecp256k1_v0_11_u128_accum_u64(&t, overflow * SECP256K1_N_C_2); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[3]); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&t); SECP256K1_SCALAR_VERIFY(r); return overflow; } -static int rustsecp256k1_v0_10_0_scalar_add(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static int rustsecp256k1_v0_11_scalar_add(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { int overflow; - rustsecp256k1_v0_10_0_uint128 t; + rustsecp256k1_v0_11_uint128 t; SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); - rustsecp256k1_v0_10_0_u128_from_u64(&t, a->d[0]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, b->d[0]); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, a->d[1]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, b->d[1]); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, a->d[2]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, b->d[2]); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, a->d[3]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, b->d[3]); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - overflow = rustsecp256k1_v0_10_0_u128_to_u64(&t) + rustsecp256k1_v0_10_0_scalar_check_overflow(r); + rustsecp256k1_v0_11_u128_from_u64(&t, a->d[0]); + rustsecp256k1_v0_11_u128_accum_u64(&t, b->d[0]); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, a->d[1]); + rustsecp256k1_v0_11_u128_accum_u64(&t, b->d[1]); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, a->d[2]); + rustsecp256k1_v0_11_u128_accum_u64(&t, b->d[2]); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, a->d[3]); + rustsecp256k1_v0_11_u128_accum_u64(&t, b->d[3]); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + overflow = rustsecp256k1_v0_11_u128_to_u64(&t) + rustsecp256k1_v0_11_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); - rustsecp256k1_v0_10_0_scalar_reduce(r, overflow); + rustsecp256k1_v0_11_scalar_reduce(r, overflow); SECP256K1_SCALAR_VERIFY(r); return overflow; } -static void rustsecp256k1_v0_10_0_scalar_cadd_bit(rustsecp256k1_v0_10_0_scalar *r, unsigned int bit, int flag) { - rustsecp256k1_v0_10_0_uint128 t; +static void rustsecp256k1_v0_11_scalar_cadd_bit(rustsecp256k1_v0_11_scalar *r, unsigned int bit, int flag) { + rustsecp256k1_v0_11_uint128 t; volatile int vflag = flag; SECP256K1_SCALAR_VERIFY(r); VERIFY_CHECK(bit < 256); bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ - rustsecp256k1_v0_10_0_u128_from_u64(&t, r->d[0]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[1]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[2]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[3]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&t); + rustsecp256k1_v0_11_u128_from_u64(&t, r->d[0]); + rustsecp256k1_v0_11_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[1]); + rustsecp256k1_v0_11_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[2]); + rustsecp256k1_v0_11_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[3]); + rustsecp256k1_v0_11_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&t); SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(rustsecp256k1_v0_10_0_u128_hi_u64(&t) == 0); + VERIFY_CHECK(rustsecp256k1_v0_11_u128_hi_u64(&t) == 0); } -static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r, const unsigned char *b32, int *overflow) { +static void rustsecp256k1_v0_11_scalar_set_b32(rustsecp256k1_v0_11_scalar *r, const unsigned char *b32, int *overflow) { int over; - r->d[0] = rustsecp256k1_v0_10_0_read_be64(&b32[24]); - r->d[1] = rustsecp256k1_v0_10_0_read_be64(&b32[16]); - r->d[2] = rustsecp256k1_v0_10_0_read_be64(&b32[8]); - r->d[3] = rustsecp256k1_v0_10_0_read_be64(&b32[0]); - over = rustsecp256k1_v0_10_0_scalar_reduce(r, rustsecp256k1_v0_10_0_scalar_check_overflow(r)); + r->d[0] = rustsecp256k1_v0_11_read_be64(&b32[24]); + r->d[1] = rustsecp256k1_v0_11_read_be64(&b32[16]); + r->d[2] = rustsecp256k1_v0_11_read_be64(&b32[8]); + r->d[3] = rustsecp256k1_v0_11_read_be64(&b32[0]); + over = rustsecp256k1_v0_11_scalar_reduce(r, rustsecp256k1_v0_11_scalar_check_overflow(r)); if (overflow) { *overflow = over; } @@ -161,43 +155,43 @@ static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_10_0_scalar* a) { +static void rustsecp256k1_v0_11_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_11_scalar* a) { SECP256K1_SCALAR_VERIFY(a); - rustsecp256k1_v0_10_0_write_be64(&bin[0], a->d[3]); - rustsecp256k1_v0_10_0_write_be64(&bin[8], a->d[2]); - rustsecp256k1_v0_10_0_write_be64(&bin[16], a->d[1]); - rustsecp256k1_v0_10_0_write_be64(&bin[24], a->d[0]); + rustsecp256k1_v0_11_write_be64(&bin[0], a->d[3]); + rustsecp256k1_v0_11_write_be64(&bin[8], a->d[2]); + rustsecp256k1_v0_11_write_be64(&bin[16], a->d[1]); + rustsecp256k1_v0_11_write_be64(&bin[24], a->d[0]); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_zero(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_zero(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; } -static void rustsecp256k1_v0_10_0_scalar_negate(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a) { - uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (rustsecp256k1_v0_10_0_scalar_is_zero(a) == 0); - rustsecp256k1_v0_10_0_uint128 t; +static void rustsecp256k1_v0_11_scalar_negate(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a) { + uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (rustsecp256k1_v0_11_scalar_is_zero(a) == 0); + rustsecp256k1_v0_11_uint128 t; SECP256K1_SCALAR_VERIFY(a); - rustsecp256k1_v0_10_0_u128_from_u64(&t, ~a->d[0]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_0 + 1); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ~a->d[1]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_1); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ~a->d[2]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_2); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, ~a->d[3]); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_3); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; + rustsecp256k1_v0_11_u128_from_u64(&t, ~a->d[0]); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_0 + 1); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, ~a->d[1]); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_1); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, ~a->d[2]); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_2); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, ~a->d[3]); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_3); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_half(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_half(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a) { /* Writing `/` for field division and `//` for integer division, we compute * * a/2 = (a - (a&1))/2 + (a&1)/2 @@ -213,38 +207,38 @@ static void rustsecp256k1_v0_10_0_scalar_half(rustsecp256k1_v0_10_0_scalar *r, c * Together they sum to (n-3)//2 + (n+1)//2 = (2n-2)//2 = n - 1, which is less than n. */ uint64_t mask = -(uint64_t)(a->d[0] & 1U); - rustsecp256k1_v0_10_0_uint128 t; + rustsecp256k1_v0_11_uint128 t; SECP256K1_SCALAR_VERIFY(a); - rustsecp256k1_v0_10_0_u128_from_u64(&t, (a->d[0] >> 1) | (a->d[1] << 63)); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, (SECP256K1_N_H_0 + 1U) & mask); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, (a->d[1] >> 1) | (a->d[2] << 63)); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_H_1 & mask); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, (a->d[2] >> 1) | (a->d[3] << 63)); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_H_2 & mask); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&t); rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&t) + (a->d[3] >> 1) + (SECP256K1_N_H_3 & mask); + rustsecp256k1_v0_11_u128_from_u64(&t, (a->d[0] >> 1) | (a->d[1] << 63)); + rustsecp256k1_v0_11_u128_accum_u64(&t, (SECP256K1_N_H_0 + 1U) & mask); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, (a->d[1] >> 1) | (a->d[2] << 63)); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_H_1 & mask); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, (a->d[2] >> 1) | (a->d[3] << 63)); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_H_2 & mask); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&t); rustsecp256k1_v0_11_u128_rshift(&t, 64); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&t) + (a->d[3] >> 1) + (SECP256K1_N_H_3 & mask); #ifdef VERIFY /* The line above only computed the bottom 64 bits of r->d[3]; redo the computation * in full 128 bits to make sure the top 64 bits are indeed zero. */ - rustsecp256k1_v0_10_0_u128_accum_u64(&t, a->d[3] >> 1); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_H_3 & mask); - rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - VERIFY_CHECK(rustsecp256k1_v0_10_0_u128_to_u64(&t) == 0); + rustsecp256k1_v0_11_u128_accum_u64(&t, a->d[3] >> 1); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_H_3 & mask); + rustsecp256k1_v0_11_u128_rshift(&t, 64); + VERIFY_CHECK(rustsecp256k1_v0_11_u128_to_u64(&t) == 0); SECP256K1_SCALAR_VERIFY(r); #endif } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_one(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_one(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; } -static int rustsecp256k1_v0_10_0_scalar_is_high(const rustsecp256k1_v0_10_0_scalar *a) { +static int rustsecp256k1_v0_11_scalar_is_high(const rustsecp256k1_v0_11_scalar *a) { int yes = 0; int no = 0; SECP256K1_SCALAR_VERIFY(a); @@ -258,27 +252,27 @@ static int rustsecp256k1_v0_10_0_scalar_is_high(const rustsecp256k1_v0_10_0_scal return yes; } -static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar *r, int flag) { +static int rustsecp256k1_v0_11_scalar_cond_negate(rustsecp256k1_v0_11_scalar *r, int flag) { /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to rustsecp256k1_v0_10_0_scalar_negate */ + * if we are flag = 1, mask = 11...11 and this is identical to rustsecp256k1_v0_11_scalar_negate */ volatile int vflag = flag; uint64_t mask = -vflag; - uint64_t nonzero = (rustsecp256k1_v0_10_0_scalar_is_zero(r) != 0) - 1; - rustsecp256k1_v0_10_0_uint128 t; + uint64_t nonzero = (rustsecp256k1_v0_11_scalar_is_zero(r) != 0) - 1; + rustsecp256k1_v0_11_uint128 t; SECP256K1_SCALAR_VERIFY(r); - rustsecp256k1_v0_10_0_u128_from_u64(&t, r->d[0] ^ mask); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, (SECP256K1_N_0 + 1) & mask); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[1] ^ mask); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_1 & mask); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[2] ^ mask); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_2 & mask); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_10_0_u128_rshift(&t, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, r->d[3] ^ mask); - rustsecp256k1_v0_10_0_u128_accum_u64(&t, SECP256K1_N_3 & mask); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&t) & nonzero; + rustsecp256k1_v0_11_u128_from_u64(&t, r->d[0] ^ mask); + rustsecp256k1_v0_11_u128_accum_u64(&t, (SECP256K1_N_0 + 1) & mask); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[1] ^ mask); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_1 & mask); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[2] ^ mask); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_2 & mask); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; rustsecp256k1_v0_11_u128_rshift(&t, 64); + rustsecp256k1_v0_11_u128_accum_u64(&t, r->d[3] ^ mask); + rustsecp256k1_v0_11_u128_accum_u64(&t, SECP256K1_N_3 & mask); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&t) & nonzero; SECP256K1_SCALAR_VERIFY(r); return 2 * (mask == 0) - 1; @@ -290,10 +284,10 @@ static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar #define muladd(a,b) { \ uint64_t tl, th; \ { \ - rustsecp256k1_v0_10_0_uint128 t; \ - rustsecp256k1_v0_10_0_u128_mul(&t, a, b); \ - th = rustsecp256k1_v0_10_0_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = rustsecp256k1_v0_10_0_u128_to_u64(&t); \ + rustsecp256k1_v0_11_uint128 t; \ + rustsecp256k1_v0_11_u128_mul(&t, a, b); \ + th = rustsecp256k1_v0_11_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = rustsecp256k1_v0_11_u128_to_u64(&t); \ } \ c0 += tl; /* overflow is handled on the next line */ \ th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ @@ -306,10 +300,10 @@ static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar #define muladd_fast(a,b) { \ uint64_t tl, th; \ { \ - rustsecp256k1_v0_10_0_uint128 t; \ - rustsecp256k1_v0_10_0_u128_mul(&t, a, b); \ - th = rustsecp256k1_v0_10_0_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \ - tl = rustsecp256k1_v0_10_0_u128_to_u64(&t); \ + rustsecp256k1_v0_11_uint128 t; \ + rustsecp256k1_v0_11_u128_mul(&t, a, b); \ + th = rustsecp256k1_v0_11_u128_hi_u64(&t); /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = rustsecp256k1_v0_11_u128_to_u64(&t); \ } \ c0 += tl; /* overflow is handled on the next line */ \ th += (c0 < tl); /* at most 0xFFFFFFFFFFFFFFFF */ \ @@ -350,7 +344,7 @@ static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar VERIFY_CHECK(c2 == 0); \ } -static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar *r, const uint64_t *l) { +static void rustsecp256k1_v0_11_scalar_reduce_512(rustsecp256k1_v0_11_scalar *r, const uint64_t *l) { #ifdef USE_ASM_X86_64 /* Reduce 512 bits into 385. */ uint64_t m0, m1, m2, m3, m4, m5, m6; @@ -462,6 +456,14 @@ static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar : "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 +543,12 @@ static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar : "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,8 +594,12 @@ static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar : "=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 - rustsecp256k1_v0_10_0_uint128 c128; + rustsecp256k1_v0_11_uint128 c128; uint64_t c, c0, c1, c2; uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; uint64_t m0, m1, m2, m3, m4, m5; @@ -645,25 +657,25 @@ static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar /* Reduce 258 bits into 256. */ /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ - rustsecp256k1_v0_10_0_u128_from_u64(&c128, p0); - rustsecp256k1_v0_10_0_u128_accum_mul(&c128, SECP256K1_N_C_0, p4); - r->d[0] = rustsecp256k1_v0_10_0_u128_to_u64(&c128); rustsecp256k1_v0_10_0_u128_rshift(&c128, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&c128, p1); - rustsecp256k1_v0_10_0_u128_accum_mul(&c128, SECP256K1_N_C_1, p4); - r->d[1] = rustsecp256k1_v0_10_0_u128_to_u64(&c128); rustsecp256k1_v0_10_0_u128_rshift(&c128, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&c128, p2); - rustsecp256k1_v0_10_0_u128_accum_u64(&c128, p4); - r->d[2] = rustsecp256k1_v0_10_0_u128_to_u64(&c128); rustsecp256k1_v0_10_0_u128_rshift(&c128, 64); - rustsecp256k1_v0_10_0_u128_accum_u64(&c128, p3); - r->d[3] = rustsecp256k1_v0_10_0_u128_to_u64(&c128); - c = rustsecp256k1_v0_10_0_u128_hi_u64(&c128); + rustsecp256k1_v0_11_u128_from_u64(&c128, p0); + rustsecp256k1_v0_11_u128_accum_mul(&c128, SECP256K1_N_C_0, p4); + r->d[0] = rustsecp256k1_v0_11_u128_to_u64(&c128); rustsecp256k1_v0_11_u128_rshift(&c128, 64); + rustsecp256k1_v0_11_u128_accum_u64(&c128, p1); + rustsecp256k1_v0_11_u128_accum_mul(&c128, SECP256K1_N_C_1, p4); + r->d[1] = rustsecp256k1_v0_11_u128_to_u64(&c128); rustsecp256k1_v0_11_u128_rshift(&c128, 64); + rustsecp256k1_v0_11_u128_accum_u64(&c128, p2); + rustsecp256k1_v0_11_u128_accum_u64(&c128, p4); + r->d[2] = rustsecp256k1_v0_11_u128_to_u64(&c128); rustsecp256k1_v0_11_u128_rshift(&c128, 64); + rustsecp256k1_v0_11_u128_accum_u64(&c128, p3); + r->d[3] = rustsecp256k1_v0_11_u128_to_u64(&c128); + c = rustsecp256k1_v0_11_u128_hi_u64(&c128); #endif /* Final reduction of r. */ - rustsecp256k1_v0_10_0_scalar_reduce(r, c + rustsecp256k1_v0_10_0_scalar_check_overflow(r)); + rustsecp256k1_v0_11_scalar_reduce(r, c + rustsecp256k1_v0_11_scalar_check_overflow(r)); } -static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static void rustsecp256k1_v0_11_scalar_mul_512(uint64_t *l8, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { #ifdef USE_ASM_X86_64 const uint64_t *pb = b->d; __asm__ __volatile__( @@ -678,7 +690,7 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 /* (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" @@ -696,7 +708,7 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 "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 */ @@ -717,7 +729,7 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 "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 */ @@ -746,7 +758,7 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 "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 */ @@ -767,7 +779,7 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 "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 */ @@ -782,51 +794,54 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 "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"); + + 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], 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 } @@ -837,18 +852,18 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint64_t l[8], const rustsecp25 #undef extract #undef extract_fast -static void rustsecp256k1_v0_10_0_scalar_mul(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static void rustsecp256k1_v0_11_scalar_mul(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { uint64_t l[8]; SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); - rustsecp256k1_v0_10_0_scalar_mul_512(l, a, b); - rustsecp256k1_v0_10_0_scalar_reduce_512(r, l); + rustsecp256k1_v0_11_scalar_mul_512(l, a, b); + rustsecp256k1_v0_11_scalar_reduce_512(r, l); SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar *r1, rustsecp256k1_v0_10_0_scalar *r2, const rustsecp256k1_v0_10_0_scalar *k) { +static void rustsecp256k1_v0_11_scalar_split_128(rustsecp256k1_v0_11_scalar *r1, rustsecp256k1_v0_11_scalar *r2, const rustsecp256k1_v0_11_scalar *k) { SECP256K1_SCALAR_VERIFY(k); r1->d[0] = k->d[0]; @@ -864,14 +879,14 @@ static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar SECP256K1_SCALAR_VERIFY(r2); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_eq(const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_eq(const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b, unsigned int shift) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_scalar_mul_shift_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b, unsigned int shift) { uint64_t l[8]; unsigned int shiftlimbs; unsigned int shiftlow; @@ -880,7 +895,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp SECP256K1_SCALAR_VERIFY(b); VERIFY_CHECK(shift >= 256); - rustsecp256k1_v0_10_0_scalar_mul_512(l, a, b); + rustsecp256k1_v0_11_scalar_mul_512(l, a, b); shiftlimbs = shift >> 6; shiftlow = shift & 0x3F; shifthigh = 64 - shiftlow; @@ -888,12 +903,12 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; - rustsecp256k1_v0_10_0_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); + rustsecp256k1_v0_11_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); SECP256K1_SCALAR_VERIFY(r); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_scalar_cmov(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, int flag) { uint64_t mask0, mask1; volatile int vflag = flag; SECP256K1_SCALAR_VERIFY(a); @@ -909,10 +924,10 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_ SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_from_signed62(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_modinv64_signed62 *a) { +static void rustsecp256k1_v0_11_scalar_from_signed62(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_modinv64_signed62 *a) { const uint64_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4]; - /* The output from rustsecp256k1_v0_10_0_modinv64{_var} should be normalized to range [0,modulus), and + /* The output from rustsecp256k1_v0_11_modinv64{_var} should be normalized to range [0,modulus), and * have limbs in [0,2^62). The modulus is < 2^256, so the top limb must be below 2^(256-62*4). */ VERIFY_CHECK(a0 >> 62 == 0); @@ -929,7 +944,7 @@ static void rustsecp256k1_v0_10_0_scalar_from_signed62(rustsecp256k1_v0_10_0_sca SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_to_signed62(rustsecp256k1_v0_10_0_modinv64_signed62 *r, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_to_signed62(rustsecp256k1_v0_11_modinv64_signed62 *r, const rustsecp256k1_v0_11_scalar *a) { const uint64_t M62 = UINT64_MAX >> 2; const uint64_t a0 = a->d[0], a1 = a->d[1], a2 = a->d[2], a3 = a->d[3]; SECP256K1_SCALAR_VERIFY(a); @@ -941,42 +956,42 @@ static void rustsecp256k1_v0_10_0_scalar_to_signed62(rustsecp256k1_v0_10_0_modin r->v[4] = a3 >> 56; } -static const rustsecp256k1_v0_10_0_modinv64_modinfo rustsecp256k1_v0_10_0_const_modinfo_scalar = { +static const rustsecp256k1_v0_11_modinv64_modinfo rustsecp256k1_v0_11_const_modinfo_scalar = { {{0x3FD25E8CD0364141LL, 0x2ABB739ABD2280EELL, -0x15LL, 0, 256}}, 0x34F20099AA774EC1LL }; -static void rustsecp256k1_v0_10_0_scalar_inverse(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *x) { - rustsecp256k1_v0_10_0_modinv64_signed62 s; +static void rustsecp256k1_v0_11_scalar_inverse(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *x) { + rustsecp256k1_v0_11_modinv64_signed62 s; #ifdef VERIFY - int zero_in = rustsecp256k1_v0_10_0_scalar_is_zero(x); + int zero_in = rustsecp256k1_v0_11_scalar_is_zero(x); #endif SECP256K1_SCALAR_VERIFY(x); - rustsecp256k1_v0_10_0_scalar_to_signed62(&s, x); - rustsecp256k1_v0_10_0_modinv64(&s, &rustsecp256k1_v0_10_0_const_modinfo_scalar); - rustsecp256k1_v0_10_0_scalar_from_signed62(r, &s); + rustsecp256k1_v0_11_scalar_to_signed62(&s, x); + rustsecp256k1_v0_11_modinv64(&s, &rustsecp256k1_v0_11_const_modinfo_scalar); + rustsecp256k1_v0_11_scalar_from_signed62(r, &s); SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(r) == zero_in); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_is_zero(r) == zero_in); } -static void rustsecp256k1_v0_10_0_scalar_inverse_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *x) { - rustsecp256k1_v0_10_0_modinv64_signed62 s; +static void rustsecp256k1_v0_11_scalar_inverse_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *x) { + rustsecp256k1_v0_11_modinv64_signed62 s; #ifdef VERIFY - int zero_in = rustsecp256k1_v0_10_0_scalar_is_zero(x); + int zero_in = rustsecp256k1_v0_11_scalar_is_zero(x); #endif SECP256K1_SCALAR_VERIFY(x); - rustsecp256k1_v0_10_0_scalar_to_signed62(&s, x); - rustsecp256k1_v0_10_0_modinv64_var(&s, &rustsecp256k1_v0_10_0_const_modinfo_scalar); - rustsecp256k1_v0_10_0_scalar_from_signed62(r, &s); + rustsecp256k1_v0_11_scalar_to_signed62(&s, x); + rustsecp256k1_v0_11_modinv64_var(&s, &rustsecp256k1_v0_11_const_modinfo_scalar); + rustsecp256k1_v0_11_scalar_from_signed62(r, &s); SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(r) == zero_in); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_is_zero(r) == zero_in); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_even(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_even(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return !(a->d[0] & 1); diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_8x32.h b/secp256k1-sys/depend/secp256k1/src/scalar_8x32.h index bcba214ce..8946c40cf 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_8x32.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_8x32.h @@ -12,7 +12,7 @@ /** A scalar modulo the group order of the secp256k1 curve. */ typedef struct { uint32_t d[8]; -} rustsecp256k1_v0_10_0_scalar; +} rustsecp256k1_v0_11_scalar; #define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h index 4aba971e2..ccb4b22b2 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_8x32_impl.h @@ -38,18 +38,7 @@ #define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) #define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_clear(rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_scalar_set_int(rustsecp256k1_v0_10_0_scalar *r, unsigned int v) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_scalar_set_int(rustsecp256k1_v0_11_scalar *r, unsigned int v) { r->d[0] = v; r->d[1] = 0; r->d[2] = 0; @@ -62,27 +51,28 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_set_int(rustsecp256k1_ SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static unsigned int rustsecp256k1_v0_10_0_scalar_get_bits(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_scalar_get_bits_limb32(const rustsecp256k1_v0_11_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 unsigned int rustsecp256k1_v0_10_0_scalar_get_bits_var(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_scalar_get_bits_var(const rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_scalar_get_bits(a, offset, count); + return rustsecp256k1_v0_11_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)); } } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_check_overflow(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_check_overflow(const rustsecp256k1_v0_11_scalar *a) { int yes = 0; int no = 0; no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ @@ -100,7 +90,7 @@ SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_check_overflow(const ru return yes; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_reduce(rustsecp256k1_v0_10_0_scalar *r, uint32_t overflow) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_reduce(rustsecp256k1_v0_11_scalar *r, uint32_t overflow) { uint64_t t; VERIFY_CHECK(overflow <= 1); @@ -125,7 +115,7 @@ SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_reduce(rustsecp256k1_v0 return overflow; } -static int rustsecp256k1_v0_10_0_scalar_add(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static int rustsecp256k1_v0_11_scalar_add(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { int overflow; uint64_t t = (uint64_t)a->d[0] + b->d[0]; SECP256K1_SCALAR_VERIFY(a); @@ -146,15 +136,15 @@ static int rustsecp256k1_v0_10_0_scalar_add(rustsecp256k1_v0_10_0_scalar *r, con r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; t += (uint64_t)a->d[7] + b->d[7]; r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; - overflow = t + rustsecp256k1_v0_10_0_scalar_check_overflow(r); + overflow = t + rustsecp256k1_v0_11_scalar_check_overflow(r); VERIFY_CHECK(overflow == 0 || overflow == 1); - rustsecp256k1_v0_10_0_scalar_reduce(r, overflow); + rustsecp256k1_v0_11_scalar_reduce(r, overflow); SECP256K1_SCALAR_VERIFY(r); return overflow; } -static void rustsecp256k1_v0_10_0_scalar_cadd_bit(rustsecp256k1_v0_10_0_scalar *r, unsigned int bit, int flag) { +static void rustsecp256k1_v0_11_scalar_cadd_bit(rustsecp256k1_v0_11_scalar *r, unsigned int bit, int flag) { uint64_t t; volatile int vflag = flag; SECP256K1_SCALAR_VERIFY(r); @@ -182,17 +172,17 @@ static void rustsecp256k1_v0_10_0_scalar_cadd_bit(rustsecp256k1_v0_10_0_scalar * VERIFY_CHECK((t >> 32) == 0); } -static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r, const unsigned char *b32, int *overflow) { +static void rustsecp256k1_v0_11_scalar_set_b32(rustsecp256k1_v0_11_scalar *r, const unsigned char *b32, int *overflow) { int over; - r->d[0] = rustsecp256k1_v0_10_0_read_be32(&b32[28]); - r->d[1] = rustsecp256k1_v0_10_0_read_be32(&b32[24]); - r->d[2] = rustsecp256k1_v0_10_0_read_be32(&b32[20]); - r->d[3] = rustsecp256k1_v0_10_0_read_be32(&b32[16]); - r->d[4] = rustsecp256k1_v0_10_0_read_be32(&b32[12]); - r->d[5] = rustsecp256k1_v0_10_0_read_be32(&b32[8]); - r->d[6] = rustsecp256k1_v0_10_0_read_be32(&b32[4]); - r->d[7] = rustsecp256k1_v0_10_0_read_be32(&b32[0]); - over = rustsecp256k1_v0_10_0_scalar_reduce(r, rustsecp256k1_v0_10_0_scalar_check_overflow(r)); + r->d[0] = rustsecp256k1_v0_11_read_be32(&b32[28]); + r->d[1] = rustsecp256k1_v0_11_read_be32(&b32[24]); + r->d[2] = rustsecp256k1_v0_11_read_be32(&b32[20]); + r->d[3] = rustsecp256k1_v0_11_read_be32(&b32[16]); + r->d[4] = rustsecp256k1_v0_11_read_be32(&b32[12]); + r->d[5] = rustsecp256k1_v0_11_read_be32(&b32[8]); + r->d[6] = rustsecp256k1_v0_11_read_be32(&b32[4]); + r->d[7] = rustsecp256k1_v0_11_read_be32(&b32[0]); + over = rustsecp256k1_v0_11_scalar_reduce(r, rustsecp256k1_v0_11_scalar_check_overflow(r)); if (overflow) { *overflow = over; } @@ -200,27 +190,27 @@ static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_10_0_scalar* a) { +static void rustsecp256k1_v0_11_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_11_scalar* a) { SECP256K1_SCALAR_VERIFY(a); - rustsecp256k1_v0_10_0_write_be32(&bin[0], a->d[7]); - rustsecp256k1_v0_10_0_write_be32(&bin[4], a->d[6]); - rustsecp256k1_v0_10_0_write_be32(&bin[8], a->d[5]); - rustsecp256k1_v0_10_0_write_be32(&bin[12], a->d[4]); - rustsecp256k1_v0_10_0_write_be32(&bin[16], a->d[3]); - rustsecp256k1_v0_10_0_write_be32(&bin[20], a->d[2]); - rustsecp256k1_v0_10_0_write_be32(&bin[24], a->d[1]); - rustsecp256k1_v0_10_0_write_be32(&bin[28], a->d[0]); + rustsecp256k1_v0_11_write_be32(&bin[0], a->d[7]); + rustsecp256k1_v0_11_write_be32(&bin[4], a->d[6]); + rustsecp256k1_v0_11_write_be32(&bin[8], a->d[5]); + rustsecp256k1_v0_11_write_be32(&bin[12], a->d[4]); + rustsecp256k1_v0_11_write_be32(&bin[16], a->d[3]); + rustsecp256k1_v0_11_write_be32(&bin[20], a->d[2]); + rustsecp256k1_v0_11_write_be32(&bin[24], a->d[1]); + rustsecp256k1_v0_11_write_be32(&bin[28], a->d[0]); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_zero(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_zero(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; } -static void rustsecp256k1_v0_10_0_scalar_negate(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a) { - uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_10_0_scalar_is_zero(a) == 0); +static void rustsecp256k1_v0_11_scalar_negate(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a) { + uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_11_scalar_is_zero(a) == 0); uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; SECP256K1_SCALAR_VERIFY(a); @@ -243,7 +233,7 @@ static void rustsecp256k1_v0_10_0_scalar_negate(rustsecp256k1_v0_10_0_scalar *r, SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_half(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_half(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a) { /* Writing `/` for field division and `//` for integer division, we compute * * a/2 = (a - (a&1))/2 + (a&1)/2 @@ -291,13 +281,13 @@ static void rustsecp256k1_v0_10_0_scalar_half(rustsecp256k1_v0_10_0_scalar *r, c SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_one(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_one(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; } -static int rustsecp256k1_v0_10_0_scalar_is_high(const rustsecp256k1_v0_10_0_scalar *a) { +static int rustsecp256k1_v0_11_scalar_is_high(const rustsecp256k1_v0_11_scalar *a) { int yes = 0; int no = 0; SECP256K1_SCALAR_VERIFY(a); @@ -317,12 +307,12 @@ static int rustsecp256k1_v0_10_0_scalar_is_high(const rustsecp256k1_v0_10_0_scal return yes; } -static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar *r, int flag) { +static int rustsecp256k1_v0_11_scalar_cond_negate(rustsecp256k1_v0_11_scalar *r, int flag) { /* If we are flag = 0, mask = 00...00 and this is a no-op; - * if we are flag = 1, mask = 11...11 and this is identical to rustsecp256k1_v0_10_0_scalar_negate */ + * if we are flag = 1, mask = 11...11 and this is identical to rustsecp256k1_v0_11_scalar_negate */ volatile int vflag = flag; uint32_t mask = -vflag; - uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_10_0_scalar_is_zero(r) == 0); + uint32_t nonzero = 0xFFFFFFFFUL * (rustsecp256k1_v0_11_scalar_is_zero(r) == 0); uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); SECP256K1_SCALAR_VERIFY(r); @@ -411,7 +401,7 @@ static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar VERIFY_CHECK(c2 == 0); \ } -static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar *r, const uint32_t *l) { +static void rustsecp256k1_v0_11_scalar_reduce_512(rustsecp256k1_v0_11_scalar *r, const uint32_t *l) { uint64_t c; uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; @@ -550,10 +540,10 @@ static void rustsecp256k1_v0_10_0_scalar_reduce_512(rustsecp256k1_v0_10_0_scalar r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; /* Final reduction of r. */ - rustsecp256k1_v0_10_0_scalar_reduce(r, c + rustsecp256k1_v0_10_0_scalar_check_overflow(r)); + rustsecp256k1_v0_11_scalar_reduce(r, c + rustsecp256k1_v0_11_scalar_check_overflow(r)); } -static void rustsecp256k1_v0_10_0_scalar_mul_512(uint32_t *l, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static void rustsecp256k1_v0_11_scalar_mul_512(uint32_t *l, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { /* 96 bit accumulator. */ uint32_t c0 = 0, c1 = 0, c2 = 0; @@ -648,18 +638,18 @@ static void rustsecp256k1_v0_10_0_scalar_mul_512(uint32_t *l, const rustsecp256k #undef extract #undef extract_fast -static void rustsecp256k1_v0_10_0_scalar_mul(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static void rustsecp256k1_v0_11_scalar_mul(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { uint32_t l[16]; SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); - rustsecp256k1_v0_10_0_scalar_mul_512(l, a, b); - rustsecp256k1_v0_10_0_scalar_reduce_512(r, l); + rustsecp256k1_v0_11_scalar_mul_512(l, a, b); + rustsecp256k1_v0_11_scalar_reduce_512(r, l); SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar *r1, rustsecp256k1_v0_10_0_scalar *r2, const rustsecp256k1_v0_10_0_scalar *k) { +static void rustsecp256k1_v0_11_scalar_split_128(rustsecp256k1_v0_11_scalar *r1, rustsecp256k1_v0_11_scalar *r2, const rustsecp256k1_v0_11_scalar *k) { SECP256K1_SCALAR_VERIFY(k); r1->d[0] = k->d[0]; @@ -683,14 +673,14 @@ static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar SECP256K1_SCALAR_VERIFY(r2); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_eq(const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_eq(const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b, unsigned int shift) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_scalar_mul_shift_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b, unsigned int shift) { uint32_t l[16]; unsigned int shiftlimbs; unsigned int shiftlow; @@ -699,7 +689,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp SECP256K1_SCALAR_VERIFY(b); VERIFY_CHECK(shift >= 256); - rustsecp256k1_v0_10_0_scalar_mul_512(l, a, b); + rustsecp256k1_v0_11_scalar_mul_512(l, a, b); shiftlimbs = shift >> 5; shiftlow = shift & 0x1F; shifthigh = 32 - shiftlow; @@ -711,12 +701,12 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_mul_shift_var(rustsecp r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; - rustsecp256k1_v0_10_0_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); + rustsecp256k1_v0_11_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); SECP256K1_SCALAR_VERIFY(r); } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_scalar_cmov(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; SECP256K1_SCALAR_VERIFY(a); @@ -736,11 +726,11 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_ SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_from_signed30(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_modinv32_signed30 *a) { +static void rustsecp256k1_v0_11_scalar_from_signed30(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_modinv32_signed30 *a) { const uint32_t a0 = a->v[0], a1 = a->v[1], a2 = a->v[2], a3 = a->v[3], a4 = a->v[4], a5 = a->v[5], a6 = a->v[6], a7 = a->v[7], a8 = a->v[8]; - /* The output from rustsecp256k1_v0_10_0_modinv32{_var} should be normalized to range [0,modulus), and + /* The output from rustsecp256k1_v0_11_modinv32{_var} should be normalized to range [0,modulus), and * have limbs in [0,2^30). The modulus is < 2^256, so the top limb must be below 2^(256-30*8). */ VERIFY_CHECK(a0 >> 30 == 0); @@ -765,7 +755,7 @@ static void rustsecp256k1_v0_10_0_scalar_from_signed30(rustsecp256k1_v0_10_0_sca SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_to_signed30(rustsecp256k1_v0_10_0_modinv32_signed30 *r, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_to_signed30(rustsecp256k1_v0_11_modinv32_signed30 *r, const rustsecp256k1_v0_11_scalar *a) { const uint32_t M30 = UINT32_MAX >> 2; const uint32_t a0 = a->d[0], a1 = a->d[1], a2 = a->d[2], a3 = a->d[3], a4 = a->d[4], a5 = a->d[5], a6 = a->d[6], a7 = a->d[7]; @@ -782,42 +772,42 @@ static void rustsecp256k1_v0_10_0_scalar_to_signed30(rustsecp256k1_v0_10_0_modin r->v[8] = a7 >> 16; } -static const rustsecp256k1_v0_10_0_modinv32_modinfo rustsecp256k1_v0_10_0_const_modinfo_scalar = { +static const rustsecp256k1_v0_11_modinv32_modinfo rustsecp256k1_v0_11_const_modinfo_scalar = { {{0x10364141L, 0x3F497A33L, 0x348A03BBL, 0x2BB739ABL, -0x146L, 0, 0, 0, 65536}}, 0x2A774EC1L }; -static void rustsecp256k1_v0_10_0_scalar_inverse(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *x) { - rustsecp256k1_v0_10_0_modinv32_signed30 s; +static void rustsecp256k1_v0_11_scalar_inverse(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *x) { + rustsecp256k1_v0_11_modinv32_signed30 s; #ifdef VERIFY - int zero_in = rustsecp256k1_v0_10_0_scalar_is_zero(x); + int zero_in = rustsecp256k1_v0_11_scalar_is_zero(x); #endif SECP256K1_SCALAR_VERIFY(x); - rustsecp256k1_v0_10_0_scalar_to_signed30(&s, x); - rustsecp256k1_v0_10_0_modinv32(&s, &rustsecp256k1_v0_10_0_const_modinfo_scalar); - rustsecp256k1_v0_10_0_scalar_from_signed30(r, &s); + rustsecp256k1_v0_11_scalar_to_signed30(&s, x); + rustsecp256k1_v0_11_modinv32(&s, &rustsecp256k1_v0_11_const_modinfo_scalar); + rustsecp256k1_v0_11_scalar_from_signed30(r, &s); SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(r) == zero_in); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_is_zero(r) == zero_in); } -static void rustsecp256k1_v0_10_0_scalar_inverse_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *x) { - rustsecp256k1_v0_10_0_modinv32_signed30 s; +static void rustsecp256k1_v0_11_scalar_inverse_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *x) { + rustsecp256k1_v0_11_modinv32_signed30 s; #ifdef VERIFY - int zero_in = rustsecp256k1_v0_10_0_scalar_is_zero(x); + int zero_in = rustsecp256k1_v0_11_scalar_is_zero(x); #endif SECP256K1_SCALAR_VERIFY(x); - rustsecp256k1_v0_10_0_scalar_to_signed30(&s, x); - rustsecp256k1_v0_10_0_modinv32_var(&s, &rustsecp256k1_v0_10_0_const_modinfo_scalar); - rustsecp256k1_v0_10_0_scalar_from_signed30(r, &s); + rustsecp256k1_v0_11_scalar_to_signed30(&s, x); + rustsecp256k1_v0_11_modinv32_var(&s, &rustsecp256k1_v0_11_const_modinfo_scalar); + rustsecp256k1_v0_11_scalar_from_signed30(r, &s); SECP256K1_SCALAR_VERIFY(r); - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(r) == zero_in); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_is_zero(r) == zero_in); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_even(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_even(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return !(a->d[0] & 1); diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_impl.h index 96a2f29ea..6bf4178a9 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_impl.h @@ -24,19 +24,23 @@ #error "Please select wide multiplication implementation" #endif -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_scalar_one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_scalar_zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); -static int rustsecp256k1_v0_10_0_scalar_set_b32_seckey(rustsecp256k1_v0_10_0_scalar *r, const unsigned char *bin) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_scalar_clear(rustsecp256k1_v0_11_scalar *r) { + rustsecp256k1_v0_11_memclear(r, sizeof(rustsecp256k1_v0_11_scalar)); +} + +static int rustsecp256k1_v0_11_scalar_set_b32_seckey(rustsecp256k1_v0_11_scalar *r, const unsigned char *bin) { int overflow; - rustsecp256k1_v0_10_0_scalar_set_b32(r, bin, &overflow); + rustsecp256k1_v0_11_scalar_set_b32(r, bin, &overflow); SECP256K1_SCALAR_VERIFY(r); - return (!overflow) & (!rustsecp256k1_v0_10_0_scalar_is_zero(r)); + return (!overflow) & (!rustsecp256k1_v0_11_scalar_is_zero(r)); } -static void rustsecp256k1_v0_10_0_scalar_verify(const rustsecp256k1_v0_10_0_scalar *r) { - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_check_overflow(r) == 0); +static void rustsecp256k1_v0_11_scalar_verify(const rustsecp256k1_v0_11_scalar *r) { + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_check_overflow(r) == 0); (void)r; } @@ -60,7 +64,7 @@ static void rustsecp256k1_v0_10_0_scalar_verify(const rustsecp256k1_v0_10_0_scal * nontrivial to get full test coverage for the exhaustive tests. We therefore * (arbitrarily) set r2 = k + 5 (mod n) and r1 = k - r2 * lambda (mod n). */ -static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT k) { +static void rustsecp256k1_v0_11_scalar_split_lambda(rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT k) { SECP256K1_SCALAR_VERIFY(k); VERIFY_CHECK(r1 != k); VERIFY_CHECK(r2 != k); @@ -76,13 +80,13 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scal /** * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where * lambda is: */ -static const rustsecp256k1_v0_10_0_scalar rustsecp256k1_v0_10_0_const_lambda = SECP256K1_SCALAR_CONST( +static const rustsecp256k1_v0_11_scalar rustsecp256k1_v0_11_const_lambda = SECP256K1_SCALAR_CONST( 0x5363AD4CUL, 0xC05C30E0UL, 0xA5261C02UL, 0x8812645AUL, 0x122E22EAUL, 0x20816678UL, 0xDF02967CUL, 0x1B23BD72UL ); #ifdef VERIFY -static void rustsecp256k1_v0_10_0_scalar_split_lambda_verify(const rustsecp256k1_v0_10_0_scalar *r1, const rustsecp256k1_v0_10_0_scalar *r2, const rustsecp256k1_v0_10_0_scalar *k); +static void rustsecp256k1_v0_11_scalar_split_lambda_verify(const rustsecp256k1_v0_11_scalar *r1, const rustsecp256k1_v0_11_scalar *r2, const rustsecp256k1_v0_11_scalar *k); #endif /* @@ -135,21 +139,21 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda_verify(const rustsecp256k1 * * See proof below. */ -static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_10_0_scalar * SECP256K1_RESTRICT k) { - rustsecp256k1_v0_10_0_scalar c1, c2; - static const rustsecp256k1_v0_10_0_scalar minus_b1 = SECP256K1_SCALAR_CONST( +static void rustsecp256k1_v0_11_scalar_split_lambda(rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT r1, rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT r2, const rustsecp256k1_v0_11_scalar * SECP256K1_RESTRICT k) { + rustsecp256k1_v0_11_scalar c1, c2; + static const rustsecp256k1_v0_11_scalar minus_b1 = SECP256K1_SCALAR_CONST( 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL ); - static const rustsecp256k1_v0_10_0_scalar minus_b2 = SECP256K1_SCALAR_CONST( + static const rustsecp256k1_v0_11_scalar minus_b2 = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL ); - static const rustsecp256k1_v0_10_0_scalar g1 = SECP256K1_SCALAR_CONST( + static const rustsecp256k1_v0_11_scalar g1 = SECP256K1_SCALAR_CONST( 0x3086D221UL, 0xA7D46BCDUL, 0xE86C90E4UL, 0x9284EB15UL, 0x3DAA8A14UL, 0x71E8CA7FUL, 0xE893209AUL, 0x45DBB031UL ); - static const rustsecp256k1_v0_10_0_scalar g2 = SECP256K1_SCALAR_CONST( + static const rustsecp256k1_v0_11_scalar g2 = SECP256K1_SCALAR_CONST( 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C4UL, 0x221208ACUL, 0x9DF506C6UL, 0x1571B4AEUL, 0x8AC47F71UL ); @@ -159,25 +163,25 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scal VERIFY_CHECK(r1 != r2); /* these _var calls are constant time since the shift amount is constant */ - rustsecp256k1_v0_10_0_scalar_mul_shift_var(&c1, k, &g1, 384); - rustsecp256k1_v0_10_0_scalar_mul_shift_var(&c2, k, &g2, 384); - rustsecp256k1_v0_10_0_scalar_mul(&c1, &c1, &minus_b1); - rustsecp256k1_v0_10_0_scalar_mul(&c2, &c2, &minus_b2); - rustsecp256k1_v0_10_0_scalar_add(r2, &c1, &c2); - rustsecp256k1_v0_10_0_scalar_mul(r1, r2, &rustsecp256k1_v0_10_0_const_lambda); - rustsecp256k1_v0_10_0_scalar_negate(r1, r1); - rustsecp256k1_v0_10_0_scalar_add(r1, r1, k); + rustsecp256k1_v0_11_scalar_mul_shift_var(&c1, k, &g1, 384); + rustsecp256k1_v0_11_scalar_mul_shift_var(&c2, k, &g2, 384); + rustsecp256k1_v0_11_scalar_mul(&c1, &c1, &minus_b1); + rustsecp256k1_v0_11_scalar_mul(&c2, &c2, &minus_b2); + rustsecp256k1_v0_11_scalar_add(r2, &c1, &c2); + rustsecp256k1_v0_11_scalar_mul(r1, r2, &rustsecp256k1_v0_11_const_lambda); + rustsecp256k1_v0_11_scalar_negate(r1, r1); + rustsecp256k1_v0_11_scalar_add(r1, r1, k); SECP256K1_SCALAR_VERIFY(r1); SECP256K1_SCALAR_VERIFY(r2); #ifdef VERIFY - rustsecp256k1_v0_10_0_scalar_split_lambda_verify(r1, r2, k); + rustsecp256k1_v0_11_scalar_split_lambda_verify(r1, r2, k); #endif } #ifdef VERIFY /* - * Proof for rustsecp256k1_v0_10_0_scalar_split_lambda's bounds. + * Proof for rustsecp256k1_v0_11_scalar_split_lambda's bounds. * * Let * - epsilon1 = 2^256 * |g1/2^384 - b2/d| @@ -229,7 +233,7 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scal * <= {triangle inequality} * a1*|k*b2/n - c1| + a2*|k*(-b1)/n - c2| * < {Lemma 1 and Lemma 2} - * a1*(2^-1 + epslion1) + a2*(2^-1 + epsilon2) + * a1*(2^-1 + epsilon1) + a2*(2^-1 + epsilon2) * < {rounding up to an integer} * (a1 + a2 + 1)/2 * < {rounding up to a power of 2} @@ -247,7 +251,7 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scal * <= {triangle inequality} * (-b1)*|k*b2/n - c1| + b2*|k*(-b1)/n - c2| * < {Lemma 1 and Lemma 2} - * (-b1)*(2^-1 + epslion1) + b2*(2^-1 + epsilon2) + * (-b1)*(2^-1 + epsilon1) + b2*(2^-1 + epsilon2) * < {rounding up to an integer} * (-b1 + b2)/2 + 1 * < {rounding up to a power of 2} @@ -280,8 +284,8 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda(rustsecp256k1_v0_10_0_scal * * Q.E.D. */ -static void rustsecp256k1_v0_10_0_scalar_split_lambda_verify(const rustsecp256k1_v0_10_0_scalar *r1, const rustsecp256k1_v0_10_0_scalar *r2, const rustsecp256k1_v0_10_0_scalar *k) { - rustsecp256k1_v0_10_0_scalar s; +static void rustsecp256k1_v0_11_scalar_split_lambda_verify(const rustsecp256k1_v0_11_scalar *r1, const rustsecp256k1_v0_11_scalar *r2, const rustsecp256k1_v0_11_scalar *k) { + rustsecp256k1_v0_11_scalar s; unsigned char buf1[32]; unsigned char buf2[32]; @@ -297,19 +301,19 @@ static void rustsecp256k1_v0_10_0_scalar_split_lambda_verify(const rustsecp256k1 0x8a, 0x65, 0x28, 0x7b, 0xd4, 0x71, 0x79, 0xfb, 0x2b, 0xe0, 0x88, 0x46, 0xce, 0xa2, 0x67, 0xed }; - rustsecp256k1_v0_10_0_scalar_mul(&s, &rustsecp256k1_v0_10_0_const_lambda, r2); - rustsecp256k1_v0_10_0_scalar_add(&s, &s, r1); - VERIFY_CHECK(rustsecp256k1_v0_10_0_scalar_eq(&s, k)); + rustsecp256k1_v0_11_scalar_mul(&s, &rustsecp256k1_v0_11_const_lambda, r2); + rustsecp256k1_v0_11_scalar_add(&s, &s, r1); + VERIFY_CHECK(rustsecp256k1_v0_11_scalar_eq(&s, k)); - rustsecp256k1_v0_10_0_scalar_negate(&s, r1); - rustsecp256k1_v0_10_0_scalar_get_b32(buf1, r1); - rustsecp256k1_v0_10_0_scalar_get_b32(buf2, &s); - VERIFY_CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf1, k1_bound, 32) < 0 || rustsecp256k1_v0_10_0_memcmp_var(buf2, k1_bound, 32) < 0); + rustsecp256k1_v0_11_scalar_negate(&s, r1); + rustsecp256k1_v0_11_scalar_get_b32(buf1, r1); + rustsecp256k1_v0_11_scalar_get_b32(buf2, &s); + VERIFY_CHECK(rustsecp256k1_v0_11_memcmp_var(buf1, k1_bound, 32) < 0 || rustsecp256k1_v0_11_memcmp_var(buf2, k1_bound, 32) < 0); - rustsecp256k1_v0_10_0_scalar_negate(&s, r2); - rustsecp256k1_v0_10_0_scalar_get_b32(buf1, r2); - rustsecp256k1_v0_10_0_scalar_get_b32(buf2, &s); - VERIFY_CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf1, k2_bound, 32) < 0 || rustsecp256k1_v0_10_0_memcmp_var(buf2, k2_bound, 32) < 0); + rustsecp256k1_v0_11_scalar_negate(&s, r2); + rustsecp256k1_v0_11_scalar_get_b32(buf1, r2); + rustsecp256k1_v0_11_scalar_get_b32(buf2, &s); + VERIFY_CHECK(rustsecp256k1_v0_11_memcmp_var(buf1, k2_bound, 32) < 0 || rustsecp256k1_v0_11_memcmp_var(buf2, k2_bound, 32) < 0); } #endif /* VERIFY */ #endif /* !defined(EXHAUSTIVE_TEST_ORDER) */ diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_low.h b/secp256k1-sys/depend/secp256k1/src/scalar_low.h index b5ad2a95b..1995c1468 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_low.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_low.h @@ -10,7 +10,7 @@ #include /** A scalar modulo the group order of the secp256k1 curve. */ -typedef uint32_t rustsecp256k1_v0_10_0_scalar; +typedef uint32_t rustsecp256k1_v0_11_scalar; /* A compile-time constant equal to 2^32 (modulo order). */ #define SCALAR_2P32 ((0xffffffffUL % EXHAUSTIVE_TEST_ORDER) + 1U) diff --git a/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h b/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h index 377ae6ddb..b0fb66f12 100644 --- a/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scalar_low_impl.h @@ -13,38 +13,38 @@ #include -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_even(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_even(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return !(*a & 1); } -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_clear(rustsecp256k1_v0_10_0_scalar *r) { *r = 0; } - -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_scalar_set_int(rustsecp256k1_v0_10_0_scalar *r, unsigned int v) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_scalar_set_int(rustsecp256k1_v0_11_scalar *r, unsigned int v) { *r = v % EXHAUSTIVE_TEST_ORDER; SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static unsigned int rustsecp256k1_v0_10_0_scalar_get_bits(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_scalar_get_bits_limb32(const rustsecp256k1_v0_11_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 unsigned int rustsecp256k1_v0_10_0_scalar_get_bits_var(const rustsecp256k1_v0_10_0_scalar *a, unsigned int offset, unsigned int count) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_scalar_get_bits_var(const rustsecp256k1_v0_11_scalar *a, unsigned int offset, unsigned int count) { SECP256K1_SCALAR_VERIFY(a); - return rustsecp256k1_v0_10_0_scalar_get_bits(a, offset, count); + return rustsecp256k1_v0_11_scalar_get_bits_limb32(a, offset, count); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_check_overflow(const rustsecp256k1_v0_10_0_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_check_overflow(const rustsecp256k1_v0_11_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } -static int rustsecp256k1_v0_10_0_scalar_add(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static int rustsecp256k1_v0_11_scalar_add(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); @@ -54,7 +54,7 @@ static int rustsecp256k1_v0_10_0_scalar_add(rustsecp256k1_v0_10_0_scalar *r, con return *r < *b; } -static void rustsecp256k1_v0_10_0_scalar_cadd_bit(rustsecp256k1_v0_10_0_scalar *r, unsigned int bit, int flag) { +static void rustsecp256k1_v0_11_scalar_cadd_bit(rustsecp256k1_v0_11_scalar *r, unsigned int bit, int flag) { SECP256K1_SCALAR_VERIFY(r); if (flag && bit < 32) @@ -66,7 +66,7 @@ static void rustsecp256k1_v0_10_0_scalar_cadd_bit(rustsecp256k1_v0_10_0_scalar * VERIFY_CHECK(((uint32_t)1 << bit) - 1 <= UINT32_MAX - EXHAUSTIVE_TEST_ORDER); } -static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r, const unsigned char *b32, int *overflow) { +static void rustsecp256k1_v0_11_scalar_set_b32(rustsecp256k1_v0_11_scalar *r, const unsigned char *b32, int *overflow) { int i; int over = 0; *r = 0; @@ -82,20 +82,20 @@ static void rustsecp256k1_v0_10_0_scalar_set_b32(rustsecp256k1_v0_10_0_scalar *r SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_10_0_scalar* a) { +static void rustsecp256k1_v0_11_scalar_get_b32(unsigned char *bin, const rustsecp256k1_v0_11_scalar* a) { SECP256K1_SCALAR_VERIFY(a); memset(bin, 0, 32); bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_zero(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_zero(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return *a == 0; } -static void rustsecp256k1_v0_10_0_scalar_negate(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_negate(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); if (*a == 0) { @@ -107,28 +107,28 @@ static void rustsecp256k1_v0_10_0_scalar_negate(rustsecp256k1_v0_10_0_scalar *r, SECP256K1_SCALAR_VERIFY(r); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_is_one(const rustsecp256k1_v0_10_0_scalar *a) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_is_one(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return *a == 1; } -static int rustsecp256k1_v0_10_0_scalar_is_high(const rustsecp256k1_v0_10_0_scalar *a) { +static int rustsecp256k1_v0_11_scalar_is_high(const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); return *a > EXHAUSTIVE_TEST_ORDER / 2; } -static int rustsecp256k1_v0_10_0_scalar_cond_negate(rustsecp256k1_v0_10_0_scalar *r, int flag) { +static int rustsecp256k1_v0_11_scalar_cond_negate(rustsecp256k1_v0_11_scalar *r, int flag) { SECP256K1_SCALAR_VERIFY(r); - if (flag) rustsecp256k1_v0_10_0_scalar_negate(r, r); + if (flag) rustsecp256k1_v0_11_scalar_negate(r, r); SECP256K1_SCALAR_VERIFY(r); return flag ? -1 : 1; } -static void rustsecp256k1_v0_10_0_scalar_mul(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +static void rustsecp256k1_v0_11_scalar_mul(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); @@ -137,7 +137,7 @@ static void rustsecp256k1_v0_10_0_scalar_mul(rustsecp256k1_v0_10_0_scalar *r, co SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar *r1, rustsecp256k1_v0_10_0_scalar *r2, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_split_128(rustsecp256k1_v0_11_scalar *r1, rustsecp256k1_v0_11_scalar *r2, const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); *r1 = *a; @@ -147,14 +147,14 @@ static void rustsecp256k1_v0_10_0_scalar_split_128(rustsecp256k1_v0_10_0_scalar SECP256K1_SCALAR_VERIFY(r2); } -SECP256K1_INLINE static int rustsecp256k1_v0_10_0_scalar_eq(const rustsecp256k1_v0_10_0_scalar *a, const rustsecp256k1_v0_10_0_scalar *b) { +SECP256K1_INLINE static int rustsecp256k1_v0_11_scalar_eq(const rustsecp256k1_v0_11_scalar *a, const rustsecp256k1_v0_11_scalar *b) { SECP256K1_SCALAR_VERIFY(a); SECP256K1_SCALAR_VERIFY(b); return *a == *b; } -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_scalar_cmov(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a, int flag) { uint32_t mask0, mask1; volatile int vflag = flag; SECP256K1_SCALAR_VERIFY(a); @@ -167,30 +167,35 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_scalar_cmov(rustsecp256k1_v0_ SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_inverse(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *x) { +static void rustsecp256k1_v0_11_scalar_inverse(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_scalar_inverse_var(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *x) { +static void rustsecp256k1_v0_11_scalar_inverse_var(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *x) { SECP256K1_SCALAR_VERIFY(x); - rustsecp256k1_v0_10_0_scalar_inverse(r, x); + rustsecp256k1_v0_11_scalar_inverse(r, x); SECP256K1_SCALAR_VERIFY(r); } -static void rustsecp256k1_v0_10_0_scalar_half(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_scalar *a) { +static void rustsecp256k1_v0_11_scalar_half(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_scalar *a) { SECP256K1_SCALAR_VERIFY(a); *r = (*a + ((-(uint32_t)(*a & 1)) & EXHAUSTIVE_TEST_ORDER)) >> 1; diff --git a/secp256k1-sys/depend/secp256k1/src/scratch.h b/secp256k1-sys/depend/secp256k1/src/scratch.h index 7dc178804..9a9cffa32 100644 --- a/secp256k1-sys/depend/secp256k1/src/scratch.h +++ b/secp256k1-sys/depend/secp256k1/src/scratch.h @@ -9,7 +9,7 @@ /* The typedef is used internally; the struct name is used in the public API * (where it is exposed as a different typedef) */ -typedef struct rustsecp256k1_v0_10_0_scratch_space_struct { +typedef struct rustsecp256k1_v0_11_scratch_space_struct { /** guard against interpreting this object as other types */ unsigned char magic[8]; /** actual allocated data */ @@ -19,24 +19,22 @@ typedef struct rustsecp256k1_v0_10_0_scratch_space_struct { size_t alloc_size; /** maximum size available to allocate */ size_t max_size; -} rustsecp256k1_v0_10_0_scratch; +} rustsecp256k1_v0_11_scratch; -static rustsecp256k1_v0_10_0_scratch* rustsecp256k1_v0_10_0_scratch_create(const rustsecp256k1_v0_10_0_callback* error_callback, size_t max_size); - -static void rustsecp256k1_v0_10_0_scratch_destroy(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch* scratch); +typedef struct rustsecp256k1_v0_11_scratch_space_struct rustsecp256k1_v0_11_scratch_space; /** Returns an opaque object used to "checkpoint" a scratch space. Used - * with `rustsecp256k1_v0_10_0_scratch_apply_checkpoint` to undo allocations. */ -static size_t rustsecp256k1_v0_10_0_scratch_checkpoint(const rustsecp256k1_v0_10_0_callback* error_callback, const rustsecp256k1_v0_10_0_scratch* scratch); + * with `rustsecp256k1_v0_11_scratch_apply_checkpoint` to undo allocations. */ +static size_t rustsecp256k1_v0_11_scratch_checkpoint(const rustsecp256k1_v0_11_callback* error_callback, const rustsecp256k1_v0_11_scratch* scratch); -/** Applies a check point received from `rustsecp256k1_v0_10_0_scratch_checkpoint`, +/** Applies a check point received from `rustsecp256k1_v0_11_scratch_checkpoint`, * undoing all allocations since that point. */ -static void rustsecp256k1_v0_10_0_scratch_apply_checkpoint(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch* scratch, size_t checkpoint); +static void rustsecp256k1_v0_11_scratch_apply_checkpoint(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch* scratch, size_t checkpoint); /** Returns the maximum allocation the scratch space will allow */ -static size_t rustsecp256k1_v0_10_0_scratch_max_allocation(const rustsecp256k1_v0_10_0_callback* error_callback, const rustsecp256k1_v0_10_0_scratch* scratch, size_t n_objects); +static size_t rustsecp256k1_v0_11_scratch_max_allocation(const rustsecp256k1_v0_11_callback* error_callback, const rustsecp256k1_v0_11_scratch* scratch, size_t n_objects); /** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */ -static void *rustsecp256k1_v0_10_0_scratch_alloc(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch* scratch, size_t n); +static void *rustsecp256k1_v0_11_scratch_alloc(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch* scratch, size_t n); #endif diff --git a/secp256k1-sys/depend/secp256k1/src/scratch_impl.h b/secp256k1-sys/depend/secp256k1/src/scratch_impl.h index cfcb464a3..98677ddb4 100644 --- a/secp256k1-sys/depend/secp256k1/src/scratch_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/scratch_impl.h @@ -10,29 +10,29 @@ #include "util.h" #include "scratch.h" -static size_t rustsecp256k1_v0_10_0_scratch_checkpoint(const rustsecp256k1_v0_10_0_callback* error_callback, const rustsecp256k1_v0_10_0_scratch* scratch) { - if (rustsecp256k1_v0_10_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { - rustsecp256k1_v0_10_0_callback_call(error_callback, "invalid scratch space"); +static size_t rustsecp256k1_v0_11_scratch_checkpoint(const rustsecp256k1_v0_11_callback* error_callback, const rustsecp256k1_v0_11_scratch* scratch) { + if (rustsecp256k1_v0_11_memcmp_var(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_11_callback_call(error_callback, "invalid scratch space"); return 0; } return scratch->alloc_size; } -static void rustsecp256k1_v0_10_0_scratch_apply_checkpoint(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch* scratch, size_t checkpoint) { - if (rustsecp256k1_v0_10_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { - rustsecp256k1_v0_10_0_callback_call(error_callback, "invalid scratch space"); +static void rustsecp256k1_v0_11_scratch_apply_checkpoint(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch* scratch, size_t checkpoint) { + if (rustsecp256k1_v0_11_memcmp_var(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_11_callback_call(error_callback, "invalid scratch space"); return; } if (checkpoint > scratch->alloc_size) { - rustsecp256k1_v0_10_0_callback_call(error_callback, "invalid checkpoint"); + rustsecp256k1_v0_11_callback_call(error_callback, "invalid checkpoint"); return; } scratch->alloc_size = checkpoint; } -static size_t rustsecp256k1_v0_10_0_scratch_max_allocation(const rustsecp256k1_v0_10_0_callback* error_callback, const rustsecp256k1_v0_10_0_scratch* scratch, size_t objects) { - if (rustsecp256k1_v0_10_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { - rustsecp256k1_v0_10_0_callback_call(error_callback, "invalid scratch space"); +static size_t rustsecp256k1_v0_11_scratch_max_allocation(const rustsecp256k1_v0_11_callback* error_callback, const rustsecp256k1_v0_11_scratch* scratch, size_t objects) { + if (rustsecp256k1_v0_11_memcmp_var(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_11_callback_call(error_callback, "invalid scratch space"); return 0; } /* Ensure that multiplication will not wrap around */ @@ -45,7 +45,7 @@ static size_t rustsecp256k1_v0_10_0_scratch_max_allocation(const rustsecp256k1_v return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); } -static void *rustsecp256k1_v0_10_0_scratch_alloc(const rustsecp256k1_v0_10_0_callback* error_callback, rustsecp256k1_v0_10_0_scratch* scratch, size_t size) { +static void *rustsecp256k1_v0_11_scratch_alloc(const rustsecp256k1_v0_11_callback* error_callback, rustsecp256k1_v0_11_scratch* scratch, size_t size) { void *ret; size_t rounded_size; @@ -56,8 +56,8 @@ static void *rustsecp256k1_v0_10_0_scratch_alloc(const rustsecp256k1_v0_10_0_cal } size = rounded_size; - if (rustsecp256k1_v0_10_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { - rustsecp256k1_v0_10_0_callback_call(error_callback, "invalid scratch space"); + if (rustsecp256k1_v0_11_memcmp_var(scratch->magic, "scratch", 8) != 0) { + rustsecp256k1_v0_11_callback_call(error_callback, "invalid scratch space"); return NULL; } diff --git a/secp256k1-sys/depend/secp256k1/src/secp256k1.c b/secp256k1-sys/depend/secp256k1/src/secp256k1.c index 7e8314ed9..565641936 100644 --- a/secp256k1-sys/depend/secp256k1/src/secp256k1.c +++ b/secp256k1-sys/depend/secp256k1/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" @@ -43,64 +44,64 @@ #define ARG_CHECK(cond) do { \ if (EXPECT(!(cond), 0)) { \ - rustsecp256k1_v0_10_0_callback_call(&ctx->illegal_callback, #cond); \ + rustsecp256k1_v0_11_callback_call(&ctx->illegal_callback, #cond); \ return 0; \ } \ } while(0) #define ARG_CHECK_VOID(cond) do { \ if (EXPECT(!(cond), 0)) { \ - rustsecp256k1_v0_10_0_callback_call(&ctx->illegal_callback, #cond); \ + rustsecp256k1_v0_11_callback_call(&ctx->illegal_callback, #cond); \ return; \ } \ } while(0) /* Note that whenever you change the context struct, you must also change the * context_eq function. */ -struct rustsecp256k1_v0_10_0_context_struct { - rustsecp256k1_v0_10_0_ecmult_gen_context ecmult_gen_ctx; - rustsecp256k1_v0_10_0_callback illegal_callback; - rustsecp256k1_v0_10_0_callback error_callback; +struct rustsecp256k1_v0_11_context_struct { + rustsecp256k1_v0_11_ecmult_gen_context ecmult_gen_ctx; + rustsecp256k1_v0_11_callback illegal_callback; + rustsecp256k1_v0_11_callback error_callback; int declassify; }; -static const rustsecp256k1_v0_10_0_context rustsecp256k1_v0_10_0_context_static_ = { +static const rustsecp256k1_v0_11_context rustsecp256k1_v0_11_context_static_ = { { 0 }, - { rustsecp256k1_v0_10_0_default_illegal_callback_fn, 0 }, - { rustsecp256k1_v0_10_0_default_error_callback_fn, 0 }, + { rustsecp256k1_v0_11_default_illegal_callback_fn, 0 }, + { rustsecp256k1_v0_11_default_error_callback_fn, 0 }, 0 }; -const rustsecp256k1_v0_10_0_context *rustsecp256k1_v0_10_0_context_static = &rustsecp256k1_v0_10_0_context_static_; -const rustsecp256k1_v0_10_0_context *rustsecp256k1_v0_10_0_context_no_precomp = &rustsecp256k1_v0_10_0_context_static_; +const rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_static = &rustsecp256k1_v0_11_context_static_; +const rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_no_precomp = &rustsecp256k1_v0_11_context_static_; /* 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 rustsecp256k1_v0_10_0_context_clone. Function which need specific + * This is intended for "context" functions such as rustsecp256k1_v0_11_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 rustsecp256k1_v0_10_0_context_is_proper(const rustsecp256k1_v0_10_0_context* ctx) { - return rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx); +static int rustsecp256k1_v0_11_context_is_proper(const rustsecp256k1_v0_11_context* ctx) { + return rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx); } -void rustsecp256k1_v0_10_0_selftest(void) { - if (!rustsecp256k1_v0_10_0_selftest_passes()) { - rustsecp256k1_v0_10_0_callback_call(&default_error_callback, "self test failed"); +void rustsecp256k1_v0_11_selftest(void) { + if (!rustsecp256k1_v0_11_selftest_passes()) { + rustsecp256k1_v0_11_callback_call(&default_error_callback, "self test failed"); } } -size_t rustsecp256k1_v0_10_0_context_preallocated_size(unsigned int flags) { - size_t ret = sizeof(rustsecp256k1_v0_10_0_context); +size_t rustsecp256k1_v0_11_context_preallocated_size(unsigned int flags) { + size_t ret = sizeof(rustsecp256k1_v0_11_context); /* A return value of 0 is reserved as an indicator for errors when we call this function internally. */ VERIFY_CHECK(ret != 0); if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { - rustsecp256k1_v0_10_0_callback_call(&default_illegal_callback, + rustsecp256k1_v0_11_callback_call(&default_illegal_callback, "Invalid flags"); return 0; } if (EXPECT(!SECP256K1_CHECKMEM_RUNNING() && (flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY), 0)) { - rustsecp256k1_v0_10_0_callback_call(&default_illegal_callback, + rustsecp256k1_v0_11_callback_call(&default_illegal_callback, "Declassify flag requires running with memory checking"); return 0; } @@ -108,76 +109,76 @@ size_t rustsecp256k1_v0_10_0_context_preallocated_size(unsigned int flags) { return ret; } -size_t rustsecp256k1_v0_10_0_context_preallocated_clone_size(const rustsecp256k1_v0_10_0_context* ctx) { +size_t rustsecp256k1_v0_11_context_preallocated_clone_size(const rustsecp256k1_v0_11_context* ctx) { VERIFY_CHECK(ctx != NULL); - ARG_CHECK(rustsecp256k1_v0_10_0_context_is_proper(ctx)); - return sizeof(rustsecp256k1_v0_10_0_context); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); + return sizeof(rustsecp256k1_v0_11_context); } -rustsecp256k1_v0_10_0_context* rustsecp256k1_v0_10_0_context_preallocated_create(void* prealloc, unsigned int flags) { +rustsecp256k1_v0_11_context* rustsecp256k1_v0_11_context_preallocated_create(void* prealloc, unsigned int flags) { size_t prealloc_size; - rustsecp256k1_v0_10_0_context* ret; + rustsecp256k1_v0_11_context* ret; - rustsecp256k1_v0_10_0_selftest(); + rustsecp256k1_v0_11_selftest(); - prealloc_size = rustsecp256k1_v0_10_0_context_preallocated_size(flags); + prealloc_size = rustsecp256k1_v0_11_context_preallocated_size(flags); if (prealloc_size == 0) { return NULL; } VERIFY_CHECK(prealloc != NULL); - ret = (rustsecp256k1_v0_10_0_context*)prealloc; + ret = (rustsecp256k1_v0_11_context*)prealloc; ret->illegal_callback = default_illegal_callback; ret->error_callback = default_error_callback; - /* Flags have been checked by rustsecp256k1_v0_10_0_context_preallocated_size. */ + /* Flags have been checked by rustsecp256k1_v0_11_context_preallocated_size. */ VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT); - rustsecp256k1_v0_10_0_ecmult_gen_context_build(&ret->ecmult_gen_ctx); + rustsecp256k1_v0_11_ecmult_gen_context_build(&ret->ecmult_gen_ctx); ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); return ret; } -rustsecp256k1_v0_10_0_context* rustsecp256k1_v0_10_0_context_preallocated_clone(const rustsecp256k1_v0_10_0_context* ctx, void* prealloc) { - rustsecp256k1_v0_10_0_context* ret; +rustsecp256k1_v0_11_context* rustsecp256k1_v0_11_context_preallocated_clone(const rustsecp256k1_v0_11_context* ctx, void* prealloc) { + rustsecp256k1_v0_11_context* ret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(prealloc != NULL); - ARG_CHECK(rustsecp256k1_v0_10_0_context_is_proper(ctx)); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); - ret = (rustsecp256k1_v0_10_0_context*)prealloc; + ret = (rustsecp256k1_v0_11_context*)prealloc; *ret = *ctx; return ret; } -void rustsecp256k1_v0_10_0_context_preallocated_destroy(rustsecp256k1_v0_10_0_context* ctx) { - ARG_CHECK_VOID(ctx == NULL || rustsecp256k1_v0_10_0_context_is_proper(ctx)); +void rustsecp256k1_v0_11_context_preallocated_destroy(rustsecp256k1_v0_11_context* ctx) { + ARG_CHECK_VOID(ctx == NULL || rustsecp256k1_v0_11_context_is_proper(ctx)); /* Defined as noop */ if (ctx == NULL) { return; } - rustsecp256k1_v0_10_0_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); + rustsecp256k1_v0_11_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); } -void rustsecp256k1_v0_10_0_context_set_illegal_callback(rustsecp256k1_v0_10_0_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - /* We compare pointers instead of checking rustsecp256k1_v0_10_0_context_is_proper() here +void rustsecp256k1_v0_11_context_set_illegal_callback(rustsecp256k1_v0_11_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + /* We compare pointers instead of checking rustsecp256k1_v0_11_context_is_proper() here because setting callbacks is allowed on *copies* of the static context: it's harmless and makes testing easier. */ - ARG_CHECK_VOID(ctx != rustsecp256k1_v0_10_0_context_static); + ARG_CHECK_VOID(ctx != rustsecp256k1_v0_11_context_static); if (fun == NULL) { - fun = rustsecp256k1_v0_10_0_default_illegal_callback_fn; + fun = rustsecp256k1_v0_11_default_illegal_callback_fn; } ctx->illegal_callback.fn = fun; ctx->illegal_callback.data = data; } -void rustsecp256k1_v0_10_0_context_set_error_callback(rustsecp256k1_v0_10_0_context* ctx, void (*fun)(const char* message, void* data), const void* data) { - /* We compare pointers instead of checking rustsecp256k1_v0_10_0_context_is_proper() here +void rustsecp256k1_v0_11_context_set_error_callback(rustsecp256k1_v0_11_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + /* We compare pointers instead of checking rustsecp256k1_v0_11_context_is_proper() here because setting callbacks is allowed on *copies* of the static context: it's harmless and makes testing easier. */ - ARG_CHECK_VOID(ctx != rustsecp256k1_v0_10_0_context_static); + ARG_CHECK_VOID(ctx != rustsecp256k1_v0_11_context_static); if (fun == NULL) { - fun = rustsecp256k1_v0_10_0_default_error_callback_fn; + fun = rustsecp256k1_v0_11_default_error_callback_fn; } ctx->error_callback.fn = fun; ctx->error_callback.data = data; @@ -186,63 +187,40 @@ void rustsecp256k1_v0_10_0_context_set_error_callback(rustsecp256k1_v0_10_0_cont /* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour * of the software. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_declassify(const rustsecp256k1_v0_10_0_context* ctx, const void *p, size_t len) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_declassify(const rustsecp256k1_v0_11_context* ctx, const void *p, size_t len) { if (EXPECT(ctx->declassify, 0)) SECP256K1_CHECKMEM_DEFINE(p, len); } -static int rustsecp256k1_v0_10_0_pubkey_load(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ge* ge, const rustsecp256k1_v0_10_0_pubkey* pubkey) { - if (sizeof(rustsecp256k1_v0_10_0_ge_storage) == 64) { - /* When the rustsecp256k1_v0_10_0_ge_storage type is exactly 64 byte, use its - * representation inside rustsecp256k1_v0_10_0_pubkey, as conversion is very fast. - * Note that rustsecp256k1_v0_10_0_pubkey_save must use the same representation. */ - rustsecp256k1_v0_10_0_ge_storage s; - memcpy(&s, &pubkey->data[0], sizeof(s)); - rustsecp256k1_v0_10_0_ge_from_storage(ge, &s); - } else { - /* Otherwise, fall back to 32-byte big endian for X and Y. */ - rustsecp256k1_v0_10_0_fe x, y; - ARG_CHECK(rustsecp256k1_v0_10_0_fe_set_b32_limit(&x, pubkey->data)); - ARG_CHECK(rustsecp256k1_v0_10_0_fe_set_b32_limit(&y, pubkey->data + 32)); - rustsecp256k1_v0_10_0_ge_set_xy(ge, &x, &y); - } - ARG_CHECK(!rustsecp256k1_v0_10_0_fe_is_zero(&ge->x)); +static int rustsecp256k1_v0_11_pubkey_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ge* ge, const rustsecp256k1_v0_11_pubkey* pubkey) { + rustsecp256k1_v0_11_ge_from_bytes(ge, pubkey->data); + ARG_CHECK(!rustsecp256k1_v0_11_fe_is_zero(&ge->x)); return 1; } -static void rustsecp256k1_v0_10_0_pubkey_save(rustsecp256k1_v0_10_0_pubkey* pubkey, rustsecp256k1_v0_10_0_ge* ge) { - if (sizeof(rustsecp256k1_v0_10_0_ge_storage) == 64) { - rustsecp256k1_v0_10_0_ge_storage s; - rustsecp256k1_v0_10_0_ge_to_storage(&s, ge); - memcpy(&pubkey->data[0], &s, sizeof(s)); - } else { - VERIFY_CHECK(!rustsecp256k1_v0_10_0_ge_is_infinity(ge)); - rustsecp256k1_v0_10_0_fe_normalize_var(&ge->x); - rustsecp256k1_v0_10_0_fe_normalize_var(&ge->y); - rustsecp256k1_v0_10_0_fe_get_b32(pubkey->data, &ge->x); - rustsecp256k1_v0_10_0_fe_get_b32(pubkey->data + 32, &ge->y); - } +static void rustsecp256k1_v0_11_pubkey_save(rustsecp256k1_v0_11_pubkey* pubkey, rustsecp256k1_v0_11_ge* ge) { + rustsecp256k1_v0_11_ge_to_bytes(pubkey->data, ge); } -int rustsecp256k1_v0_10_0_ec_pubkey_parse(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey* pubkey, const unsigned char *input, size_t inputlen) { - rustsecp256k1_v0_10_0_ge Q; +int rustsecp256k1_v0_11_ec_pubkey_parse(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey* pubkey, const unsigned char *input, size_t inputlen) { + rustsecp256k1_v0_11_ge Q; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(input != NULL); - if (!rustsecp256k1_v0_10_0_eckey_pubkey_parse(&Q, input, inputlen)) { + if (!rustsecp256k1_v0_11_eckey_pubkey_parse(&Q, input, inputlen)) { return 0; } - if (!rustsecp256k1_v0_10_0_ge_is_in_correct_subgroup(&Q)) { + if (!rustsecp256k1_v0_11_ge_is_in_correct_subgroup(&Q)) { return 0; } - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &Q); - rustsecp256k1_v0_10_0_ge_clear(&Q); + rustsecp256k1_v0_11_pubkey_save(pubkey, &Q); + rustsecp256k1_v0_11_ge_clear(&Q); return 1; } -int rustsecp256k1_v0_10_0_ec_pubkey_serialize(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_10_0_pubkey* pubkey, unsigned int flags) { - rustsecp256k1_v0_10_0_ge Q; +int rustsecp256k1_v0_11_ec_pubkey_serialize(const rustsecp256k1_v0_11_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_11_pubkey* pubkey, unsigned int flags) { + rustsecp256k1_v0_11_ge Q; size_t len; int ret = 0; @@ -255,8 +233,8 @@ int rustsecp256k1_v0_10_0_ec_pubkey_serialize(const rustsecp256k1_v0_10_0_contex memset(output, 0, len); ARG_CHECK(pubkey != NULL); ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); - if (rustsecp256k1_v0_10_0_pubkey_load(ctx, &Q, pubkey)) { - ret = rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + if (rustsecp256k1_v0_11_pubkey_load(ctx, &Q, pubkey)) { + ret = rustsecp256k1_v0_11_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); if (ret) { *outputlen = len; } @@ -264,9 +242,9 @@ int rustsecp256k1_v0_10_0_ec_pubkey_serialize(const rustsecp256k1_v0_10_0_contex return ret; } -int rustsecp256k1_v0_10_0_ec_pubkey_cmp(const rustsecp256k1_v0_10_0_context* ctx, const rustsecp256k1_v0_10_0_pubkey* pubkey0, const rustsecp256k1_v0_10_0_pubkey* pubkey1) { +int rustsecp256k1_v0_11_ec_pubkey_cmp(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_pubkey* pubkey0, const rustsecp256k1_v0_11_pubkey* pubkey1) { unsigned char out[2][33]; - const rustsecp256k1_v0_10_0_pubkey* pk[2]; + const rustsecp256k1_v0_11_pubkey* pk[2]; int i; VERIFY_CHECK(ctx != NULL); @@ -279,7 +257,7 @@ int rustsecp256k1_v0_10_0_ec_pubkey_cmp(const rustsecp256k1_v0_10_0_context* ctx * results in consistent comparisons even if NULL or invalid pubkeys are * involved and prevents edge cases such as sorting algorithms that use * this function and do not terminate as a result. */ - if (!rustsecp256k1_v0_10_0_ec_pubkey_serialize(ctx, out[i], &out_size, pk[i], SECP256K1_EC_COMPRESSED)) { + if (!rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, out[i], &out_size, pk[i], SECP256K1_EC_COMPRESSED)) { /* Note that ec_pubkey_serialize should already set the output to * zero in that case, but it's not guaranteed by the API, we can't * test it and writing a VERIFY_CHECK is more complex than @@ -287,42 +265,70 @@ int rustsecp256k1_v0_10_0_ec_pubkey_cmp(const rustsecp256k1_v0_10_0_context* ctx memset(out[i], 0, sizeof(out[i])); } } - return rustsecp256k1_v0_10_0_memcmp_var(out[0], out[1], sizeof(out[0])); + return rustsecp256k1_v0_11_memcmp_var(out[0], out[1], sizeof(out[0])); } -static void rustsecp256k1_v0_10_0_ecdsa_signature_load(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_scalar* r, rustsecp256k1_v0_10_0_scalar* s, const rustsecp256k1_v0_10_0_ecdsa_signature* sig) { +static int rustsecp256k1_v0_11_ec_pubkey_sort_cmp(const void* pk1, const void* pk2, void *ctx) { + return rustsecp256k1_v0_11_ec_pubkey_cmp((rustsecp256k1_v0_11_context *)ctx, + *(rustsecp256k1_v0_11_pubkey **)pk1, + *(rustsecp256k1_v0_11_pubkey **)pk2); +} + +int rustsecp256k1_v0_11_ec_pubkey_sort(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_hsort nor + * rustsecp256k1_v0_11_ec_pubkey_sort_cmp modify the data pointed to by the cmp_data + * argument. */ + rustsecp256k1_v0_11_hsort(pubkeys, n_pubkeys, sizeof(*pubkeys), rustsecp256k1_v0_11_ec_pubkey_sort_cmp, (void *)ctx); + + #if defined(_MSC_VER) && (_MSC_VER < 1933) + #pragma warning(pop) + #endif + + return 1; +} + +static void rustsecp256k1_v0_11_ecdsa_signature_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar* r, rustsecp256k1_v0_11_scalar* s, const rustsecp256k1_v0_11_ecdsa_signature* sig) { (void)ctx; - if (sizeof(rustsecp256k1_v0_10_0_scalar) == 32) { - /* When the rustsecp256k1_v0_10_0_scalar type is exactly 32 byte, use its - * representation inside rustsecp256k1_v0_10_0_ecdsa_signature, as conversion is very fast. - * Note that rustsecp256k1_v0_10_0_ecdsa_signature_save must use the same representation. */ + if (sizeof(rustsecp256k1_v0_11_scalar) == 32) { + /* When the rustsecp256k1_v0_11_scalar type is exactly 32 byte, use its + * representation inside rustsecp256k1_v0_11_ecdsa_signature, as conversion is very fast. + * Note that rustsecp256k1_v0_11_ecdsa_signature_save must use the same representation. */ memcpy(r, &sig->data[0], 32); memcpy(s, &sig->data[32], 32); } else { - rustsecp256k1_v0_10_0_scalar_set_b32(r, &sig->data[0], NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(s, &sig->data[32], NULL); + rustsecp256k1_v0_11_scalar_set_b32(r, &sig->data[0], NULL); + rustsecp256k1_v0_11_scalar_set_b32(s, &sig->data[32], NULL); } } -static void rustsecp256k1_v0_10_0_ecdsa_signature_save(rustsecp256k1_v0_10_0_ecdsa_signature* sig, const rustsecp256k1_v0_10_0_scalar* r, const rustsecp256k1_v0_10_0_scalar* s) { - if (sizeof(rustsecp256k1_v0_10_0_scalar) == 32) { +static void rustsecp256k1_v0_11_ecdsa_signature_save(rustsecp256k1_v0_11_ecdsa_signature* sig, const rustsecp256k1_v0_11_scalar* r, const rustsecp256k1_v0_11_scalar* s) { + if (sizeof(rustsecp256k1_v0_11_scalar) == 32) { memcpy(&sig->data[0], r, 32); memcpy(&sig->data[32], s, 32); } else { - rustsecp256k1_v0_10_0_scalar_get_b32(&sig->data[0], r); - rustsecp256k1_v0_10_0_scalar_get_b32(&sig->data[32], s); + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[0], r); + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[32], s); } } -int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_signature_parse_der(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + rustsecp256k1_v0_11_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(input != NULL); - if (rustsecp256k1_v0_10_0_ecdsa_sig_parse(&r, &s, input, inputlen)) { - rustsecp256k1_v0_10_0_ecdsa_signature_save(sig, &r, &s); + if (rustsecp256k1_v0_11_ecdsa_sig_parse(&r, &s, input, inputlen)) { + rustsecp256k1_v0_11_ecdsa_signature_save(sig, &r, &s); return 1; } else { memset(sig, 0, sizeof(*sig)); @@ -330,8 +336,8 @@ int rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(const rustsecp256k1_v0_10_0_ } } -int rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_signature* sig, const unsigned char *input64) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_signature_parse_compact(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature* sig, const unsigned char *input64) { + rustsecp256k1_v0_11_scalar r, s; int ret = 1; int overflow = 0; @@ -339,76 +345,76 @@ int rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(const rustsecp256k1_v0_1 ARG_CHECK(sig != NULL); ARG_CHECK(input64 != NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(&r, &input64[0], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&r, &input64[0], &overflow); ret &= !overflow; - rustsecp256k1_v0_10_0_scalar_set_b32(&s, &input64[32], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&s, &input64[32], &overflow); ret &= !overflow; if (ret) { - rustsecp256k1_v0_10_0_ecdsa_signature_save(sig, &r, &s); + rustsecp256k1_v0_11_ecdsa_signature_save(sig, &r, &s); } else { memset(sig, 0, sizeof(*sig)); } return ret; } -int rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_10_0_ecdsa_signature* sig) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_signature_serialize_der(const rustsecp256k1_v0_11_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_11_ecdsa_signature* sig) { + rustsecp256k1_v0_11_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output != NULL); ARG_CHECK(outputlen != NULL); ARG_CHECK(sig != NULL); - rustsecp256k1_v0_10_0_ecdsa_signature_load(ctx, &r, &s, sig); - return rustsecp256k1_v0_10_0_ecdsa_sig_serialize(output, outputlen, &r, &s); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sig); + return rustsecp256k1_v0_11_ecdsa_sig_serialize(output, outputlen, &r, &s); } -int rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *output64, const rustsecp256k1_v0_10_0_ecdsa_signature* sig) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(const rustsecp256k1_v0_11_context* ctx, unsigned char *output64, const rustsecp256k1_v0_11_ecdsa_signature* sig) { + rustsecp256k1_v0_11_scalar r, s; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output64 != NULL); ARG_CHECK(sig != NULL); - rustsecp256k1_v0_10_0_ecdsa_signature_load(ctx, &r, &s, sig); - rustsecp256k1_v0_10_0_scalar_get_b32(&output64[0], &r); - rustsecp256k1_v0_10_0_scalar_get_b32(&output64[32], &s); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sig); + rustsecp256k1_v0_11_scalar_get_b32(&output64[0], &r); + rustsecp256k1_v0_11_scalar_get_b32(&output64[32], &s); return 1; } -int rustsecp256k1_v0_10_0_ecdsa_signature_normalize(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_signature *sigout, const rustsecp256k1_v0_10_0_ecdsa_signature *sigin) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_signature_normalize(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature *sigout, const rustsecp256k1_v0_11_ecdsa_signature *sigin) { + rustsecp256k1_v0_11_scalar r, s; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(sigin != NULL); - rustsecp256k1_v0_10_0_ecdsa_signature_load(ctx, &r, &s, sigin); - ret = rustsecp256k1_v0_10_0_scalar_is_high(&s); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sigin); + ret = rustsecp256k1_v0_11_scalar_is_high(&s); if (sigout != NULL) { if (ret) { - rustsecp256k1_v0_10_0_scalar_negate(&s, &s); + rustsecp256k1_v0_11_scalar_negate(&s, &s); } - rustsecp256k1_v0_10_0_ecdsa_signature_save(sigout, &r, &s); + rustsecp256k1_v0_11_ecdsa_signature_save(sigout, &r, &s); } return ret; } -int rustsecp256k1_v0_10_0_ecdsa_verify(const rustsecp256k1_v0_10_0_context* ctx, const rustsecp256k1_v0_10_0_ecdsa_signature *sig, const unsigned char *msghash32, const rustsecp256k1_v0_10_0_pubkey *pubkey) { - rustsecp256k1_v0_10_0_ge q; - rustsecp256k1_v0_10_0_scalar r, s; - rustsecp256k1_v0_10_0_scalar m; +int rustsecp256k1_v0_11_ecdsa_verify(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *msghash32, const rustsecp256k1_v0_11_pubkey *pubkey) { + rustsecp256k1_v0_11_ge q; + rustsecp256k1_v0_11_scalar r, s; + rustsecp256k1_v0_11_scalar m; VERIFY_CHECK(ctx != NULL); ARG_CHECK(msghash32 != NULL); ARG_CHECK(sig != NULL); ARG_CHECK(pubkey != NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(&m, msghash32, NULL); - rustsecp256k1_v0_10_0_ecdsa_signature_load(ctx, &r, &s, sig); - return (!rustsecp256k1_v0_10_0_scalar_is_high(&s) && - rustsecp256k1_v0_10_0_pubkey_load(ctx, &q, pubkey) && - rustsecp256k1_v0_10_0_ecdsa_sig_verify(&r, &s, &q, &m)); + rustsecp256k1_v0_11_scalar_set_b32(&m, msghash32, NULL); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sig); + return (!rustsecp256k1_v0_11_scalar_is_high(&s) && + rustsecp256k1_v0_11_pubkey_load(ctx, &q, pubkey) && + rustsecp256k1_v0_11_ecdsa_sig_verify(&r, &s, &q, &m)); } static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { @@ -419,12 +425,12 @@ static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *off 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) { unsigned char keydata[112]; unsigned int offset = 0; - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 rng; + rustsecp256k1_v0_11_rfc6979_hmac_sha256 rng; unsigned int i; - rustsecp256k1_v0_10_0_scalar msg; + rustsecp256k1_v0_11_scalar msg; unsigned char msgmod32[32]; - rustsecp256k1_v0_10_0_scalar_set_b32(&msg, msg32, NULL); - rustsecp256k1_v0_10_0_scalar_get_b32(msgmod32, &msg); + rustsecp256k1_v0_11_scalar_set_b32(&msg, msg32, NULL); + rustsecp256k1_v0_11_scalar_get_b32(msgmod32, &msg); /* We feed a byte array to the PRNG as input, consisting of: * - the private key (32 bytes) and reduced message (32 bytes), see RFC 6979 3.2d. * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. @@ -441,51 +447,53 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m if (algo16 != NULL) { buffer_append(keydata, &offset, algo16, 16); } - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); - memset(keydata, 0, sizeof(keydata)); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); for (i = 0; i <= counter; i++) { - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); } - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(&rng); + + rustsecp256k1_v0_11_memclear(keydata, sizeof(keydata)); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_clear(&rng); return 1; } -const rustsecp256k1_v0_10_0_nonce_function rustsecp256k1_v0_10_0_nonce_function_rfc6979 = nonce_function_rfc6979; -const rustsecp256k1_v0_10_0_nonce_function rustsecp256k1_v0_10_0_nonce_function_default = nonce_function_rfc6979; +const rustsecp256k1_v0_11_nonce_function rustsecp256k1_v0_11_nonce_function_rfc6979 = nonce_function_rfc6979; +const rustsecp256k1_v0_11_nonce_function rustsecp256k1_v0_11_nonce_function_default = nonce_function_rfc6979; -static int rustsecp256k1_v0_10_0_ecdsa_sign_inner(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_scalar* r, rustsecp256k1_v0_10_0_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, rustsecp256k1_v0_10_0_nonce_function noncefp, const void* noncedata) { - rustsecp256k1_v0_10_0_scalar sec, non, msg; +static int rustsecp256k1_v0_11_ecdsa_sign_inner(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar* r, rustsecp256k1_v0_11_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, rustsecp256k1_v0_11_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_11_scalar sec, non, msg; int ret = 0; int is_sec_valid; unsigned char nonce32[32]; unsigned int count = 0; /* Default initialization here is important so we won't pass uninit values to the cmov in the end */ - *r = rustsecp256k1_v0_10_0_scalar_zero; - *s = rustsecp256k1_v0_10_0_scalar_zero; + *r = rustsecp256k1_v0_11_scalar_zero; + *s = rustsecp256k1_v0_11_scalar_zero; if (recid) { *recid = 0; } if (noncefp == NULL) { - noncefp = rustsecp256k1_v0_10_0_nonce_function_default; + noncefp = rustsecp256k1_v0_11_nonce_function_default; } /* Fail if the secret key is invalid. */ - is_sec_valid = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&sec, seckey); - rustsecp256k1_v0_10_0_scalar_cmov(&sec, &rustsecp256k1_v0_10_0_scalar_one, !is_sec_valid); - rustsecp256k1_v0_10_0_scalar_set_b32(&msg, msg32, NULL); + is_sec_valid = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_one, !is_sec_valid); + rustsecp256k1_v0_11_scalar_set_b32(&msg, msg32, NULL); while (1) { int is_nonce_valid; ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); if (!ret) { break; } - is_nonce_valid = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&non, nonce32); - /* The nonce is still secret here, but it being invalid is is less likely than 1:2^255. */ - rustsecp256k1_v0_10_0_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); + is_nonce_valid = rustsecp256k1_v0_11_scalar_set_b32_seckey(&non, nonce32); + /* The nonce is still secret here, but it being invalid is less likely than 1:2^255. */ + rustsecp256k1_v0_11_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); if (is_nonce_valid) { - ret = rustsecp256k1_v0_10_0_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid); + ret = rustsecp256k1_v0_11_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid); /* The final signature is no longer a secret, nor is the fact that we were successful or not. */ - rustsecp256k1_v0_10_0_declassify(ctx, &ret, sizeof(ret)); + rustsecp256k1_v0_11_declassify(ctx, &ret, sizeof(ret)); if (ret) { break; } @@ -496,203 +504,204 @@ static int rustsecp256k1_v0_10_0_ecdsa_sign_inner(const rustsecp256k1_v0_10_0_co * 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); - rustsecp256k1_v0_10_0_scalar_clear(&msg); - rustsecp256k1_v0_10_0_scalar_clear(&non); - rustsecp256k1_v0_10_0_scalar_clear(&sec); - rustsecp256k1_v0_10_0_scalar_cmov(r, &rustsecp256k1_v0_10_0_scalar_zero, !ret); - rustsecp256k1_v0_10_0_scalar_cmov(s, &rustsecp256k1_v0_10_0_scalar_zero, !ret); + rustsecp256k1_v0_11_memclear(nonce32, sizeof(nonce32)); + rustsecp256k1_v0_11_scalar_clear(&msg); + rustsecp256k1_v0_11_scalar_clear(&non); + rustsecp256k1_v0_11_scalar_clear(&sec); + rustsecp256k1_v0_11_scalar_cmov(r, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_cmov(s, &rustsecp256k1_v0_11_scalar_zero, !ret); if (recid) { const int zero = 0; - rustsecp256k1_v0_10_0_int_cmov(recid, &zero, !ret); + rustsecp256k1_v0_11_int_cmov(recid, &zero, !ret); } return ret; } -int rustsecp256k1_v0_10_0_ecdsa_sign(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_ecdsa_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, rustsecp256k1_v0_10_0_nonce_function noncefp, const void* noncedata) { - rustsecp256k1_v0_10_0_scalar r, s; +int rustsecp256k1_v0_11_ecdsa_sign(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, rustsecp256k1_v0_11_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_11_scalar r, s; int ret; VERIFY_CHECK(ctx != NULL); - ARG_CHECK(rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(signature != NULL); ARG_CHECK(seckey != NULL); - ret = rustsecp256k1_v0_10_0_ecdsa_sign_inner(ctx, &r, &s, NULL, msghash32, seckey, noncefp, noncedata); - rustsecp256k1_v0_10_0_ecdsa_signature_save(signature, &r, &s); + ret = rustsecp256k1_v0_11_ecdsa_sign_inner(ctx, &r, &s, NULL, msghash32, seckey, noncefp, noncedata); + rustsecp256k1_v0_11_ecdsa_signature_save(signature, &r, &s); return ret; } -int rustsecp256k1_v0_10_0_ec_seckey_verify(const rustsecp256k1_v0_10_0_context* ctx, const unsigned char *seckey) { - rustsecp256k1_v0_10_0_scalar sec; +int rustsecp256k1_v0_11_ec_seckey_verify(const rustsecp256k1_v0_11_context* ctx, const unsigned char *seckey) { + rustsecp256k1_v0_11_scalar sec; int ret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); - ret = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&sec, seckey); - rustsecp256k1_v0_10_0_scalar_clear(&sec); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + rustsecp256k1_v0_11_scalar_clear(&sec); return ret; } -static int rustsecp256k1_v0_10_0_ec_pubkey_create_helper(const rustsecp256k1_v0_10_0_ecmult_gen_context *ecmult_gen_ctx, rustsecp256k1_v0_10_0_scalar *seckey_scalar, rustsecp256k1_v0_10_0_ge *p, const unsigned char *seckey) { - rustsecp256k1_v0_10_0_gej pj; +static int rustsecp256k1_v0_11_ec_pubkey_create_helper(const rustsecp256k1_v0_11_ecmult_gen_context *ecmult_gen_ctx, rustsecp256k1_v0_11_scalar *seckey_scalar, rustsecp256k1_v0_11_ge *p, const unsigned char *seckey) { + rustsecp256k1_v0_11_gej pj; int ret; - ret = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(seckey_scalar, seckey); - rustsecp256k1_v0_10_0_scalar_cmov(seckey_scalar, &rustsecp256k1_v0_10_0_scalar_one, !ret); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(seckey_scalar, seckey); + rustsecp256k1_v0_11_scalar_cmov(seckey_scalar, &rustsecp256k1_v0_11_scalar_one, !ret); - rustsecp256k1_v0_10_0_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); - rustsecp256k1_v0_10_0_ge_set_gej(p, &pj); + rustsecp256k1_v0_11_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); + rustsecp256k1_v0_11_ge_set_gej(p, &pj); + rustsecp256k1_v0_11_gej_clear(&pj); return ret; } -int rustsecp256k1_v0_10_0_ec_pubkey_create(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubkey, const unsigned char *seckey) { - rustsecp256k1_v0_10_0_ge p; - rustsecp256k1_v0_10_0_scalar seckey_scalar; +int rustsecp256k1_v0_11_ec_pubkey_create(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *seckey) { + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_scalar seckey_scalar; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); - ARG_CHECK(rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey != NULL); - ret = rustsecp256k1_v0_10_0_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey); - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &p); - rustsecp256k1_v0_10_0_memczero(pubkey, sizeof(*pubkey), !ret); + ret = rustsecp256k1_v0_11_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey); + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); + rustsecp256k1_v0_11_memczero(pubkey, sizeof(*pubkey), !ret); - rustsecp256k1_v0_10_0_scalar_clear(&seckey_scalar); + rustsecp256k1_v0_11_scalar_clear(&seckey_scalar); return ret; } -int rustsecp256k1_v0_10_0_ec_seckey_negate(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey) { - rustsecp256k1_v0_10_0_scalar sec; +int rustsecp256k1_v0_11_ec_seckey_negate(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey) { + rustsecp256k1_v0_11_scalar sec; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); - ret = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&sec, seckey); - rustsecp256k1_v0_10_0_scalar_cmov(&sec, &rustsecp256k1_v0_10_0_scalar_zero, !ret); - rustsecp256k1_v0_10_0_scalar_negate(&sec, &sec); - rustsecp256k1_v0_10_0_scalar_get_b32(seckey, &sec); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_negate(&sec, &sec); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sec); - rustsecp256k1_v0_10_0_scalar_clear(&sec); + rustsecp256k1_v0_11_scalar_clear(&sec); return ret; } -int rustsecp256k1_v0_10_0_ec_privkey_negate(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey) { - return rustsecp256k1_v0_10_0_ec_seckey_negate(ctx, seckey); +int rustsecp256k1_v0_11_ec_privkey_negate(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey) { + return rustsecp256k1_v0_11_ec_seckey_negate(ctx, seckey); } -int rustsecp256k1_v0_10_0_ec_pubkey_negate(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubkey) { +int rustsecp256k1_v0_11_ec_pubkey_negate(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey) { int ret = 0; - rustsecp256k1_v0_10_0_ge p; + rustsecp256k1_v0_11_ge p; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); - ret = rustsecp256k1_v0_10_0_pubkey_load(ctx, &p, pubkey); + ret = rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey); memset(pubkey, 0, sizeof(*pubkey)); if (ret) { - rustsecp256k1_v0_10_0_ge_neg(&p, &p); - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &p); + rustsecp256k1_v0_11_ge_neg(&p, &p); + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); } return ret; } -static int rustsecp256k1_v0_10_0_ec_seckey_tweak_add_helper(rustsecp256k1_v0_10_0_scalar *sec, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_scalar term; +static int rustsecp256k1_v0_11_ec_seckey_tweak_add_helper(rustsecp256k1_v0_11_scalar *sec, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar term; int overflow = 0; int ret = 0; - rustsecp256k1_v0_10_0_scalar_set_b32(&term, tweak32, &overflow); - ret = (!overflow) & rustsecp256k1_v0_10_0_eckey_privkey_tweak_add(sec, &term); - rustsecp256k1_v0_10_0_scalar_clear(&term); + rustsecp256k1_v0_11_scalar_set_b32(&term, tweak32, &overflow); + ret = (!overflow) & rustsecp256k1_v0_11_eckey_privkey_tweak_add(sec, &term); + rustsecp256k1_v0_11_scalar_clear(&term); return ret; } -int rustsecp256k1_v0_10_0_ec_seckey_tweak_add(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_scalar sec; +int rustsecp256k1_v0_11_ec_seckey_tweak_add(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar sec; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak32 != NULL); - ret = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&sec, seckey); - ret &= rustsecp256k1_v0_10_0_ec_seckey_tweak_add_helper(&sec, tweak32); - rustsecp256k1_v0_10_0_scalar_cmov(&sec, &rustsecp256k1_v0_10_0_scalar_zero, !ret); - rustsecp256k1_v0_10_0_scalar_get_b32(seckey, &sec); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + ret &= rustsecp256k1_v0_11_ec_seckey_tweak_add_helper(&sec, tweak32); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sec); - rustsecp256k1_v0_10_0_scalar_clear(&sec); + rustsecp256k1_v0_11_scalar_clear(&sec); return ret; } -int rustsecp256k1_v0_10_0_ec_privkey_tweak_add(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - return rustsecp256k1_v0_10_0_ec_seckey_tweak_add(ctx, seckey, tweak32); +int rustsecp256k1_v0_11_ec_privkey_tweak_add(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + return rustsecp256k1_v0_11_ec_seckey_tweak_add(ctx, seckey, tweak32); } -static int rustsecp256k1_v0_10_0_ec_pubkey_tweak_add_helper(rustsecp256k1_v0_10_0_ge *p, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_scalar term; +static int rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(rustsecp256k1_v0_11_ge *p, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar term; int overflow = 0; - rustsecp256k1_v0_10_0_scalar_set_b32(&term, tweak32, &overflow); - return !overflow && rustsecp256k1_v0_10_0_eckey_pubkey_tweak_add(p, &term); + rustsecp256k1_v0_11_scalar_set_b32(&term, tweak32, &overflow); + return !overflow && rustsecp256k1_v0_11_eckey_pubkey_tweak_add(p, &term); } -int rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubkey, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_ge p; +int rustsecp256k1_v0_11_ec_pubkey_tweak_add(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge p; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); ARG_CHECK(tweak32 != NULL); - ret = rustsecp256k1_v0_10_0_pubkey_load(ctx, &p, pubkey); + ret = rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey); memset(pubkey, 0, sizeof(*pubkey)); - ret = ret && rustsecp256k1_v0_10_0_ec_pubkey_tweak_add_helper(&p, tweak32); + ret = ret && rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(&p, tweak32); if (ret) { - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &p); + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); } return ret; } -int rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_scalar factor; - rustsecp256k1_v0_10_0_scalar sec; +int rustsecp256k1_v0_11_ec_seckey_tweak_mul(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar factor; + rustsecp256k1_v0_11_scalar sec; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); ARG_CHECK(tweak32 != NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(&factor, tweak32, &overflow); - ret = rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&sec, seckey); - ret &= (!overflow) & rustsecp256k1_v0_10_0_eckey_privkey_tweak_mul(&sec, &factor); - rustsecp256k1_v0_10_0_scalar_cmov(&sec, &rustsecp256k1_v0_10_0_scalar_zero, !ret); - rustsecp256k1_v0_10_0_scalar_get_b32(seckey, &sec); + rustsecp256k1_v0_11_scalar_set_b32(&factor, tweak32, &overflow); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + ret &= (!overflow) & rustsecp256k1_v0_11_eckey_privkey_tweak_mul(&sec, &factor); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sec); - rustsecp256k1_v0_10_0_scalar_clear(&sec); - rustsecp256k1_v0_10_0_scalar_clear(&factor); + rustsecp256k1_v0_11_scalar_clear(&sec); + rustsecp256k1_v0_11_scalar_clear(&factor); return ret; } -int rustsecp256k1_v0_10_0_ec_privkey_tweak_mul(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { - return rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(ctx, seckey, tweak32); +int rustsecp256k1_v0_11_ec_privkey_tweak_mul(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + return rustsecp256k1_v0_11_ec_seckey_tweak_mul(ctx, seckey, tweak32); } -int rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubkey, const unsigned char *tweak32) { - rustsecp256k1_v0_10_0_ge p; - rustsecp256k1_v0_10_0_scalar factor; +int rustsecp256k1_v0_11_ec_pubkey_tweak_mul(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_scalar factor; int ret = 0; int overflow = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); ARG_CHECK(tweak32 != NULL); - rustsecp256k1_v0_10_0_scalar_set_b32(&factor, tweak32, &overflow); - ret = !overflow && rustsecp256k1_v0_10_0_pubkey_load(ctx, &p, pubkey); + rustsecp256k1_v0_11_scalar_set_b32(&factor, tweak32, &overflow); + ret = !overflow && rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey); memset(pubkey, 0, sizeof(*pubkey)); if (ret) { - if (rustsecp256k1_v0_10_0_eckey_pubkey_tweak_mul(&p, &factor)) { - rustsecp256k1_v0_10_0_pubkey_save(pubkey, &p); + if (rustsecp256k1_v0_11_eckey_pubkey_tweak_mul(&p, &factor)) { + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); } else { ret = 0; } @@ -701,20 +710,20 @@ int rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(const rustsecp256k1_v0_10_0_contex return ret; } -int rustsecp256k1_v0_10_0_context_randomize(rustsecp256k1_v0_10_0_context* ctx, const unsigned char *seed32) { +int rustsecp256k1_v0_11_context_randomize(rustsecp256k1_v0_11_context* ctx, const unsigned char *seed32) { VERIFY_CHECK(ctx != NULL); - ARG_CHECK(rustsecp256k1_v0_10_0_context_is_proper(ctx)); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); - if (rustsecp256k1_v0_10_0_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { - rustsecp256k1_v0_10_0_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + if (rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { + rustsecp256k1_v0_11_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); } return 1; } -int rustsecp256k1_v0_10_0_ec_pubkey_combine(const rustsecp256k1_v0_10_0_context* ctx, rustsecp256k1_v0_10_0_pubkey *pubnonce, const rustsecp256k1_v0_10_0_pubkey * const *pubnonces, size_t n) { +int rustsecp256k1_v0_11_ec_pubkey_combine(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubnonce, const rustsecp256k1_v0_11_pubkey * const *pubnonces, size_t n) { size_t i; - rustsecp256k1_v0_10_0_gej Qj; - rustsecp256k1_v0_10_0_ge Q; + rustsecp256k1_v0_11_gej Qj; + rustsecp256k1_v0_11_ge Q; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubnonce != NULL); @@ -722,31 +731,32 @@ int rustsecp256k1_v0_10_0_ec_pubkey_combine(const rustsecp256k1_v0_10_0_context* ARG_CHECK(n >= 1); ARG_CHECK(pubnonces != NULL); - rustsecp256k1_v0_10_0_gej_set_infinity(&Qj); + rustsecp256k1_v0_11_gej_set_infinity(&Qj); for (i = 0; i < n; i++) { ARG_CHECK(pubnonces[i] != NULL); - rustsecp256k1_v0_10_0_pubkey_load(ctx, &Q, pubnonces[i]); - rustsecp256k1_v0_10_0_gej_add_ge(&Qj, &Qj, &Q); + rustsecp256k1_v0_11_pubkey_load(ctx, &Q, pubnonces[i]); + rustsecp256k1_v0_11_gej_add_ge(&Qj, &Qj, &Q); } - if (rustsecp256k1_v0_10_0_gej_is_infinity(&Qj)) { + if (rustsecp256k1_v0_11_gej_is_infinity(&Qj)) { return 0; } - rustsecp256k1_v0_10_0_ge_set_gej(&Q, &Qj); - rustsecp256k1_v0_10_0_pubkey_save(pubnonce, &Q); + rustsecp256k1_v0_11_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_11_pubkey_save(pubnonce, &Q); return 1; } -int rustsecp256k1_v0_10_0_tagged_sha256(const rustsecp256k1_v0_10_0_context* ctx, unsigned char *hash32, const unsigned char *tag, size_t taglen, const unsigned char *msg, size_t msglen) { - rustsecp256k1_v0_10_0_sha256 sha; +int rustsecp256k1_v0_11_tagged_sha256(const rustsecp256k1_v0_11_context* ctx, unsigned char *hash32, const unsigned char *tag, size_t taglen, const unsigned char *msg, size_t msglen) { + rustsecp256k1_v0_11_sha256 sha; VERIFY_CHECK(ctx != NULL); ARG_CHECK(hash32 != NULL); ARG_CHECK(tag != NULL); ARG_CHECK(msg != NULL); - rustsecp256k1_v0_10_0_sha256_initialize_tagged(&sha, tag, taglen); - rustsecp256k1_v0_10_0_sha256_write(&sha, msg, msglen); - rustsecp256k1_v0_10_0_sha256_finalize(&sha, hash32); + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, tag, taglen); + rustsecp256k1_v0_11_sha256_write(&sha, msg, msglen); + rustsecp256k1_v0_11_sha256_finalize(&sha, hash32); + rustsecp256k1_v0_11_sha256_clear(&sha); return 1; } @@ -766,6 +776,10 @@ int rustsecp256k1_v0_10_0_tagged_sha256(const rustsecp256k1_v0_10_0_context* ctx # 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/secp256k1-sys/depend/secp256k1/src/secp256k1.c.orig b/secp256k1-sys/depend/secp256k1/src/secp256k1.c.orig new file mode 100644 index 000000000..6dc6cfc2b --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/src/secp256k1.c.orig @@ -0,0 +1,831 @@ +/*********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ + +/* This is a C project. It should not be compiled with a C++ compiler, + * and we error out if we detect one. + * + * We still want to be able to test the project with a C++ compiler + * because it is still good to know if this will lead to real trouble, so + * there is a possibility to override the check. But be warned that + * compiling with a C++ compiler is not supported. */ +#if defined(__cplusplus) && !defined(SECP256K1_CPLUSPLUS_TEST_OVERRIDE) +#error Trying to compile a C project with a C++ compiler. +#endif + +#define SECP256K1_BUILD + +#include "../include/secp256k1.h" +#include "../include/secp256k1_preallocated.h" + +#include "assumptions.h" +#include "checkmem.h" +#include "util.h" + +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_gen_impl.h" +#include "ecdsa_impl.h" +#include "eckey_impl.h" +#include "hash_impl.h" +#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" +#endif + +#define ARG_CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + rustsecp256k1_v0_11_callback_call(&ctx->illegal_callback, #cond); \ + return 0; \ + } \ +} while(0) + +#define ARG_CHECK_VOID(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + rustsecp256k1_v0_11_callback_call(&ctx->illegal_callback, #cond); \ + return; \ + } \ +} while(0) + +/* Note that whenever you change the context struct, you must also change the + * context_eq function. */ +struct rustsecp256k1_v0_11_context_struct { + rustsecp256k1_v0_11_ecmult_gen_context ecmult_gen_ctx; + rustsecp256k1_v0_11_callback illegal_callback; + rustsecp256k1_v0_11_callback error_callback; + int declassify; +}; + +static const rustsecp256k1_v0_11_context rustsecp256k1_v0_11_context_static_ = { + { 0 }, + { rustsecp256k1_v0_11_default_illegal_callback_fn, 0 }, + { rustsecp256k1_v0_11_default_error_callback_fn, 0 }, + 0 +}; +const rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_static = &rustsecp256k1_v0_11_context_static_; +const rustsecp256k1_v0_11_context *rustsecp256k1_v0_11_context_no_precomp = &rustsecp256k1_v0_11_context_static_; + +/* 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 rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_context_is_proper(const rustsecp256k1_v0_11_context* ctx) { + return rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx); +} + +void rustsecp256k1_v0_11_selftest(void) { + if (!rustsecp256k1_v0_11_selftest_passes()) { + rustsecp256k1_v0_11_callback_call(&default_error_callback, "self test failed"); + } +} + +size_t rustsecp256k1_v0_11_context_preallocated_size(unsigned int flags) { + size_t ret = sizeof(rustsecp256k1_v0_11_context); + /* A return value of 0 is reserved as an indicator for errors when we call this function internally. */ + VERIFY_CHECK(ret != 0); + + if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { + rustsecp256k1_v0_11_callback_call(&default_illegal_callback, + "Invalid flags"); + return 0; + } + + if (EXPECT(!SECP256K1_CHECKMEM_RUNNING() && (flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY), 0)) { + rustsecp256k1_v0_11_callback_call(&default_illegal_callback, + "Declassify flag requires running with memory checking"); + return 0; + } + + return ret; +} + +size_t rustsecp256k1_v0_11_context_preallocated_clone_size(const rustsecp256k1_v0_11_context* ctx) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); + return sizeof(rustsecp256k1_v0_11_context); +} + +rustsecp256k1_v0_11_context* rustsecp256k1_v0_11_context_preallocated_create(void* prealloc, unsigned int flags) { + size_t prealloc_size; + rustsecp256k1_v0_11_context* ret; + + rustsecp256k1_v0_11_selftest(); + + prealloc_size = rustsecp256k1_v0_11_context_preallocated_size(flags); + if (prealloc_size == 0) { + return NULL; + } + VERIFY_CHECK(prealloc != NULL); + ret = (rustsecp256k1_v0_11_context*)prealloc; + ret->illegal_callback = default_illegal_callback; + ret->error_callback = default_error_callback; + + /* Flags have been checked by rustsecp256k1_v0_11_context_preallocated_size. */ + VERIFY_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_CONTEXT); + rustsecp256k1_v0_11_ecmult_gen_context_build(&ret->ecmult_gen_ctx); + ret->declassify = !!(flags & SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY); + + return ret; +} + +rustsecp256k1_v0_11_context* rustsecp256k1_v0_11_context_create(unsigned int flags) { + size_t const prealloc_size = rustsecp256k1_v0_11_context_preallocated_size(flags); + rustsecp256k1_v0_11_context* ctx = (rustsecp256k1_v0_11_context*)checked_malloc(&default_error_callback, prealloc_size); + if (EXPECT(rustsecp256k1_v0_11_context_preallocated_create(ctx, flags) == NULL, 0)) { + free(ctx); + return NULL; + } + + return ctx; +} + +rustsecp256k1_v0_11_context* rustsecp256k1_v0_11_context_preallocated_clone(const rustsecp256k1_v0_11_context* ctx, void* prealloc) { + rustsecp256k1_v0_11_context* ret; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(prealloc != NULL); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); + + ret = (rustsecp256k1_v0_11_context*)prealloc; + *ret = *ctx; + return ret; +} + +rustsecp256k1_v0_11_context* rustsecp256k1_v0_11_context_clone(const rustsecp256k1_v0_11_context* ctx) { + rustsecp256k1_v0_11_context* ret; + size_t prealloc_size; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); + + prealloc_size = rustsecp256k1_v0_11_context_preallocated_clone_size(ctx); + ret = (rustsecp256k1_v0_11_context*)checked_malloc(&ctx->error_callback, prealloc_size); + ret = rustsecp256k1_v0_11_context_preallocated_clone(ctx, ret); + return ret; +} + +void rustsecp256k1_v0_11_context_preallocated_destroy(rustsecp256k1_v0_11_context* ctx) { + ARG_CHECK_VOID(ctx == NULL || rustsecp256k1_v0_11_context_is_proper(ctx)); + + /* Defined as noop */ + if (ctx == NULL) { + return; + } + + rustsecp256k1_v0_11_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); +} + +void rustsecp256k1_v0_11_context_destroy(rustsecp256k1_v0_11_context* ctx) { + ARG_CHECK_VOID(ctx == NULL || rustsecp256k1_v0_11_context_is_proper(ctx)); + + /* Defined as noop */ + if (ctx == NULL) { + return; + } + + rustsecp256k1_v0_11_context_preallocated_destroy(ctx); + free(ctx); +} + +void rustsecp256k1_v0_11_context_set_illegal_callback(rustsecp256k1_v0_11_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + /* We compare pointers instead of checking rustsecp256k1_v0_11_context_is_proper() here + because setting callbacks is allowed on *copies* of the static context: + it's harmless and makes testing easier. */ + ARG_CHECK_VOID(ctx != rustsecp256k1_v0_11_context_static); + if (fun == NULL) { + fun = rustsecp256k1_v0_11_default_illegal_callback_fn; + } + ctx->illegal_callback.fn = fun; + ctx->illegal_callback.data = data; +} + +void rustsecp256k1_v0_11_context_set_error_callback(rustsecp256k1_v0_11_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + /* We compare pointers instead of checking rustsecp256k1_v0_11_context_is_proper() here + because setting callbacks is allowed on *copies* of the static context: + it's harmless and makes testing easier. */ + ARG_CHECK_VOID(ctx != rustsecp256k1_v0_11_context_static); + if (fun == NULL) { + fun = rustsecp256k1_v0_11_default_error_callback_fn; + } + ctx->error_callback.fn = fun; + ctx->error_callback.data = data; +} + +static rustsecp256k1_v0_11_scratch_space* rustsecp256k1_v0_11_scratch_space_create(const rustsecp256k1_v0_11_context* ctx, size_t max_size) { + VERIFY_CHECK(ctx != NULL); + return rustsecp256k1_v0_11_scratch_create(&ctx->error_callback, max_size); +} + +static void rustsecp256k1_v0_11_scratch_space_destroy(const rustsecp256k1_v0_11_context *ctx, rustsecp256k1_v0_11_scratch_space* scratch) { + VERIFY_CHECK(ctx != NULL); + rustsecp256k1_v0_11_scratch_destroy(&ctx->error_callback, scratch); +} + +/* Mark memory as no-longer-secret for the purpose of analysing constant-time behaviour + * of the software. + */ +static SECP256K1_INLINE void rustsecp256k1_v0_11_declassify(const rustsecp256k1_v0_11_context* ctx, const void *p, size_t len) { + if (EXPECT(ctx->declassify, 0)) SECP256K1_CHECKMEM_DEFINE(p, len); +} + +static int rustsecp256k1_v0_11_pubkey_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ge* ge, const rustsecp256k1_v0_11_pubkey* pubkey) { + rustsecp256k1_v0_11_ge_from_bytes(ge, pubkey->data); + ARG_CHECK(!rustsecp256k1_v0_11_fe_is_zero(&ge->x)); + return 1; +} + +static void rustsecp256k1_v0_11_pubkey_save(rustsecp256k1_v0_11_pubkey* pubkey, rustsecp256k1_v0_11_ge* ge) { + rustsecp256k1_v0_11_ge_to_bytes(pubkey->data, ge); +} + +int rustsecp256k1_v0_11_ec_pubkey_parse(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey* pubkey, const unsigned char *input, size_t inputlen) { + rustsecp256k1_v0_11_ge Q; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(input != NULL); + if (!rustsecp256k1_v0_11_eckey_pubkey_parse(&Q, input, inputlen)) { + return 0; + } + if (!rustsecp256k1_v0_11_ge_is_in_correct_subgroup(&Q)) { + return 0; + } + rustsecp256k1_v0_11_pubkey_save(pubkey, &Q); + rustsecp256k1_v0_11_ge_clear(&Q); + return 1; +} + +int rustsecp256k1_v0_11_ec_pubkey_serialize(const rustsecp256k1_v0_11_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_11_pubkey* pubkey, unsigned int flags) { + rustsecp256k1_v0_11_ge Q; + size_t len; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33u : 65u)); + len = *outputlen; + *outputlen = 0; + ARG_CHECK(output != NULL); + memset(output, 0, len); + ARG_CHECK(pubkey != NULL); + ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); + if (rustsecp256k1_v0_11_pubkey_load(ctx, &Q, pubkey)) { + ret = rustsecp256k1_v0_11_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + if (ret) { + *outputlen = len; + } + } + return ret; +} + +int rustsecp256k1_v0_11_ec_pubkey_cmp(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_pubkey* pubkey0, const rustsecp256k1_v0_11_pubkey* pubkey1) { + unsigned char out[2][33]; + const rustsecp256k1_v0_11_pubkey* pk[2]; + int i; + + VERIFY_CHECK(ctx != NULL); + pk[0] = pubkey0; pk[1] = pubkey1; + for (i = 0; i < 2; i++) { + size_t out_size = sizeof(out[i]); + /* If the public key is NULL or invalid, ec_pubkey_serialize will call + * the illegal_callback and return 0. In that case we will serialize the + * key as all zeros which is less than any valid public key. This + * results in consistent comparisons even if NULL or invalid pubkeys are + * involved and prevents edge cases such as sorting algorithms that use + * this function and do not terminate as a result. */ + if (!rustsecp256k1_v0_11_ec_pubkey_serialize(ctx, out[i], &out_size, pk[i], SECP256K1_EC_COMPRESSED)) { + /* Note that ec_pubkey_serialize should already set the output to + * zero in that case, but it's not guaranteed by the API, we can't + * test it and writing a VERIFY_CHECK is more complex than + * explicitly memsetting (again). */ + memset(out[i], 0, sizeof(out[i])); + } + } + return rustsecp256k1_v0_11_memcmp_var(out[0], out[1], sizeof(out[0])); +} + +static int rustsecp256k1_v0_11_ec_pubkey_sort_cmp(const void* pk1, const void* pk2, void *ctx) { + return rustsecp256k1_v0_11_ec_pubkey_cmp((rustsecp256k1_v0_11_context *)ctx, + *(rustsecp256k1_v0_11_pubkey **)pk1, + *(rustsecp256k1_v0_11_pubkey **)pk2); +} + +int rustsecp256k1_v0_11_ec_pubkey_sort(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_hsort nor + * rustsecp256k1_v0_11_ec_pubkey_sort_cmp modify the data pointed to by the cmp_data + * argument. */ + rustsecp256k1_v0_11_hsort(pubkeys, n_pubkeys, sizeof(*pubkeys), rustsecp256k1_v0_11_ec_pubkey_sort_cmp, (void *)ctx); + + #if defined(_MSC_VER) && (_MSC_VER < 1933) + #pragma warning(pop) + #endif + + return 1; +} + +static void rustsecp256k1_v0_11_ecdsa_signature_load(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar* r, rustsecp256k1_v0_11_scalar* s, const rustsecp256k1_v0_11_ecdsa_signature* sig) { + (void)ctx; + if (sizeof(rustsecp256k1_v0_11_scalar) == 32) { + /* When the rustsecp256k1_v0_11_scalar type is exactly 32 byte, use its + * representation inside rustsecp256k1_v0_11_ecdsa_signature, as conversion is very fast. + * Note that rustsecp256k1_v0_11_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + rustsecp256k1_v0_11_scalar_set_b32(r, &sig->data[0], NULL); + rustsecp256k1_v0_11_scalar_set_b32(s, &sig->data[32], NULL); + } +} + +static void rustsecp256k1_v0_11_ecdsa_signature_save(rustsecp256k1_v0_11_ecdsa_signature* sig, const rustsecp256k1_v0_11_scalar* r, const rustsecp256k1_v0_11_scalar* s) { + if (sizeof(rustsecp256k1_v0_11_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[0], r); + rustsecp256k1_v0_11_scalar_get_b32(&sig->data[32], s); + } +} + +int rustsecp256k1_v0_11_ecdsa_signature_parse_der(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + rustsecp256k1_v0_11_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input != NULL); + + if (rustsecp256k1_v0_11_ecdsa_sig_parse(&r, &s, input, inputlen)) { + rustsecp256k1_v0_11_ecdsa_signature_save(sig, &r, &s); + return 1; + } else { + memset(sig, 0, sizeof(*sig)); + return 0; + } +} + +int rustsecp256k1_v0_11_ecdsa_signature_parse_compact(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature* sig, const unsigned char *input64) { + rustsecp256k1_v0_11_scalar r, s; + int ret = 1; + int overflow = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input64 != NULL); + + rustsecp256k1_v0_11_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + rustsecp256k1_v0_11_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + rustsecp256k1_v0_11_ecdsa_signature_save(sig, &r, &s); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int rustsecp256k1_v0_11_ecdsa_signature_serialize_der(const rustsecp256k1_v0_11_context* ctx, unsigned char *output, size_t *outputlen, const rustsecp256k1_v0_11_ecdsa_signature* sig) { + rustsecp256k1_v0_11_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(sig != NULL); + + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sig); + return rustsecp256k1_v0_11_ecdsa_sig_serialize(output, outputlen, &r, &s); +} + +int rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(const rustsecp256k1_v0_11_context* ctx, unsigned char *output64, const rustsecp256k1_v0_11_ecdsa_signature* sig) { + rustsecp256k1_v0_11_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sig); + rustsecp256k1_v0_11_scalar_get_b32(&output64[0], &r); + rustsecp256k1_v0_11_scalar_get_b32(&output64[32], &s); + return 1; +} + +int rustsecp256k1_v0_11_ecdsa_signature_normalize(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature *sigout, const rustsecp256k1_v0_11_ecdsa_signature *sigin) { + rustsecp256k1_v0_11_scalar r, s; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sigin != NULL); + + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sigin); + ret = rustsecp256k1_v0_11_scalar_is_high(&s); + if (sigout != NULL) { + if (ret) { + rustsecp256k1_v0_11_scalar_negate(&s, &s); + } + rustsecp256k1_v0_11_ecdsa_signature_save(sigout, &r, &s); + } + + return ret; +} + +int rustsecp256k1_v0_11_ecdsa_verify(const rustsecp256k1_v0_11_context* ctx, const rustsecp256k1_v0_11_ecdsa_signature *sig, const unsigned char *msghash32, const rustsecp256k1_v0_11_pubkey *pubkey) { + rustsecp256k1_v0_11_ge q; + rustsecp256k1_v0_11_scalar r, s; + rustsecp256k1_v0_11_scalar m; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(msghash32 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(pubkey != NULL); + + rustsecp256k1_v0_11_scalar_set_b32(&m, msghash32, NULL); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, sig); + return (!rustsecp256k1_v0_11_scalar_is_high(&s) && + rustsecp256k1_v0_11_pubkey_load(ctx, &q, pubkey) && + rustsecp256k1_v0_11_ecdsa_sig_verify(&r, &s, &q, &m)); +} + +static SECP256K1_INLINE void buffer_append(unsigned char *buf, unsigned int *offset, const void *data, unsigned int len) { + memcpy(buf + *offset, data, len); + *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) { + unsigned char keydata[112]; + unsigned int offset = 0; + rustsecp256k1_v0_11_rfc6979_hmac_sha256 rng; + unsigned int i; + rustsecp256k1_v0_11_scalar msg; + unsigned char msgmod32[32]; + rustsecp256k1_v0_11_scalar_set_b32(&msg, msg32, NULL); + rustsecp256k1_v0_11_scalar_get_b32(msgmod32, &msg); + /* We feed a byte array to the PRNG as input, consisting of: + * - the private key (32 bytes) and reduced message (32 bytes), see RFC 6979 3.2d. + * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. + * - optionally 16 extra bytes with the algorithm name. + * Because the arguments have distinct fixed lengths it is not possible for + * different argument mixtures to emulate each other and result in the same + * nonces. + */ + buffer_append(keydata, &offset, key32, 32); + buffer_append(keydata, &offset, msgmod32, 32); + if (data != NULL) { + buffer_append(keydata, &offset, data, 32); + } + if (algo16 != NULL) { + buffer_append(keydata, &offset, algo16, 16); + } + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, keydata, offset); + for (i = 0; i <= counter; i++) { + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + } + rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(&rng); + + rustsecp256k1_v0_11_memclear(keydata, sizeof(keydata)); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_clear(&rng); + return 1; +} + +const rustsecp256k1_v0_11_nonce_function rustsecp256k1_v0_11_nonce_function_rfc6979 = nonce_function_rfc6979; +const rustsecp256k1_v0_11_nonce_function rustsecp256k1_v0_11_nonce_function_default = nonce_function_rfc6979; + +static int rustsecp256k1_v0_11_ecdsa_sign_inner(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_scalar* r, rustsecp256k1_v0_11_scalar* s, int* recid, const unsigned char *msg32, const unsigned char *seckey, rustsecp256k1_v0_11_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_11_scalar sec, non, msg; + int ret = 0; + int is_sec_valid; + unsigned char nonce32[32]; + unsigned int count = 0; + /* Default initialization here is important so we won't pass uninit values to the cmov in the end */ + *r = rustsecp256k1_v0_11_scalar_zero; + *s = rustsecp256k1_v0_11_scalar_zero; + if (recid) { + *recid = 0; + } + if (noncefp == NULL) { + noncefp = rustsecp256k1_v0_11_nonce_function_default; + } + + /* Fail if the secret key is invalid. */ + is_sec_valid = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_one, !is_sec_valid); + rustsecp256k1_v0_11_scalar_set_b32(&msg, msg32, NULL); + while (1) { + int is_nonce_valid; + ret = !!noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + is_nonce_valid = rustsecp256k1_v0_11_scalar_set_b32_seckey(&non, nonce32); + /* The nonce is still secret here, but it being invalid is less likely than 1:2^255. */ + rustsecp256k1_v0_11_declassify(ctx, &is_nonce_valid, sizeof(is_nonce_valid)); + if (is_nonce_valid) { + ret = rustsecp256k1_v0_11_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, r, s, &sec, &msg, &non, recid); + /* The final signature is no longer a secret, nor is the fact that we were successful or not. */ + rustsecp256k1_v0_11_declassify(ctx, &ret, sizeof(ret)); + if (ret) { + break; + } + } + count++; + } + /* We don't want to declassify is_sec_valid and therefore the range of + * seckey. As a result is_sec_valid is included in ret only after ret was + * used as a branching variable. */ + ret &= is_sec_valid; + rustsecp256k1_v0_11_memclear(nonce32, sizeof(nonce32)); + rustsecp256k1_v0_11_scalar_clear(&msg); + rustsecp256k1_v0_11_scalar_clear(&non); + rustsecp256k1_v0_11_scalar_clear(&sec); + rustsecp256k1_v0_11_scalar_cmov(r, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_cmov(s, &rustsecp256k1_v0_11_scalar_zero, !ret); + if (recid) { + const int zero = 0; + rustsecp256k1_v0_11_int_cmov(recid, &zero, !ret); + } + return ret; +} + +int rustsecp256k1_v0_11_ecdsa_sign(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_ecdsa_signature *signature, const unsigned char *msghash32, const unsigned char *seckey, rustsecp256k1_v0_11_nonce_function noncefp, const void* noncedata) { + rustsecp256k1_v0_11_scalar r, s; + int ret; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msghash32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + + ret = rustsecp256k1_v0_11_ecdsa_sign_inner(ctx, &r, &s, NULL, msghash32, seckey, noncefp, noncedata); + rustsecp256k1_v0_11_ecdsa_signature_save(signature, &r, &s); + return ret; +} + +int rustsecp256k1_v0_11_ec_seckey_verify(const rustsecp256k1_v0_11_context* ctx, const unsigned char *seckey) { + rustsecp256k1_v0_11_scalar sec; + int ret; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + rustsecp256k1_v0_11_scalar_clear(&sec); + return ret; +} + +static int rustsecp256k1_v0_11_ec_pubkey_create_helper(const rustsecp256k1_v0_11_ecmult_gen_context *ecmult_gen_ctx, rustsecp256k1_v0_11_scalar *seckey_scalar, rustsecp256k1_v0_11_ge *p, const unsigned char *seckey) { + rustsecp256k1_v0_11_gej pj; + int ret; + + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(seckey_scalar, seckey); + rustsecp256k1_v0_11_scalar_cmov(seckey_scalar, &rustsecp256k1_v0_11_scalar_one, !ret); + + rustsecp256k1_v0_11_ecmult_gen(ecmult_gen_ctx, &pj, seckey_scalar); + rustsecp256k1_v0_11_ge_set_gej(p, &pj); + rustsecp256k1_v0_11_gej_clear(&pj); + return ret; +} + +int rustsecp256k1_v0_11_ec_pubkey_create(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *seckey) { + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_scalar seckey_scalar; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(seckey != NULL); + + ret = rustsecp256k1_v0_11_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey); + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); + rustsecp256k1_v0_11_memczero(pubkey, sizeof(*pubkey), !ret); + + rustsecp256k1_v0_11_scalar_clear(&seckey_scalar); + return ret; +} + +int rustsecp256k1_v0_11_ec_seckey_negate(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey) { + rustsecp256k1_v0_11_scalar sec; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_negate(&sec, &sec); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sec); + + rustsecp256k1_v0_11_scalar_clear(&sec); + return ret; +} + +int rustsecp256k1_v0_11_ec_privkey_negate(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey) { + return rustsecp256k1_v0_11_ec_seckey_negate(ctx, seckey); +} + +int rustsecp256k1_v0_11_ec_pubkey_negate(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey) { + int ret = 0; + rustsecp256k1_v0_11_ge p; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + + ret = rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + rustsecp256k1_v0_11_ge_neg(&p, &p); + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); + } + return ret; +} + + +static int rustsecp256k1_v0_11_ec_seckey_tweak_add_helper(rustsecp256k1_v0_11_scalar *sec, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar term; + int overflow = 0; + int ret = 0; + + rustsecp256k1_v0_11_scalar_set_b32(&term, tweak32, &overflow); + ret = (!overflow) & rustsecp256k1_v0_11_eckey_privkey_tweak_add(sec, &term); + rustsecp256k1_v0_11_scalar_clear(&term); + return ret; +} + +int rustsecp256k1_v0_11_ec_seckey_tweak_add(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar sec; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak32 != NULL); + + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + ret &= rustsecp256k1_v0_11_ec_seckey_tweak_add_helper(&sec, tweak32); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sec); + + rustsecp256k1_v0_11_scalar_clear(&sec); + return ret; +} + +int rustsecp256k1_v0_11_ec_privkey_tweak_add(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + return rustsecp256k1_v0_11_ec_seckey_tweak_add(ctx, seckey, tweak32); +} + +static int rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(rustsecp256k1_v0_11_ge *p, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar term; + int overflow = 0; + rustsecp256k1_v0_11_scalar_set_b32(&term, tweak32, &overflow); + return !overflow && rustsecp256k1_v0_11_eckey_pubkey_tweak_add(p, &term); +} + +int rustsecp256k1_v0_11_ec_pubkey_tweak_add(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge p; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak32 != NULL); + + ret = rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + ret = ret && rustsecp256k1_v0_11_ec_pubkey_tweak_add_helper(&p, tweak32); + if (ret) { + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); + } + + return ret; +} + +int rustsecp256k1_v0_11_ec_seckey_tweak_mul(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_scalar factor; + rustsecp256k1_v0_11_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak32 != NULL); + + rustsecp256k1_v0_11_scalar_set_b32(&factor, tweak32, &overflow); + ret = rustsecp256k1_v0_11_scalar_set_b32_seckey(&sec, seckey); + ret &= (!overflow) & rustsecp256k1_v0_11_eckey_privkey_tweak_mul(&sec, &factor); + rustsecp256k1_v0_11_scalar_cmov(&sec, &rustsecp256k1_v0_11_scalar_zero, !ret); + rustsecp256k1_v0_11_scalar_get_b32(seckey, &sec); + + rustsecp256k1_v0_11_scalar_clear(&sec); + rustsecp256k1_v0_11_scalar_clear(&factor); + return ret; +} + +int rustsecp256k1_v0_11_ec_privkey_tweak_mul(const rustsecp256k1_v0_11_context* ctx, unsigned char *seckey, const unsigned char *tweak32) { + return rustsecp256k1_v0_11_ec_seckey_tweak_mul(ctx, seckey, tweak32); +} + +int rustsecp256k1_v0_11_ec_pubkey_tweak_mul(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubkey, const unsigned char *tweak32) { + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_scalar factor; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak32 != NULL); + + rustsecp256k1_v0_11_scalar_set_b32(&factor, tweak32, &overflow); + ret = !overflow && rustsecp256k1_v0_11_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (rustsecp256k1_v0_11_eckey_pubkey_tweak_mul(&p, &factor)) { + rustsecp256k1_v0_11_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int rustsecp256k1_v0_11_context_randomize(rustsecp256k1_v0_11_context* ctx, const unsigned char *seed32) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(rustsecp256k1_v0_11_context_is_proper(ctx)); + + if (rustsecp256k1_v0_11_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)) { + rustsecp256k1_v0_11_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + } + return 1; +} + +int rustsecp256k1_v0_11_ec_pubkey_combine(const rustsecp256k1_v0_11_context* ctx, rustsecp256k1_v0_11_pubkey *pubnonce, const rustsecp256k1_v0_11_pubkey * const *pubnonces, size_t n) { + size_t i; + rustsecp256k1_v0_11_gej Qj; + rustsecp256k1_v0_11_ge Q; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubnonce != NULL); + memset(pubnonce, 0, sizeof(*pubnonce)); + ARG_CHECK(n >= 1); + ARG_CHECK(pubnonces != NULL); + + rustsecp256k1_v0_11_gej_set_infinity(&Qj); + + for (i = 0; i < n; i++) { + ARG_CHECK(pubnonces[i] != NULL); + rustsecp256k1_v0_11_pubkey_load(ctx, &Q, pubnonces[i]); + rustsecp256k1_v0_11_gej_add_ge(&Qj, &Qj, &Q); + } + if (rustsecp256k1_v0_11_gej_is_infinity(&Qj)) { + return 0; + } + rustsecp256k1_v0_11_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_11_pubkey_save(pubnonce, &Q); + return 1; +} + +int rustsecp256k1_v0_11_tagged_sha256(const rustsecp256k1_v0_11_context* ctx, unsigned char *hash32, const unsigned char *tag, size_t taglen, const unsigned char *msg, size_t msglen) { + rustsecp256k1_v0_11_sha256 sha; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(hash32 != NULL); + ARG_CHECK(tag != NULL); + ARG_CHECK(msg != NULL); + + rustsecp256k1_v0_11_sha256_initialize_tagged(&sha, tag, taglen); + rustsecp256k1_v0_11_sha256_write(&sha, msg, msglen); + rustsecp256k1_v0_11_sha256_finalize(&sha, hash32); + rustsecp256k1_v0_11_sha256_clear(&sha); + return 1; +} + +#ifdef ENABLE_MODULE_ECDH +# include "modules/ecdh/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_RECOVERY +# include "modules/recovery/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_EXTRAKEYS +# include "modules/extrakeys/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_SCHNORRSIG +# 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/secp256k1-sys/depend/secp256k1/src/selftest.h b/secp256k1-sys/depend/secp256k1/src/selftest.h index 621765fe9..6675a19f4 100644 --- a/secp256k1-sys/depend/secp256k1/src/selftest.h +++ b/secp256k1-sys/depend/secp256k1/src/selftest.h @@ -11,22 +11,22 @@ #include -static int rustsecp256k1_v0_10_0_selftest_sha256(void) { +static int rustsecp256k1_v0_11_selftest_sha256(void) { 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, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42, }; unsigned char out[32]; - rustsecp256k1_v0_10_0_sha256 hasher; - rustsecp256k1_v0_10_0_sha256_initialize(&hasher); - rustsecp256k1_v0_10_0_sha256_write(&hasher, (const unsigned char*)input63, 63); - rustsecp256k1_v0_10_0_sha256_finalize(&hasher, out); - return rustsecp256k1_v0_10_0_memcmp_var(out, output32, 32) == 0; + rustsecp256k1_v0_11_sha256 hasher; + rustsecp256k1_v0_11_sha256_initialize(&hasher); + rustsecp256k1_v0_11_sha256_write(&hasher, (const unsigned char*)input63, 63); + rustsecp256k1_v0_11_sha256_finalize(&hasher, out); + return rustsecp256k1_v0_11_memcmp_var(out, output32, 32) == 0; } -static int rustsecp256k1_v0_10_0_selftest_passes(void) { - return rustsecp256k1_v0_10_0_selftest_sha256(); +static int rustsecp256k1_v0_11_selftest_passes(void) { + return rustsecp256k1_v0_11_selftest_sha256(); } #endif /* SECP256K1_SELFTEST_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/testrand.h b/secp256k1-sys/depend/secp256k1/src/testrand.h index 362618028..3c1ed3d45 100644 --- a/secp256k1-sys/depend/secp256k1/src/testrand.h +++ b/secp256k1-sys/depend/secp256k1/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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_testrand_int(uint32_t range); +static uint32_t testrand_int(uint32_t range); /** Generate a pseudorandom 32-byte array. */ -static void rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_testrand_init(const char* hexseed); +static void testrand_init(const char* hexseed); /** Print final test information. */ -static void rustsecp256k1_v0_10_0_testrand_finish(void); +static void testrand_finish(void); #endif /* SECP256K1_TESTRAND_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/testrand_impl.h b/secp256k1-sys/depend/secp256k1/src/testrand_impl.h index a75ba04cc..d23155ee1 100644 --- a/secp256k1-sys/depend/secp256k1/src/testrand_impl.h +++ b/secp256k1-sys/depend/secp256k1/src/testrand_impl.h @@ -15,24 +15,24 @@ #include "hash.h" #include "util.h" -static uint64_t rustsecp256k1_v0_10_0_test_state[4]; +static uint64_t rustsecp256k1_v0_11_test_state[4]; -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_testrand_seed(const unsigned char *seed16) { - static const unsigned char PREFIX[19] = "secp256k1 test init"; +SECP256K1_INLINE static void testrand_seed(const unsigned char *seed16) { + 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]; - rustsecp256k1_v0_10_0_sha256 hash; + rustsecp256k1_v0_11_sha256 hash; int i; /* Use SHA256(PREFIX || seed16) as initial state. */ - rustsecp256k1_v0_10_0_sha256_initialize(&hash); - rustsecp256k1_v0_10_0_sha256_write(&hash, PREFIX, sizeof(PREFIX)); - rustsecp256k1_v0_10_0_sha256_write(&hash, seed16, 16); - rustsecp256k1_v0_10_0_sha256_finalize(&hash, out32); + rustsecp256k1_v0_11_sha256_initialize(&hash); + rustsecp256k1_v0_11_sha256_write(&hash, PREFIX, sizeof(PREFIX)); + rustsecp256k1_v0_11_sha256_write(&hash, seed16, 16); + rustsecp256k1_v0_11_sha256_finalize(&hash, out32); for (i = 0; i < 4; ++i) { uint64_t s = 0; int j; for (j = 0; j < 8; ++j) s = (s << 8) | out32[8*i + j]; - rustsecp256k1_v0_10_0_test_state[i] = s; + rustsecp256k1_v0_11_test_state[i] = s; } } @@ -40,29 +40,29 @@ SECP256K1_INLINE static uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); } -SECP256K1_INLINE static uint64_t rustsecp256k1_v0_10_0_testrand64(void) { +SECP256K1_INLINE static uint64_t testrand64(void) { /* Test-only Xoshiro256++ RNG. See https://prng.di.unimi.it/ */ - const uint64_t result = rotl(rustsecp256k1_v0_10_0_test_state[0] + rustsecp256k1_v0_10_0_test_state[3], 23) + rustsecp256k1_v0_10_0_test_state[0]; - const uint64_t t = rustsecp256k1_v0_10_0_test_state[1] << 17; - rustsecp256k1_v0_10_0_test_state[2] ^= rustsecp256k1_v0_10_0_test_state[0]; - rustsecp256k1_v0_10_0_test_state[3] ^= rustsecp256k1_v0_10_0_test_state[1]; - rustsecp256k1_v0_10_0_test_state[1] ^= rustsecp256k1_v0_10_0_test_state[2]; - rustsecp256k1_v0_10_0_test_state[0] ^= rustsecp256k1_v0_10_0_test_state[3]; - rustsecp256k1_v0_10_0_test_state[2] ^= t; - rustsecp256k1_v0_10_0_test_state[3] = rotl(rustsecp256k1_v0_10_0_test_state[3], 45); + const uint64_t result = rotl(rustsecp256k1_v0_11_test_state[0] + rustsecp256k1_v0_11_test_state[3], 23) + rustsecp256k1_v0_11_test_state[0]; + const uint64_t t = rustsecp256k1_v0_11_test_state[1] << 17; + rustsecp256k1_v0_11_test_state[2] ^= rustsecp256k1_v0_11_test_state[0]; + rustsecp256k1_v0_11_test_state[3] ^= rustsecp256k1_v0_11_test_state[1]; + rustsecp256k1_v0_11_test_state[1] ^= rustsecp256k1_v0_11_test_state[2]; + rustsecp256k1_v0_11_test_state[0] ^= rustsecp256k1_v0_11_test_state[3]; + rustsecp256k1_v0_11_test_state[2] ^= t; + rustsecp256k1_v0_11_test_state[3] = rotl(rustsecp256k1_v0_11_test_state[3], 45); return result; } -SECP256K1_INLINE static uint64_t rustsecp256k1_v0_10_0_testrand_bits(int bits) { +SECP256K1_INLINE static uint64_t testrand_bits(int bits) { if (bits == 0) return 0; - return rustsecp256k1_v0_10_0_testrand64() >> (64 - bits); + return testrand64() >> (64 - bits); } -SECP256K1_INLINE static uint32_t rustsecp256k1_v0_10_0_testrand32(void) { - return rustsecp256k1_v0_10_0_testrand64() >> 32; +SECP256K1_INLINE static uint32_t testrand32(void) { + return testrand64() >> 32; } -static uint32_t rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_testrand_int(uint32_t range) { } /* Generation loop. */ while (1) { - uint32_t val = rustsecp256k1_v0_10_0_testrand64() & mask; + uint32_t val = testrand64() & mask; if (val <= range) return val; } } -static void rustsecp256k1_v0_10_0_testrand256(unsigned char *b32) { +static void testrand256(unsigned char *b32) { int i; for (i = 0; i < 4; ++i) { - uint64_t val = rustsecp256k1_v0_10_0_testrand64(); + uint64_t val = testrand64(); b32[0] = val; b32[1] = val >> 8; b32[2] = val >> 16; @@ -97,14 +97,14 @@ static void rustsecp256k1_v0_10_0_testrand256(unsigned char *b32) { } } -static void rustsecp256k1_v0_10_0_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 + (rustsecp256k1_v0_10_0_testrand_bits(6) * rustsecp256k1_v0_10_0_testrand_bits(5) + 16) / 31; - val = rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_testrand_bytes_test(unsigned char *bytes, size } } -static void rustsecp256k1_v0_10_0_testrand256_test(unsigned char *b32) { - rustsecp256k1_v0_10_0_testrand_bytes_test(b32, 32); +static void testrand256_test(unsigned char *b32) { + testrand_bytes_test(b32, 32); } -static void rustsecp256k1_v0_10_0_testrand_flip(unsigned char *b, size_t len) { - b[rustsecp256k1_v0_10_0_testrand_int(len)] ^= (1 << rustsecp256k1_v0_10_0_testrand_bits(3)); +static void testrand_flip(unsigned char *b, size_t len) { + b[testrand_int(len)] ^= (1 << testrand_bits(3)); } -static void rustsecp256k1_v0_10_0_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 rustsecp256k1_v0_10_0_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]); - rustsecp256k1_v0_10_0_testrand_seed(seed16); + testrand_seed(seed16); } -static void rustsecp256k1_v0_10_0_testrand_finish(void) { +static void testrand_finish(void) { unsigned char run32[32]; - rustsecp256k1_v0_10_0_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/secp256k1-sys/depend/secp256k1/src/tests.c b/secp256k1-sys/depend/secp256k1/src/tests.c index 1b6e65496..5939d8c5e 100644 --- a/secp256k1-sys/depend/secp256k1/src/tests.c +++ b/secp256k1-sys/depend/secp256k1/src/tests.c @@ -37,9 +37,9 @@ #define CONDITIONAL_TEST(cnt, nam) if (COUNT < (cnt)) { printf("Skipping %s (iteration count too low)\n", nam); } else -static int COUNT = 64; -static rustsecp256k1_v0_10_0_context *CTX = NULL; -static rustsecp256k1_v0_10_0_context *STATIC_CTX = NULL; +static int COUNT = 16; +static rustsecp256k1_v0_11_context *CTX = NULL; +static rustsecp256k1_v0_11_context *STATIC_CTX = NULL; static int all_bytes_equal(const void* s, unsigned char value, size_t n) { const unsigned char *p = s; @@ -55,7 +55,7 @@ static int all_bytes_equal(const void* s, unsigned char value, size_t n) { #define CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, callback, callback_setter) do { \ int32_t _calls_to_callback = 0; \ - rustsecp256k1_v0_10_0_callback _saved_callback = ctx->callback; \ + rustsecp256k1_v0_11_callback _saved_callback = ctx->callback; \ callback_setter(ctx, counting_callback_fn, &_calls_to_callback); \ { expr_or_stmt; } \ ctx->callback = _saved_callback; \ @@ -66,9 +66,9 @@ static int all_bytes_equal(const void* s, unsigned char value, size_t n) { * * Useful for checking functions that return void (e.g., API functions that use ARG_CHECK_VOID) */ #define CHECK_ERROR_VOID(ctx, expr_or_stmt) \ - CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, error_callback, rustsecp256k1_v0_10_0_context_set_error_callback) + CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, error_callback, rustsecp256k1_v0_11_context_set_error_callback) #define CHECK_ILLEGAL_VOID(ctx, expr_or_stmt) \ - CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, illegal_callback, rustsecp256k1_v0_10_0_context_set_illegal_callback) + CHECK_COUNTING_CALLBACK_VOID(ctx, expr_or_stmt, illegal_callback, rustsecp256k1_v0_11_context_set_illegal_callback) /* CHECK that * - expr calls the illegal callback of ctx exactly once and, @@ -96,128 +96,12 @@ static void uncounting_illegal_callback_fn(const char* str, void* data) { (*p)--; } -static void random_field_element_magnitude(rustsecp256k1_v0_10_0_fe *fe, int m) { - rustsecp256k1_v0_10_0_fe zero; - int n = rustsecp256k1_v0_10_0_testrand_int(m + 1); - rustsecp256k1_v0_10_0_fe_normalize(fe); - if (n == 0) { - return; - } - rustsecp256k1_v0_10_0_fe_clear(&zero); - rustsecp256k1_v0_10_0_fe_negate(&zero, &zero, 0); - rustsecp256k1_v0_10_0_fe_mul_int_unchecked(&zero, n - 1); - rustsecp256k1_v0_10_0_fe_add(fe, &zero); -#ifdef VERIFY - CHECK(fe->magnitude == n); -#endif -} - -static void random_fe_test(rustsecp256k1_v0_10_0_fe *x) { - unsigned char bin[32]; - do { - rustsecp256k1_v0_10_0_testrand256_test(bin); - if (rustsecp256k1_v0_10_0_fe_set_b32_limit(x, bin)) { - return; - } - } while(1); -} - -static void random_fe_non_zero_test(rustsecp256k1_v0_10_0_fe *fe) { - do { - random_fe_test(fe); - } while(rustsecp256k1_v0_10_0_fe_is_zero(fe)); -} - -static void random_fe_magnitude(rustsecp256k1_v0_10_0_fe *fe) { - random_field_element_magnitude(fe, 8); -} - -static void random_ge_x_magnitude(rustsecp256k1_v0_10_0_ge *ge) { - random_field_element_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); -} - -static void random_ge_y_magnitude(rustsecp256k1_v0_10_0_ge *ge) { - random_field_element_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); -} - -static void random_gej_x_magnitude(rustsecp256k1_v0_10_0_gej *gej) { - random_field_element_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); -} - -static void random_gej_y_magnitude(rustsecp256k1_v0_10_0_gej *gej) { - random_field_element_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); -} - -static void random_gej_z_magnitude(rustsecp256k1_v0_10_0_gej *gej) { - random_field_element_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); -} - -static void random_group_element_test(rustsecp256k1_v0_10_0_ge *ge) { - rustsecp256k1_v0_10_0_fe fe; - do { - random_fe_test(&fe); - if (rustsecp256k1_v0_10_0_ge_set_xo_var(ge, &fe, rustsecp256k1_v0_10_0_testrand_bits(1))) { - rustsecp256k1_v0_10_0_fe_normalize(&ge->y); - break; - } - } while(1); - ge->infinity = 0; -} - -static void random_group_element_jacobian_test(rustsecp256k1_v0_10_0_gej *gej, const rustsecp256k1_v0_10_0_ge *ge) { - rustsecp256k1_v0_10_0_fe z2, z3; - random_fe_non_zero_test(&gej->z); - rustsecp256k1_v0_10_0_fe_sqr(&z2, &gej->z); - rustsecp256k1_v0_10_0_fe_mul(&z3, &z2, &gej->z); - rustsecp256k1_v0_10_0_fe_mul(&gej->x, &ge->x, &z2); - rustsecp256k1_v0_10_0_fe_mul(&gej->y, &ge->y, &z3); - gej->infinity = ge->infinity; -} - -static void random_gej_test(rustsecp256k1_v0_10_0_gej *gej) { - rustsecp256k1_v0_10_0_ge ge; - random_group_element_test(&ge); - random_group_element_jacobian_test(gej, &ge); -} - -static void random_scalar_order_test(rustsecp256k1_v0_10_0_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - rustsecp256k1_v0_10_0_testrand256_test(b32); - rustsecp256k1_v0_10_0_scalar_set_b32(num, b32, &overflow); - if (overflow || rustsecp256k1_v0_10_0_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -static void random_scalar_order(rustsecp256k1_v0_10_0_scalar *num) { - do { - unsigned char b32[32]; - int overflow = 0; - rustsecp256k1_v0_10_0_testrand256(b32); - rustsecp256k1_v0_10_0_scalar_set_b32(num, b32, &overflow); - if (overflow || rustsecp256k1_v0_10_0_scalar_is_zero(num)) { - continue; - } - break; - } while(1); -} - -static void random_scalar_order_b32(unsigned char *b32) { - rustsecp256k1_v0_10_0_scalar num; - random_scalar_order(&num); - rustsecp256k1_v0_10_0_scalar_get_b32(b32, &num); -} - static void run_xoshiro256pp_tests(void) { { size_t i; /* Sanity check that we run before the actual seeding. */ - for (i = 0; i < sizeof(rustsecp256k1_v0_10_0_test_state)/sizeof(rustsecp256k1_v0_10_0_test_state[0]); i++) { - CHECK(rustsecp256k1_v0_10_0_test_state[i] == 0); + for (i = 0; i < sizeof(rustsecp256k1_v0_11_test_state)/sizeof(rustsecp256k1_v0_11_test_state[0]); i++) { + CHECK(rustsecp256k1_v0_11_test_state[i] == 0); } } { @@ -233,26 +117,27 @@ static void run_xoshiro256pp_tests(void) { 0x4C, 0xCC, 0xC1, 0x18, 0xB2, 0xD8, 0x8F, 0xEF, 0x43, 0x26, 0x15, 0x57, 0x37, 0x00, 0xEF, 0x30, }; - rustsecp256k1_v0_10_0_testrand_seed(seed16); + testrand_seed(seed16); for (i = 0; i < 17; i++) { - rustsecp256k1_v0_10_0_testrand256(buf32); + testrand256(buf32); } - CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(buf32, buf32_expected, sizeof(buf32)) == 0); } } static void run_selftest_tests(void) { /* Test public API */ - rustsecp256k1_v0_10_0_selftest(); + rustsecp256k1_v0_11_selftest(); } -static int ecmult_gen_context_eq(const rustsecp256k1_v0_10_0_ecmult_gen_context *a, const rustsecp256k1_v0_10_0_ecmult_gen_context *b) { +static int ecmult_gen_context_eq(const rustsecp256k1_v0_11_ecmult_gen_context *a, const rustsecp256k1_v0_11_ecmult_gen_context *b) { return a->built == b->built - && rustsecp256k1_v0_10_0_scalar_eq(&a->blind, &b->blind) - && rustsecp256k1_v0_10_0_gej_eq_var(&a->initial, &b->initial); + && rustsecp256k1_v0_11_scalar_eq(&a->scalar_offset, &b->scalar_offset) + && rustsecp256k1_v0_11_ge_eq_var(&a->ge_offset, &b->ge_offset) + && rustsecp256k1_v0_11_fe_equal(&a->proj_blind, &b->proj_blind); } -static int context_eq(const rustsecp256k1_v0_10_0_context *a, const rustsecp256k1_v0_10_0_context *b) { +static int context_eq(const rustsecp256k1_v0_11_context *a, const rustsecp256k1_v0_11_context *b) { return a->declassify == b->declassify && ecmult_gen_context_eq(&a->ecmult_gen_ctx, &b->ecmult_gen_ctx) && a->illegal_callback.fn == b->illegal_callback.fn @@ -267,22 +152,22 @@ static void run_deprecated_context_flags_test(void) { unsigned int flags[] = { SECP256K1_CONTEXT_SIGN, SECP256K1_CONTEXT_VERIFY, SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY }; - rustsecp256k1_v0_10_0_context *none_ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + rustsecp256k1_v0_11_context *none_ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); int i; for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) { - rustsecp256k1_v0_10_0_context *tmp_ctx; - CHECK(rustsecp256k1_v0_10_0_context_preallocated_size(SECP256K1_CONTEXT_NONE) == rustsecp256k1_v0_10_0_context_preallocated_size(flags[i])); - tmp_ctx = rustsecp256k1_v0_10_0_context_create(flags[i]); + rustsecp256k1_v0_11_context *tmp_ctx; + CHECK(rustsecp256k1_v0_11_context_preallocated_size(SECP256K1_CONTEXT_NONE) == rustsecp256k1_v0_11_context_preallocated_size(flags[i])); + tmp_ctx = rustsecp256k1_v0_11_context_create(flags[i]); CHECK(context_eq(none_ctx, tmp_ctx)); - rustsecp256k1_v0_10_0_context_destroy(tmp_ctx); + rustsecp256k1_v0_11_context_destroy(tmp_ctx); } - rustsecp256k1_v0_10_0_context_destroy(none_ctx); + rustsecp256k1_v0_11_context_destroy(none_ctx); } static void run_ec_illegal_argument_tests(void) { - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_pubkey zero_pubkey; - rustsecp256k1_v0_10_0_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_pubkey zero_pubkey; + rustsecp256k1_v0_11_ecdsa_signature sig; unsigned char ctmp[32]; /* Setup */ @@ -290,187 +175,187 @@ static void run_ec_illegal_argument_tests(void) { memset(&zero_pubkey, 0, sizeof(zero_pubkey)); /* Verify context-type checking illegal-argument errors. */ - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_ec_pubkey_create(STATIC_CTX, &pubkey, ctmp)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_ec_pubkey_create(STATIC_CTX, &pubkey, ctmp)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_ecdsa_sign(STATIC_CTX, &sig, ctmp, ctmp, NULL, NULL)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_ecdsa_sign(STATIC_CTX, &sig, ctmp, ctmp, NULL, NULL)); SECP256K1_CHECKMEM_UNDEFINE(&sig, sizeof(sig)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, ctmp, ctmp, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, ctmp, ctmp, NULL, NULL) == 1); SECP256K1_CHECKMEM_CHECK(&sig, sizeof(sig)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, ctmp, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(STATIC_CTX, &sig, ctmp, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, ctmp) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(STATIC_CTX, &pubkey, ctmp) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey, ctmp) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_negate(STATIC_CTX, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_negate(CTX, &pubkey) == 1); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_ec_pubkey_negate(STATIC_CTX, &zero_pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_negate(CTX, NULL)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(STATIC_CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, ctmp, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(STATIC_CTX, &sig, ctmp, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(STATIC_CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_negate(STATIC_CTX, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_negate(CTX, &pubkey) == 1); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_ec_pubkey_negate(STATIC_CTX, &zero_pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_negate(CTX, NULL)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_mul(STATIC_CTX, &pubkey, ctmp) == 1); } static void run_static_context_tests(int use_prealloc) { - /* Check that deprecated rustsecp256k1_v0_10_0_context_no_precomp is an alias to rustsecp256k1_v0_10_0_context_static. */ - CHECK(rustsecp256k1_v0_10_0_context_no_precomp == rustsecp256k1_v0_10_0_context_static); + /* Check that deprecated rustsecp256k1_v0_11_context_no_precomp is an alias to rustsecp256k1_v0_11_context_static. */ + CHECK(rustsecp256k1_v0_11_context_no_precomp == rustsecp256k1_v0_11_context_static); { unsigned char seed[32] = {0x17}; - /* Randomizing rustsecp256k1_v0_10_0_context_static is not supported. */ - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_context_randomize(STATIC_CTX, seed)); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_context_randomize(STATIC_CTX, NULL)); + /* Randomizing rustsecp256k1_v0_11_context_static is not supported. */ + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_context_randomize(STATIC_CTX, seed)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_context_randomize(STATIC_CTX, NULL)); - /* Destroying or cloning rustsecp256k1_v0_10_0_context_static is not supported. */ + /* Destroying or cloning rustsecp256k1_v0_11_context_static is not supported. */ if (use_prealloc) { - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_context_preallocated_clone_size(STATIC_CTX)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_context_preallocated_clone_size(STATIC_CTX)); { - rustsecp256k1_v0_10_0_context *my_static_ctx = malloc(sizeof(*STATIC_CTX)); + rustsecp256k1_v0_11_context *my_static_ctx = malloc(sizeof(*STATIC_CTX)); CHECK(my_static_ctx != NULL); memset(my_static_ctx, 0x2a, sizeof(*my_static_ctx)); - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_context_preallocated_clone(STATIC_CTX, my_static_ctx)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_context_preallocated_clone(STATIC_CTX, my_static_ctx)); CHECK(all_bytes_equal(my_static_ctx, 0x2a, sizeof(*my_static_ctx))); free(my_static_ctx); } - CHECK_ILLEGAL_VOID(STATIC_CTX, rustsecp256k1_v0_10_0_context_preallocated_destroy(STATIC_CTX)); + CHECK_ILLEGAL_VOID(STATIC_CTX, rustsecp256k1_v0_11_context_preallocated_destroy(STATIC_CTX)); } else { - CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_10_0_context_clone(STATIC_CTX)); - CHECK_ILLEGAL_VOID(STATIC_CTX, rustsecp256k1_v0_10_0_context_destroy(STATIC_CTX)); + CHECK_ILLEGAL(STATIC_CTX, rustsecp256k1_v0_11_context_clone(STATIC_CTX)); + CHECK_ILLEGAL_VOID(STATIC_CTX, rustsecp256k1_v0_11_context_destroy(STATIC_CTX)); } } { /* Verify that setting and resetting illegal callback works */ int32_t dummy = 0; - rustsecp256k1_v0_10_0_context_set_illegal_callback(STATIC_CTX, counting_callback_fn, &dummy); + rustsecp256k1_v0_11_context_set_illegal_callback(STATIC_CTX, counting_callback_fn, &dummy); CHECK(STATIC_CTX->illegal_callback.fn == counting_callback_fn); CHECK(STATIC_CTX->illegal_callback.data == &dummy); - rustsecp256k1_v0_10_0_context_set_illegal_callback(STATIC_CTX, NULL, NULL); - CHECK(STATIC_CTX->illegal_callback.fn == rustsecp256k1_v0_10_0_default_illegal_callback_fn); + rustsecp256k1_v0_11_context_set_illegal_callback(STATIC_CTX, NULL, NULL); + CHECK(STATIC_CTX->illegal_callback.fn == rustsecp256k1_v0_11_default_illegal_callback_fn); CHECK(STATIC_CTX->illegal_callback.data == NULL); } } static void run_proper_context_tests(int use_prealloc) { int32_t dummy = 0; - rustsecp256k1_v0_10_0_context *my_ctx, *my_ctx_fresh; + rustsecp256k1_v0_11_context *my_ctx, *my_ctx_fresh; void *my_ctx_prealloc = NULL; unsigned char seed[32] = {0x17}; - rustsecp256k1_v0_10_0_gej pubj; - rustsecp256k1_v0_10_0_ge pub; - rustsecp256k1_v0_10_0_scalar msg, key, nonce; - rustsecp256k1_v0_10_0_scalar sigr, sigs; + rustsecp256k1_v0_11_gej pubj; + rustsecp256k1_v0_11_ge pub; + rustsecp256k1_v0_11_scalar msg, key, nonce; + rustsecp256k1_v0_11_scalar sigr, sigs; /* Fresh reference context for comparison */ - my_ctx_fresh = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + my_ctx_fresh = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); if (use_prealloc) { - my_ctx_prealloc = malloc(rustsecp256k1_v0_10_0_context_preallocated_size(SECP256K1_CONTEXT_NONE)); + my_ctx_prealloc = malloc(rustsecp256k1_v0_11_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(my_ctx_prealloc != NULL); - my_ctx = rustsecp256k1_v0_10_0_context_preallocated_create(my_ctx_prealloc, SECP256K1_CONTEXT_NONE); + my_ctx = rustsecp256k1_v0_11_context_preallocated_create(my_ctx_prealloc, SECP256K1_CONTEXT_NONE); } else { - my_ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + my_ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); } /* Randomize and reset randomization */ CHECK(context_eq(my_ctx, my_ctx_fresh)); - CHECK(rustsecp256k1_v0_10_0_context_randomize(my_ctx, seed) == 1); + CHECK(rustsecp256k1_v0_11_context_randomize(my_ctx, seed) == 1); CHECK(!context_eq(my_ctx, my_ctx_fresh)); - CHECK(rustsecp256k1_v0_10_0_context_randomize(my_ctx, NULL) == 1); + CHECK(rustsecp256k1_v0_11_context_randomize(my_ctx, NULL) == 1); CHECK(context_eq(my_ctx, my_ctx_fresh)); - /* set error callback (to a function that still aborts in case malloc() fails in rustsecp256k1_v0_10_0_context_clone() below) */ - rustsecp256k1_v0_10_0_context_set_error_callback(my_ctx, rustsecp256k1_v0_10_0_default_illegal_callback_fn, NULL); - CHECK(my_ctx->error_callback.fn != rustsecp256k1_v0_10_0_default_error_callback_fn); - CHECK(my_ctx->error_callback.fn == rustsecp256k1_v0_10_0_default_illegal_callback_fn); + /* set error callback (to a function that still aborts in case malloc() fails in rustsecp256k1_v0_11_context_clone() below) */ + rustsecp256k1_v0_11_context_set_error_callback(my_ctx, rustsecp256k1_v0_11_default_illegal_callback_fn, NULL); + CHECK(my_ctx->error_callback.fn != rustsecp256k1_v0_11_default_error_callback_fn); + CHECK(my_ctx->error_callback.fn == rustsecp256k1_v0_11_default_illegal_callback_fn); /* check if sizes for cloning are consistent */ - CHECK(rustsecp256k1_v0_10_0_context_preallocated_clone_size(my_ctx) == rustsecp256k1_v0_10_0_context_preallocated_size(SECP256K1_CONTEXT_NONE)); + CHECK(rustsecp256k1_v0_11_context_preallocated_clone_size(my_ctx) == rustsecp256k1_v0_11_context_preallocated_size(SECP256K1_CONTEXT_NONE)); /*** clone and destroy all of them to make sure cloning was complete ***/ { - rustsecp256k1_v0_10_0_context *ctx_tmp; + rustsecp256k1_v0_11_context *ctx_tmp; if (use_prealloc) { /* clone into a non-preallocated context and then again into a new preallocated one. */ ctx_tmp = my_ctx; - my_ctx = rustsecp256k1_v0_10_0_context_clone(my_ctx); + my_ctx = rustsecp256k1_v0_11_context_clone(my_ctx); CHECK(context_eq(ctx_tmp, my_ctx)); - rustsecp256k1_v0_10_0_context_preallocated_destroy(ctx_tmp); + rustsecp256k1_v0_11_context_preallocated_destroy(ctx_tmp); free(my_ctx_prealloc); - my_ctx_prealloc = malloc(rustsecp256k1_v0_10_0_context_preallocated_size(SECP256K1_CONTEXT_NONE)); + my_ctx_prealloc = malloc(rustsecp256k1_v0_11_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(my_ctx_prealloc != NULL); ctx_tmp = my_ctx; - my_ctx = rustsecp256k1_v0_10_0_context_preallocated_clone(my_ctx, my_ctx_prealloc); + my_ctx = rustsecp256k1_v0_11_context_preallocated_clone(my_ctx, my_ctx_prealloc); CHECK(context_eq(ctx_tmp, my_ctx)); - rustsecp256k1_v0_10_0_context_destroy(ctx_tmp); + rustsecp256k1_v0_11_context_destroy(ctx_tmp); } else { /* clone into a preallocated context and then again into a new non-preallocated one. */ void *prealloc_tmp; - prealloc_tmp = malloc(rustsecp256k1_v0_10_0_context_preallocated_size(SECP256K1_CONTEXT_NONE)); + prealloc_tmp = malloc(rustsecp256k1_v0_11_context_preallocated_size(SECP256K1_CONTEXT_NONE)); CHECK(prealloc_tmp != NULL); ctx_tmp = my_ctx; - my_ctx = rustsecp256k1_v0_10_0_context_preallocated_clone(my_ctx, prealloc_tmp); + my_ctx = rustsecp256k1_v0_11_context_preallocated_clone(my_ctx, prealloc_tmp); CHECK(context_eq(ctx_tmp, my_ctx)); - rustsecp256k1_v0_10_0_context_destroy(ctx_tmp); + rustsecp256k1_v0_11_context_destroy(ctx_tmp); ctx_tmp = my_ctx; - my_ctx = rustsecp256k1_v0_10_0_context_clone(my_ctx); + my_ctx = rustsecp256k1_v0_11_context_clone(my_ctx); CHECK(context_eq(ctx_tmp, my_ctx)); - rustsecp256k1_v0_10_0_context_preallocated_destroy(ctx_tmp); + rustsecp256k1_v0_11_context_preallocated_destroy(ctx_tmp); free(prealloc_tmp); } } /* Verify that the error callback makes it across the clone. */ - CHECK(my_ctx->error_callback.fn != rustsecp256k1_v0_10_0_default_error_callback_fn); - CHECK(my_ctx->error_callback.fn == rustsecp256k1_v0_10_0_default_illegal_callback_fn); + CHECK(my_ctx->error_callback.fn != rustsecp256k1_v0_11_default_error_callback_fn); + CHECK(my_ctx->error_callback.fn == rustsecp256k1_v0_11_default_illegal_callback_fn); /* And that it resets back to default. */ - rustsecp256k1_v0_10_0_context_set_error_callback(my_ctx, NULL, NULL); - CHECK(my_ctx->error_callback.fn == rustsecp256k1_v0_10_0_default_error_callback_fn); + rustsecp256k1_v0_11_context_set_error_callback(my_ctx, NULL, NULL); + CHECK(my_ctx->error_callback.fn == rustsecp256k1_v0_11_default_error_callback_fn); CHECK(context_eq(my_ctx, my_ctx_fresh)); /* Verify that setting and resetting illegal callback works */ - rustsecp256k1_v0_10_0_context_set_illegal_callback(my_ctx, counting_callback_fn, &dummy); + rustsecp256k1_v0_11_context_set_illegal_callback(my_ctx, counting_callback_fn, &dummy); CHECK(my_ctx->illegal_callback.fn == counting_callback_fn); CHECK(my_ctx->illegal_callback.data == &dummy); - rustsecp256k1_v0_10_0_context_set_illegal_callback(my_ctx, NULL, NULL); - CHECK(my_ctx->illegal_callback.fn == rustsecp256k1_v0_10_0_default_illegal_callback_fn); + rustsecp256k1_v0_11_context_set_illegal_callback(my_ctx, NULL, NULL); + CHECK(my_ctx->illegal_callback.fn == rustsecp256k1_v0_11_default_illegal_callback_fn); CHECK(my_ctx->illegal_callback.data == NULL); CHECK(context_eq(my_ctx, my_ctx_fresh)); /*** attempt to use them ***/ - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - rustsecp256k1_v0_10_0_ecmult_gen(&my_ctx->ecmult_gen_ctx, &pubj, &key); - rustsecp256k1_v0_10_0_ge_set_gej(&pub, &pubj); + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); + rustsecp256k1_v0_11_ecmult_gen(&my_ctx->ecmult_gen_ctx, &pubj, &key); + rustsecp256k1_v0_11_ge_set_gej(&pub, &pubj); /* obtain a working nonce */ do { - random_scalar_order_test(&nonce); - } while(!rustsecp256k1_v0_10_0_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + testutil_random_scalar_order_test(&nonce); + } while(!rustsecp256k1_v0_11_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try signing */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_sign(&my_ctx->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try verifying */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); /* cleanup */ if (use_prealloc) { - rustsecp256k1_v0_10_0_context_preallocated_destroy(my_ctx); + rustsecp256k1_v0_11_context_preallocated_destroy(my_ctx); free(my_ctx_prealloc); } else { - rustsecp256k1_v0_10_0_context_destroy(my_ctx); + rustsecp256k1_v0_11_context_destroy(my_ctx); } - rustsecp256k1_v0_10_0_context_destroy(my_ctx_fresh); + rustsecp256k1_v0_11_context_destroy(my_ctx_fresh); /* Defined as no-op. */ - rustsecp256k1_v0_10_0_context_destroy(NULL); - rustsecp256k1_v0_10_0_context_preallocated_destroy(NULL); + rustsecp256k1_v0_11_context_destroy(NULL); + rustsecp256k1_v0_11_context_preallocated_destroy(NULL); } static void run_scratch_tests(void) { @@ -478,69 +363,69 @@ static void run_scratch_tests(void) { size_t checkpoint; size_t checkpoint_2; - rustsecp256k1_v0_10_0_scratch_space *scratch; - rustsecp256k1_v0_10_0_scratch_space local_scratch; + rustsecp256k1_v0_11_scratch_space *scratch; + rustsecp256k1_v0_11_scratch_space local_scratch; /* Test public API */ - scratch = rustsecp256k1_v0_10_0_scratch_space_create(CTX, 1000); + scratch = rustsecp256k1_v0_11_scratch_space_create(CTX, 1000); CHECK(scratch != NULL); /* Test internal API */ - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1)); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - (ALIGNMENT - 1)); CHECK(scratch->alloc_size == 0); CHECK(scratch->alloc_size % ALIGNMENT == 0); /* Allocating 500 bytes succeeds */ - checkpoint = rustsecp256k1_v0_10_0_scratch_checkpoint(&CTX->error_callback, scratch); - CHECK(rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, 500) != NULL); - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000 - adj_alloc); - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); + checkpoint = rustsecp256k1_v0_11_scratch_checkpoint(&CTX->error_callback, scratch); + CHECK(rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, 500) != NULL); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000 - adj_alloc); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); CHECK(scratch->alloc_size != 0); CHECK(scratch->alloc_size % ALIGNMENT == 0); /* Allocating another 501 bytes fails */ - CHECK(rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, 501) == NULL); - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000 - adj_alloc); - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); + CHECK(rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, 501) == NULL); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000 - adj_alloc); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 1) == 1000 - adj_alloc - (ALIGNMENT - 1)); CHECK(scratch->alloc_size != 0); CHECK(scratch->alloc_size % ALIGNMENT == 0); /* ...but it succeeds once we apply the checkpoint to undo it */ - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); + rustsecp256k1_v0_11_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); CHECK(scratch->alloc_size == 0); - CHECK(rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); - CHECK(rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, 500) != NULL); + CHECK(rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 0) == 1000); + CHECK(rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, 500) != NULL); CHECK(scratch->alloc_size != 0); /* try to apply a bad checkpoint */ - checkpoint_2 = rustsecp256k1_v0_10_0_scratch_checkpoint(&CTX->error_callback, scratch); - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); - CHECK_ERROR_VOID(CTX, rustsecp256k1_v0_10_0_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint_2)); /* checkpoint_2 is after checkpoint */ - CHECK_ERROR_VOID(CTX, rustsecp256k1_v0_10_0_scratch_apply_checkpoint(&CTX->error_callback, scratch, (size_t) -1)); /* this is just wildly invalid */ + checkpoint_2 = rustsecp256k1_v0_11_scratch_checkpoint(&CTX->error_callback, scratch); + rustsecp256k1_v0_11_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); + CHECK_ERROR_VOID(CTX, rustsecp256k1_v0_11_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint_2)); /* checkpoint_2 is after checkpoint */ + CHECK_ERROR_VOID(CTX, rustsecp256k1_v0_11_scratch_apply_checkpoint(&CTX->error_callback, scratch, (size_t) -1)); /* this is just wildly invalid */ /* try to use badly initialized scratch space */ - rustsecp256k1_v0_10_0_scratch_space_destroy(CTX, scratch); + rustsecp256k1_v0_11_scratch_space_destroy(CTX, scratch); memset(&local_scratch, 0, sizeof(local_scratch)); scratch = &local_scratch; - CHECK_ERROR(CTX, rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, 0)); - CHECK_ERROR(CTX, rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, 500)); - CHECK_ERROR_VOID(CTX, rustsecp256k1_v0_10_0_scratch_space_destroy(CTX, scratch)); + CHECK_ERROR(CTX, rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, 0)); + CHECK_ERROR(CTX, rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, 500)); + CHECK_ERROR_VOID(CTX, rustsecp256k1_v0_11_scratch_space_destroy(CTX, scratch)); /* Test that large integers do not wrap around in a bad way */ - scratch = rustsecp256k1_v0_10_0_scratch_space_create(CTX, 1000); + scratch = rustsecp256k1_v0_11_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. */ - CHECK(ALIGNMENT <= 1 || !rustsecp256k1_v0_10_0_scratch_max_allocation(&CTX->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1)); + CHECK(ALIGNMENT <= 1 || !rustsecp256k1_v0_11_scratch_max_allocation(&CTX->error_callback, scratch, (SIZE_MAX / (ALIGNMENT - 1)) + 1)); /* Try allocating SIZE_MAX to test wrap around which only happens if * ALIGNMENT > 1, otherwise it returns NULL anyway because the scratch * space is too small. */ - CHECK(rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, SIZE_MAX) == NULL); - rustsecp256k1_v0_10_0_scratch_space_destroy(CTX, scratch); + CHECK(rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, SIZE_MAX) == NULL); + rustsecp256k1_v0_11_scratch_space_destroy(CTX, scratch); /* cleanup */ - rustsecp256k1_v0_10_0_scratch_space_destroy(CTX, NULL); /* no-op */ + rustsecp256k1_v0_11_scratch_space_destroy(CTX, NULL); /* no-op */ } static void run_ctz_tests(void) { @@ -550,14 +435,14 @@ static void run_ctz_tests(void) { unsigned i; for (i = 0; i < sizeof(b32) / sizeof(b32[0]); ++i) { for (shift = 0; shift < 32; ++shift) { - CHECK(rustsecp256k1_v0_10_0_ctz32_var_debruijn(b32[i] << shift) == shift); - CHECK(rustsecp256k1_v0_10_0_ctz32_var(b32[i] << shift) == shift); + CHECK(rustsecp256k1_v0_11_ctz32_var_debruijn(b32[i] << shift) == shift); + CHECK(rustsecp256k1_v0_11_ctz32_var(b32[i] << shift) == shift); } } for (i = 0; i < sizeof(b64) / sizeof(b64[0]); ++i) { for (shift = 0; shift < 64; ++shift) { - CHECK(rustsecp256k1_v0_10_0_ctz64_var_debruijn(b64[i] << shift) == shift); - CHECK(rustsecp256k1_v0_10_0_ctz64_var(b64[i] << shift) == shift); + CHECK(rustsecp256k1_v0_11_ctz64_var_debruijn(b64[i] << shift) == shift); + CHECK(rustsecp256k1_v0_11_ctz64_var(b64[i] << shift) == shift); } } } @@ -594,29 +479,29 @@ static void run_sha256_known_output_tests(void) { for (i = 0; i < ninputs; i++) { unsigned char out[32]; - rustsecp256k1_v0_10_0_sha256 hasher; + rustsecp256k1_v0_11_sha256 hasher; unsigned int j; /* 1. Run: simply write the input bytestrings */ j = repeat[i]; - rustsecp256k1_v0_10_0_sha256_initialize(&hasher); + rustsecp256k1_v0_11_sha256_initialize(&hasher); while (j > 0) { - rustsecp256k1_v0_10_0_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + rustsecp256k1_v0_11_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); j--; } - rustsecp256k1_v0_10_0_sha256_finalize(&hasher, out); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, outputs[i], 32) == 0); + rustsecp256k1_v0_11_sha256_finalize(&hasher, out); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, outputs[i], 32) == 0); /* 2. Run: split the input bytestrings randomly before writing */ if (strlen(inputs[i]) > 0) { - int split = rustsecp256k1_v0_10_0_testrand_int(strlen(inputs[i])); - rustsecp256k1_v0_10_0_sha256_initialize(&hasher); + int split = testrand_int(strlen(inputs[i])); + rustsecp256k1_v0_11_sha256_initialize(&hasher); j = repeat[i]; while (j > 0) { - rustsecp256k1_v0_10_0_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - rustsecp256k1_v0_10_0_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + rustsecp256k1_v0_11_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + rustsecp256k1_v0_11_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); j--; } - rustsecp256k1_v0_10_0_sha256_finalize(&hasher, out); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, outputs[i], 32) == 0); + rustsecp256k1_v0_11_sha256_finalize(&hasher, out); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, outputs[i], 32) == 0); } } } @@ -667,7 +552,7 @@ for x in digests: */ static void run_sha256_counter_tests(void) { static const char *input = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"; - static const rustsecp256k1_v0_10_0_sha256 midstates[] = { + static const rustsecp256k1_v0_11_sha256 midstates[] = { {{0xa2b5c8bb, 0x26c88bb3, 0x2abdc3d2, 0x9def99a3, 0xdfd21a6e, 0x41fe585b, 0x7ef2c440, 0x2b79adda}, {0x00}, 0xfffc0}, {{0xa0d29445, 0x9287de66, 0x76aabd71, 0x41acd765, 0x0c7528b4, 0x84e14906, 0x942faec6, 0xcc5a7b26}, @@ -716,22 +601,22 @@ static void run_sha256_counter_tests(void) { unsigned int i; for (i = 0; i < sizeof(midstates)/sizeof(midstates[0]); i++) { unsigned char out[32]; - rustsecp256k1_v0_10_0_sha256 hasher = midstates[i]; - rustsecp256k1_v0_10_0_sha256_write(&hasher, (const unsigned char*)input, strlen(input)); - rustsecp256k1_v0_10_0_sha256_finalize(&hasher, out); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, outputs[i], 32) == 0); + rustsecp256k1_v0_11_sha256 hasher = midstates[i]; + rustsecp256k1_v0_11_sha256_write(&hasher, (const unsigned char*)input, strlen(input)); + rustsecp256k1_v0_11_sha256_finalize(&hasher, out); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, outputs[i], 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. This function is used by some module tests. */ -static void test_sha256_eq(const rustsecp256k1_v0_10_0_sha256 *sha1, const rustsecp256k1_v0_10_0_sha256 *sha2) { +static void test_sha256_eq(const rustsecp256k1_v0_11_sha256 *sha1, const rustsecp256k1_v0_11_sha256 *sha2) { /* Is buffer fully consumed? */ CHECK((sha1->bytes & 0x3F) == 0); CHECK(sha1->bytes == sha2->bytes); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); } static void run_hmac_sha256_tests(void) { @@ -761,19 +646,19 @@ static void run_hmac_sha256_tests(void) { }; int i; for (i = 0; i < 6; i++) { - rustsecp256k1_v0_10_0_hmac_sha256 hasher; + rustsecp256k1_v0_11_hmac_sha256 hasher; unsigned char out[32]; - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hasher, out); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, outputs[i], 32) == 0); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + rustsecp256k1_v0_11_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hasher, out); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, outputs[i], 32) == 0); if (strlen(inputs[i]) > 0) { - int split = rustsecp256k1_v0_10_0_testrand_int(strlen(inputs[i])); - rustsecp256k1_v0_10_0_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); - rustsecp256k1_v0_10_0_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); - rustsecp256k1_v0_10_0_hmac_sha256_finalize(&hasher, out); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, outputs[i], 32) == 0); + int split = testrand_int(strlen(inputs[i])); + rustsecp256k1_v0_11_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + rustsecp256k1_v0_11_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + rustsecp256k1_v0_11_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + rustsecp256k1_v0_11_hmac_sha256_finalize(&hasher, out); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, outputs[i], 32) == 0); } } } @@ -793,30 +678,30 @@ 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} }; - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256 rng; + rustsecp256k1_v0_11_rfc6979_hmac_sha256 rng; unsigned char out[32]; int i; - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(&rng, key1, 64); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, key1, 64); for (i = 0; i < 3; i++) { - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, out1[i], 32) == 0); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, out1[i], 32) == 0); } - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(&rng); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(&rng, key1, 65); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, key1, 65); for (i = 0; i < 3; i++) { - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, out1[i], 32) != 0); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, out1[i], 32) != 0); } - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(&rng); - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_initialize(&rng, key2, 64); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_initialize(&rng, key2, 64); for (i = 0; i < 3; i++) { - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_generate(&rng, out, 32); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, out2[i], 32) == 0); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, out2[i], 32) == 0); } - rustsecp256k1_v0_10_0_rfc6979_hmac_sha256_finalize(&rng); + rustsecp256k1_v0_11_rfc6979_hmac_sha256_finalize(&rng); } static void run_tagged_sha256_tests(void) { @@ -831,16 +716,16 @@ static void run_tagged_sha256_tests(void) { }; /* API test */ - CHECK(rustsecp256k1_v0_10_0_tagged_sha256(CTX, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_tagged_sha256(CTX, NULL, tag, sizeof(tag), msg, sizeof(msg))); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_tagged_sha256(CTX, hash32, NULL, 0, msg, sizeof(msg))); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_tagged_sha256(CTX, hash32, tag, sizeof(tag), NULL, 0)); + CHECK(rustsecp256k1_v0_11_tagged_sha256(CTX, hash32, tag, sizeof(tag), msg, sizeof(msg)) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_tagged_sha256(CTX, NULL, tag, sizeof(tag), msg, sizeof(msg))); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_tagged_sha256(CTX, hash32, NULL, 0, msg, sizeof(msg))); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_tagged_sha256(CTX, hash32, tag, sizeof(tag), NULL, 0)); /* Static test vector */ memcpy(tag, "tag", 3); memcpy(msg, "msg", 3); - CHECK(rustsecp256k1_v0_10_0_tagged_sha256(CTX, hash32, tag, 3, msg, 3) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0); + CHECK(rustsecp256k1_v0_11_tagged_sha256(CTX, hash32, tag, 3, msg, 3) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(hash32, hash_expected, sizeof(hash32)) == 0); } /***** MODINV TESTS *****/ @@ -947,7 +832,7 @@ static void mulmod256(uint16_t* out, const uint16_t* a, const uint16_t* b, const } /* Convert a 256-bit number represented as 16 uint16_t's to signed30 notation. */ -static void uint16_to_signed30(rustsecp256k1_v0_10_0_modinv32_signed30* out, const uint16_t* in) { +static void uint16_to_signed30(rustsecp256k1_v0_11_modinv32_signed30* out, const uint16_t* in) { int i; memset(out->v, 0, sizeof(out->v)); for (i = 0; i < 256; ++i) { @@ -956,7 +841,7 @@ static void uint16_to_signed30(rustsecp256k1_v0_10_0_modinv32_signed30* out, con } /* Convert a 256-bit number in signed30 notation to a representation as 16 uint16_t's. */ -static void signed30_to_uint16(uint16_t* out, const rustsecp256k1_v0_10_0_modinv32_signed30* in) { +static void signed30_to_uint16(uint16_t* out, const rustsecp256k1_v0_11_modinv32_signed30* in) { int i; memset(out, 0, 32); for (i = 0; i < 256; ++i) { @@ -965,10 +850,10 @@ static void signed30_to_uint16(uint16_t* out, const rustsecp256k1_v0_10_0_modinv } /* Randomly mutate the sign of limbs in signed30 representation, without changing the value. */ -static void mutate_sign_signed30(rustsecp256k1_v0_10_0_modinv32_signed30* x) { +static void mutate_sign_signed30(rustsecp256k1_v0_11_modinv32_signed30* x) { int i; for (i = 0; i < 16; ++i) { - int pos = rustsecp256k1_v0_10_0_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; @@ -979,11 +864,11 @@ static void mutate_sign_signed30(rustsecp256k1_v0_10_0_modinv32_signed30* x) { } } -/* Test rustsecp256k1_v0_10_0_modinv32{_var}, using inputs in 16-bit limb format, and returning inverse. */ +/* Test rustsecp256k1_v0_11_modinv32{_var}, using inputs in 16-bit limb format, and returning inverse. */ static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16_t* mod) { uint16_t tmp[16]; - rustsecp256k1_v0_10_0_modinv32_signed30 x; - rustsecp256k1_v0_10_0_modinv32_modinfo m; + rustsecp256k1_v0_11_modinv32_signed30 x; + rustsecp256k1_v0_11_modinv32_modinfo m; int i, vartime, nonzero; uint16_to_signed30(&x, in); @@ -994,14 +879,14 @@ static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16 m.modulus_inv30 = modinv2p64(m.modulus.v[0]) & 0x3fffffff; CHECK(((m.modulus_inv30 * m.modulus.v[0]) & 0x3fffffff) == 1); - /* Test rustsecp256k1_v0_10_0_jacobi32_maybe_var. */ + /* Test rustsecp256k1_v0_11_jacobi32_maybe_var. */ if (nonzero) { int jac; uint16_t sqr[16], negone[16]; mulmod256(sqr, in, in, mod); uint16_to_signed30(&x, sqr); /* Compute jacobi symbol of in^2, which must be 1 (or uncomputable). */ - jac = rustsecp256k1_v0_10_0_jacobi32_maybe_var(&x, &m); + jac = rustsecp256k1_v0_11_jacobi32_maybe_var(&x, &m); CHECK(jac == 0 || jac == 1); /* Then compute the jacobi symbol of -(in^2). x and -x have opposite * jacobi symbols if and only if (mod % 4) == 3. */ @@ -1009,7 +894,7 @@ static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16 for (i = 1; i < 16; ++i) negone[i] = mod[i]; mulmod256(sqr, sqr, negone, mod); uint16_to_signed30(&x, sqr); - jac = rustsecp256k1_v0_10_0_jacobi32_maybe_var(&x, &m); + jac = rustsecp256k1_v0_11_jacobi32_maybe_var(&x, &m); CHECK(jac == 0 || jac == 1 - (mod[0] & 2)); } @@ -1017,7 +902,7 @@ static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16 mutate_sign_signed30(&m.modulus); for (vartime = 0; vartime < 2; ++vartime) { /* compute inverse */ - (vartime ? rustsecp256k1_v0_10_0_modinv32_var : rustsecp256k1_v0_10_0_modinv32)(&x, &m); + (vartime ? rustsecp256k1_v0_11_modinv32_var : rustsecp256k1_v0_11_modinv32)(&x, &m); /* produce output */ signed30_to_uint16(out, &x); @@ -1028,7 +913,7 @@ static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16 for (i = 1; i < 16; ++i) CHECK(tmp[i] == 0); /* invert again */ - (vartime ? rustsecp256k1_v0_10_0_modinv32_var : rustsecp256k1_v0_10_0_modinv32)(&x, &m); + (vartime ? rustsecp256k1_v0_11_modinv32_var : rustsecp256k1_v0_11_modinv32)(&x, &m); /* check if the result is equal to the input */ signed30_to_uint16(tmp, &x); @@ -1038,7 +923,7 @@ static void test_modinv32_uint16(uint16_t* out, const uint16_t* in, const uint16 #ifdef SECP256K1_WIDEMUL_INT128 /* Convert a 256-bit number represented as 16 uint16_t's to signed62 notation. */ -static void uint16_to_signed62(rustsecp256k1_v0_10_0_modinv64_signed62* out, const uint16_t* in) { +static void uint16_to_signed62(rustsecp256k1_v0_11_modinv64_signed62* out, const uint16_t* in) { int i; memset(out->v, 0, sizeof(out->v)); for (i = 0; i < 256; ++i) { @@ -1047,7 +932,7 @@ static void uint16_to_signed62(rustsecp256k1_v0_10_0_modinv64_signed62* out, con } /* Convert a 256-bit number in signed62 notation to a representation as 16 uint16_t's. */ -static void signed62_to_uint16(uint16_t* out, const rustsecp256k1_v0_10_0_modinv64_signed62* in) { +static void signed62_to_uint16(uint16_t* out, const rustsecp256k1_v0_11_modinv64_signed62* in) { int i; memset(out, 0, 32); for (i = 0; i < 256; ++i) { @@ -1056,11 +941,11 @@ static void signed62_to_uint16(uint16_t* out, const rustsecp256k1_v0_10_0_modinv } /* Randomly mutate the sign of limbs in signed62 representation, without changing the value. */ -static void mutate_sign_signed62(rustsecp256k1_v0_10_0_modinv64_signed62* x) { +static void mutate_sign_signed62(rustsecp256k1_v0_11_modinv64_signed62* x) { static const int64_t M62 = (int64_t)(UINT64_MAX >> 2); int i; for (i = 0; i < 8; ++i) { - int pos = rustsecp256k1_v0_10_0_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; @@ -1071,12 +956,12 @@ static void mutate_sign_signed62(rustsecp256k1_v0_10_0_modinv64_signed62* x) { } } -/* Test rustsecp256k1_v0_10_0_modinv64{_var}, using inputs in 16-bit limb format, and returning inverse. */ +/* Test rustsecp256k1_v0_11_modinv64{_var}, using inputs in 16-bit limb format, and returning inverse. */ static void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16_t* mod) { static const int64_t M62 = (int64_t)(UINT64_MAX >> 2); uint16_t tmp[16]; - rustsecp256k1_v0_10_0_modinv64_signed62 x; - rustsecp256k1_v0_10_0_modinv64_modinfo m; + rustsecp256k1_v0_11_modinv64_signed62 x; + rustsecp256k1_v0_11_modinv64_modinfo m; int i, vartime, nonzero; uint16_to_signed62(&x, in); @@ -1087,14 +972,14 @@ static void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16 m.modulus_inv62 = modinv2p64(m.modulus.v[0]) & M62; CHECK(((m.modulus_inv62 * m.modulus.v[0]) & M62) == 1); - /* Test rustsecp256k1_v0_10_0_jacobi64_maybe_var. */ + /* Test rustsecp256k1_v0_11_jacobi64_maybe_var. */ if (nonzero) { int jac; uint16_t sqr[16], negone[16]; mulmod256(sqr, in, in, mod); uint16_to_signed62(&x, sqr); /* Compute jacobi symbol of in^2, which must be 1 (or uncomputable). */ - jac = rustsecp256k1_v0_10_0_jacobi64_maybe_var(&x, &m); + jac = rustsecp256k1_v0_11_jacobi64_maybe_var(&x, &m); CHECK(jac == 0 || jac == 1); /* Then compute the jacobi symbol of -(in^2). x and -x have opposite * jacobi symbols if and only if (mod % 4) == 3. */ @@ -1102,7 +987,7 @@ static void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16 for (i = 1; i < 16; ++i) negone[i] = mod[i]; mulmod256(sqr, sqr, negone, mod); uint16_to_signed62(&x, sqr); - jac = rustsecp256k1_v0_10_0_jacobi64_maybe_var(&x, &m); + jac = rustsecp256k1_v0_11_jacobi64_maybe_var(&x, &m); CHECK(jac == 0 || jac == 1 - (mod[0] & 2)); } @@ -1110,7 +995,7 @@ static void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16 mutate_sign_signed62(&m.modulus); for (vartime = 0; vartime < 2; ++vartime) { /* compute inverse */ - (vartime ? rustsecp256k1_v0_10_0_modinv64_var : rustsecp256k1_v0_10_0_modinv64)(&x, &m); + (vartime ? rustsecp256k1_v0_11_modinv64_var : rustsecp256k1_v0_11_modinv64)(&x, &m); /* produce output */ signed62_to_uint16(out, &x); @@ -1121,7 +1006,7 @@ static void test_modinv64_uint16(uint16_t* out, const uint16_t* in, const uint16 for (i = 1; i < 16; ++i) CHECK(tmp[i] == 0); /* invert again */ - (vartime ? rustsecp256k1_v0_10_0_modinv64_var : rustsecp256k1_v0_10_0_modinv64)(&x, &m); + (vartime ? rustsecp256k1_v0_11_modinv64_var : rustsecp256k1_v0_11_modinv64)(&x, &m); /* check if the result is equal to the input */ signed62_to_uint16(tmp, &x); @@ -1773,8 +1658,8 @@ static void run_modinv_tests(void) { /* generate random xd and md, so that md is odd, md>1, xd> (j % 16)) uwa_bits = 1 + j; } for (j = 0; j < 128; ++j) { - CHECK(rustsecp256k1_v0_10_0_u128_check_bits(&uwa, j) == (uwa_bits <= j)); + CHECK(rustsecp256k1_v0_11_u128_check_bits(&uwa, j) == (uwa_bits <= j)); } } - /* test rustsecp256k1_v0_10_0_i128_mul */ + /* test rustsecp256k1_v0_11_i128_mul */ mulmod256(rswr, rsb, rsc, NULL); - rustsecp256k1_v0_10_0_i128_mul(&swz, sb, sc); + rustsecp256k1_v0_11_i128_mul(&swz, sb, sc); load256i128(rswz, &swz); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(rswr, rswz, 16) == 0); - /* test rustsecp256k1_v0_10_0_i128_accum_mul */ + CHECK(rustsecp256k1_v0_11_memcmp_var(rswr, rswz, 16) == 0); + /* test rustsecp256k1_v0_11_i128_accum_mul */ mulmod256(rswr, rsb, rsc, NULL); add256(rswr, rswr, rswa); if (int256is127(rswr)) { swz = swa; - rustsecp256k1_v0_10_0_i128_accum_mul(&swz, sb, sc); + rustsecp256k1_v0_11_i128_accum_mul(&swz, sb, sc); load256i128(rswz, &swz); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(rswr, rswz, 16) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(rswr, rswz, 16) == 0); } - /* test rustsecp256k1_v0_10_0_i128_det */ + /* test rustsecp256k1_v0_11_i128_det */ { uint16_t rsd[16], rse[16], rst[32]; int64_t sd = v[0], se = v[1]; @@ -1995,25 +1880,25 @@ static void run_int128_test_case(void) { neg256(rst, rst); mulmod256(rswr, rsb, rse, NULL); add256(rswr, rswr, rst); - rustsecp256k1_v0_10_0_i128_det(&swz, sb, sc, sd, se); + rustsecp256k1_v0_11_i128_det(&swz, sb, sc, sd, se); load256i128(rswz, &swz); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(rswr, rswz, 16) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(rswr, rswz, 16) == 0); } - /* test rustsecp256k1_v0_10_0_i128_rshift */ + /* test rustsecp256k1_v0_11_i128_rshift */ rshift256(rswr, rswa, uc % 127, 1); swz = swa; - rustsecp256k1_v0_10_0_i128_rshift(&swz, uc % 127); + rustsecp256k1_v0_11_i128_rshift(&swz, uc % 127); load256i128(rswz, &swz); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(rswr, rswz, 16) == 0); - /* test rustsecp256k1_v0_10_0_i128_to_u64 */ - CHECK(rustsecp256k1_v0_10_0_i128_to_u64(&swa) == v[0]); - /* test rustsecp256k1_v0_10_0_i128_from_i64 */ - rustsecp256k1_v0_10_0_i128_from_i64(&swz, sb); + CHECK(rustsecp256k1_v0_11_memcmp_var(rswr, rswz, 16) == 0); + /* test rustsecp256k1_v0_11_i128_to_u64 */ + CHECK(rustsecp256k1_v0_11_i128_to_u64(&swa) == v[0]); + /* test rustsecp256k1_v0_11_i128_from_i64 */ + rustsecp256k1_v0_11_i128_from_i64(&swz, sb); load256i128(rswz, &swz); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(rsb, rswz, 16) == 0); - /* test rustsecp256k1_v0_10_0_i128_to_i64 */ - CHECK(rustsecp256k1_v0_10_0_i128_to_i64(&swz) == sb); - /* test rustsecp256k1_v0_10_0_i128_eq_var */ + CHECK(rustsecp256k1_v0_11_memcmp_var(rsb, rswz, 16) == 0); + /* test rustsecp256k1_v0_11_i128_to_i64 */ + CHECK(rustsecp256k1_v0_11_i128_to_i64(&swz) == sb); + /* test rustsecp256k1_v0_11_i128_eq_var */ { int expect = (uc & 1); swz = swa; @@ -2025,11 +1910,11 @@ static void run_int128_test_case(void) { } else { v0c ^= (((uint64_t)1) << (ub & 63)); } - rustsecp256k1_v0_10_0_i128_load(&swz, v1c, v0c); + rustsecp256k1_v0_11_i128_load(&swz, v1c, v0c); } - CHECK(rustsecp256k1_v0_10_0_i128_eq_var(&swa, &swz) == expect); + CHECK(rustsecp256k1_v0_11_i128_eq_var(&swa, &swz) == expect); } - /* test rustsecp256k1_v0_10_0_i128_check_pow2 (sign == 1) */ + /* test rustsecp256k1_v0_11_i128_check_pow2 (sign == 1) */ { int expect = (uc & 1); int pos = ub % 127; @@ -2042,7 +1927,7 @@ static void run_int128_test_case(void) { } else { lo = (((uint64_t)1) << (pos & 63)); } - rustsecp256k1_v0_10_0_i128_load(&swz, hi, lo); + rustsecp256k1_v0_11_i128_load(&swz, hi, lo); } else { /* If expect==0, set swz = swa, but update expect=1 if swa happens to equal 2^pos. */ if (pos >= 64) { @@ -2052,9 +1937,9 @@ static void run_int128_test_case(void) { } swz = swa; } - CHECK(rustsecp256k1_v0_10_0_i128_check_pow2(&swz, pos, 1) == expect); + CHECK(rustsecp256k1_v0_11_i128_check_pow2(&swz, pos, 1) == expect); } - /* test rustsecp256k1_v0_10_0_i128_check_pow2 (sign == -1) */ + /* test rustsecp256k1_v0_11_i128_check_pow2 (sign == -1) */ { int expect = (uc & 1); int pos = ub % 127; @@ -2068,7 +1953,7 @@ static void run_int128_test_case(void) { } else { lo <<= (pos & 63); } - rustsecp256k1_v0_10_0_i128_load(&swz, hi, lo); + rustsecp256k1_v0_11_i128_load(&swz, hi, lo); } else { /* If expect==0, set swz = swa, but update expect=1 if swa happens to equal -2^pos. */ if (pos >= 64) { @@ -2078,42 +1963,42 @@ static void run_int128_test_case(void) { } swz = swa; } - CHECK(rustsecp256k1_v0_10_0_i128_check_pow2(&swz, pos, -1) == expect); + CHECK(rustsecp256k1_v0_11_i128_check_pow2(&swz, pos, -1) == expect); } } static void run_int128_tests(void) { - { /* rustsecp256k1_v0_10_0_u128_accum_mul */ - rustsecp256k1_v0_10_0_uint128 res; - - /* Check rustsecp256k1_v0_10_0_u128_accum_mul overflow */ - rustsecp256k1_v0_10_0_u128_mul(&res, UINT64_MAX, UINT64_MAX); - rustsecp256k1_v0_10_0_u128_accum_mul(&res, UINT64_MAX, UINT64_MAX); - CHECK(rustsecp256k1_v0_10_0_u128_to_u64(&res) == 2); - CHECK(rustsecp256k1_v0_10_0_u128_hi_u64(&res) == 18446744073709551612U); - } - { /* rustsecp256k1_v0_10_0_u128_accum_mul */ - rustsecp256k1_v0_10_0_int128 res; - - /* Compute INT128_MAX = 2^127 - 1 with rustsecp256k1_v0_10_0_i128_accum_mul */ - rustsecp256k1_v0_10_0_i128_mul(&res, INT64_MAX, INT64_MAX); - rustsecp256k1_v0_10_0_i128_accum_mul(&res, INT64_MAX, INT64_MAX); - CHECK(rustsecp256k1_v0_10_0_i128_to_u64(&res) == 2); - rustsecp256k1_v0_10_0_i128_accum_mul(&res, 4, 9223372036854775807); - rustsecp256k1_v0_10_0_i128_accum_mul(&res, 1, 1); - CHECK(rustsecp256k1_v0_10_0_i128_to_u64(&res) == UINT64_MAX); - rustsecp256k1_v0_10_0_i128_rshift(&res, 64); - CHECK(rustsecp256k1_v0_10_0_i128_to_i64(&res) == INT64_MAX); - - /* Compute INT128_MIN = - 2^127 with rustsecp256k1_v0_10_0_i128_accum_mul */ - rustsecp256k1_v0_10_0_i128_mul(&res, INT64_MAX, INT64_MIN); - CHECK(rustsecp256k1_v0_10_0_i128_to_u64(&res) == (uint64_t)INT64_MIN); - rustsecp256k1_v0_10_0_i128_accum_mul(&res, INT64_MAX, INT64_MIN); - CHECK(rustsecp256k1_v0_10_0_i128_to_u64(&res) == 0); - rustsecp256k1_v0_10_0_i128_accum_mul(&res, 2, INT64_MIN); - CHECK(rustsecp256k1_v0_10_0_i128_to_u64(&res) == 0); - rustsecp256k1_v0_10_0_i128_rshift(&res, 64); - CHECK(rustsecp256k1_v0_10_0_i128_to_i64(&res) == INT64_MIN); + { /* rustsecp256k1_v0_11_u128_accum_mul */ + rustsecp256k1_v0_11_uint128 res; + + /* Check rustsecp256k1_v0_11_u128_accum_mul overflow */ + rustsecp256k1_v0_11_u128_mul(&res, UINT64_MAX, UINT64_MAX); + rustsecp256k1_v0_11_u128_accum_mul(&res, UINT64_MAX, UINT64_MAX); + CHECK(rustsecp256k1_v0_11_u128_to_u64(&res) == 2); + CHECK(rustsecp256k1_v0_11_u128_hi_u64(&res) == 18446744073709551612U); + } + { /* rustsecp256k1_v0_11_u128_accum_mul */ + rustsecp256k1_v0_11_int128 res; + + /* Compute INT128_MAX = 2^127 - 1 with rustsecp256k1_v0_11_i128_accum_mul */ + rustsecp256k1_v0_11_i128_mul(&res, INT64_MAX, INT64_MAX); + rustsecp256k1_v0_11_i128_accum_mul(&res, INT64_MAX, INT64_MAX); + CHECK(rustsecp256k1_v0_11_i128_to_u64(&res) == 2); + rustsecp256k1_v0_11_i128_accum_mul(&res, 4, 9223372036854775807); + rustsecp256k1_v0_11_i128_accum_mul(&res, 1, 1); + CHECK(rustsecp256k1_v0_11_i128_to_u64(&res) == UINT64_MAX); + rustsecp256k1_v0_11_i128_rshift(&res, 64); + CHECK(rustsecp256k1_v0_11_i128_to_i64(&res) == INT64_MAX); + + /* Compute INT128_MIN = - 2^127 with rustsecp256k1_v0_11_i128_accum_mul */ + rustsecp256k1_v0_11_i128_mul(&res, INT64_MAX, INT64_MIN); + CHECK(rustsecp256k1_v0_11_i128_to_u64(&res) == (uint64_t)INT64_MIN); + rustsecp256k1_v0_11_i128_accum_mul(&res, INT64_MAX, INT64_MIN); + CHECK(rustsecp256k1_v0_11_i128_to_u64(&res) == 0); + rustsecp256k1_v0_11_i128_accum_mul(&res, 2, INT64_MIN); + CHECK(rustsecp256k1_v0_11_i128_to_u64(&res) == 0); + rustsecp256k1_v0_11_i128_rshift(&res, 64); + CHECK(rustsecp256k1_v0_11_i128_to_i64(&res) == INT64_MIN); } { /* Randomized tests. */ @@ -2126,175 +2011,175 @@ static void run_int128_tests(void) { /***** SCALAR TESTS *****/ static void scalar_test(void) { - rustsecp256k1_v0_10_0_scalar s; - rustsecp256k1_v0_10_0_scalar s1; - rustsecp256k1_v0_10_0_scalar s2; + rustsecp256k1_v0_11_scalar s; + rustsecp256k1_v0_11_scalar s1; + rustsecp256k1_v0_11_scalar s2; 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); - rustsecp256k1_v0_10_0_scalar_get_b32(c, &s2); + testutil_random_scalar_order_test(&s2); + rustsecp256k1_v0_11_scalar_get_b32(c, &s2); { int i; /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ - rustsecp256k1_v0_10_0_scalar n; - rustsecp256k1_v0_10_0_scalar_set_int(&n, 0); + rustsecp256k1_v0_11_scalar n; + rustsecp256k1_v0_11_scalar_set_int(&n, 0); for (i = 0; i < 256; i += 4) { - rustsecp256k1_v0_10_0_scalar t; + rustsecp256k1_v0_11_scalar t; int j; - rustsecp256k1_v0_10_0_scalar_set_int(&t, rustsecp256k1_v0_10_0_scalar_get_bits(&s, 256 - 4 - i, 4)); + rustsecp256k1_v0_11_scalar_set_int(&t, rustsecp256k1_v0_11_scalar_get_bits_limb32(&s, 256 - 4 - i, 4)); for (j = 0; j < 4; j++) { - rustsecp256k1_v0_10_0_scalar_add(&n, &n, &n); + rustsecp256k1_v0_11_scalar_add(&n, &n, &n); } - rustsecp256k1_v0_10_0_scalar_add(&n, &n, &t); + rustsecp256k1_v0_11_scalar_add(&n, &n, &t); } - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&n, &s)); + CHECK(rustsecp256k1_v0_11_scalar_eq(&n, &s)); } { /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ - rustsecp256k1_v0_10_0_scalar n; + rustsecp256k1_v0_11_scalar n; int i = 0; - rustsecp256k1_v0_10_0_scalar_set_int(&n, 0); + rustsecp256k1_v0_11_scalar_set_int(&n, 0); while (i < 256) { - rustsecp256k1_v0_10_0_scalar t; + rustsecp256k1_v0_11_scalar t; int j; - int now = rustsecp256k1_v0_10_0_testrand_int(15) + 1; + int now = testrand_int(15) + 1; if (now + i > 256) { now = 256 - i; } - rustsecp256k1_v0_10_0_scalar_set_int(&t, rustsecp256k1_v0_10_0_scalar_get_bits_var(&s, 256 - now - i, now)); + rustsecp256k1_v0_11_scalar_set_int(&t, rustsecp256k1_v0_11_scalar_get_bits_var(&s, 256 - now - i, now)); for (j = 0; j < now; j++) { - rustsecp256k1_v0_10_0_scalar_add(&n, &n, &n); + rustsecp256k1_v0_11_scalar_add(&n, &n, &n); } - rustsecp256k1_v0_10_0_scalar_add(&n, &n, &t); + rustsecp256k1_v0_11_scalar_add(&n, &n, &t); i += now; } - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&n, &s)); + CHECK(rustsecp256k1_v0_11_scalar_eq(&n, &s)); } { /* Test commutativity of add. */ - rustsecp256k1_v0_10_0_scalar r1, r2; - rustsecp256k1_v0_10_0_scalar_add(&r1, &s1, &s2); - rustsecp256k1_v0_10_0_scalar_add(&r2, &s2, &s1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar r1, r2; + rustsecp256k1_v0_11_scalar_add(&r1, &s1, &s2); + rustsecp256k1_v0_11_scalar_add(&r2, &s2, &s1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); } { - rustsecp256k1_v0_10_0_scalar r1, r2; - rustsecp256k1_v0_10_0_scalar b; + rustsecp256k1_v0_11_scalar r1, r2; + rustsecp256k1_v0_11_scalar b; int i; /* Test add_bit. */ - int bit = rustsecp256k1_v0_10_0_testrand_bits(8); - rustsecp256k1_v0_10_0_scalar_set_int(&b, 1); - CHECK(rustsecp256k1_v0_10_0_scalar_is_one(&b)); + int bit = testrand_bits(8); + rustsecp256k1_v0_11_scalar_set_int(&b, 1); + CHECK(rustsecp256k1_v0_11_scalar_is_one(&b)); for (i = 0; i < bit; i++) { - rustsecp256k1_v0_10_0_scalar_add(&b, &b, &b); + rustsecp256k1_v0_11_scalar_add(&b, &b, &b); } r1 = s1; r2 = s1; - if (!rustsecp256k1_v0_10_0_scalar_add(&r1, &r1, &b)) { + if (!rustsecp256k1_v0_11_scalar_add(&r1, &r1, &b)) { /* No overflow happened. */ - rustsecp256k1_v0_10_0_scalar_cadd_bit(&r2, bit, 1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar_cadd_bit(&r2, bit, 1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); /* cadd is a noop when flag is zero */ - rustsecp256k1_v0_10_0_scalar_cadd_bit(&r2, bit, 0); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar_cadd_bit(&r2, bit, 0); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); } } { /* Test commutativity of mul. */ - rustsecp256k1_v0_10_0_scalar r1, r2; - rustsecp256k1_v0_10_0_scalar_mul(&r1, &s1, &s2); - rustsecp256k1_v0_10_0_scalar_mul(&r2, &s2, &s1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar r1, r2; + rustsecp256k1_v0_11_scalar_mul(&r1, &s1, &s2); + rustsecp256k1_v0_11_scalar_mul(&r2, &s2, &s1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); } { /* Test associativity of add. */ - rustsecp256k1_v0_10_0_scalar r1, r2; - rustsecp256k1_v0_10_0_scalar_add(&r1, &s1, &s2); - rustsecp256k1_v0_10_0_scalar_add(&r1, &r1, &s); - rustsecp256k1_v0_10_0_scalar_add(&r2, &s2, &s); - rustsecp256k1_v0_10_0_scalar_add(&r2, &s1, &r2); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar r1, r2; + rustsecp256k1_v0_11_scalar_add(&r1, &s1, &s2); + rustsecp256k1_v0_11_scalar_add(&r1, &r1, &s); + rustsecp256k1_v0_11_scalar_add(&r2, &s2, &s); + rustsecp256k1_v0_11_scalar_add(&r2, &s1, &r2); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); } { /* Test associativity of mul. */ - rustsecp256k1_v0_10_0_scalar r1, r2; - rustsecp256k1_v0_10_0_scalar_mul(&r1, &s1, &s2); - rustsecp256k1_v0_10_0_scalar_mul(&r1, &r1, &s); - rustsecp256k1_v0_10_0_scalar_mul(&r2, &s2, &s); - rustsecp256k1_v0_10_0_scalar_mul(&r2, &s1, &r2); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar r1, r2; + rustsecp256k1_v0_11_scalar_mul(&r1, &s1, &s2); + rustsecp256k1_v0_11_scalar_mul(&r1, &r1, &s); + rustsecp256k1_v0_11_scalar_mul(&r2, &s2, &s); + rustsecp256k1_v0_11_scalar_mul(&r2, &s1, &r2); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); } { /* Test distributitivity of mul over add. */ - rustsecp256k1_v0_10_0_scalar r1, r2, t; - rustsecp256k1_v0_10_0_scalar_add(&r1, &s1, &s2); - rustsecp256k1_v0_10_0_scalar_mul(&r1, &r1, &s); - rustsecp256k1_v0_10_0_scalar_mul(&r2, &s1, &s); - rustsecp256k1_v0_10_0_scalar_mul(&t, &s2, &s); - rustsecp256k1_v0_10_0_scalar_add(&r2, &r2, &t); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &r2)); + rustsecp256k1_v0_11_scalar r1, r2, t; + rustsecp256k1_v0_11_scalar_add(&r1, &s1, &s2); + rustsecp256k1_v0_11_scalar_mul(&r1, &r1, &s); + rustsecp256k1_v0_11_scalar_mul(&r2, &s1, &s); + rustsecp256k1_v0_11_scalar_mul(&t, &s2, &s); + rustsecp256k1_v0_11_scalar_add(&r2, &r2, &t); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &r2)); } { /* Test multiplicative identity. */ - rustsecp256k1_v0_10_0_scalar r1; - rustsecp256k1_v0_10_0_scalar_mul(&r1, &s1, &rustsecp256k1_v0_10_0_scalar_one); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &s1)); + rustsecp256k1_v0_11_scalar r1; + rustsecp256k1_v0_11_scalar_mul(&r1, &s1, &rustsecp256k1_v0_11_scalar_one); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &s1)); } { /* Test additive identity. */ - rustsecp256k1_v0_10_0_scalar r1; - rustsecp256k1_v0_10_0_scalar_add(&r1, &s1, &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &s1)); + rustsecp256k1_v0_11_scalar r1; + rustsecp256k1_v0_11_scalar_add(&r1, &s1, &rustsecp256k1_v0_11_scalar_zero); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &s1)); } { /* Test zero product property. */ - rustsecp256k1_v0_10_0_scalar r1; - rustsecp256k1_v0_10_0_scalar_mul(&r1, &s1, &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &rustsecp256k1_v0_10_0_scalar_zero)); + rustsecp256k1_v0_11_scalar r1; + rustsecp256k1_v0_11_scalar_mul(&r1, &s1, &rustsecp256k1_v0_11_scalar_zero); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &rustsecp256k1_v0_11_scalar_zero)); } { /* Test halving. */ - rustsecp256k1_v0_10_0_scalar r; - rustsecp256k1_v0_10_0_scalar_add(&r, &s, &s); - rustsecp256k1_v0_10_0_scalar_half(&r, &r); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r, &s)); + rustsecp256k1_v0_11_scalar r; + rustsecp256k1_v0_11_scalar_add(&r, &s, &s); + rustsecp256k1_v0_11_scalar_half(&r, &r); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r, &s)); } } static void run_scalar_set_b32_seckey_tests(void) { unsigned char b32[32]; - rustsecp256k1_v0_10_0_scalar s1; - rustsecp256k1_v0_10_0_scalar s2; + rustsecp256k1_v0_11_scalar s1; + rustsecp256k1_v0_11_scalar s2; /* Usually set_b32 and set_b32_seckey give the same result */ - random_scalar_order_b32(b32); - rustsecp256k1_v0_10_0_scalar_set_b32(&s1, b32, NULL); - CHECK(rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&s2, b32) == 1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&s1, &s2) == 1); + testutil_random_scalar_order_b32(b32); + rustsecp256k1_v0_11_scalar_set_b32(&s1, b32, NULL); + CHECK(rustsecp256k1_v0_11_scalar_set_b32_seckey(&s2, b32) == 1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&s1, &s2) == 1); memset(b32, 0, sizeof(b32)); - CHECK(rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&s2, b32) == 0); + CHECK(rustsecp256k1_v0_11_scalar_set_b32_seckey(&s2, b32) == 0); memset(b32, 0xFF, sizeof(b32)); - CHECK(rustsecp256k1_v0_10_0_scalar_set_b32_seckey(&s2, b32) == 0); + CHECK(rustsecp256k1_v0_11_scalar_set_b32_seckey(&s2, b32) == 0); } static void run_scalar_tests(void) { @@ -2307,32 +2192,32 @@ static void run_scalar_tests(void) { } { - /* Check that the scalar constants rustsecp256k1_v0_10_0_scalar_zero and - rustsecp256k1_v0_10_0_scalar_one contain the expected values. */ - rustsecp256k1_v0_10_0_scalar zero, one; + /* Check that the scalar constants rustsecp256k1_v0_11_scalar_zero and + rustsecp256k1_v0_11_scalar_one contain the expected values. */ + rustsecp256k1_v0_11_scalar zero, one; - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&rustsecp256k1_v0_10_0_scalar_zero)); - rustsecp256k1_v0_10_0_scalar_set_int(&zero, 0); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&zero, &rustsecp256k1_v0_10_0_scalar_zero)); + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&rustsecp256k1_v0_11_scalar_zero)); + rustsecp256k1_v0_11_scalar_set_int(&zero, 0); + CHECK(rustsecp256k1_v0_11_scalar_eq(&zero, &rustsecp256k1_v0_11_scalar_zero)); - CHECK(rustsecp256k1_v0_10_0_scalar_is_one(&rustsecp256k1_v0_10_0_scalar_one)); - rustsecp256k1_v0_10_0_scalar_set_int(&one, 1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&one, &rustsecp256k1_v0_10_0_scalar_one)); + CHECK(rustsecp256k1_v0_11_scalar_is_one(&rustsecp256k1_v0_11_scalar_one)); + rustsecp256k1_v0_11_scalar_set_int(&one, 1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&one, &rustsecp256k1_v0_11_scalar_one)); } { /* (-1)+1 should be zero. */ - rustsecp256k1_v0_10_0_scalar o; - rustsecp256k1_v0_10_0_scalar_negate(&o, &rustsecp256k1_v0_10_0_scalar_one); - rustsecp256k1_v0_10_0_scalar_add(&o, &o, &rustsecp256k1_v0_10_0_scalar_one); - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&o)); - rustsecp256k1_v0_10_0_scalar_negate(&o, &o); - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&o)); + rustsecp256k1_v0_11_scalar o; + rustsecp256k1_v0_11_scalar_negate(&o, &rustsecp256k1_v0_11_scalar_one); + rustsecp256k1_v0_11_scalar_add(&o, &o, &rustsecp256k1_v0_11_scalar_one); + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&o)); + rustsecp256k1_v0_11_scalar_negate(&o, &o); + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&o)); } { /* Test that halving and doubling roundtrips on some fixed values. */ - static const rustsecp256k1_v0_10_0_scalar HALF_TESTS[] = { + static const rustsecp256k1_v0_11_scalar HALF_TESTS[] = { /* 0 */ SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0), /* 1 */ @@ -2352,23 +2237,23 @@ static void run_scalar_tests(void) { }; unsigned n; for (n = 0; n < sizeof(HALF_TESTS) / sizeof(HALF_TESTS[0]); ++n) { - rustsecp256k1_v0_10_0_scalar s; - rustsecp256k1_v0_10_0_scalar_half(&s, &HALF_TESTS[n]); - rustsecp256k1_v0_10_0_scalar_add(&s, &s, &s); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&s, &HALF_TESTS[n])); - rustsecp256k1_v0_10_0_scalar_add(&s, &s, &s); - rustsecp256k1_v0_10_0_scalar_half(&s, &s); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&s, &HALF_TESTS[n])); + rustsecp256k1_v0_11_scalar s; + rustsecp256k1_v0_11_scalar_half(&s, &HALF_TESTS[n]); + rustsecp256k1_v0_11_scalar_add(&s, &s, &s); + CHECK(rustsecp256k1_v0_11_scalar_eq(&s, &HALF_TESTS[n])); + rustsecp256k1_v0_11_scalar_add(&s, &s, &s); + rustsecp256k1_v0_11_scalar_half(&s, &s); + CHECK(rustsecp256k1_v0_11_scalar_eq(&s, &HALF_TESTS[n])); } } { /* Does check_overflow check catch all ones? */ - static const rustsecp256k1_v0_10_0_scalar overflowed = SECP256K1_SCALAR_CONST( + static const rustsecp256k1_v0_11_scalar overflowed = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); - CHECK(rustsecp256k1_v0_10_0_scalar_check_overflow(&overflowed)); + CHECK(rustsecp256k1_v0_11_scalar_check_overflow(&overflowed)); } { @@ -2377,13 +2262,13 @@ static void run_scalar_tests(void) { * and edge-case coverage on 32-bit and 64-bit implementations. * The responses were generated with Sage 5.9. */ - rustsecp256k1_v0_10_0_scalar x; - rustsecp256k1_v0_10_0_scalar y; - rustsecp256k1_v0_10_0_scalar z; - rustsecp256k1_v0_10_0_scalar zz; - rustsecp256k1_v0_10_0_scalar r1; - rustsecp256k1_v0_10_0_scalar r2; - rustsecp256k1_v0_10_0_scalar zzv; + rustsecp256k1_v0_11_scalar x; + rustsecp256k1_v0_11_scalar y; + rustsecp256k1_v0_11_scalar z; + rustsecp256k1_v0_11_scalar zz; + rustsecp256k1_v0_11_scalar r1; + rustsecp256k1_v0_11_scalar r2; + rustsecp256k1_v0_11_scalar zzv; int overflow; unsigned char chal[33][2][32] = { {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, @@ -2918,48 +2803,46 @@ static void run_scalar_tests(void) { 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} }; for (i = 0; i < 33; i++) { - rustsecp256k1_v0_10_0_scalar_set_b32(&x, chal[i][0], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&x, chal[i][0], &overflow); CHECK(!overflow); - rustsecp256k1_v0_10_0_scalar_set_b32(&y, chal[i][1], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&y, chal[i][1], &overflow); CHECK(!overflow); - rustsecp256k1_v0_10_0_scalar_set_b32(&r1, res[i][0], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&r1, res[i][0], &overflow); CHECK(!overflow); - rustsecp256k1_v0_10_0_scalar_set_b32(&r2, res[i][1], &overflow); + rustsecp256k1_v0_11_scalar_set_b32(&r2, res[i][1], &overflow); CHECK(!overflow); - rustsecp256k1_v0_10_0_scalar_mul(&z, &x, &y); - CHECK(!rustsecp256k1_v0_10_0_scalar_check_overflow(&z)); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&r1, &z)); - if (!rustsecp256k1_v0_10_0_scalar_is_zero(&y)) { - rustsecp256k1_v0_10_0_scalar_inverse(&zz, &y); - CHECK(!rustsecp256k1_v0_10_0_scalar_check_overflow(&zz)); - rustsecp256k1_v0_10_0_scalar_inverse_var(&zzv, &y); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&zzv, &zz)); - rustsecp256k1_v0_10_0_scalar_mul(&z, &z, &zz); - CHECK(!rustsecp256k1_v0_10_0_scalar_check_overflow(&z)); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&x, &z)); - rustsecp256k1_v0_10_0_scalar_mul(&zz, &zz, &y); - CHECK(!rustsecp256k1_v0_10_0_scalar_check_overflow(&zz)); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&rustsecp256k1_v0_10_0_scalar_one, &zz)); + rustsecp256k1_v0_11_scalar_mul(&z, &x, &y); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r1, &z)); + if (!rustsecp256k1_v0_11_scalar_is_zero(&y)) { + rustsecp256k1_v0_11_scalar_inverse(&zz, &y); + rustsecp256k1_v0_11_scalar_inverse_var(&zzv, &y); + CHECK(rustsecp256k1_v0_11_scalar_eq(&zzv, &zz)); + rustsecp256k1_v0_11_scalar_mul(&z, &z, &zz); + CHECK(rustsecp256k1_v0_11_scalar_eq(&x, &z)); + rustsecp256k1_v0_11_scalar_mul(&zz, &zz, &y); + CHECK(rustsecp256k1_v0_11_scalar_eq(&rustsecp256k1_v0_11_scalar_one, &zz)); } + rustsecp256k1_v0_11_scalar_mul(&z, &x, &x); + CHECK(rustsecp256k1_v0_11_scalar_eq(&r2, &z)); } } } /***** FIELD TESTS *****/ -static void random_fe_non_square(rustsecp256k1_v0_10_0_fe *ns) { - rustsecp256k1_v0_10_0_fe r; - random_fe_non_zero(ns); - if (rustsecp256k1_v0_10_0_fe_sqrt(&r, ns)) { - rustsecp256k1_v0_10_0_fe_negate(ns, ns, 1); +static void random_fe_non_square(rustsecp256k1_v0_11_fe *ns) { + rustsecp256k1_v0_11_fe r; + testutil_random_fe_non_zero(ns); + if (rustsecp256k1_v0_11_fe_sqrt(&r, ns)) { + rustsecp256k1_v0_11_fe_negate(ns, ns, 1); } } -static int check_fe_equal(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b) { - rustsecp256k1_v0_10_0_fe an = *a; - rustsecp256k1_v0_10_0_fe bn = *b; - rustsecp256k1_v0_10_0_fe_normalize_weak(&an); - return rustsecp256k1_v0_10_0_fe_equal(&an, &bn); +static int fe_equal(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b) { + rustsecp256k1_v0_11_fe an = *a; + rustsecp256k1_v0_11_fe bn = *b; + rustsecp256k1_v0_11_fe_normalize_weak(&an); + return rustsecp256k1_v0_11_fe_equal(&an, &bn); } static void run_field_convert(void) { @@ -2969,27 +2852,27 @@ static void run_field_convert(void) { 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 }; - static const rustsecp256k1_v0_10_0_fe_storage fes = SECP256K1_FE_STORAGE_CONST( + static const rustsecp256k1_v0_11_fe_storage fes = SECP256K1_FE_STORAGE_CONST( 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL ); - static const rustsecp256k1_v0_10_0_fe fe = SECP256K1_FE_CONST( + static const rustsecp256k1_v0_11_fe fe = SECP256K1_FE_CONST( 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL ); - rustsecp256k1_v0_10_0_fe fe2; + rustsecp256k1_v0_11_fe fe2; unsigned char b322[32]; - rustsecp256k1_v0_10_0_fe_storage fes2; + rustsecp256k1_v0_11_fe_storage fes2; /* Check conversions to fe. */ - CHECK(rustsecp256k1_v0_10_0_fe_set_b32_limit(&fe2, b32)); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&fe, &fe2)); - rustsecp256k1_v0_10_0_fe_from_storage(&fe2, &fes); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&fe, &fe2)); + CHECK(rustsecp256k1_v0_11_fe_set_b32_limit(&fe2, b32)); + CHECK(rustsecp256k1_v0_11_fe_equal(&fe, &fe2)); + rustsecp256k1_v0_11_fe_from_storage(&fe2, &fes); + CHECK(rustsecp256k1_v0_11_fe_equal(&fe, &fe2)); /* Check conversion from fe. */ - rustsecp256k1_v0_10_0_fe_get_b32(b322, &fe); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(b322, b32, 32) == 0); - rustsecp256k1_v0_10_0_fe_to_storage(&fes2, &fe); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&fes2, &fes, sizeof(fes)) == 0); + rustsecp256k1_v0_11_fe_get_b32(b322, &fe); + CHECK(rustsecp256k1_v0_11_memcmp_var(b322, b32, 32) == 0); + rustsecp256k1_v0_11_fe_to_storage(&fes2, &fe); + CHECK(rustsecp256k1_v0_11_memcmp_var(&fes2, &fes, sizeof(fes)) == 0); } static void run_field_be32_overflow(void) { @@ -3002,14 +2885,14 @@ static void run_field_be32_overflow(void) { }; static const unsigned char zero[32] = { 0x00 }; unsigned char out[32]; - rustsecp256k1_v0_10_0_fe fe; - CHECK(rustsecp256k1_v0_10_0_fe_set_b32_limit(&fe, zero_overflow) == 0); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&fe, zero_overflow); - CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&fe) == 1); - rustsecp256k1_v0_10_0_fe_normalize(&fe); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&fe) == 1); - rustsecp256k1_v0_10_0_fe_get_b32(out, &fe); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, zero, 32) == 0); + rustsecp256k1_v0_11_fe fe; + CHECK(rustsecp256k1_v0_11_fe_set_b32_limit(&fe, zero_overflow) == 0); + rustsecp256k1_v0_11_fe_set_b32_mod(&fe, zero_overflow); + CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero(&fe) == 1); + rustsecp256k1_v0_11_fe_normalize(&fe); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&fe) == 1); + rustsecp256k1_v0_11_fe_get_b32(out, &fe); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, zero, 32) == 0); } { static const unsigned char one_overflow[32] = { @@ -3025,13 +2908,13 @@ static void run_field_be32_overflow(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; unsigned char out[32]; - rustsecp256k1_v0_10_0_fe fe; - CHECK(rustsecp256k1_v0_10_0_fe_set_b32_limit(&fe, one_overflow) == 0); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&fe, one_overflow); - rustsecp256k1_v0_10_0_fe_normalize(&fe); - CHECK(rustsecp256k1_v0_10_0_fe_cmp_var(&fe, &rustsecp256k1_v0_10_0_fe_one) == 0); - rustsecp256k1_v0_10_0_fe_get_b32(out, &fe); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, one, 32) == 0); + rustsecp256k1_v0_11_fe fe; + CHECK(rustsecp256k1_v0_11_fe_set_b32_limit(&fe, one_overflow) == 0); + rustsecp256k1_v0_11_fe_set_b32_mod(&fe, one_overflow); + rustsecp256k1_v0_11_fe_normalize(&fe); + CHECK(rustsecp256k1_v0_11_fe_cmp_var(&fe, &rustsecp256k1_v0_11_fe_one) == 0); + rustsecp256k1_v0_11_fe_get_b32(out, &fe); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, one, 32) == 0); } { static const unsigned char ff_overflow[32] = { @@ -3047,116 +2930,116 @@ static void run_field_be32_overflow(void) { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xD0, }; unsigned char out[32]; - rustsecp256k1_v0_10_0_fe fe; - const rustsecp256k1_v0_10_0_fe fe_ff = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0x01, 0x000003d0); - CHECK(rustsecp256k1_v0_10_0_fe_set_b32_limit(&fe, ff_overflow) == 0); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&fe, ff_overflow); - rustsecp256k1_v0_10_0_fe_normalize(&fe); - CHECK(rustsecp256k1_v0_10_0_fe_cmp_var(&fe, &fe_ff) == 0); - rustsecp256k1_v0_10_0_fe_get_b32(out, &fe); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(out, ff, 32) == 0); + rustsecp256k1_v0_11_fe fe; + const rustsecp256k1_v0_11_fe fe_ff = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0x01, 0x000003d0); + CHECK(rustsecp256k1_v0_11_fe_set_b32_limit(&fe, ff_overflow) == 0); + rustsecp256k1_v0_11_fe_set_b32_mod(&fe, ff_overflow); + rustsecp256k1_v0_11_fe_normalize(&fe); + CHECK(rustsecp256k1_v0_11_fe_cmp_var(&fe, &fe_ff) == 0); + rustsecp256k1_v0_11_fe_get_b32(out, &fe); + CHECK(rustsecp256k1_v0_11_memcmp_var(out, ff, 32) == 0); } } /* Returns true if two field elements have the same representation. */ -static int fe_identical(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *b) { +static int fe_identical(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *b) { int ret = 1; /* Compare the struct member that holds the limbs. */ - ret &= (rustsecp256k1_v0_10_0_memcmp_var(a->n, b->n, sizeof(a->n)) == 0); + ret &= (rustsecp256k1_v0_11_memcmp_var(a->n, b->n, sizeof(a->n)) == 0); return ret; } static void run_field_half(void) { - rustsecp256k1_v0_10_0_fe t, u; + rustsecp256k1_v0_11_fe t, u; int m; /* Check magnitude 0 input */ - rustsecp256k1_v0_10_0_fe_get_bounds(&t, 0); - rustsecp256k1_v0_10_0_fe_half(&t); + rustsecp256k1_v0_11_fe_get_bounds(&t, 0); + rustsecp256k1_v0_11_fe_half(&t); #ifdef VERIFY CHECK(t.magnitude == 1); CHECK(t.normalized == 0); #endif - CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&t)); + CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero(&t)); /* Check non-zero magnitudes in the supported range */ for (m = 1; m < 32; m++) { /* Check max-value input */ - rustsecp256k1_v0_10_0_fe_get_bounds(&t, m); + rustsecp256k1_v0_11_fe_get_bounds(&t, m); u = t; - rustsecp256k1_v0_10_0_fe_half(&u); + rustsecp256k1_v0_11_fe_half(&u); #ifdef VERIFY CHECK(u.magnitude == (m >> 1) + 1); CHECK(u.normalized == 0); #endif - rustsecp256k1_v0_10_0_fe_normalize_weak(&u); - rustsecp256k1_v0_10_0_fe_add(&u, &u); - CHECK(check_fe_equal(&t, &u)); + rustsecp256k1_v0_11_fe_normalize_weak(&u); + rustsecp256k1_v0_11_fe_add(&u, &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 * generate a carry are initially even and all limbs of P are odd in * every existing field implementation. */ - rustsecp256k1_v0_10_0_fe_get_bounds(&t, m); + rustsecp256k1_v0_11_fe_get_bounds(&t, m); CHECK(t.n[0] > 0); CHECK((t.n[0] & 1) == 0); --t.n[0]; u = t; - rustsecp256k1_v0_10_0_fe_half(&u); + rustsecp256k1_v0_11_fe_half(&u); #ifdef VERIFY CHECK(u.magnitude == (m >> 1) + 1); CHECK(u.normalized == 0); #endif - rustsecp256k1_v0_10_0_fe_normalize_weak(&u); - rustsecp256k1_v0_10_0_fe_add(&u, &u); - CHECK(check_fe_equal(&t, &u)); + rustsecp256k1_v0_11_fe_normalize_weak(&u); + rustsecp256k1_v0_11_fe_add(&u, &u); + CHECK(fe_equal(&t, &u)); } } static void run_field_misc(void) { - rustsecp256k1_v0_10_0_fe x; - rustsecp256k1_v0_10_0_fe y; - rustsecp256k1_v0_10_0_fe z; - rustsecp256k1_v0_10_0_fe q; + rustsecp256k1_v0_11_fe x; + rustsecp256k1_v0_11_fe y; + rustsecp256k1_v0_11_fe z; + rustsecp256k1_v0_11_fe q; int v; - rustsecp256k1_v0_10_0_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); + rustsecp256k1_v0_11_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); int i, j; for (i = 0; i < 1000 * COUNT; i++) { - rustsecp256k1_v0_10_0_fe_storage xs, ys, zs; + rustsecp256k1_v0_11_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); - v = rustsecp256k1_v0_10_0_testrand_bits(15); + testutil_random_fe_non_zero(&y); + v = testrand_bits(15); /* Test that fe_add_int is equivalent to fe_set_int + fe_add. */ - rustsecp256k1_v0_10_0_fe_set_int(&q, v); /* q = v */ + rustsecp256k1_v0_11_fe_set_int(&q, v); /* q = v */ z = x; /* z = x */ - rustsecp256k1_v0_10_0_fe_add(&z, &q); /* z = x+v */ + rustsecp256k1_v0_11_fe_add(&z, &q); /* z = x+v */ q = x; /* q = x */ - rustsecp256k1_v0_10_0_fe_add_int(&q, v); /* q = x+v */ - CHECK(check_fe_equal(&q, &z)); + rustsecp256k1_v0_11_fe_add_int(&q, v); /* q = x+v */ + CHECK(fe_equal(&q, &z)); /* Test the fe equality and comparison operations. */ - CHECK(rustsecp256k1_v0_10_0_fe_cmp_var(&x, &x) == 0); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&x, &x)); + CHECK(rustsecp256k1_v0_11_fe_cmp_var(&x, &x) == 0); + CHECK(rustsecp256k1_v0_11_fe_equal(&x, &x)); z = x; - rustsecp256k1_v0_10_0_fe_add(&z,&y); + rustsecp256k1_v0_11_fe_add(&z,&y); /* Test fe conditional move; z is not normalized here. */ q = x; - rustsecp256k1_v0_10_0_fe_cmov(&x, &z, 0); + rustsecp256k1_v0_11_fe_cmov(&x, &z, 0); #ifdef VERIFY CHECK(!x.normalized); CHECK((x.magnitude == q.magnitude) || (x.magnitude == z.magnitude)); CHECK((x.magnitude >= q.magnitude) && (x.magnitude >= z.magnitude)); #endif x = q; - rustsecp256k1_v0_10_0_fe_cmov(&x, &x, 1); + rustsecp256k1_v0_11_fe_cmov(&x, &x, 1); CHECK(!fe_identical(&x, &z)); CHECK(fe_identical(&x, &q)); - rustsecp256k1_v0_10_0_fe_cmov(&q, &z, 1); + rustsecp256k1_v0_11_fe_cmov(&q, &z, 1); #ifdef VERIFY CHECK(!q.normalized); CHECK((q.magnitude == x.magnitude) || (q.magnitude == z.magnitude)); @@ -3164,67 +3047,67 @@ static void run_field_misc(void) { #endif CHECK(fe_identical(&q, &z)); q = z; - rustsecp256k1_v0_10_0_fe_normalize_var(&x); - rustsecp256k1_v0_10_0_fe_normalize_var(&z); - CHECK(!rustsecp256k1_v0_10_0_fe_equal(&x, &z)); - rustsecp256k1_v0_10_0_fe_normalize_var(&q); - rustsecp256k1_v0_10_0_fe_cmov(&q, &z, (i&1)); + rustsecp256k1_v0_11_fe_normalize_var(&x); + rustsecp256k1_v0_11_fe_normalize_var(&z); + CHECK(!rustsecp256k1_v0_11_fe_equal(&x, &z)); + rustsecp256k1_v0_11_fe_normalize_var(&q); + rustsecp256k1_v0_11_fe_cmov(&q, &z, (i&1)); #ifdef VERIFY CHECK(q.normalized && q.magnitude == 1); #endif for (j = 0; j < 6; j++) { - rustsecp256k1_v0_10_0_fe_negate_unchecked(&z, &z, j+1); - rustsecp256k1_v0_10_0_fe_normalize_var(&q); - rustsecp256k1_v0_10_0_fe_cmov(&q, &z, (j&1)); + rustsecp256k1_v0_11_fe_negate_unchecked(&z, &z, j+1); + rustsecp256k1_v0_11_fe_normalize_var(&q); + rustsecp256k1_v0_11_fe_cmov(&q, &z, (j&1)); #ifdef VERIFY CHECK(!q.normalized && q.magnitude == z.magnitude); #endif } - rustsecp256k1_v0_10_0_fe_normalize_var(&z); + rustsecp256k1_v0_11_fe_normalize_var(&z); /* Test storage conversion and conditional moves. */ - rustsecp256k1_v0_10_0_fe_to_storage(&xs, &x); - rustsecp256k1_v0_10_0_fe_to_storage(&ys, &y); - rustsecp256k1_v0_10_0_fe_to_storage(&zs, &z); - rustsecp256k1_v0_10_0_fe_storage_cmov(&zs, &xs, 0); - rustsecp256k1_v0_10_0_fe_storage_cmov(&zs, &zs, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xs, &zs, sizeof(xs)) != 0); - rustsecp256k1_v0_10_0_fe_storage_cmov(&ys, &xs, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&xs, &ys, sizeof(xs)) == 0); - rustsecp256k1_v0_10_0_fe_from_storage(&x, &xs); - rustsecp256k1_v0_10_0_fe_from_storage(&y, &ys); - rustsecp256k1_v0_10_0_fe_from_storage(&z, &zs); + rustsecp256k1_v0_11_fe_to_storage(&xs, &x); + rustsecp256k1_v0_11_fe_to_storage(&ys, &y); + rustsecp256k1_v0_11_fe_to_storage(&zs, &z); + rustsecp256k1_v0_11_fe_storage_cmov(&zs, &xs, 0); + rustsecp256k1_v0_11_fe_storage_cmov(&zs, &zs, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xs, &zs, sizeof(xs)) != 0); + rustsecp256k1_v0_11_fe_storage_cmov(&ys, &xs, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&xs, &ys, sizeof(xs)) == 0); + rustsecp256k1_v0_11_fe_from_storage(&x, &xs); + rustsecp256k1_v0_11_fe_from_storage(&y, &ys); + rustsecp256k1_v0_11_fe_from_storage(&z, &zs); /* Test that mul_int, mul, and add agree. */ - rustsecp256k1_v0_10_0_fe_add(&y, &x); - rustsecp256k1_v0_10_0_fe_add(&y, &x); + rustsecp256k1_v0_11_fe_add(&y, &x); + rustsecp256k1_v0_11_fe_add(&y, &x); z = x; - rustsecp256k1_v0_10_0_fe_mul_int(&z, 3); - CHECK(check_fe_equal(&y, &z)); - rustsecp256k1_v0_10_0_fe_add(&y, &x); - rustsecp256k1_v0_10_0_fe_add(&z, &x); - CHECK(check_fe_equal(&z, &y)); + rustsecp256k1_v0_11_fe_mul_int(&z, 3); + CHECK(fe_equal(&y, &z)); + rustsecp256k1_v0_11_fe_add(&y, &x); + rustsecp256k1_v0_11_fe_add(&z, &x); + CHECK(fe_equal(&z, &y)); z = x; - rustsecp256k1_v0_10_0_fe_mul_int(&z, 5); - rustsecp256k1_v0_10_0_fe_mul(&q, &x, &fe5); - CHECK(check_fe_equal(&z, &q)); - rustsecp256k1_v0_10_0_fe_negate(&x, &x, 1); - rustsecp256k1_v0_10_0_fe_add(&z, &x); - rustsecp256k1_v0_10_0_fe_add(&q, &x); - CHECK(check_fe_equal(&y, &z)); - CHECK(check_fe_equal(&q, &y)); - /* Check rustsecp256k1_v0_10_0_fe_half. */ + rustsecp256k1_v0_11_fe_mul_int(&z, 5); + rustsecp256k1_v0_11_fe_mul(&q, &x, &fe5); + CHECK(fe_equal(&z, &q)); + rustsecp256k1_v0_11_fe_negate(&x, &x, 1); + rustsecp256k1_v0_11_fe_add(&z, &x); + rustsecp256k1_v0_11_fe_add(&q, &x); + CHECK(fe_equal(&y, &z)); + CHECK(fe_equal(&q, &y)); + /* Check rustsecp256k1_v0_11_fe_half. */ z = x; - rustsecp256k1_v0_10_0_fe_half(&z); - rustsecp256k1_v0_10_0_fe_add(&z, &z); - CHECK(check_fe_equal(&x, &z)); - rustsecp256k1_v0_10_0_fe_add(&z, &z); - rustsecp256k1_v0_10_0_fe_half(&z); - CHECK(check_fe_equal(&x, &z)); + rustsecp256k1_v0_11_fe_half(&z); + rustsecp256k1_v0_11_fe_add(&z, &z); + CHECK(fe_equal(&x, &z)); + rustsecp256k1_v0_11_fe_add(&z, &z); + rustsecp256k1_v0_11_fe_half(&z); + CHECK(fe_equal(&x, &z)); } } -static void test_fe_mul(const rustsecp256k1_v0_10_0_fe* a, const rustsecp256k1_v0_10_0_fe* b, int use_sqr) +static void test_fe_mul(const rustsecp256k1_v0_11_fe* a, const rustsecp256k1_v0_11_fe* b, int use_sqr) { - rustsecp256k1_v0_10_0_fe c, an, bn; + rustsecp256k1_v0_11_fe c, an, bn; /* Variables in BE 32-byte format. */ unsigned char a32[32], b32[32], c32[32]; /* Variables in LE 16x uint16_t format. */ @@ -3240,20 +3123,20 @@ static void test_fe_mul(const rustsecp256k1_v0_10_0_fe* a, const rustsecp256k1_v /* Compute C = A * B in fe format. */ c = *a; if (use_sqr) { - rustsecp256k1_v0_10_0_fe_sqr(&c, &c); + rustsecp256k1_v0_11_fe_sqr(&c, &c); } else { - rustsecp256k1_v0_10_0_fe_mul(&c, &c, b); + rustsecp256k1_v0_11_fe_mul(&c, &c, b); } /* Convert A, B, C into LE 16x uint16_t format. */ an = *a; bn = *b; - rustsecp256k1_v0_10_0_fe_normalize_var(&c); - rustsecp256k1_v0_10_0_fe_normalize_var(&an); - rustsecp256k1_v0_10_0_fe_normalize_var(&bn); - rustsecp256k1_v0_10_0_fe_get_b32(a32, &an); - rustsecp256k1_v0_10_0_fe_get_b32(b32, &bn); - rustsecp256k1_v0_10_0_fe_get_b32(c32, &c); + rustsecp256k1_v0_11_fe_normalize_var(&c); + rustsecp256k1_v0_11_fe_normalize_var(&an); + rustsecp256k1_v0_11_fe_normalize_var(&bn); + rustsecp256k1_v0_11_fe_get_b32(a32, &an); + rustsecp256k1_v0_11_fe_get_b32(b32, &bn); + rustsecp256k1_v0_11_fe_get_b32(c32, &c); for (i = 0; i < 16; ++i) { a16[i] = a32[31 - 2*i] + ((uint16_t)a32[30 - 2*i] << 8); b16[i] = b32[31 - 2*i] + ((uint16_t)b32[30 - 2*i] << 8); @@ -3262,21 +3145,21 @@ static void test_fe_mul(const rustsecp256k1_v0_10_0_fe* a, const rustsecp256k1_v /* Compute T = A * B in LE 16x uint16_t format. */ mulmod256(t16, a16, b16, m16); /* Compare */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(t16, c16, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(t16, c16, 32) == 0); } static void run_fe_mul(void) { int i; for (i = 0; i < 100 * COUNT; ++i) { - rustsecp256k1_v0_10_0_fe a, b, c, d; - random_fe(&a); - random_fe_magnitude(&a); - random_fe(&b); - random_fe_magnitude(&b); - random_fe_test(&c); - random_fe_magnitude(&c); - random_fe_test(&d); - random_fe_magnitude(&d); + rustsecp256k1_v0_11_fe a, b, c, d; + 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); @@ -3287,50 +3170,63 @@ static void run_fe_mul(void) { } static void run_sqr(void) { - rustsecp256k1_v0_10_0_fe x, s; + int i; + rustsecp256k1_v0_11_fe x, y, lhs, rhs, tmp; - { - int i; - rustsecp256k1_v0_10_0_fe_set_int(&x, 1); - rustsecp256k1_v0_10_0_fe_negate(&x, &x, 1); + rustsecp256k1_v0_11_fe_set_int(&x, 1); + rustsecp256k1_v0_11_fe_negate(&x, &x, 1); - for (i = 1; i <= 512; ++i) { - rustsecp256k1_v0_10_0_fe_mul_int(&x, 2); - rustsecp256k1_v0_10_0_fe_normalize(&x); - rustsecp256k1_v0_10_0_fe_sqr(&s, &x); - } + for (i = 1; i <= 512; ++i) { + rustsecp256k1_v0_11_fe_mul_int(&x, 2); + rustsecp256k1_v0_11_fe_normalize(&x); + + /* Check that (x+y)*(x-y) = x^2 - y*2 for some random values y */ + testutil_random_fe_test(&y); + + lhs = x; + rustsecp256k1_v0_11_fe_add(&lhs, &y); /* lhs = x+y */ + rustsecp256k1_v0_11_fe_negate(&tmp, &y, 1); /* tmp = -y */ + rustsecp256k1_v0_11_fe_add(&tmp, &x); /* tmp = x-y */ + rustsecp256k1_v0_11_fe_mul(&lhs, &lhs, &tmp); /* lhs = (x+y)*(x-y) */ + + rustsecp256k1_v0_11_fe_sqr(&rhs, &x); /* rhs = x^2 */ + rustsecp256k1_v0_11_fe_sqr(&tmp, &y); /* tmp = y^2 */ + rustsecp256k1_v0_11_fe_negate(&tmp, &tmp, 1); /* tmp = -y^2 */ + rustsecp256k1_v0_11_fe_add(&rhs, &tmp); /* rhs = x^2 - y^2 */ + + CHECK(fe_equal(&lhs, &rhs)); } } -static void test_sqrt(const rustsecp256k1_v0_10_0_fe *a, const rustsecp256k1_v0_10_0_fe *k) { - rustsecp256k1_v0_10_0_fe r1, r2; - int v = rustsecp256k1_v0_10_0_fe_sqrt(&r1, a); +static void test_sqrt(const rustsecp256k1_v0_11_fe *a, const rustsecp256k1_v0_11_fe *k) { + rustsecp256k1_v0_11_fe r1, r2; + int v = rustsecp256k1_v0_11_fe_sqrt(&r1, a); CHECK((v == 0) == (k == NULL)); if (k != NULL) { /* Check that the returned root is +/- the given known answer */ - rustsecp256k1_v0_10_0_fe_negate(&r2, &r1, 1); - rustsecp256k1_v0_10_0_fe_add(&r1, k); rustsecp256k1_v0_10_0_fe_add(&r2, k); - rustsecp256k1_v0_10_0_fe_normalize(&r1); rustsecp256k1_v0_10_0_fe_normalize(&r2); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&r1) || rustsecp256k1_v0_10_0_fe_is_zero(&r2)); + rustsecp256k1_v0_11_fe_negate(&r2, &r1, 1); + rustsecp256k1_v0_11_fe_add(&r1, k); rustsecp256k1_v0_11_fe_add(&r2, k); + rustsecp256k1_v0_11_fe_normalize(&r1); rustsecp256k1_v0_11_fe_normalize(&r2); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&r1) || rustsecp256k1_v0_11_fe_is_zero(&r2)); } } static void run_sqrt(void) { - rustsecp256k1_v0_10_0_fe ns, x, s, t; + rustsecp256k1_v0_11_fe ns, x, s, t; int i; /* Check sqrt(0) is 0 */ - rustsecp256k1_v0_10_0_fe_set_int(&x, 0); - rustsecp256k1_v0_10_0_fe_sqr(&s, &x); + rustsecp256k1_v0_11_fe_set_int(&x, 0); + rustsecp256k1_v0_11_fe_sqr(&s, &x); test_sqrt(&s, &x); /* Check sqrt of small squares (and their negatives) */ for (i = 1; i <= 100; i++) { - rustsecp256k1_v0_10_0_fe_set_int(&x, i); - rustsecp256k1_v0_10_0_fe_sqr(&s, &x); + rustsecp256k1_v0_11_fe_set_int(&x, i); + rustsecp256k1_v0_11_fe_sqr(&s, &x); test_sqrt(&s, &x); - rustsecp256k1_v0_10_0_fe_negate(&t, &s, 1); + rustsecp256k1_v0_11_fe_negate(&t, &s, 1); test_sqrt(&t, NULL); } @@ -3339,14 +3235,14 @@ static void run_sqrt(void) { int j; random_fe_non_square(&ns); for (j = 0; j < COUNT; j++) { - random_fe(&x); - rustsecp256k1_v0_10_0_fe_sqr(&s, &x); - CHECK(rustsecp256k1_v0_10_0_fe_is_square_var(&s)); + testutil_random_fe(&x); + rustsecp256k1_v0_11_fe_sqr(&s, &x); + CHECK(rustsecp256k1_v0_11_fe_is_square_var(&s)); test_sqrt(&s, &x); - rustsecp256k1_v0_10_0_fe_negate(&t, &s, 1); - CHECK(!rustsecp256k1_v0_10_0_fe_is_square_var(&t)); + rustsecp256k1_v0_11_fe_negate(&t, &s, 1); + CHECK(!rustsecp256k1_v0_11_fe_is_square_var(&t)); test_sqrt(&t, NULL); - rustsecp256k1_v0_10_0_fe_mul(&t, &s, &ns); + rustsecp256k1_v0_11_fe_mul(&t, &s, &ns); test_sqrt(&t, NULL); } } @@ -3354,12 +3250,12 @@ static void run_sqrt(void) { /***** FIELD/SCALAR INVERSE TESTS *****/ -static const rustsecp256k1_v0_10_0_scalar scalar_minus_one = SECP256K1_SCALAR_CONST( +static const rustsecp256k1_v0_11_scalar scalar_minus_one = SECP256K1_SCALAR_CONST( 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xBAAEDCE6, 0xAF48A03B, 0xBFD25E8C, 0xD0364140 ); -static const rustsecp256k1_v0_10_0_fe fe_minus_one = SECP256K1_FE_CONST( +static const rustsecp256k1_v0_11_fe fe_minus_one = SECP256K1_FE_CONST( 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFC2E ); @@ -3371,57 +3267,57 @@ static const rustsecp256k1_v0_10_0_fe fe_minus_one = SECP256K1_FE_CONST( * for x!=0 and x!=1: 1/(1/x - 1) + 1 == -1/(x-1) */ -static void test_inverse_scalar(rustsecp256k1_v0_10_0_scalar* out, const rustsecp256k1_v0_10_0_scalar* x, int var) +static void test_inverse_scalar(rustsecp256k1_v0_11_scalar* out, const rustsecp256k1_v0_11_scalar* x, int var) { - rustsecp256k1_v0_10_0_scalar l, r, t; + rustsecp256k1_v0_11_scalar l, r, t; - (var ? rustsecp256k1_v0_10_0_scalar_inverse_var : rustsecp256k1_v0_10_0_scalar_inverse)(&l, x); /* l = 1/x */ + (var ? rustsecp256k1_v0_11_scalar_inverse_var : rustsecp256k1_v0_11_scalar_inverse)(&l, x); /* l = 1/x */ if (out) *out = l; - if (rustsecp256k1_v0_10_0_scalar_is_zero(x)) { - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&l)); + if (rustsecp256k1_v0_11_scalar_is_zero(x)) { + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&l)); return; } - rustsecp256k1_v0_10_0_scalar_mul(&t, x, &l); /* t = x*(1/x) */ - CHECK(rustsecp256k1_v0_10_0_scalar_is_one(&t)); /* x*(1/x) == 1 */ - rustsecp256k1_v0_10_0_scalar_add(&r, x, &scalar_minus_one); /* r = x-1 */ - if (rustsecp256k1_v0_10_0_scalar_is_zero(&r)) return; - (var ? rustsecp256k1_v0_10_0_scalar_inverse_var : rustsecp256k1_v0_10_0_scalar_inverse)(&r, &r); /* r = 1/(x-1) */ - rustsecp256k1_v0_10_0_scalar_add(&l, &scalar_minus_one, &l); /* l = 1/x-1 */ - (var ? rustsecp256k1_v0_10_0_scalar_inverse_var : rustsecp256k1_v0_10_0_scalar_inverse)(&l, &l); /* l = 1/(1/x-1) */ - rustsecp256k1_v0_10_0_scalar_add(&l, &l, &rustsecp256k1_v0_10_0_scalar_one); /* l = 1/(1/x-1)+1 */ - rustsecp256k1_v0_10_0_scalar_add(&l, &r, &l); /* l = 1/(1/x-1)+1 + 1/(x-1) */ - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&l)); /* l == 0 */ + rustsecp256k1_v0_11_scalar_mul(&t, x, &l); /* t = x*(1/x) */ + CHECK(rustsecp256k1_v0_11_scalar_is_one(&t)); /* x*(1/x) == 1 */ + rustsecp256k1_v0_11_scalar_add(&r, x, &scalar_minus_one); /* r = x-1 */ + if (rustsecp256k1_v0_11_scalar_is_zero(&r)) return; + (var ? rustsecp256k1_v0_11_scalar_inverse_var : rustsecp256k1_v0_11_scalar_inverse)(&r, &r); /* r = 1/(x-1) */ + rustsecp256k1_v0_11_scalar_add(&l, &scalar_minus_one, &l); /* l = 1/x-1 */ + (var ? rustsecp256k1_v0_11_scalar_inverse_var : rustsecp256k1_v0_11_scalar_inverse)(&l, &l); /* l = 1/(1/x-1) */ + rustsecp256k1_v0_11_scalar_add(&l, &l, &rustsecp256k1_v0_11_scalar_one); /* l = 1/(1/x-1)+1 */ + rustsecp256k1_v0_11_scalar_add(&l, &r, &l); /* l = 1/(1/x-1)+1 + 1/(x-1) */ + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&l)); /* l == 0 */ } -static void test_inverse_field(rustsecp256k1_v0_10_0_fe* out, const rustsecp256k1_v0_10_0_fe* x, int var) +static void test_inverse_field(rustsecp256k1_v0_11_fe* out, const rustsecp256k1_v0_11_fe* x, int var) { - rustsecp256k1_v0_10_0_fe l, r, t; + rustsecp256k1_v0_11_fe l, r, t; - (var ? rustsecp256k1_v0_10_0_fe_inv_var : rustsecp256k1_v0_10_0_fe_inv)(&l, x) ; /* l = 1/x */ + (var ? rustsecp256k1_v0_11_fe_inv_var : rustsecp256k1_v0_11_fe_inv)(&l, x) ; /* l = 1/x */ if (out) *out = l; t = *x; /* t = x */ - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&t)) { - CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&l)); + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&t)) { + CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero(&l)); return; } - rustsecp256k1_v0_10_0_fe_mul(&t, x, &l); /* t = x*(1/x) */ - rustsecp256k1_v0_10_0_fe_add(&t, &fe_minus_one); /* t = x*(1/x)-1 */ - CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero(&t)); /* x*(1/x)-1 == 0 */ + rustsecp256k1_v0_11_fe_mul(&t, x, &l); /* t = x*(1/x) */ + rustsecp256k1_v0_11_fe_add(&t, &fe_minus_one); /* t = x*(1/x)-1 */ + CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero(&t)); /* x*(1/x)-1 == 0 */ r = *x; /* r = x */ - rustsecp256k1_v0_10_0_fe_add(&r, &fe_minus_one); /* r = x-1 */ - if (rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&r)) return; - (var ? rustsecp256k1_v0_10_0_fe_inv_var : rustsecp256k1_v0_10_0_fe_inv)(&r, &r); /* r = 1/(x-1) */ - rustsecp256k1_v0_10_0_fe_add(&l, &fe_minus_one); /* l = 1/x-1 */ - (var ? rustsecp256k1_v0_10_0_fe_inv_var : rustsecp256k1_v0_10_0_fe_inv)(&l, &l); /* l = 1/(1/x-1) */ - rustsecp256k1_v0_10_0_fe_add_int(&l, 1); /* l = 1/(1/x-1)+1 */ - rustsecp256k1_v0_10_0_fe_add(&l, &r); /* l = 1/(1/x-1)+1 + 1/(x-1) */ - CHECK(rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&l)); /* l == 0 */ + rustsecp256k1_v0_11_fe_add(&r, &fe_minus_one); /* r = x-1 */ + if (rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&r)) return; + (var ? rustsecp256k1_v0_11_fe_inv_var : rustsecp256k1_v0_11_fe_inv)(&r, &r); /* r = 1/(x-1) */ + rustsecp256k1_v0_11_fe_add(&l, &fe_minus_one); /* l = 1/x-1 */ + (var ? rustsecp256k1_v0_11_fe_inv_var : rustsecp256k1_v0_11_fe_inv)(&l, &l); /* l = 1/(1/x-1) */ + rustsecp256k1_v0_11_fe_add_int(&l, 1); /* l = 1/(1/x-1)+1 */ + rustsecp256k1_v0_11_fe_add(&l, &r); /* l = 1/(1/x-1)+1 + 1/(x-1) */ + CHECK(rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&l)); /* l == 0 */ } static void run_inverse_tests(void) { /* Fixed test cases for field inverses: pairs of (x, 1/x) mod p. */ - static const rustsecp256k1_v0_10_0_fe fe_cases[][2] = { + static const rustsecp256k1_v0_11_fe fe_cases[][2] = { /* 0 */ {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0)}, @@ -3526,7 +3422,7 @@ static void run_inverse_tests(void) SECP256K1_FE_CONST(0x9a94b9b5, 0x57eb71ee, 0x4c975b8b, 0xac5262a8, 0x077b0595, 0xe12a6b1f, 0xd728edef, 0x1a6bf956)} }; /* Fixed test cases for scalar inverses: pairs of (x, 1/x) mod n. */ - static const rustsecp256k1_v0_10_0_scalar scalar_cases[][2] = { + static const rustsecp256k1_v0_11_scalar scalar_cases[][2] = { /* 0 */ {SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0)}, @@ -3613,38 +3509,38 @@ static void run_inverse_tests(void) }; int i, var, testrand; unsigned char b32[32]; - rustsecp256k1_v0_10_0_fe x_fe; - rustsecp256k1_v0_10_0_scalar x_scalar; + rustsecp256k1_v0_11_fe x_fe; + rustsecp256k1_v0_11_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 (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(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(fe_equal(&x_fe, &fe_cases[i][0])); } } for (i = 0; (size_t)i < sizeof(scalar_cases)/sizeof(scalar_cases[0]); ++i) { for (var = 0; var <= 1; ++var) { test_inverse_scalar(&x_scalar, &scalar_cases[i][0], var); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&x_scalar, &scalar_cases[i][1])); + CHECK(rustsecp256k1_v0_11_scalar_eq(&x_scalar, &scalar_cases[i][1])); test_inverse_scalar(&x_scalar, &scalar_cases[i][1], var); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&x_scalar, &scalar_cases[i][0])); + CHECK(rustsecp256k1_v0_11_scalar_eq(&x_scalar, &scalar_cases[i][0])); } } /* Test inputs 0..999 and their respective negations. */ for (i = 0; i < 1000; ++i) { b32[31] = i & 0xff; b32[30] = (i >> 8) & 0xff; - rustsecp256k1_v0_10_0_scalar_set_b32(&x_scalar, b32, NULL); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&x_fe, b32); + rustsecp256k1_v0_11_scalar_set_b32(&x_scalar, b32, NULL); + rustsecp256k1_v0_11_fe_set_b32_mod(&x_fe, b32); for (var = 0; var <= 1; ++var) { test_inverse_scalar(NULL, &x_scalar, var); test_inverse_field(NULL, &x_fe, var); } - rustsecp256k1_v0_10_0_scalar_negate(&x_scalar, &x_scalar); - rustsecp256k1_v0_10_0_fe_negate(&x_fe, &x_fe, 1); + rustsecp256k1_v0_11_scalar_negate(&x_scalar, &x_scalar); + rustsecp256k1_v0_11_fe_negate(&x_fe, &x_fe, 1); for (var = 0; var <= 1; ++var) { test_inverse_scalar(NULL, &x_scalar, var); test_inverse_field(NULL, &x_fe, var); @@ -3653,9 +3549,9 @@ 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 ? rustsecp256k1_v0_10_0_testrand256_test : rustsecp256k1_v0_10_0_testrand256)(b32); - rustsecp256k1_v0_10_0_scalar_set_b32(&x_scalar, b32, NULL); - rustsecp256k1_v0_10_0_fe_set_b32_mod(&x_fe, b32); + (testrand ? testrand256_test : testrand256)(b32); + rustsecp256k1_v0_11_scalar_set_b32(&x_scalar, b32, NULL); + rustsecp256k1_v0_11_fe_set_b32_mod(&x_fe, b32); for (var = 0; var <= 1; ++var) { test_inverse_scalar(NULL, &x_scalar, var); test_inverse_field(NULL, &x_fe, var); @@ -3664,26 +3560,98 @@ 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); + rustsecp256k1_v0_11_heap_swap(a, 0, 2, 200); + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_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; + + rustsecp256k1_v0_11_hsort(elements, 0, element_len, test_hsort_cmp, &data); + CHECK(data.counter == 0); + rustsecp256k1_v0_11_hsort(elements, 1, element_len, test_hsort_cmp, &data); + CHECK(data.counter == 0); + rustsecp256k1_v0_11_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 = testrand_int(NUM); + testrand_bytes_test(elements, n*element_len); + rustsecp256k1_v0_11_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. */ -static int gej_xyz_equals_gej(const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_gej *b) { - rustsecp256k1_v0_10_0_gej a2; - rustsecp256k1_v0_10_0_gej b2; +static int gej_xyz_equals_gej(const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_gej *b) { + rustsecp256k1_v0_11_gej a2; + rustsecp256k1_v0_11_gej b2; int ret = 1; ret &= a->infinity == b->infinity; if (ret && !a->infinity) { a2 = *a; b2 = *b; - rustsecp256k1_v0_10_0_fe_normalize(&a2.x); - rustsecp256k1_v0_10_0_fe_normalize(&a2.y); - rustsecp256k1_v0_10_0_fe_normalize(&a2.z); - rustsecp256k1_v0_10_0_fe_normalize(&b2.x); - rustsecp256k1_v0_10_0_fe_normalize(&b2.y); - rustsecp256k1_v0_10_0_fe_normalize(&b2.z); - ret &= rustsecp256k1_v0_10_0_fe_cmp_var(&a2.x, &b2.x) == 0; - ret &= rustsecp256k1_v0_10_0_fe_cmp_var(&a2.y, &b2.y) == 0; - ret &= rustsecp256k1_v0_10_0_fe_cmp_var(&a2.z, &b2.z) == 0; + rustsecp256k1_v0_11_fe_normalize(&a2.x); + rustsecp256k1_v0_11_fe_normalize(&a2.y); + rustsecp256k1_v0_11_fe_normalize(&a2.z); + rustsecp256k1_v0_11_fe_normalize(&b2.x); + rustsecp256k1_v0_11_fe_normalize(&b2.y); + rustsecp256k1_v0_11_fe_normalize(&b2.z); + ret &= rustsecp256k1_v0_11_fe_cmp_var(&a2.x, &b2.x) == 0; + ret &= rustsecp256k1_v0_11_fe_cmp_var(&a2.y, &b2.y) == 0; + ret &= rustsecp256k1_v0_11_fe_cmp_var(&a2.z, &b2.z) == 0; } return ret; } @@ -3697,225 +3665,224 @@ 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. */ - rustsecp256k1_v0_10_0_ge *ge = (rustsecp256k1_v0_10_0_ge *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_10_0_ge) * (1 + 4 * runs)); - rustsecp256k1_v0_10_0_gej *gej = (rustsecp256k1_v0_10_0_gej *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_10_0_gej) * (1 + 4 * runs)); - rustsecp256k1_v0_10_0_fe zf, r; - rustsecp256k1_v0_10_0_fe zfi2, zfi3; - - rustsecp256k1_v0_10_0_gej_set_infinity(&gej[0]); - rustsecp256k1_v0_10_0_ge_clear(&ge[0]); - rustsecp256k1_v0_10_0_ge_set_gej_var(&ge[0], &gej[0]); + rustsecp256k1_v0_11_ge *ge = (rustsecp256k1_v0_11_ge *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_11_ge) * (1 + 4 * runs)); + rustsecp256k1_v0_11_gej *gej = (rustsecp256k1_v0_11_gej *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_11_gej) * (1 + 4 * runs)); + rustsecp256k1_v0_11_fe zf, r; + rustsecp256k1_v0_11_fe zfi2, zfi3; + + rustsecp256k1_v0_11_gej_set_infinity(&gej[0]); + rustsecp256k1_v0_11_ge_set_infinity(&ge[0]); for (i = 0; i < runs; i++) { int j, k; - rustsecp256k1_v0_10_0_ge g; - random_group_element_test(&g); + rustsecp256k1_v0_11_ge g; + testutil_random_ge_test(&g); if (i >= runs - 2) { - rustsecp256k1_v0_10_0_ge_mul_lambda(&g, &ge[1]); - CHECK(!rustsecp256k1_v0_10_0_ge_eq_var(&g, &ge[1])); + rustsecp256k1_v0_11_ge_mul_lambda(&g, &ge[1]); + CHECK(!rustsecp256k1_v0_11_ge_eq_var(&g, &ge[1])); } if (i >= runs - 1) { - rustsecp256k1_v0_10_0_ge_mul_lambda(&g, &g); + rustsecp256k1_v0_11_ge_mul_lambda(&g, &g); } ge[1 + 4 * i] = g; ge[2 + 4 * i] = g; - rustsecp256k1_v0_10_0_ge_neg(&ge[3 + 4 * i], &g); - rustsecp256k1_v0_10_0_ge_neg(&ge[4 + 4 * i], &g); - rustsecp256k1_v0_10_0_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); - random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); - rustsecp256k1_v0_10_0_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); - random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); + rustsecp256k1_v0_11_ge_neg(&ge[3 + 4 * i], &g); + rustsecp256k1_v0_11_ge_neg(&ge[4 + 4 * i], &g); + rustsecp256k1_v0_11_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); + testutil_random_ge_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); + rustsecp256k1_v0_11_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 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) { for (k = 0; k < 4; ++k) { int expect_equal = (j >> 1) == (k >> 1); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&ge[1 + j + 4 * i], &ge[1 + k + 4 * i]) == expect_equal); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&gej[1 + j + 4 * i], &gej[1 + k + 4 * i]) == expect_equal); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&gej[1 + j + 4 * i], &ge[1 + k + 4 * i]) == expect_equal); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&gej[1 + k + 4 * i], &ge[1 + j + 4 * i]) == expect_equal); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&ge[1 + j + 4 * i], &ge[1 + k + 4 * i]) == expect_equal); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&gej[1 + j + 4 * i], &gej[1 + k + 4 * i]) == expect_equal); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&gej[1 + j + 4 * i], &ge[1 + k + 4 * i]) == expect_equal); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&gej[1 + k + 4 * i], &ge[1 + j + 4 * i]) == expect_equal); } } } /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ - random_fe_non_zero_test(&zf); - random_fe_magnitude(&zf); - rustsecp256k1_v0_10_0_fe_inv_var(&zfi3, &zf); - rustsecp256k1_v0_10_0_fe_sqr(&zfi2, &zfi3); - rustsecp256k1_v0_10_0_fe_mul(&zfi3, &zfi3, &zfi2); + testutil_random_fe_non_zero_test(&zf); + testutil_random_fe_magnitude(&zf, 8); + rustsecp256k1_v0_11_fe_inv_var(&zfi3, &zf); + rustsecp256k1_v0_11_fe_sqr(&zfi2, &zfi3); + rustsecp256k1_v0_11_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; for (i2 = 0; i2 < 1 + 4 * runs; i2++) { /* Compute reference result using gej + gej (var). */ - rustsecp256k1_v0_10_0_gej refj, resj; - rustsecp256k1_v0_10_0_ge ref; - rustsecp256k1_v0_10_0_fe zr; - rustsecp256k1_v0_10_0_gej_add_var(&refj, &gej[i1], &gej[i2], rustsecp256k1_v0_10_0_gej_is_infinity(&gej[i1]) ? NULL : &zr); + rustsecp256k1_v0_11_gej refj, resj; + rustsecp256k1_v0_11_ge ref; + rustsecp256k1_v0_11_fe zr; + rustsecp256k1_v0_11_gej_add_var(&refj, &gej[i1], &gej[i2], rustsecp256k1_v0_11_gej_is_infinity(&gej[i1]) ? NULL : &zr); /* Check Z ratio. */ - if (!rustsecp256k1_v0_10_0_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_10_0_gej_is_infinity(&refj)) { - rustsecp256k1_v0_10_0_fe zrz; rustsecp256k1_v0_10_0_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&zrz, &refj.z)); + if (!rustsecp256k1_v0_11_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_11_gej_is_infinity(&refj)) { + rustsecp256k1_v0_11_fe zrz; rustsecp256k1_v0_11_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(rustsecp256k1_v0_11_fe_equal(&zrz, &refj.z)); } - rustsecp256k1_v0_10_0_ge_set_gej_var(&ref, &refj); + rustsecp256k1_v0_11_ge_set_gej_var(&ref, &refj); /* Test gej + ge with Z ratio result (var). */ - rustsecp256k1_v0_10_0_gej_add_ge_var(&resj, &gej[i1], &ge[i2], rustsecp256k1_v0_10_0_gej_is_infinity(&gej[i1]) ? NULL : &zr); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&resj, &ref)); - if (!rustsecp256k1_v0_10_0_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_10_0_gej_is_infinity(&resj)) { - rustsecp256k1_v0_10_0_fe zrz; rustsecp256k1_v0_10_0_fe_mul(&zrz, &zr, &gej[i1].z); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&zrz, &resj.z)); + rustsecp256k1_v0_11_gej_add_ge_var(&resj, &gej[i1], &ge[i2], rustsecp256k1_v0_11_gej_is_infinity(&gej[i1]) ? NULL : &zr); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&resj, &ref)); + if (!rustsecp256k1_v0_11_gej_is_infinity(&gej[i1]) && !rustsecp256k1_v0_11_gej_is_infinity(&resj)) { + rustsecp256k1_v0_11_fe zrz; rustsecp256k1_v0_11_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(rustsecp256k1_v0_11_fe_equal(&zrz, &resj.z)); } /* Test gej + ge (var, with additional Z factor). */ { - rustsecp256k1_v0_10_0_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ - rustsecp256k1_v0_10_0_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); - rustsecp256k1_v0_10_0_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); - random_ge_x_magnitude(&ge2_zfi); - random_ge_y_magnitude(&ge2_zfi); - rustsecp256k1_v0_10_0_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&resj, &ref)); + rustsecp256k1_v0_11_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ + rustsecp256k1_v0_11_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); + rustsecp256k1_v0_11_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); + testutil_random_ge_x_magnitude(&ge2_zfi); + testutil_random_ge_y_magnitude(&ge2_zfi); + rustsecp256k1_v0_11_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&resj, &ref)); } /* Test gej + ge (const). */ if (i2 != 0) { - /* rustsecp256k1_v0_10_0_gej_add_ge does not support its second argument being infinity. */ - rustsecp256k1_v0_10_0_gej_add_ge(&resj, &gej[i1], &ge[i2]); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&resj, &ref)); + /* rustsecp256k1_v0_11_gej_add_ge does not support its second argument being infinity. */ + rustsecp256k1_v0_11_gej_add_ge(&resj, &gej[i1], &ge[i2]); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&resj, &ref)); } /* Test doubling (var). */ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { - rustsecp256k1_v0_10_0_fe zr2; + rustsecp256k1_v0_11_fe zr2; /* Normal doubling with Z ratio result. */ - rustsecp256k1_v0_10_0_gej_double_var(&resj, &gej[i1], &zr2); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&resj, &ref)); + rustsecp256k1_v0_11_gej_double_var(&resj, &gej[i1], &zr2); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&resj, &ref)); /* Check Z ratio. */ - rustsecp256k1_v0_10_0_fe_mul(&zr2, &zr2, &gej[i1].z); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&zr2, &resj.z)); + rustsecp256k1_v0_11_fe_mul(&zr2, &zr2, &gej[i1].z); + CHECK(rustsecp256k1_v0_11_fe_equal(&zr2, &resj.z)); /* Normal doubling. */ - rustsecp256k1_v0_10_0_gej_double_var(&resj, &gej[i2], NULL); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&resj, &ref)); + rustsecp256k1_v0_11_gej_double_var(&resj, &gej[i2], NULL); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&resj, &ref)); /* Constant-time doubling. */ - rustsecp256k1_v0_10_0_gej_double(&resj, &gej[i2]); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&resj, &ref)); + rustsecp256k1_v0_11_gej_double(&resj, &gej[i2]); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&resj, &ref)); } /* Test adding opposites. */ if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&ref)); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&ref)); } /* Test adding infinity. */ if (i1 == 0) { - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&ge[i1])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&gej[i1])); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&gej[i2], &ref)); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&ge[i1])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&gej[i1])); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&gej[i2], &ref)); } if (i2 == 0) { - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&ge[i2])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&gej[i2])); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&gej[i1], &ref)); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&ge[i2])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&gej[i2])); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&gej[i1], &ref)); } } } /* Test adding all points together in random order equals infinity. */ { - rustsecp256k1_v0_10_0_gej sum = SECP256K1_GEJ_CONST_INFINITY; - rustsecp256k1_v0_10_0_gej *gej_shuffled = (rustsecp256k1_v0_10_0_gej *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_10_0_gej)); + rustsecp256k1_v0_11_gej sum = SECP256K1_GEJ_CONST_INFINITY; + rustsecp256k1_v0_11_gej *gej_shuffled = (rustsecp256k1_v0_11_gej *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_11_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } for (i = 0; i < 4 * runs + 1; i++) { - int swap = i + rustsecp256k1_v0_10_0_testrand_int(4 * runs + 1 - i); + int swap = i + testrand_int(4 * runs + 1 - i); if (swap != i) { - rustsecp256k1_v0_10_0_gej t = gej_shuffled[i]; + rustsecp256k1_v0_11_gej t = gej_shuffled[i]; gej_shuffled[i] = gej_shuffled[swap]; gej_shuffled[swap] = t; } } for (i = 0; i < 4 * runs + 1; i++) { - rustsecp256k1_v0_10_0_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); + rustsecp256k1_v0_11_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); } - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&sum)); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&sum)); free(gej_shuffled); } /* Test batch gej -> ge conversion without known z ratios. */ { - rustsecp256k1_v0_10_0_ge *ge_set_all = (rustsecp256k1_v0_10_0_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_10_0_ge)); - rustsecp256k1_v0_10_0_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); + rustsecp256k1_v0_11_ge *ge_set_all = (rustsecp256k1_v0_11_ge *)checked_malloc(&CTX->error_callback, (4 * runs + 1) * sizeof(rustsecp256k1_v0_11_ge)); + rustsecp256k1_v0_11_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1); for (i = 0; i < 4 * runs + 1; i++) { - rustsecp256k1_v0_10_0_fe s; - random_fe_non_zero(&s); - rustsecp256k1_v0_10_0_gej_rescale(&gej[i], &s); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&gej[i], &ge_set_all[i])); + rustsecp256k1_v0_11_fe s; + testutil_random_fe_non_zero(&s); + rustsecp256k1_v0_11_gej_rescale(&gej[i], &s); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&gej[i], &ge_set_all[i])); } free(ge_set_all); } /* Test that all elements have X coordinates on the curve. */ for (i = 1; i < 4 * runs + 1; i++) { - rustsecp256k1_v0_10_0_fe n; - CHECK(rustsecp256k1_v0_10_0_ge_x_on_curve_var(&ge[i].x)); + rustsecp256k1_v0_11_fe n; + CHECK(rustsecp256k1_v0_11_ge_x_on_curve_var(&ge[i].x)); /* And the same holds after random rescaling. */ - rustsecp256k1_v0_10_0_fe_mul(&n, &zf, &ge[i].x); - CHECK(rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(&n, &zf)); + rustsecp256k1_v0_11_fe_mul(&n, &zf, &ge[i].x); + CHECK(rustsecp256k1_v0_11_ge_x_frac_on_curve_var(&n, &zf)); } - /* Test correspondence of rustsecp256k1_v0_10_0_ge_x{,_frac}_on_curve_var with ge_set_xo. */ + /* Test correspondence of rustsecp256k1_v0_11_ge_x{,_frac}_on_curve_var with ge_set_xo. */ { - rustsecp256k1_v0_10_0_fe n; - rustsecp256k1_v0_10_0_ge q; + rustsecp256k1_v0_11_fe n; + rustsecp256k1_v0_11_ge q; int ret_on_curve, ret_frac_on_curve, ret_set_xo; - rustsecp256k1_v0_10_0_fe_mul(&n, &zf, &r); - ret_on_curve = rustsecp256k1_v0_10_0_ge_x_on_curve_var(&r); - ret_frac_on_curve = rustsecp256k1_v0_10_0_ge_x_frac_on_curve_var(&n, &zf); - ret_set_xo = rustsecp256k1_v0_10_0_ge_set_xo_var(&q, &r, 0); + rustsecp256k1_v0_11_fe_mul(&n, &zf, &r); + ret_on_curve = rustsecp256k1_v0_11_ge_x_on_curve_var(&r); + ret_frac_on_curve = rustsecp256k1_v0_11_ge_x_frac_on_curve_var(&n, &zf); + ret_set_xo = rustsecp256k1_v0_11_ge_set_xo_var(&q, &r, 0); CHECK(ret_on_curve == ret_frac_on_curve); CHECK(ret_on_curve == ret_set_xo); - if (ret_set_xo) CHECK(rustsecp256k1_v0_10_0_fe_equal(&r, &q.x)); + if (ret_set_xo) CHECK(rustsecp256k1_v0_11_fe_equal(&r, &q.x)); } /* Test batch gej -> ge conversion with many infinities. */ for (i = 0; i < 4 * runs + 1; i++) { int odd; - random_group_element_test(&ge[i]); - odd = rustsecp256k1_v0_10_0_fe_is_odd(&ge[i].x); + testutil_random_ge_test(&ge[i]); + odd = rustsecp256k1_v0_11_fe_is_odd(&ge[i].x); CHECK(odd == 0 || odd == 1); /* randomly set half the points to infinity */ if (odd == i % 2) { - rustsecp256k1_v0_10_0_ge_set_infinity(&ge[i]); + rustsecp256k1_v0_11_ge_set_infinity(&ge[i]); } - rustsecp256k1_v0_10_0_gej_set_ge(&gej[i], &ge[i]); + rustsecp256k1_v0_11_gej_set_ge(&gej[i], &ge[i]); } /* batch convert */ - rustsecp256k1_v0_10_0_ge_set_all_gej_var(ge, gej, 4 * runs + 1); + rustsecp256k1_v0_11_ge_set_all_gej_var(ge, gej, 4 * runs + 1); /* check result */ for (i = 0; i < 4 * runs + 1; i++) { - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&gej[i], &ge[i])); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&gej[i], &ge[i])); } /* Test batch gej -> ge conversion with all infinities. */ for (i = 0; i < 4 * runs + 1; i++) { - rustsecp256k1_v0_10_0_gej_set_infinity(&gej[i]); + rustsecp256k1_v0_11_gej_set_infinity(&gej[i]); } /* batch convert */ - rustsecp256k1_v0_10_0_ge_set_all_gej_var(ge, gej, 4 * runs + 1); + rustsecp256k1_v0_11_ge_set_all_gej_var(ge, gej, 4 * runs + 1); /* check result */ for (i = 0; i < 4 * runs + 1; i++) { - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&ge[i])); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&ge[i])); } free(ge); @@ -3923,33 +3890,33 @@ static void test_ge(void) { } static void test_intialized_inf(void) { - rustsecp256k1_v0_10_0_ge p; - rustsecp256k1_v0_10_0_gej pj, npj, infj1, infj2, infj3; - rustsecp256k1_v0_10_0_fe zinv; + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_gej pj, npj, infj1, infj2, infj3; + rustsecp256k1_v0_11_fe zinv; /* Test that adding P+(-P) results in a fully initialized infinity*/ - random_group_element_test(&p); - rustsecp256k1_v0_10_0_gej_set_ge(&pj, &p); - rustsecp256k1_v0_10_0_gej_neg(&npj, &pj); + testutil_random_ge_test(&p); + rustsecp256k1_v0_11_gej_set_ge(&pj, &p); + rustsecp256k1_v0_11_gej_neg(&npj, &pj); - rustsecp256k1_v0_10_0_gej_add_var(&infj1, &pj, &npj, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&infj1)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj1.x)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj1.y)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj1.z)); + rustsecp256k1_v0_11_gej_add_var(&infj1, &pj, &npj, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&infj1)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj1.x)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj1.y)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj1.z)); - rustsecp256k1_v0_10_0_gej_add_ge_var(&infj2, &npj, &p, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&infj2)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj2.x)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj2.y)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj2.z)); + rustsecp256k1_v0_11_gej_add_ge_var(&infj2, &npj, &p, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&infj2)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj2.x)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj2.y)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj2.z)); - rustsecp256k1_v0_10_0_fe_set_int(&zinv, 1); - rustsecp256k1_v0_10_0_gej_add_zinv_var(&infj3, &npj, &p, &zinv); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&infj3)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj3.x)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj3.y)); - CHECK(rustsecp256k1_v0_10_0_fe_is_zero(&infj3.z)); + rustsecp256k1_v0_11_fe_set_int(&zinv, 1); + rustsecp256k1_v0_11_gej_add_zinv_var(&infj3, &npj, &p, &zinv); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&infj3)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj3.x)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj3.y)); + CHECK(rustsecp256k1_v0_11_fe_is_zero(&infj3.z)); } @@ -3969,7 +3936,7 @@ static void test_add_neg_y_diff_x(void) { * * These points were generated in sage as * - * load("rustsecp256k1_v0_10_0_params.sage") + * load("rustsecp256k1_v0_11_params.sage") * * # random "bad pair" * P = C.random_element() @@ -3978,40 +3945,68 @@ static void test_add_neg_y_diff_x(void) { * print(" Q: %x %x" % Q.xy()) * print("P + Q: %x %x" % (P + Q).xy()) */ - rustsecp256k1_v0_10_0_gej aj = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_11_gej aj = SECP256K1_GEJ_CONST( 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d ); - rustsecp256k1_v0_10_0_gej bj = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_11_gej bj = SECP256K1_GEJ_CONST( 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 ); - rustsecp256k1_v0_10_0_gej sumj = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_11_gej sumj = SECP256K1_GEJ_CONST( 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe ); - rustsecp256k1_v0_10_0_ge b; - rustsecp256k1_v0_10_0_gej resj; - rustsecp256k1_v0_10_0_ge res; - rustsecp256k1_v0_10_0_ge_set_gej(&b, &bj); + rustsecp256k1_v0_11_ge b; + rustsecp256k1_v0_11_gej resj; + rustsecp256k1_v0_11_ge res; + rustsecp256k1_v0_11_ge_set_gej(&b, &bj); + + rustsecp256k1_v0_11_gej_add_var(&resj, &aj, &bj, NULL); + rustsecp256k1_v0_11_ge_set_gej(&res, &resj); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&sumj, &res)); + + rustsecp256k1_v0_11_gej_add_ge(&resj, &aj, &b); + rustsecp256k1_v0_11_ge_set_gej(&res, &resj); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&sumj, &res)); + + rustsecp256k1_v0_11_gej_add_ge_var(&resj, &aj, &b, NULL); + rustsecp256k1_v0_11_ge_set_gej(&res, &resj); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&sumj, &res)); +} + +static void test_ge_bytes(void) { + int i; - rustsecp256k1_v0_10_0_gej_add_var(&resj, &aj, &bj, NULL); - rustsecp256k1_v0_10_0_ge_set_gej(&res, &resj); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&sumj, &res)); + for (i = 0; i < COUNT + 1; i++) { + unsigned char buf[64]; + rustsecp256k1_v0_11_ge p, q; - rustsecp256k1_v0_10_0_gej_add_ge(&resj, &aj, &b); - rustsecp256k1_v0_10_0_ge_set_gej(&res, &resj); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&sumj, &res)); + if (i == 0) { + rustsecp256k1_v0_11_ge_set_infinity(&p); + } else { + testutil_random_ge_test(&p); + } - rustsecp256k1_v0_10_0_gej_add_ge_var(&resj, &aj, &b, NULL); - rustsecp256k1_v0_10_0_ge_set_gej(&res, &resj); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&sumj, &res)); + if (!rustsecp256k1_v0_11_ge_is_infinity(&p)) { + rustsecp256k1_v0_11_ge_to_bytes(buf, &p); + + rustsecp256k1_v0_11_ge_from_bytes(&q, buf); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&p, &q)); + + rustsecp256k1_v0_11_ge_from_bytes_ext(&q, buf); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&p, &q)); + } + rustsecp256k1_v0_11_ge_to_bytes_ext(buf, &p); + rustsecp256k1_v0_11_ge_from_bytes_ext(&q, buf); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&p, &q)); + } } static void run_ge(void) { @@ -4021,74 +4016,75 @@ static void run_ge(void) { } test_add_neg_y_diff_x(); test_intialized_inf(); + test_ge_bytes(); } -static void test_gej_cmov(const rustsecp256k1_v0_10_0_gej *a, const rustsecp256k1_v0_10_0_gej *b) { - rustsecp256k1_v0_10_0_gej t = *a; - rustsecp256k1_v0_10_0_gej_cmov(&t, b, 0); +static void test_gej_cmov(const rustsecp256k1_v0_11_gej *a, const rustsecp256k1_v0_11_gej *b) { + rustsecp256k1_v0_11_gej t = *a; + rustsecp256k1_v0_11_gej_cmov(&t, b, 0); CHECK(gej_xyz_equals_gej(&t, a)); - rustsecp256k1_v0_10_0_gej_cmov(&t, b, 1); + rustsecp256k1_v0_11_gej_cmov(&t, b, 1); CHECK(gej_xyz_equals_gej(&t, b)); } static void run_gej(void) { int i; - rustsecp256k1_v0_10_0_gej a, b; + rustsecp256k1_v0_11_gej a, b; - /* Tests for rustsecp256k1_v0_10_0_gej_cmov */ + /* Tests for rustsecp256k1_v0_11_gej_cmov */ for (i = 0; i < COUNT; i++) { - rustsecp256k1_v0_10_0_gej_set_infinity(&a); - rustsecp256k1_v0_10_0_gej_set_infinity(&b); + rustsecp256k1_v0_11_gej_set_infinity(&a); + rustsecp256k1_v0_11_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); } - /* Tests for rustsecp256k1_v0_10_0_gej_eq_var */ + /* Tests for rustsecp256k1_v0_11_gej_eq_var */ for (i = 0; i < COUNT; i++) { - rustsecp256k1_v0_10_0_fe fe; - random_gej_test(&a); - random_gej_test(&b); - CHECK(!rustsecp256k1_v0_10_0_gej_eq_var(&a, &b)); + rustsecp256k1_v0_11_fe fe; + testutil_random_gej_test(&a); + testutil_random_gej_test(&b); + CHECK(!rustsecp256k1_v0_11_gej_eq_var(&a, &b)); b = a; - random_fe_non_zero_test(&fe); - rustsecp256k1_v0_10_0_gej_rescale(&a, &fe); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&a, &b)); + testutil_random_fe_non_zero_test(&fe); + rustsecp256k1_v0_11_gej_rescale(&a, &fe); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&a, &b)); } } static void test_ec_combine(void) { - rustsecp256k1_v0_10_0_scalar sum = rustsecp256k1_v0_10_0_scalar_zero; - rustsecp256k1_v0_10_0_pubkey data[6]; - const rustsecp256k1_v0_10_0_pubkey* d[6]; - rustsecp256k1_v0_10_0_pubkey sd; - rustsecp256k1_v0_10_0_pubkey sd2; - rustsecp256k1_v0_10_0_gej Qj; - rustsecp256k1_v0_10_0_ge Q; + rustsecp256k1_v0_11_scalar sum = rustsecp256k1_v0_11_scalar_zero; + rustsecp256k1_v0_11_pubkey data[6]; + const rustsecp256k1_v0_11_pubkey* d[6]; + rustsecp256k1_v0_11_pubkey sd; + rustsecp256k1_v0_11_pubkey sd2; + rustsecp256k1_v0_11_gej Qj; + rustsecp256k1_v0_11_ge Q; int i; for (i = 1; i <= 6; i++) { - rustsecp256k1_v0_10_0_scalar s; - random_scalar_order_test(&s); - rustsecp256k1_v0_10_0_scalar_add(&sum, &sum, &s); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &s); - rustsecp256k1_v0_10_0_ge_set_gej(&Q, &Qj); - rustsecp256k1_v0_10_0_pubkey_save(&data[i - 1], &Q); + rustsecp256k1_v0_11_scalar s; + testutil_random_scalar_order_test(&s); + rustsecp256k1_v0_11_scalar_add(&sum, &sum, &s); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &s); + rustsecp256k1_v0_11_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_11_pubkey_save(&data[i - 1], &Q); d[i - 1] = &data[i - 1]; - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &sum); - rustsecp256k1_v0_10_0_ge_set_gej(&Q, &Qj); - rustsecp256k1_v0_10_0_pubkey_save(&sd, &Q); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &sd2, d, i) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&sd, &sd2, sizeof(sd)) == 0); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &Qj, &sum); + rustsecp256k1_v0_11_ge_set_gej(&Q, &Qj); + rustsecp256k1_v0_11_pubkey_save(&sd, &Q); + CHECK(rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &sd2, d, i) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&sd, &sd2, sizeof(sd)) == 0); } } @@ -4099,53 +4095,53 @@ static void run_ec_combine(void) { } } -static void test_group_decompress(const rustsecp256k1_v0_10_0_fe* x) { +static void test_group_decompress(const rustsecp256k1_v0_11_fe* x) { /* The input itself, normalized. */ - rustsecp256k1_v0_10_0_fe fex = *x; + rustsecp256k1_v0_11_fe fex = *x; /* Results of set_xo_var(..., 0), set_xo_var(..., 1). */ - rustsecp256k1_v0_10_0_ge ge_even, ge_odd; + rustsecp256k1_v0_11_ge ge_even, ge_odd; /* Return values of the above calls. */ int res_even, res_odd; - rustsecp256k1_v0_10_0_fe_normalize_var(&fex); + rustsecp256k1_v0_11_fe_normalize_var(&fex); - res_even = rustsecp256k1_v0_10_0_ge_set_xo_var(&ge_even, &fex, 0); - res_odd = rustsecp256k1_v0_10_0_ge_set_xo_var(&ge_odd, &fex, 1); + res_even = rustsecp256k1_v0_11_ge_set_xo_var(&ge_even, &fex, 0); + res_odd = rustsecp256k1_v0_11_ge_set_xo_var(&ge_odd, &fex, 1); CHECK(res_even == res_odd); if (res_even) { - rustsecp256k1_v0_10_0_fe_normalize_var(&ge_odd.x); - rustsecp256k1_v0_10_0_fe_normalize_var(&ge_even.x); - rustsecp256k1_v0_10_0_fe_normalize_var(&ge_odd.y); - rustsecp256k1_v0_10_0_fe_normalize_var(&ge_even.y); + rustsecp256k1_v0_11_fe_normalize_var(&ge_odd.x); + rustsecp256k1_v0_11_fe_normalize_var(&ge_even.x); + rustsecp256k1_v0_11_fe_normalize_var(&ge_odd.y); + rustsecp256k1_v0_11_fe_normalize_var(&ge_even.y); /* No infinity allowed. */ CHECK(!ge_even.infinity); CHECK(!ge_odd.infinity); /* Check that the x coordinates check out. */ - CHECK(rustsecp256k1_v0_10_0_fe_equal(&ge_even.x, x)); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&ge_odd.x, x)); + CHECK(rustsecp256k1_v0_11_fe_equal(&ge_even.x, x)); + CHECK(rustsecp256k1_v0_11_fe_equal(&ge_odd.x, x)); /* Check odd/even Y in ge_odd, ge_even. */ - CHECK(rustsecp256k1_v0_10_0_fe_is_odd(&ge_odd.y)); - CHECK(!rustsecp256k1_v0_10_0_fe_is_odd(&ge_even.y)); + CHECK(rustsecp256k1_v0_11_fe_is_odd(&ge_odd.y)); + CHECK(!rustsecp256k1_v0_11_fe_is_odd(&ge_even.y)); } } static void run_group_decompress(void) { int i; for (i = 0; i < COUNT * 4; i++) { - rustsecp256k1_v0_10_0_fe fe; - random_fe_test(&fe); + rustsecp256k1_v0_11_fe fe; + testutil_random_fe_test(&fe); test_group_decompress(&fe); } } /***** ECMULT TESTS *****/ -static void test_pre_g_table(const rustsecp256k1_v0_10_0_ge_storage * pre_g, size_t n) { +static void test_pre_g_table(const rustsecp256k1_v0_11_ge_storage * pre_g, size_t n) { /* Tests the pre_g / pre_g_128 tables for consistency. * For independent verification we take a "geometric" approach to verification. * We check that every entry is on-curve. @@ -4156,168 +4152,168 @@ static void test_pre_g_table(const rustsecp256k1_v0_10_0_ge_storage * pre_g, siz * * Checking the table's generators are correct is done in run_ecmult_pre_g. */ - rustsecp256k1_v0_10_0_gej g2; - rustsecp256k1_v0_10_0_ge p, q, gg; - rustsecp256k1_v0_10_0_fe dpx, dpy, dqx, dqy; + rustsecp256k1_v0_11_gej g2; + rustsecp256k1_v0_11_ge p, q, gg; + rustsecp256k1_v0_11_fe dpx, dpy, dqx, dqy; size_t i; CHECK(0 < n); - rustsecp256k1_v0_10_0_ge_from_storage(&p, &pre_g[0]); - CHECK(rustsecp256k1_v0_10_0_ge_is_valid_var(&p)); + rustsecp256k1_v0_11_ge_from_storage(&p, &pre_g[0]); + CHECK(rustsecp256k1_v0_11_ge_is_valid_var(&p)); - rustsecp256k1_v0_10_0_gej_set_ge(&g2, &p); - rustsecp256k1_v0_10_0_gej_double_var(&g2, &g2, NULL); - rustsecp256k1_v0_10_0_ge_set_gej_var(&gg, &g2); + rustsecp256k1_v0_11_gej_set_ge(&g2, &p); + rustsecp256k1_v0_11_gej_double_var(&g2, &g2, NULL); + rustsecp256k1_v0_11_ge_set_gej_var(&gg, &g2); for (i = 1; i < n; ++i) { - rustsecp256k1_v0_10_0_fe_negate(&dpx, &p.x, 1); rustsecp256k1_v0_10_0_fe_add(&dpx, &gg.x); rustsecp256k1_v0_10_0_fe_normalize_weak(&dpx); - rustsecp256k1_v0_10_0_fe_negate(&dpy, &p.y, 1); rustsecp256k1_v0_10_0_fe_add(&dpy, &gg.y); rustsecp256k1_v0_10_0_fe_normalize_weak(&dpy); + rustsecp256k1_v0_11_fe_negate(&dpx, &p.x, 1); rustsecp256k1_v0_11_fe_add(&dpx, &gg.x); rustsecp256k1_v0_11_fe_normalize_weak(&dpx); + rustsecp256k1_v0_11_fe_negate(&dpy, &p.y, 1); rustsecp256k1_v0_11_fe_add(&dpy, &gg.y); rustsecp256k1_v0_11_fe_normalize_weak(&dpy); /* Check that p is not equal to gg */ - CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&dpx) || !rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&dpy)); + CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&dpx) || !rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&dpy)); - rustsecp256k1_v0_10_0_ge_from_storage(&q, &pre_g[i]); - CHECK(rustsecp256k1_v0_10_0_ge_is_valid_var(&q)); + rustsecp256k1_v0_11_ge_from_storage(&q, &pre_g[i]); + CHECK(rustsecp256k1_v0_11_ge_is_valid_var(&q)); - rustsecp256k1_v0_10_0_fe_negate(&dqx, &q.x, 1); rustsecp256k1_v0_10_0_fe_add(&dqx, &gg.x); - dqy = q.y; rustsecp256k1_v0_10_0_fe_add(&dqy, &gg.y); + rustsecp256k1_v0_11_fe_negate(&dqx, &q.x, 1); rustsecp256k1_v0_11_fe_add(&dqx, &gg.x); + dqy = q.y; rustsecp256k1_v0_11_fe_add(&dqy, &gg.y); /* Check that -q is not equal to gg */ - CHECK(!rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&dqx) || !rustsecp256k1_v0_10_0_fe_normalizes_to_zero_var(&dqy)); + CHECK(!rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&dqx) || !rustsecp256k1_v0_11_fe_normalizes_to_zero_var(&dqy)); /* Check that -q is not equal to p */ - CHECK(!rustsecp256k1_v0_10_0_fe_equal(&dpx, &dqx) || !rustsecp256k1_v0_10_0_fe_equal(&dpy, &dqy)); + CHECK(!rustsecp256k1_v0_11_fe_equal(&dpx, &dqx) || !rustsecp256k1_v0_11_fe_equal(&dpy, &dqy)); /* Check that p, -q and gg are colinear */ - rustsecp256k1_v0_10_0_fe_mul(&dpx, &dpx, &dqy); - rustsecp256k1_v0_10_0_fe_mul(&dpy, &dpy, &dqx); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&dpx, &dpy)); + rustsecp256k1_v0_11_fe_mul(&dpx, &dpx, &dqy); + rustsecp256k1_v0_11_fe_mul(&dpy, &dpy, &dqx); + CHECK(rustsecp256k1_v0_11_fe_equal(&dpx, &dpy)); p = q; } } static void run_ecmult_pre_g(void) { - rustsecp256k1_v0_10_0_ge_storage gs; - rustsecp256k1_v0_10_0_gej gj; - rustsecp256k1_v0_10_0_ge g; + rustsecp256k1_v0_11_ge_storage gs; + rustsecp256k1_v0_11_gej gj; + rustsecp256k1_v0_11_ge g; size_t i; /* Check that the pre_g and pre_g_128 tables are consistent. */ - test_pre_g_table(rustsecp256k1_v0_10_0_pre_g, ECMULT_TABLE_SIZE(WINDOW_G)); - test_pre_g_table(rustsecp256k1_v0_10_0_pre_g_128, ECMULT_TABLE_SIZE(WINDOW_G)); + test_pre_g_table(rustsecp256k1_v0_11_pre_g, ECMULT_TABLE_SIZE(WINDOW_G)); + test_pre_g_table(rustsecp256k1_v0_11_pre_g_128, ECMULT_TABLE_SIZE(WINDOW_G)); /* Check the first entry from the pre_g table. */ - rustsecp256k1_v0_10_0_ge_to_storage(&gs, &rustsecp256k1_v0_10_0_ge_const_g); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&gs, &rustsecp256k1_v0_10_0_pre_g[0], sizeof(gs)) == 0); + rustsecp256k1_v0_11_ge_to_storage(&gs, &rustsecp256k1_v0_11_ge_const_g); + CHECK(rustsecp256k1_v0_11_memcmp_var(&gs, &rustsecp256k1_v0_11_pre_g[0], sizeof(gs)) == 0); /* Check the first entry from the pre_g_128 table. */ - rustsecp256k1_v0_10_0_gej_set_ge(&gj, &rustsecp256k1_v0_10_0_ge_const_g); + rustsecp256k1_v0_11_gej_set_ge(&gj, &rustsecp256k1_v0_11_ge_const_g); for (i = 0; i < 128; ++i) { - rustsecp256k1_v0_10_0_gej_double_var(&gj, &gj, NULL); + rustsecp256k1_v0_11_gej_double_var(&gj, &gj, NULL); } - rustsecp256k1_v0_10_0_ge_set_gej(&g, &gj); - rustsecp256k1_v0_10_0_ge_to_storage(&gs, &g); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&gs, &rustsecp256k1_v0_10_0_pre_g_128[0], sizeof(gs)) == 0); + rustsecp256k1_v0_11_ge_set_gej(&g, &gj); + rustsecp256k1_v0_11_ge_to_storage(&gs, &g); + CHECK(rustsecp256k1_v0_11_memcmp_var(&gs, &rustsecp256k1_v0_11_pre_g_128[0], sizeof(gs)) == 0); } static void run_ecmult_chain(void) { /* random starting point A (on the curve) */ - rustsecp256k1_v0_10_0_gej a = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_11_gej a = SECP256K1_GEJ_CONST( 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f ); /* two random initial factors xn and gn */ - rustsecp256k1_v0_10_0_scalar xn = SECP256K1_SCALAR_CONST( + rustsecp256k1_v0_11_scalar xn = SECP256K1_SCALAR_CONST( 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 ); - rustsecp256k1_v0_10_0_scalar gn = SECP256K1_SCALAR_CONST( + rustsecp256k1_v0_11_scalar gn = SECP256K1_SCALAR_CONST( 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de ); /* two small multipliers to be applied to xn and gn in every iteration: */ - static const rustsecp256k1_v0_10_0_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); - static const rustsecp256k1_v0_10_0_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); + static const rustsecp256k1_v0_11_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); + static const rustsecp256k1_v0_11_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); /* accumulators with the resulting coefficients to A and G */ - rustsecp256k1_v0_10_0_scalar ae = rustsecp256k1_v0_10_0_scalar_one; - rustsecp256k1_v0_10_0_scalar ge = rustsecp256k1_v0_10_0_scalar_zero; + rustsecp256k1_v0_11_scalar ae = rustsecp256k1_v0_11_scalar_one; + rustsecp256k1_v0_11_scalar ge = rustsecp256k1_v0_11_scalar_zero; /* actual points */ - rustsecp256k1_v0_10_0_gej x; - rustsecp256k1_v0_10_0_gej x2; + rustsecp256k1_v0_11_gej x; + rustsecp256k1_v0_11_gej x2; int i; /* the point being computed */ x = a; for (i = 0; i < 200*COUNT; i++) { /* in each iteration, compute X = xn*X + gn*G; */ - rustsecp256k1_v0_10_0_ecmult(&x, &x, &xn, &gn); + rustsecp256k1_v0_11_ecmult(&x, &x, &xn, &gn); /* also compute ae and ge: the actual accumulated factors for A and G */ /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ - rustsecp256k1_v0_10_0_scalar_mul(&ae, &ae, &xn); - rustsecp256k1_v0_10_0_scalar_mul(&ge, &ge, &xn); - rustsecp256k1_v0_10_0_scalar_add(&ge, &ge, &gn); + rustsecp256k1_v0_11_scalar_mul(&ae, &ae, &xn); + rustsecp256k1_v0_11_scalar_mul(&ge, &ge, &xn); + rustsecp256k1_v0_11_scalar_add(&ge, &ge, &gn); /* modify xn and gn */ - rustsecp256k1_v0_10_0_scalar_mul(&xn, &xn, &xf); - rustsecp256k1_v0_10_0_scalar_mul(&gn, &gn, &gf); + rustsecp256k1_v0_11_scalar_mul(&xn, &xn, &xf); + rustsecp256k1_v0_11_scalar_mul(&gn, &gn, &gf); /* verify */ if (i == 19999) { /* expected result after 19999 iterations */ - rustsecp256k1_v0_10_0_gej rp = SECP256K1_GEJ_CONST( + rustsecp256k1_v0_11_gej rp = SECP256K1_GEJ_CONST( 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 ); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&rp, &x)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&rp, &x)); } } /* redo the computation, but directly with the resulting ae and ge coefficients: */ - rustsecp256k1_v0_10_0_ecmult(&x2, &a, &ae, &ge); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&x, &x2)); + rustsecp256k1_v0_11_ecmult(&x2, &a, &ae, &ge); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&x, &x2)); } -static void test_point_times_order(const rustsecp256k1_v0_10_0_gej *point) { +static void test_point_times_order(const rustsecp256k1_v0_11_gej *point) { /* X * (point + G) + (order-X) * (pointer + G) = 0 */ - rustsecp256k1_v0_10_0_scalar x; - rustsecp256k1_v0_10_0_scalar nx; - rustsecp256k1_v0_10_0_gej res1, res2; - rustsecp256k1_v0_10_0_ge res3; + rustsecp256k1_v0_11_scalar x; + rustsecp256k1_v0_11_scalar nx; + rustsecp256k1_v0_11_gej res1, res2; + rustsecp256k1_v0_11_ge res3; unsigned char pub[65]; size_t psize = 65; - random_scalar_order_test(&x); - rustsecp256k1_v0_10_0_scalar_negate(&nx, &x); - rustsecp256k1_v0_10_0_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ - rustsecp256k1_v0_10_0_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ - rustsecp256k1_v0_10_0_gej_add_var(&res1, &res1, &res2, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&res1)); - rustsecp256k1_v0_10_0_ge_set_gej(&res3, &res1); - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&res3)); - CHECK(rustsecp256k1_v0_10_0_ge_is_valid_var(&res3) == 0); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); + testutil_random_scalar_order_test(&x); + rustsecp256k1_v0_11_scalar_negate(&nx, &x); + rustsecp256k1_v0_11_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */ + rustsecp256k1_v0_11_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ + rustsecp256k1_v0_11_gej_add_var(&res1, &res1, &res2, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&res1)); + rustsecp256k1_v0_11_ge_set_gej(&res3, &res1); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&res3)); + CHECK(rustsecp256k1_v0_11_ge_is_valid_var(&res3) == 0); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); psize = 65; - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); /* check zero/one edge cases */ - rustsecp256k1_v0_10_0_ecmult(&res1, point, &rustsecp256k1_v0_10_0_scalar_zero, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ge_set_gej(&res3, &res1); - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&res3)); - rustsecp256k1_v0_10_0_ecmult(&res1, point, &rustsecp256k1_v0_10_0_scalar_one, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ge_set_gej(&res3, &res1); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(point, &res3)); - rustsecp256k1_v0_10_0_ecmult(&res1, point, &rustsecp256k1_v0_10_0_scalar_zero, &rustsecp256k1_v0_10_0_scalar_one); - rustsecp256k1_v0_10_0_ge_set_gej(&res3, &res1); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&rustsecp256k1_v0_10_0_ge_const_g, &res3)); -} - -/* These scalars reach large (in absolute value) outputs when fed to rustsecp256k1_v0_10_0_scalar_split_lambda. + rustsecp256k1_v0_11_ecmult(&res1, point, &rustsecp256k1_v0_11_scalar_zero, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ge_set_gej(&res3, &res1); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&res3)); + rustsecp256k1_v0_11_ecmult(&res1, point, &rustsecp256k1_v0_11_scalar_one, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ge_set_gej(&res3, &res1); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(point, &res3)); + rustsecp256k1_v0_11_ecmult(&res1, point, &rustsecp256k1_v0_11_scalar_zero, &rustsecp256k1_v0_11_scalar_one); + rustsecp256k1_v0_11_ge_set_gej(&res3, &res1); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&rustsecp256k1_v0_11_ge_const_g, &res3)); +} + +/* These scalars reach large (in absolute value) outputs when fed to rustsecp256k1_v0_11_scalar_split_lambda. * * They are computed as: * - For a in [-2, -1, 0, 1, 2]: * - For b in [-3, -1, 1, 3]: * - Output (a*LAMBDA + (ORDER+b)/2) % ORDER */ -static const rustsecp256k1_v0_10_0_scalar scalars_near_split_bounds[20] = { +static const rustsecp256k1_v0_11_scalar scalars_near_split_bounds[20] = { SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fc), SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fd), SECP256K1_SCALAR_CONST(0xd938a566, 0x7f479e3e, 0xb5b3c7fa, 0xefdb3749, 0x3aa0585c, 0xc5ea2367, 0xe1b660db, 0x0209e6fe), @@ -4340,42 +4336,42 @@ static const rustsecp256k1_v0_10_0_scalar scalars_near_split_bounds[20] = { SECP256K1_SCALAR_CONST(0x26c75a99, 0x80b861c1, 0x4a4c3805, 0x1024c8b4, 0x704d760e, 0xe95e7cd3, 0xde1bfdb1, 0xce2c5a45) }; -static void test_ecmult_target(const rustsecp256k1_v0_10_0_scalar* target, int mode) { +static void test_ecmult_target(const rustsecp256k1_v0_11_scalar* target, int mode) { /* Mode: 0=ecmult_gen, 1=ecmult, 2=ecmult_const */ - rustsecp256k1_v0_10_0_scalar n1, n2; - rustsecp256k1_v0_10_0_ge p; - rustsecp256k1_v0_10_0_gej pj, p1j, p2j, ptj; + rustsecp256k1_v0_11_scalar n1, n2; + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_gej pj, p1j, p2j, ptj; /* Generate random n1,n2 such that n1+n2 = -target. */ - random_scalar_order_test(&n1); - rustsecp256k1_v0_10_0_scalar_add(&n2, &n1, target); - rustsecp256k1_v0_10_0_scalar_negate(&n2, &n2); + testutil_random_scalar_order_test(&n1); + rustsecp256k1_v0_11_scalar_add(&n2, &n1, target); + rustsecp256k1_v0_11_scalar_negate(&n2, &n2); /* Generate a random input point. */ if (mode != 0) { - random_group_element_test(&p); - rustsecp256k1_v0_10_0_gej_set_ge(&pj, &p); + testutil_random_ge_test(&p); + rustsecp256k1_v0_11_gej_set_ge(&pj, &p); } /* EC multiplications */ if (mode == 0) { - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &p1j, &n1); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &p2j, &n2); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &ptj, target); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &p1j, &n1); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &p2j, &n2); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &ptj, target); } else if (mode == 1) { - rustsecp256k1_v0_10_0_ecmult(&p1j, &pj, &n1, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ecmult(&p2j, &pj, &n2, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ecmult(&ptj, &pj, target, &rustsecp256k1_v0_10_0_scalar_zero); + rustsecp256k1_v0_11_ecmult(&p1j, &pj, &n1, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ecmult(&p2j, &pj, &n2, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ecmult(&ptj, &pj, target, &rustsecp256k1_v0_11_scalar_zero); } else { - rustsecp256k1_v0_10_0_ecmult_const(&p1j, &p, &n1); - rustsecp256k1_v0_10_0_ecmult_const(&p2j, &p, &n2); - rustsecp256k1_v0_10_0_ecmult_const(&ptj, &p, target); + rustsecp256k1_v0_11_ecmult_const(&p1j, &p, &n1); + rustsecp256k1_v0_11_ecmult_const(&p2j, &p, &n2); + rustsecp256k1_v0_11_ecmult_const(&ptj, &p, target); } /* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */ - rustsecp256k1_v0_10_0_gej_add_var(&ptj, &ptj, &p1j, NULL); - rustsecp256k1_v0_10_0_gej_add_var(&ptj, &ptj, &p2j, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&ptj)); + rustsecp256k1_v0_11_gej_add_var(&ptj, &ptj, &p1j, NULL); + rustsecp256k1_v0_11_gej_add_var(&ptj, &ptj, &p2j, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&ptj)); } static void run_ecmult_near_split_bound(void) { @@ -4392,119 +4388,119 @@ static void run_ecmult_near_split_bound(void) { static void run_point_times_order(void) { int i; - rustsecp256k1_v0_10_0_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); - static const rustsecp256k1_v0_10_0_fe xr = SECP256K1_FE_CONST( + rustsecp256k1_v0_11_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); + static const rustsecp256k1_v0_11_fe xr = SECP256K1_FE_CONST( 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 ); for (i = 0; i < 500; i++) { - rustsecp256k1_v0_10_0_ge p; - if (rustsecp256k1_v0_10_0_ge_set_xo_var(&p, &x, 1)) { - rustsecp256k1_v0_10_0_gej j; - CHECK(rustsecp256k1_v0_10_0_ge_is_valid_var(&p)); - rustsecp256k1_v0_10_0_gej_set_ge(&j, &p); + rustsecp256k1_v0_11_ge p; + if (rustsecp256k1_v0_11_ge_set_xo_var(&p, &x, 1)) { + rustsecp256k1_v0_11_gej j; + CHECK(rustsecp256k1_v0_11_ge_is_valid_var(&p)); + rustsecp256k1_v0_11_gej_set_ge(&j, &p); test_point_times_order(&j); } - rustsecp256k1_v0_10_0_fe_sqr(&x, &x); + rustsecp256k1_v0_11_fe_sqr(&x, &x); } - rustsecp256k1_v0_10_0_fe_normalize_var(&x); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&x, &xr)); + rustsecp256k1_v0_11_fe_normalize_var(&x); + CHECK(rustsecp256k1_v0_11_fe_equal(&x, &xr)); } static void ecmult_const_random_mult(void) { /* random starting point A (on the curve) */ - rustsecp256k1_v0_10_0_ge a = SECP256K1_GE_CONST( + rustsecp256k1_v0_11_ge a = SECP256K1_GE_CONST( 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d ); /* random initial factor xn */ - rustsecp256k1_v0_10_0_scalar xn = SECP256K1_SCALAR_CONST( + rustsecp256k1_v0_11_scalar xn = SECP256K1_SCALAR_CONST( 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b ); /* expected xn * A (from sage) */ - rustsecp256k1_v0_10_0_ge expected_b = SECP256K1_GE_CONST( + rustsecp256k1_v0_11_ge expected_b = SECP256K1_GE_CONST( 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 ); - rustsecp256k1_v0_10_0_gej b; - rustsecp256k1_v0_10_0_ecmult_const(&b, &a, &xn); + rustsecp256k1_v0_11_gej b; + rustsecp256k1_v0_11_ecmult_const(&b, &a, &xn); - CHECK(rustsecp256k1_v0_10_0_ge_is_valid_var(&a)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&b, &expected_b)); + CHECK(rustsecp256k1_v0_11_ge_is_valid_var(&a)); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&b, &expected_b)); } static void ecmult_const_commutativity(void) { - rustsecp256k1_v0_10_0_scalar a; - rustsecp256k1_v0_10_0_scalar b; - rustsecp256k1_v0_10_0_gej res1; - rustsecp256k1_v0_10_0_gej res2; - rustsecp256k1_v0_10_0_ge mid1; - rustsecp256k1_v0_10_0_ge mid2; - random_scalar_order_test(&a); - random_scalar_order_test(&b); - - rustsecp256k1_v0_10_0_ecmult_const(&res1, &rustsecp256k1_v0_10_0_ge_const_g, &a); - rustsecp256k1_v0_10_0_ecmult_const(&res2, &rustsecp256k1_v0_10_0_ge_const_g, &b); - rustsecp256k1_v0_10_0_ge_set_gej(&mid1, &res1); - rustsecp256k1_v0_10_0_ge_set_gej(&mid2, &res2); - rustsecp256k1_v0_10_0_ecmult_const(&res1, &mid1, &b); - rustsecp256k1_v0_10_0_ecmult_const(&res2, &mid2, &a); - rustsecp256k1_v0_10_0_ge_set_gej(&mid1, &res1); - rustsecp256k1_v0_10_0_ge_set_gej(&mid2, &res2); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&mid1, &mid2)); + rustsecp256k1_v0_11_scalar a; + rustsecp256k1_v0_11_scalar b; + rustsecp256k1_v0_11_gej res1; + rustsecp256k1_v0_11_gej res2; + rustsecp256k1_v0_11_ge mid1; + rustsecp256k1_v0_11_ge mid2; + testutil_random_scalar_order_test(&a); + testutil_random_scalar_order_test(&b); + + rustsecp256k1_v0_11_ecmult_const(&res1, &rustsecp256k1_v0_11_ge_const_g, &a); + rustsecp256k1_v0_11_ecmult_const(&res2, &rustsecp256k1_v0_11_ge_const_g, &b); + rustsecp256k1_v0_11_ge_set_gej(&mid1, &res1); + rustsecp256k1_v0_11_ge_set_gej(&mid2, &res2); + rustsecp256k1_v0_11_ecmult_const(&res1, &mid1, &b); + rustsecp256k1_v0_11_ecmult_const(&res2, &mid2, &a); + rustsecp256k1_v0_11_ge_set_gej(&mid1, &res1); + rustsecp256k1_v0_11_ge_set_gej(&mid2, &res2); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&mid1, &mid2)); } static void ecmult_const_mult_zero_one(void) { - rustsecp256k1_v0_10_0_scalar s; - rustsecp256k1_v0_10_0_scalar negone; - rustsecp256k1_v0_10_0_gej res1; - rustsecp256k1_v0_10_0_ge res2; - rustsecp256k1_v0_10_0_ge point; - rustsecp256k1_v0_10_0_ge inf; - - random_scalar_order_test(&s); - rustsecp256k1_v0_10_0_scalar_negate(&negone, &rustsecp256k1_v0_10_0_scalar_one); - random_group_element_test(&point); - rustsecp256k1_v0_10_0_ge_set_infinity(&inf); + rustsecp256k1_v0_11_scalar s; + rustsecp256k1_v0_11_scalar negone; + rustsecp256k1_v0_11_gej res1; + rustsecp256k1_v0_11_ge res2; + rustsecp256k1_v0_11_ge point; + rustsecp256k1_v0_11_ge inf; + + testutil_random_scalar_order_test(&s); + rustsecp256k1_v0_11_scalar_negate(&negone, &rustsecp256k1_v0_11_scalar_one); + testutil_random_ge_test(&point); + rustsecp256k1_v0_11_ge_set_infinity(&inf); /* 0*point */ - rustsecp256k1_v0_10_0_ecmult_const(&res1, &point, &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&res1)); + rustsecp256k1_v0_11_ecmult_const(&res1, &point, &rustsecp256k1_v0_11_scalar_zero); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&res1)); /* s*inf */ - rustsecp256k1_v0_10_0_ecmult_const(&res1, &inf, &s); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&res1)); + rustsecp256k1_v0_11_ecmult_const(&res1, &inf, &s); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&res1)); /* 1*point */ - rustsecp256k1_v0_10_0_ecmult_const(&res1, &point, &rustsecp256k1_v0_10_0_scalar_one); - rustsecp256k1_v0_10_0_ge_set_gej(&res2, &res1); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&res2, &point)); + rustsecp256k1_v0_11_ecmult_const(&res1, &point, &rustsecp256k1_v0_11_scalar_one); + rustsecp256k1_v0_11_ge_set_gej(&res2, &res1); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&res2, &point)); /* -1*point */ - rustsecp256k1_v0_10_0_ecmult_const(&res1, &point, &negone); - rustsecp256k1_v0_10_0_gej_neg(&res1, &res1); - rustsecp256k1_v0_10_0_ge_set_gej(&res2, &res1); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&res2, &point)); + rustsecp256k1_v0_11_ecmult_const(&res1, &point, &negone); + rustsecp256k1_v0_11_gej_neg(&res1, &res1); + rustsecp256k1_v0_11_ge_set_gej(&res2, &res1); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&res2, &point)); } -static void ecmult_const_check_result(const rustsecp256k1_v0_10_0_ge *A, const rustsecp256k1_v0_10_0_scalar* q, const rustsecp256k1_v0_10_0_gej *res) { - rustsecp256k1_v0_10_0_gej pointj, res2j; - rustsecp256k1_v0_10_0_ge res2; - rustsecp256k1_v0_10_0_gej_set_ge(&pointj, A); - rustsecp256k1_v0_10_0_ecmult(&res2j, &pointj, q, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ge_set_gej(&res2, &res2j); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(res, &res2)); +static void ecmult_const_check_result(const rustsecp256k1_v0_11_ge *A, const rustsecp256k1_v0_11_scalar* q, const rustsecp256k1_v0_11_gej *res) { + rustsecp256k1_v0_11_gej pointj, res2j; + rustsecp256k1_v0_11_ge res2; + rustsecp256k1_v0_11_gej_set_ge(&pointj, A); + rustsecp256k1_v0_11_ecmult(&res2j, &pointj, q, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ge_set_gej(&res2, &res2j); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(res, &res2)); } static void ecmult_const_edges(void) { - rustsecp256k1_v0_10_0_scalar q; - rustsecp256k1_v0_10_0_ge point; - rustsecp256k1_v0_10_0_gej res; + rustsecp256k1_v0_11_scalar q; + rustsecp256k1_v0_11_ge point; + rustsecp256k1_v0_11_gej res; size_t i; size_t cases = 1 + sizeof(scalars_near_split_bounds) / sizeof(scalars_near_split_bounds[0]); @@ -4517,13 +4513,13 @@ static void ecmult_const_edges(void) { * <=> q = 2*scalars_near_split_bounds[i] - K */ for (i = 0; i < cases; ++i) { - rustsecp256k1_v0_10_0_scalar_negate(&q, &rustsecp256k1_v0_10_0_ecmult_const_K); + rustsecp256k1_v0_11_scalar_negate(&q, &rustsecp256k1_v0_11_ecmult_const_K); if (i > 0) { - rustsecp256k1_v0_10_0_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); - rustsecp256k1_v0_10_0_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); + rustsecp256k1_v0_11_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); + rustsecp256k1_v0_11_scalar_add(&q, &q, &scalars_near_split_bounds[i - 1]); } - random_group_element_test(&point); - rustsecp256k1_v0_10_0_ecmult_const(&res, &point, &q); + testutil_random_ge_test(&point); + rustsecp256k1_v0_11_ecmult_const(&res, &point, &q); ecmult_const_check_result(&point, &q, &res); } } @@ -4531,82 +4527,82 @@ static void ecmult_const_edges(void) { static void ecmult_const_mult_xonly(void) { int i; - /* Test correspondence between rustsecp256k1_v0_10_0_ecmult_const and rustsecp256k1_v0_10_0_ecmult_const_xonly. */ + /* Test correspondence between rustsecp256k1_v0_11_ecmult_const and rustsecp256k1_v0_11_ecmult_const_xonly. */ for (i = 0; i < 2*COUNT; ++i) { - rustsecp256k1_v0_10_0_ge base; - rustsecp256k1_v0_10_0_gej basej, resj; - rustsecp256k1_v0_10_0_fe n, d, resx, v; - rustsecp256k1_v0_10_0_scalar q; + rustsecp256k1_v0_11_ge base; + rustsecp256k1_v0_11_gej basej, resj; + rustsecp256k1_v0_11_fe n, d, resx, v; + rustsecp256k1_v0_11_scalar q; int res; /* Random base point. */ - random_group_element_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); - rustsecp256k1_v0_10_0_fe_mul(&n, &base.x, &d); + testutil_random_fe_non_zero_test(&d); + rustsecp256k1_v0_11_fe_mul(&n, &base.x, &d); } else { n = base.x; } /* Perform x-only multiplication. */ - res = rustsecp256k1_v0_10_0_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, i & 2); + res = rustsecp256k1_v0_11_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, i & 2); CHECK(res); /* Perform normal multiplication. */ - rustsecp256k1_v0_10_0_gej_set_ge(&basej, &base); - rustsecp256k1_v0_10_0_ecmult(&resj, &basej, &q, NULL); + rustsecp256k1_v0_11_gej_set_ge(&basej, &base); + rustsecp256k1_v0_11_ecmult(&resj, &basej, &q, NULL); /* Check that resj's X coordinate corresponds with resx. */ - rustsecp256k1_v0_10_0_fe_sqr(&v, &resj.z); - rustsecp256k1_v0_10_0_fe_mul(&v, &v, &resx); - CHECK(check_fe_equal(&v, &resj.x)); + rustsecp256k1_v0_11_fe_sqr(&v, &resj.z); + rustsecp256k1_v0_11_fe_mul(&v, &v, &resx); + CHECK(fe_equal(&v, &resj.x)); } - /* Test that rustsecp256k1_v0_10_0_ecmult_const_xonly correctly rejects X coordinates not on curve. */ + /* Test that rustsecp256k1_v0_11_ecmult_const_xonly correctly rejects X coordinates not on curve. */ for (i = 0; i < 2*COUNT; ++i) { - rustsecp256k1_v0_10_0_fe x, n, d, r; + rustsecp256k1_v0_11_fe x, n, d, r; int res; - rustsecp256k1_v0_10_0_scalar q; - random_scalar_order_test(&q); + rustsecp256k1_v0_11_scalar q; + testutil_random_scalar_order_test(&q); /* Generate random X coordinate not on the curve. */ do { - random_fe_test(&x); - } while (rustsecp256k1_v0_10_0_ge_x_on_curve_var(&x)); + testutil_random_fe_test(&x); + } while (rustsecp256k1_v0_11_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); - rustsecp256k1_v0_10_0_fe_mul(&n, &x, &d); + testutil_random_fe_non_zero_test(&d); + rustsecp256k1_v0_11_fe_mul(&n, &x, &d); } else { n = x; } - res = rustsecp256k1_v0_10_0_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 0); + res = rustsecp256k1_v0_11_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 0); CHECK(res == 0); } } static void ecmult_const_chain_multiply(void) { /* Check known result (randomly generated test problem from sage) */ - const rustsecp256k1_v0_10_0_scalar scalar = SECP256K1_SCALAR_CONST( + const rustsecp256k1_v0_11_scalar scalar = SECP256K1_SCALAR_CONST( 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b ); - const rustsecp256k1_v0_10_0_gej expected_point = SECP256K1_GEJ_CONST( + const rustsecp256k1_v0_11_gej expected_point = SECP256K1_GEJ_CONST( 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 ); - rustsecp256k1_v0_10_0_gej point; - rustsecp256k1_v0_10_0_ge res; + rustsecp256k1_v0_11_gej point; + rustsecp256k1_v0_11_ge res; int i; - rustsecp256k1_v0_10_0_gej_set_ge(&point, &rustsecp256k1_v0_10_0_ge_const_g); + rustsecp256k1_v0_11_gej_set_ge(&point, &rustsecp256k1_v0_11_ge_const_g); for (i = 0; i < 100; ++i) { - rustsecp256k1_v0_10_0_ge tmp; - rustsecp256k1_v0_10_0_ge_set_gej(&tmp, &point); - rustsecp256k1_v0_10_0_ecmult_const(&point, &tmp, &scalar); + rustsecp256k1_v0_11_ge tmp; + rustsecp256k1_v0_11_ge_set_gej(&tmp, &point); + rustsecp256k1_v0_11_ecmult_const(&point, &tmp, &scalar); } - rustsecp256k1_v0_10_0_ge_set_gej(&res, &point); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&expected_point, &res)); + rustsecp256k1_v0_11_ge_set_gej(&res, &point); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&expected_point, &res)); } static void run_ecmult_const_tests(void) { @@ -4619,18 +4615,18 @@ static void run_ecmult_const_tests(void) { } typedef struct { - rustsecp256k1_v0_10_0_scalar *sc; - rustsecp256k1_v0_10_0_ge *pt; + rustsecp256k1_v0_11_scalar *sc; + rustsecp256k1_v0_11_ge *pt; } ecmult_multi_data; -static int ecmult_multi_callback(rustsecp256k1_v0_10_0_scalar *sc, rustsecp256k1_v0_10_0_ge *pt, size_t idx, void *cbdata) { +static int ecmult_multi_callback(rustsecp256k1_v0_11_scalar *sc, rustsecp256k1_v0_11_ge *pt, size_t idx, void *cbdata) { ecmult_multi_data *data = (ecmult_multi_data*) cbdata; *sc = data->sc[idx]; *pt = data->pt[idx]; return 1; } -static int ecmult_multi_false_callback(rustsecp256k1_v0_10_0_scalar *sc, rustsecp256k1_v0_10_0_ge *pt, size_t idx, void *cbdata) { +static int ecmult_multi_false_callback(rustsecp256k1_v0_11_scalar *sc, rustsecp256k1_v0_11_ge *pt, size_t idx, void *cbdata) { (void)sc; (void)pt; (void)idx; @@ -4638,12 +4634,12 @@ static int ecmult_multi_false_callback(rustsecp256k1_v0_10_0_scalar *sc, rustsec return 0; } -static void test_ecmult_multi(rustsecp256k1_v0_10_0_scratch *scratch, rustsecp256k1_v0_10_0_ecmult_multi_func ecmult_multi) { +static void test_ecmult_multi(rustsecp256k1_v0_11_scratch *scratch, rustsecp256k1_v0_11_ecmult_multi_func ecmult_multi) { int ncount; - rustsecp256k1_v0_10_0_scalar sc[32]; - rustsecp256k1_v0_10_0_ge pt[32]; - rustsecp256k1_v0_10_0_gej r; - rustsecp256k1_v0_10_0_gej r2; + rustsecp256k1_v0_11_scalar sc[32]; + rustsecp256k1_v0_11_ge pt[32]; + rustsecp256k1_v0_11_gej r; + rustsecp256k1_v0_11_gej r2; ecmult_multi_data data; data.sc = sc; @@ -4654,206 +4650,206 @@ static void test_ecmult_multi(rustsecp256k1_v0_10_0_scratch *scratch, rustsecp25 /* Check 1- and 2-point multiplies against ecmult */ for (ncount = 0; ncount < COUNT; ncount++) { - rustsecp256k1_v0_10_0_ge ptg; - rustsecp256k1_v0_10_0_gej ptgj; - random_scalar_order(&sc[0]); - random_scalar_order(&sc[1]); + rustsecp256k1_v0_11_ge ptg; + rustsecp256k1_v0_11_gej ptgj; + testutil_random_scalar_order(&sc[0]); + testutil_random_scalar_order(&sc[1]); - random_group_element_test(&ptg); - rustsecp256k1_v0_10_0_gej_set_ge(&ptgj, &ptg); + testutil_random_ge_test(&ptg); + rustsecp256k1_v0_11_gej_set_ge(&ptgj, &ptg); pt[0] = ptg; - pt[1] = rustsecp256k1_v0_10_0_ge_const_g; + pt[1] = rustsecp256k1_v0_11_ge_const_g; /* only G scalar */ - rustsecp256k1_v0_10_0_ecmult(&r2, &ptgj, &rustsecp256k1_v0_10_0_scalar_zero, &sc[0]); + rustsecp256k1_v0_11_ecmult(&r2, &ptgj, &rustsecp256k1_v0_11_scalar_zero, &sc[0]); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &sc[0], ecmult_multi_callback, &data, 0)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&r, &r2)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&r, &r2)); /* 1-point */ - rustsecp256k1_v0_10_0_ecmult(&r2, &ptgj, &sc[0], &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 1)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&r, &r2)); + rustsecp256k1_v0_11_ecmult(&r2, &ptgj, &sc[0], &rustsecp256k1_v0_11_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 1)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&r, &r2)); /* Try to multiply 1 point, but callback returns false */ - CHECK(!ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_false_callback, &data, 1)); + CHECK(!ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_false_callback, &data, 1)); /* 2-point */ - rustsecp256k1_v0_10_0_ecmult(&r2, &ptgj, &sc[0], &sc[1]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 2)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&r, &r2)); + rustsecp256k1_v0_11_ecmult(&r2, &ptgj, &sc[0], &sc[1]); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 2)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&r, &r2)); /* 2-point with G scalar */ - rustsecp256k1_v0_10_0_ecmult(&r2, &ptgj, &sc[0], &sc[1]); + rustsecp256k1_v0_11_ecmult(&r2, &ptgj, &sc[0], &sc[1]); CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &sc[1], ecmult_multi_callback, &data, 1)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&r, &r2)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&r, &r2)); } /* Check infinite outputs of various forms */ for (ncount = 0; ncount < COUNT; ncount++) { - rustsecp256k1_v0_10_0_ge ptg; + rustsecp256k1_v0_11_ge ptg; size_t i, j; size_t sizes[] = { 2, 10, 32 }; for (j = 0; j < 3; j++) { for (i = 0; i < 32; i++) { - random_scalar_order(&sc[i]); - rustsecp256k1_v0_10_0_ge_set_infinity(&pt[i]); + testutil_random_scalar_order(&sc[i]); + rustsecp256k1_v0_11_ge_set_infinity(&pt[i]); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, sizes[j])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); } for (j = 0; j < 3; j++) { for (i = 0; i < 32; i++) { - random_group_element_test(&ptg); + testutil_random_ge_test(&ptg); pt[i] = ptg; - rustsecp256k1_v0_10_0_scalar_set_int(&sc[i], 0); + rustsecp256k1_v0_11_scalar_set_int(&sc[i], 0); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, sizes[j])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); } for (j = 0; j < 3; j++) { - random_group_element_test(&ptg); + testutil_random_ge_test(&ptg); for (i = 0; i < 16; i++) { - random_scalar_order(&sc[2*i]); - rustsecp256k1_v0_10_0_scalar_negate(&sc[2*i + 1], &sc[2*i]); + testutil_random_scalar_order(&sc[2*i]); + rustsecp256k1_v0_11_scalar_negate(&sc[2*i + 1], &sc[2*i]); pt[2 * i] = ptg; pt[2 * i + 1] = ptg; } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, sizes[j])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); - random_scalar_order(&sc[0]); + testutil_random_scalar_order(&sc[0]); for (i = 0; i < 16; i++) { - random_group_element_test(&ptg); + testutil_random_ge_test(&ptg); sc[2*i] = sc[0]; sc[2*i+1] = sc[0]; pt[2 * i] = ptg; - rustsecp256k1_v0_10_0_ge_neg(&pt[2*i+1], &pt[2*i]); + rustsecp256k1_v0_11_ge_neg(&pt[2*i+1], &pt[2*i]); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, sizes[j])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, sizes[j])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); } - random_group_element_test(&ptg); - rustsecp256k1_v0_10_0_scalar_set_int(&sc[0], 0); + testutil_random_ge_test(&ptg); + rustsecp256k1_v0_11_scalar_set_int(&sc[0], 0); pt[0] = ptg; for (i = 1; i < 32; i++) { pt[i] = ptg; - random_scalar_order(&sc[i]); - rustsecp256k1_v0_10_0_scalar_add(&sc[0], &sc[0], &sc[i]); - rustsecp256k1_v0_10_0_scalar_negate(&sc[i], &sc[i]); + testutil_random_scalar_order(&sc[i]); + rustsecp256k1_v0_11_scalar_add(&sc[0], &sc[0], &sc[i]); + rustsecp256k1_v0_11_scalar_negate(&sc[i], &sc[i]); } - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 32)); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 32)); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); } /* Check random points, constant scalar */ for (ncount = 0; ncount < COUNT; ncount++) { size_t i; - rustsecp256k1_v0_10_0_gej_set_infinity(&r); + rustsecp256k1_v0_11_gej_set_infinity(&r); - random_scalar_order(&sc[0]); + testutil_random_scalar_order(&sc[0]); for (i = 0; i < 20; i++) { - rustsecp256k1_v0_10_0_ge ptg; + rustsecp256k1_v0_11_ge ptg; sc[i] = sc[0]; - random_group_element_test(&ptg); + testutil_random_ge_test(&ptg); pt[i] = ptg; - rustsecp256k1_v0_10_0_gej_add_ge_var(&r, &r, &pt[i], NULL); + rustsecp256k1_v0_11_gej_add_ge_var(&r, &r, &pt[i], NULL); } - rustsecp256k1_v0_10_0_ecmult(&r2, &r, &sc[0], &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 20)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&r, &r2)); + rustsecp256k1_v0_11_ecmult(&r2, &r, &sc[0], &rustsecp256k1_v0_11_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 20)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&r, &r2)); } /* Check random scalars, constant point */ for (ncount = 0; ncount < COUNT; ncount++) { size_t i; - rustsecp256k1_v0_10_0_ge ptg; - rustsecp256k1_v0_10_0_gej p0j; - rustsecp256k1_v0_10_0_scalar rs; - rustsecp256k1_v0_10_0_scalar_set_int(&rs, 0); + rustsecp256k1_v0_11_ge ptg; + rustsecp256k1_v0_11_gej p0j; + rustsecp256k1_v0_11_scalar rs; + rustsecp256k1_v0_11_scalar_set_int(&rs, 0); - random_group_element_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; - rustsecp256k1_v0_10_0_scalar_add(&rs, &rs, &sc[i]); + rustsecp256k1_v0_11_scalar_add(&rs, &rs, &sc[i]); } - rustsecp256k1_v0_10_0_gej_set_ge(&p0j, &pt[0]); - rustsecp256k1_v0_10_0_ecmult(&r2, &p0j, &rs, &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 20)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&r, &r2)); + rustsecp256k1_v0_11_gej_set_ge(&p0j, &pt[0]); + rustsecp256k1_v0_11_ecmult(&r2, &p0j, &rs, &rustsecp256k1_v0_11_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 20)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&r, &r2)); } /* 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]); + testutil_random_scalar_order(&sc[ncount]); + testutil_random_ge_test(&pt[ncount]); } - rustsecp256k1_v0_10_0_scalar_clear(&sc[0]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 20)); - rustsecp256k1_v0_10_0_scalar_clear(&sc[1]); - rustsecp256k1_v0_10_0_scalar_clear(&sc[2]); - rustsecp256k1_v0_10_0_scalar_clear(&sc[3]); - rustsecp256k1_v0_10_0_scalar_clear(&sc[4]); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 6)); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 5)); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); + rustsecp256k1_v0_11_scalar_set_int(&sc[0], 0); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 20)); + rustsecp256k1_v0_11_scalar_set_int(&sc[1], 0); + rustsecp256k1_v0_11_scalar_set_int(&sc[2], 0); + rustsecp256k1_v0_11_scalar_set_int(&sc[3], 0); + rustsecp256k1_v0_11_scalar_set_int(&sc[4], 0); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 6)); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 5)); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); /* Run through s0*(t0*P) + s1*(t1*P) exhaustively for many small values of s0, s1, t0, t1 */ { const size_t TOP = 8; size_t s0i, s1i; size_t t0i, t1i; - rustsecp256k1_v0_10_0_ge ptg; - rustsecp256k1_v0_10_0_gej ptgj; + rustsecp256k1_v0_11_ge ptg; + rustsecp256k1_v0_11_gej ptgj; - random_group_element_test(&ptg); - rustsecp256k1_v0_10_0_gej_set_ge(&ptgj, &ptg); + testutil_random_ge_test(&ptg); + rustsecp256k1_v0_11_gej_set_ge(&ptgj, &ptg); for(t0i = 0; t0i < TOP; t0i++) { for(t1i = 0; t1i < TOP; t1i++) { - rustsecp256k1_v0_10_0_gej t0p, t1p; - rustsecp256k1_v0_10_0_scalar t0, t1; + rustsecp256k1_v0_11_gej t0p, t1p; + rustsecp256k1_v0_11_scalar t0, t1; - rustsecp256k1_v0_10_0_scalar_set_int(&t0, (t0i + 1) / 2); - rustsecp256k1_v0_10_0_scalar_cond_negate(&t0, t0i & 1); - rustsecp256k1_v0_10_0_scalar_set_int(&t1, (t1i + 1) / 2); - rustsecp256k1_v0_10_0_scalar_cond_negate(&t1, t1i & 1); + rustsecp256k1_v0_11_scalar_set_int(&t0, (t0i + 1) / 2); + rustsecp256k1_v0_11_scalar_cond_negate(&t0, t0i & 1); + rustsecp256k1_v0_11_scalar_set_int(&t1, (t1i + 1) / 2); + rustsecp256k1_v0_11_scalar_cond_negate(&t1, t1i & 1); - rustsecp256k1_v0_10_0_ecmult(&t0p, &ptgj, &t0, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ecmult(&t1p, &ptgj, &t1, &rustsecp256k1_v0_10_0_scalar_zero); + rustsecp256k1_v0_11_ecmult(&t0p, &ptgj, &t0, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ecmult(&t1p, &ptgj, &t1, &rustsecp256k1_v0_11_scalar_zero); for(s0i = 0; s0i < TOP; s0i++) { for(s1i = 0; s1i < TOP; s1i++) { - rustsecp256k1_v0_10_0_scalar tmp1, tmp2; - rustsecp256k1_v0_10_0_gej expected, actual; + rustsecp256k1_v0_11_scalar tmp1, tmp2; + rustsecp256k1_v0_11_gej expected, actual; - rustsecp256k1_v0_10_0_ge_set_gej(&pt[0], &t0p); - rustsecp256k1_v0_10_0_ge_set_gej(&pt[1], &t1p); + rustsecp256k1_v0_11_ge_set_gej(&pt[0], &t0p); + rustsecp256k1_v0_11_ge_set_gej(&pt[1], &t1p); - rustsecp256k1_v0_10_0_scalar_set_int(&sc[0], (s0i + 1) / 2); - rustsecp256k1_v0_10_0_scalar_cond_negate(&sc[0], s0i & 1); - rustsecp256k1_v0_10_0_scalar_set_int(&sc[1], (s1i + 1) / 2); - rustsecp256k1_v0_10_0_scalar_cond_negate(&sc[1], s1i & 1); + rustsecp256k1_v0_11_scalar_set_int(&sc[0], (s0i + 1) / 2); + rustsecp256k1_v0_11_scalar_cond_negate(&sc[0], s0i & 1); + rustsecp256k1_v0_11_scalar_set_int(&sc[1], (s1i + 1) / 2); + rustsecp256k1_v0_11_scalar_cond_negate(&sc[1], s1i & 1); - rustsecp256k1_v0_10_0_scalar_mul(&tmp1, &t0, &sc[0]); - rustsecp256k1_v0_10_0_scalar_mul(&tmp2, &t1, &sc[1]); - rustsecp256k1_v0_10_0_scalar_add(&tmp1, &tmp1, &tmp2); + rustsecp256k1_v0_11_scalar_mul(&tmp1, &t0, &sc[0]); + rustsecp256k1_v0_11_scalar_mul(&tmp2, &t1, &sc[1]); + rustsecp256k1_v0_11_scalar_add(&tmp1, &tmp1, &tmp2); - rustsecp256k1_v0_10_0_ecmult(&expected, &ptgj, &tmp1, &rustsecp256k1_v0_10_0_scalar_zero); - CHECK(ecmult_multi(&CTX->error_callback, scratch, &actual, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 2)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&actual, &expected)); + rustsecp256k1_v0_11_ecmult(&expected, &ptgj, &tmp1, &rustsecp256k1_v0_11_scalar_zero); + CHECK(ecmult_multi(&CTX->error_callback, scratch, &actual, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 2)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&actual, &expected)); } } } @@ -4861,7 +4857,7 @@ static void test_ecmult_multi(rustsecp256k1_v0_10_0_scratch *scratch, rustsecp25 } } -static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_scratch *scratch) { +static int test_ecmult_multi_random(rustsecp256k1_v0_11_scratch *scratch) { /* Large random test for ecmult_multi_* functions which exercises: * - Few or many inputs (0 up to 128, roughly exponentially distributed). * - Few or many 0*P or a*INF inputs (roughly uniformly distributed). @@ -4875,60 +4871,60 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_scratch *scratch) { * scalars[0..filled-1] and gejs[0..filled-1] are the scalars and points * which form its normal inputs. */ int filled = 0; - rustsecp256k1_v0_10_0_scalar g_scalar = rustsecp256k1_v0_10_0_scalar_zero; - rustsecp256k1_v0_10_0_scalar scalars[128]; - rustsecp256k1_v0_10_0_gej gejs[128]; + rustsecp256k1_v0_11_scalar g_scalar = rustsecp256k1_v0_11_scalar_zero; + rustsecp256k1_v0_11_scalar scalars[128]; + rustsecp256k1_v0_11_gej gejs[128]; /* The expected result, and the computed result. */ - rustsecp256k1_v0_10_0_gej expected, computed; + rustsecp256k1_v0_11_gej expected, computed; /* Temporaries. */ - rustsecp256k1_v0_10_0_scalar sc_tmp; - rustsecp256k1_v0_10_0_ge ge_tmp; + rustsecp256k1_v0_11_scalar sc_tmp; + rustsecp256k1_v0_11_ge ge_tmp; /* Variables needed for the actual input to ecmult_multi. */ - rustsecp256k1_v0_10_0_ge ges[128]; + rustsecp256k1_v0_11_ge ges[128]; ecmult_multi_data data; int i; /* Which multiplication function to use */ - int fn = rustsecp256k1_v0_10_0_testrand_int(3); - rustsecp256k1_v0_10_0_ecmult_multi_func ecmult_multi = fn == 0 ? rustsecp256k1_v0_10_0_ecmult_multi_var : - fn == 1 ? rustsecp256k1_v0_10_0_ecmult_strauss_batch_single : - rustsecp256k1_v0_10_0_ecmult_pippenger_batch_single; + int fn = testrand_int(3); + rustsecp256k1_v0_11_ecmult_multi_func ecmult_multi = fn == 0 ? rustsecp256k1_v0_11_ecmult_multi_var : + fn == 1 ? rustsecp256k1_v0_11_ecmult_strauss_batch_single : + rustsecp256k1_v0_11_ecmult_pippenger_batch_single; /* Simulate exponentially distributed num. */ - int num_bits = 2 + rustsecp256k1_v0_10_0_testrand_int(6); + int num_bits = 2 + testrand_int(6); /* Number of (scalar, point) inputs (excluding g). */ - int num = rustsecp256k1_v0_10_0_testrand_int((1 << num_bits) + 1); + int num = testrand_int((1 << num_bits) + 1); /* Number of those which are nonzero. */ - int num_nonzero = rustsecp256k1_v0_10_0_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 = rustsecp256k1_v0_10_0_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)rustsecp256k1_v0_10_0_testrand_bits(1); + (int)testrand_bits(1); /* Which g_scalar pointer to pass into ecmult_multi(). */ - const rustsecp256k1_v0_10_0_scalar* g_scalar_ptr = (g_nonzero || rustsecp256k1_v0_10_0_testrand_bits(1)) ? &g_scalar : NULL; + const rustsecp256k1_v0_11_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)rustsecp256k1_v0_10_0_testrand_bits(3); + int rands = (int)testrand_bits(3); if (rands > num_nonzero) rands = num_nonzero; - rustsecp256k1_v0_10_0_gej_set_infinity(&expected); - rustsecp256k1_v0_10_0_gej_set_infinity(&gejs[0]); - rustsecp256k1_v0_10_0_scalar_set_int(&scalars[0], 0); + rustsecp256k1_v0_11_gej_set_infinity(&expected); + rustsecp256k1_v0_11_gej_set_infinity(&gejs[0]); + rustsecp256k1_v0_11_scalar_set_int(&scalars[0], 0); 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); - rustsecp256k1_v0_10_0_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar); - rustsecp256k1_v0_10_0_scalar_inverse_var(&sc_tmp, &sc_tmp); - rustsecp256k1_v0_10_0_scalar_negate(&sc_tmp, &sc_tmp); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp); + testutil_random_scalar_order_test(&sc_tmp); + rustsecp256k1_v0_11_scalar_mul(&scalars[filled], &sc_tmp, &g_scalar); + rustsecp256k1_v0_11_scalar_inverse_var(&sc_tmp, &sc_tmp); + rustsecp256k1_v0_11_scalar_negate(&sc_tmp, &sc_tmp); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &gejs[filled], &sc_tmp); ++filled; ++mults; } @@ -4936,16 +4932,16 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_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); - rustsecp256k1_v0_10_0_gej_set_ge(&gejs[filled], &ge_tmp); + testutil_random_scalar_order_test(&scalars[filled]); + testutil_random_ge_test(&ge_tmp); + rustsecp256k1_v0_11_gej_set_ge(&gejs[filled], &ge_tmp); ++filled; } if (nonzero_result) { /* Compute the expected result using normal ecmult. */ CHECK(filled <= 1); - rustsecp256k1_v0_10_0_ecmult(&expected, &gejs[0], &scalars[0], &g_scalar); + rustsecp256k1_v0_11_ecmult(&expected, &gejs[0], &scalars[0], &g_scalar); mults += filled + g_nonzero; } @@ -4956,13 +4952,13 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_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 (rustsecp256k1_v0_10_0_testrand_bits(1)) { - rustsecp256k1_v0_10_0_gej_set_infinity(&gejs[filled]); - random_scalar_order_test(&scalars[filled]); + if (testrand_bits(1)) { + rustsecp256k1_v0_11_gej_set_infinity(&gejs[filled]); + testutil_random_scalar_order_test(&scalars[filled]); } else { - rustsecp256k1_v0_10_0_scalar_set_int(&scalars[filled], 0); - random_group_element_test(&ge_tmp); - rustsecp256k1_v0_10_0_gej_set_ge(&gejs[filled], &ge_tmp); + rustsecp256k1_v0_11_scalar_set_int(&scalars[filled], 0); + testutil_random_ge_test(&ge_tmp); + rustsecp256k1_v0_11_gej_set_ge(&gejs[filled], &ge_tmp); } ++filled; } @@ -4972,13 +4968,13 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_scratch *scratch) { * convert some of them to be both non-0-scalar and non-infinity-point. */ for (i = 0; i < rands; ++i) { int j; - rustsecp256k1_v0_10_0_scalar v, iv; + rustsecp256k1_v0_11_scalar v, iv; /* Shuffle the entries. */ for (j = 0; j < num_nonzero; ++j) { - int k = rustsecp256k1_v0_10_0_testrand_int(num_nonzero - j); + int k = testrand_int(num_nonzero - j); if (k != 0) { - rustsecp256k1_v0_10_0_gej gej = gejs[j]; - rustsecp256k1_v0_10_0_scalar sc = scalars[j]; + rustsecp256k1_v0_11_gej gej = gejs[j]; + rustsecp256k1_v0_11_scalar sc = scalars[j]; gejs[j] = gejs[j + k]; scalars[j] = scalars[j + k]; gejs[j + k] = gej; @@ -4988,26 +4984,26 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_scratch *scratch) { /* Perturb all consecutive pairs of inputs: * a*P + b*Q -> (a+b)*P + b*(Q-P). */ for (j = 0; j + 1 < num_nonzero; j += 2) { - rustsecp256k1_v0_10_0_gej gej; - rustsecp256k1_v0_10_0_scalar_add(&scalars[j], &scalars[j], &scalars[j+1]); - rustsecp256k1_v0_10_0_gej_neg(&gej, &gejs[j]); - rustsecp256k1_v0_10_0_gej_add_var(&gejs[j+1], &gejs[j+1], &gej, NULL); + rustsecp256k1_v0_11_gej gej; + rustsecp256k1_v0_11_scalar_add(&scalars[j], &scalars[j], &scalars[j+1]); + rustsecp256k1_v0_11_gej_neg(&gej, &gejs[j]); + rustsecp256k1_v0_11_gej_add_var(&gejs[j+1], &gejs[j+1], &gej, NULL); } /* Transform the last input: a*P -> (v*a) * ((1/v)*P). */ CHECK(num_nonzero >= 1); - random_scalar_order_test(&v); - rustsecp256k1_v0_10_0_scalar_inverse(&iv, &v); - rustsecp256k1_v0_10_0_scalar_mul(&scalars[num_nonzero - 1], &scalars[num_nonzero - 1], &v); - rustsecp256k1_v0_10_0_ecmult(&gejs[num_nonzero - 1], &gejs[num_nonzero - 1], &iv, NULL); + testutil_random_scalar_order_test(&v); + rustsecp256k1_v0_11_scalar_inverse(&iv, &v); + rustsecp256k1_v0_11_scalar_mul(&scalars[num_nonzero - 1], &scalars[num_nonzero - 1], &v); + rustsecp256k1_v0_11_ecmult(&gejs[num_nonzero - 1], &gejs[num_nonzero - 1], &iv, NULL); ++mults; } /* Shuffle all entries (0..num-1). */ for (i = 0; i < num; ++i) { - int j = rustsecp256k1_v0_10_0_testrand_int(num - i); + int j = testrand_int(num - i); if (j != 0) { - rustsecp256k1_v0_10_0_gej gej = gejs[i]; - rustsecp256k1_v0_10_0_scalar sc = scalars[i]; + rustsecp256k1_v0_11_gej gej = gejs[i]; + rustsecp256k1_v0_11_scalar sc = scalars[i]; gejs[i] = gejs[i + j]; scalars[i] = scalars[i + j]; gejs[i + j] = gej; @@ -5016,47 +5012,47 @@ static int test_ecmult_multi_random(rustsecp256k1_v0_10_0_scratch *scratch) { } /* Compute affine versions of all inputs. */ - rustsecp256k1_v0_10_0_ge_set_all_gej_var(ges, gejs, filled); + rustsecp256k1_v0_11_ge_set_all_gej_var(ges, gejs, filled); /* Invoke ecmult_multi code. */ data.sc = scalars; data.pt = ges; CHECK(ecmult_multi(&CTX->error_callback, scratch, &computed, g_scalar_ptr, ecmult_multi_callback, &data, filled)); mults += num_nonzero + g_nonzero; /* Compare with expected result. */ - CHECK(rustsecp256k1_v0_10_0_gej_eq_var(&computed, &expected)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&computed, &expected)); return mults; } -static void test_ecmult_multi_batch_single(rustsecp256k1_v0_10_0_ecmult_multi_func ecmult_multi) { - rustsecp256k1_v0_10_0_scalar sc; - rustsecp256k1_v0_10_0_ge pt; - rustsecp256k1_v0_10_0_gej r; +static void test_ecmult_multi_batch_single(rustsecp256k1_v0_11_ecmult_multi_func ecmult_multi) { + rustsecp256k1_v0_11_scalar sc; + rustsecp256k1_v0_11_ge pt; + rustsecp256k1_v0_11_gej r; ecmult_multi_data data; - rustsecp256k1_v0_10_0_scratch *scratch_empty; + rustsecp256k1_v0_11_scratch *scratch_empty; - random_group_element_test(&pt); - random_scalar_order(&sc); + testutil_random_ge_test(&pt); + testutil_random_scalar_order(&sc); data.sc = ≻ data.pt = &pt; /* Try to multiply 1 point, but scratch space is empty.*/ - scratch_empty = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, 0); - CHECK(!ecmult_multi(&CTX->error_callback, scratch_empty, &r, &rustsecp256k1_v0_10_0_scalar_zero, ecmult_multi_callback, &data, 1)); - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch_empty); + scratch_empty = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, 0); + CHECK(!ecmult_multi(&CTX->error_callback, scratch_empty, &r, &rustsecp256k1_v0_11_scalar_zero, ecmult_multi_callback, &data, 1)); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch_empty); } -static void test_rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(void) { +static void test_rustsecp256k1_v0_11_pippenger_bucket_window_inv(void) { int i; - CHECK(rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(0) == 0); + CHECK(rustsecp256k1_v0_11_pippenger_bucket_window_inv(0) == 0); for(i = 1; i <= PIPPENGER_MAX_BUCKET_WINDOW; i++) { /* Bucket_window of 8 is not used with endo */ if (i == 8) { continue; } - CHECK(rustsecp256k1_v0_10_0_pippenger_bucket_window(rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(i)) == i); + CHECK(rustsecp256k1_v0_11_pippenger_bucket_window(rustsecp256k1_v0_11_pippenger_bucket_window_inv(i)) == i); if (i != PIPPENGER_MAX_BUCKET_WINDOW) { - CHECK(rustsecp256k1_v0_10_0_pippenger_bucket_window(rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(i)+1) > i); + CHECK(rustsecp256k1_v0_11_pippenger_bucket_window(rustsecp256k1_v0_11_pippenger_bucket_window_inv(i)+1) > i); } } } @@ -5066,9 +5062,9 @@ static void test_rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(void) { * for a given scratch space. */ static void test_ecmult_multi_pippenger_max_points(void) { - size_t scratch_size = rustsecp256k1_v0_10_0_testrand_bits(8); - size_t max_size = rustsecp256k1_v0_10_0_pippenger_scratch_size(rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); - rustsecp256k1_v0_10_0_scratch *scratch; + size_t scratch_size = testrand_bits(8); + size_t max_size = rustsecp256k1_v0_11_pippenger_scratch_size(rustsecp256k1_v0_11_pippenger_bucket_window_inv(PIPPENGER_MAX_BUCKET_WINDOW-1)+512, 12); + rustsecp256k1_v0_11_scratch *scratch; size_t n_points_supported; int bucket_window = 0; @@ -5076,24 +5072,24 @@ static void test_ecmult_multi_pippenger_max_points(void) { size_t i; size_t total_alloc; size_t checkpoint; - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, scratch_size); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, scratch_size); CHECK(scratch != NULL); - checkpoint = rustsecp256k1_v0_10_0_scratch_checkpoint(&CTX->error_callback, scratch); - n_points_supported = rustsecp256k1_v0_10_0_pippenger_max_points(&CTX->error_callback, scratch); + checkpoint = rustsecp256k1_v0_11_scratch_checkpoint(&CTX->error_callback, scratch); + n_points_supported = rustsecp256k1_v0_11_pippenger_max_points(&CTX->error_callback, scratch); if (n_points_supported == 0) { - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); continue; } - bucket_window = rustsecp256k1_v0_10_0_pippenger_bucket_window(n_points_supported); + bucket_window = rustsecp256k1_v0_11_pippenger_bucket_window(n_points_supported); /* allocate `total_alloc` bytes over `PIPPENGER_SCRATCH_OBJECTS` many allocations */ - total_alloc = rustsecp256k1_v0_10_0_pippenger_scratch_size(n_points_supported, bucket_window); + total_alloc = rustsecp256k1_v0_11_pippenger_scratch_size(n_points_supported, bucket_window); for (i = 0; i < PIPPENGER_SCRATCH_OBJECTS - 1; i++) { - CHECK(rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, 1)); + CHECK(rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, 1)); total_alloc--; } - CHECK(rustsecp256k1_v0_10_0_scratch_alloc(&CTX->error_callback, scratch, total_alloc)); - rustsecp256k1_v0_10_0_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + CHECK(rustsecp256k1_v0_11_scratch_alloc(&CTX->error_callback, scratch, total_alloc)); + rustsecp256k1_v0_11_scratch_apply_checkpoint(&CTX->error_callback, scratch, checkpoint); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); } CHECK(bucket_window == PIPPENGER_MAX_BUCKET_WINDOW); } @@ -5103,154 +5099,154 @@ static void test_ecmult_multi_batch_size_helper(void) { max_n_batch_points = 0; n = 1; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 0); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 0); max_n_batch_points = 1; n = 0; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 0); CHECK(n_batch_points == 0); max_n_batch_points = 2; n = 5; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 3); CHECK(n_batch_points == 2); max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH; n = ECMULT_MAX_POINTS_PER_BATCH; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 1); CHECK(n_batch_points == ECMULT_MAX_POINTS_PER_BATCH); max_n_batch_points = ECMULT_MAX_POINTS_PER_BATCH + 1; n = ECMULT_MAX_POINTS_PER_BATCH + 1; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == 2); CHECK(n_batch_points == ECMULT_MAX_POINTS_PER_BATCH/2 + 1); max_n_batch_points = 1; n = SIZE_MAX; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == SIZE_MAX); CHECK(n_batch_points == 1); max_n_batch_points = 2; n = SIZE_MAX; - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); + CHECK(rustsecp256k1_v0_11_ecmult_multi_batch_size_helper(&n_batches, &n_batch_points, max_n_batch_points, n) == 1); CHECK(n_batches == SIZE_MAX/2 + 1); CHECK(n_batch_points == 2); } /** - * Run rustsecp256k1_v0_10_0_ecmult_multi_var with num points and a scratch space restricted to + * Run rustsecp256k1_v0_11_ecmult_multi_var with num points and a scratch space restricted to * 1 <= i <= num points. */ static void test_ecmult_multi_batching(void) { static const int n_points = 2*ECMULT_PIPPENGER_THRESHOLD; - rustsecp256k1_v0_10_0_scalar scG; - rustsecp256k1_v0_10_0_scalar *sc = (rustsecp256k1_v0_10_0_scalar *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_10_0_scalar) * n_points); - rustsecp256k1_v0_10_0_ge *pt = (rustsecp256k1_v0_10_0_ge *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_10_0_ge) * n_points); - rustsecp256k1_v0_10_0_gej r; - rustsecp256k1_v0_10_0_gej r2; + rustsecp256k1_v0_11_scalar scG; + rustsecp256k1_v0_11_scalar *sc = (rustsecp256k1_v0_11_scalar *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_11_scalar) * n_points); + rustsecp256k1_v0_11_ge *pt = (rustsecp256k1_v0_11_ge *)checked_malloc(&CTX->error_callback, sizeof(rustsecp256k1_v0_11_ge) * n_points); + rustsecp256k1_v0_11_gej r; + rustsecp256k1_v0_11_gej r2; ecmult_multi_data data; int i; - rustsecp256k1_v0_10_0_scratch *scratch; + rustsecp256k1_v0_11_scratch *scratch; - rustsecp256k1_v0_10_0_gej_set_infinity(&r2); + rustsecp256k1_v0_11_gej_set_infinity(&r2); /* Get random scalars and group elements and compute result */ - random_scalar_order(&scG); - rustsecp256k1_v0_10_0_ecmult(&r2, &r2, &rustsecp256k1_v0_10_0_scalar_zero, &scG); + testutil_random_scalar_order(&scG); + rustsecp256k1_v0_11_ecmult(&r2, &r2, &rustsecp256k1_v0_11_scalar_zero, &scG); for(i = 0; i < n_points; i++) { - rustsecp256k1_v0_10_0_ge ptg; - rustsecp256k1_v0_10_0_gej ptgj; - random_group_element_test(&ptg); - rustsecp256k1_v0_10_0_gej_set_ge(&ptgj, &ptg); + rustsecp256k1_v0_11_ge ptg; + rustsecp256k1_v0_11_gej ptgj; + testutil_random_ge_test(&ptg); + rustsecp256k1_v0_11_gej_set_ge(&ptgj, &ptg); pt[i] = ptg; - random_scalar_order(&sc[i]); - rustsecp256k1_v0_10_0_ecmult(&ptgj, &ptgj, &sc[i], NULL); - rustsecp256k1_v0_10_0_gej_add_var(&r2, &r2, &ptgj, NULL); + testutil_random_scalar_order(&sc[i]); + rustsecp256k1_v0_11_ecmult(&ptgj, &ptgj, &sc[i], NULL); + rustsecp256k1_v0_11_gej_add_var(&r2, &r2, &ptgj, NULL); } data.sc = sc; data.pt = pt; - rustsecp256k1_v0_10_0_gej_neg(&r2, &r2); + rustsecp256k1_v0_11_gej_neg(&r2, &r2); /* Test with empty scratch space. It should compute the correct result using * ecmult_mult_simple algorithm which doesn't require a scratch space. */ - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, 0); - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - rustsecp256k1_v0_10_0_gej_add_var(&r, &r, &r2, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, 0); + CHECK(rustsecp256k1_v0_11_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + rustsecp256k1_v0_11_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); /* Test with space for 1 point in pippenger. That's not enough because * ecmult_multi selects strauss which requires more memory. It should * therefore select the simple algorithm. */ - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, rustsecp256k1_v0_10_0_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - rustsecp256k1_v0_10_0_gej_add_var(&r, &r, &r2, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, rustsecp256k1_v0_11_pippenger_scratch_size(1, 1) + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + CHECK(rustsecp256k1_v0_11_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + rustsecp256k1_v0_11_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); for(i = 1; i <= n_points; i++) { if (i > ECMULT_PIPPENGER_THRESHOLD) { - int bucket_window = rustsecp256k1_v0_10_0_pippenger_bucket_window(i); - size_t scratch_size = rustsecp256k1_v0_10_0_pippenger_scratch_size(i, bucket_window); - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); + int bucket_window = rustsecp256k1_v0_11_pippenger_bucket_window(i); + size_t scratch_size = rustsecp256k1_v0_11_pippenger_scratch_size(i, bucket_window); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, scratch_size + PIPPENGER_SCRATCH_OBJECTS*ALIGNMENT); } else { - size_t scratch_size = rustsecp256k1_v0_10_0_strauss_scratch_size(i); - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); + size_t scratch_size = rustsecp256k1_v0_11_strauss_scratch_size(i); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, scratch_size + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); } - CHECK(rustsecp256k1_v0_10_0_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); - rustsecp256k1_v0_10_0_gej_add_var(&r, &r, &r2, NULL); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&r)); - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + CHECK(rustsecp256k1_v0_11_ecmult_multi_var(&CTX->error_callback, scratch, &r, &scG, ecmult_multi_callback, &data, n_points)); + rustsecp256k1_v0_11_gej_add_var(&r, &r, &r2, NULL); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&r)); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); } free(sc); free(pt); } static void run_ecmult_multi_tests(void) { - rustsecp256k1_v0_10_0_scratch *scratch; + rustsecp256k1_v0_11_scratch *scratch; int64_t todo = (int64_t)320 * COUNT; - test_rustsecp256k1_v0_10_0_pippenger_bucket_window_inv(); + test_rustsecp256k1_v0_11_pippenger_bucket_window_inv(); test_ecmult_multi_pippenger_max_points(); - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, 819200); - test_ecmult_multi(scratch, rustsecp256k1_v0_10_0_ecmult_multi_var); - test_ecmult_multi(NULL, rustsecp256k1_v0_10_0_ecmult_multi_var); - test_ecmult_multi(scratch, rustsecp256k1_v0_10_0_ecmult_pippenger_batch_single); - test_ecmult_multi_batch_single(rustsecp256k1_v0_10_0_ecmult_pippenger_batch_single); - test_ecmult_multi(scratch, rustsecp256k1_v0_10_0_ecmult_strauss_batch_single); - test_ecmult_multi_batch_single(rustsecp256k1_v0_10_0_ecmult_strauss_batch_single); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, 819200); + test_ecmult_multi(scratch, rustsecp256k1_v0_11_ecmult_multi_var); + test_ecmult_multi(NULL, rustsecp256k1_v0_11_ecmult_multi_var); + test_ecmult_multi(scratch, rustsecp256k1_v0_11_ecmult_pippenger_batch_single); + test_ecmult_multi_batch_single(rustsecp256k1_v0_11_ecmult_pippenger_batch_single); + test_ecmult_multi(scratch, rustsecp256k1_v0_11_ecmult_strauss_batch_single); + test_ecmult_multi_batch_single(rustsecp256k1_v0_11_ecmult_strauss_batch_single); while (todo > 0) { todo -= test_ecmult_multi_random(scratch); } - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); /* Run test_ecmult_multi with space for exactly one point */ - scratch = rustsecp256k1_v0_10_0_scratch_create(&CTX->error_callback, rustsecp256k1_v0_10_0_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); - test_ecmult_multi(scratch, rustsecp256k1_v0_10_0_ecmult_multi_var); - rustsecp256k1_v0_10_0_scratch_destroy(&CTX->error_callback, scratch); + scratch = rustsecp256k1_v0_11_scratch_create(&CTX->error_callback, rustsecp256k1_v0_11_strauss_scratch_size(1) + STRAUSS_SCRATCH_OBJECTS*ALIGNMENT); + test_ecmult_multi(scratch, rustsecp256k1_v0_11_ecmult_multi_var); + rustsecp256k1_v0_11_scratch_destroy(&CTX->error_callback, scratch); test_ecmult_multi_batch_size_helper(); test_ecmult_multi_batching(); } -static void test_wnaf(const rustsecp256k1_v0_10_0_scalar *number, int w) { - rustsecp256k1_v0_10_0_scalar x, two, t; +static void test_wnaf(const rustsecp256k1_v0_11_scalar *number, int w) { + rustsecp256k1_v0_11_scalar x, two, t; int wnaf[256]; int zeroes = -1; int i; int bits; - rustsecp256k1_v0_10_0_scalar_set_int(&x, 0); - rustsecp256k1_v0_10_0_scalar_set_int(&two, 2); - bits = rustsecp256k1_v0_10_0_ecmult_wnaf(wnaf, 256, number, w); + rustsecp256k1_v0_11_scalar_set_int(&x, 0); + rustsecp256k1_v0_11_scalar_set_int(&two, 2); + bits = rustsecp256k1_v0_11_ecmult_wnaf(wnaf, 256, number, w); CHECK(bits <= 256); for (i = bits-1; i >= 0; i--) { int v = wnaf[i]; - rustsecp256k1_v0_10_0_scalar_mul(&x, &x, &two); + rustsecp256k1_v0_11_scalar_mul(&x, &x, &two); if (v) { CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ zeroes=0; @@ -5262,48 +5258,48 @@ static void test_wnaf(const rustsecp256k1_v0_10_0_scalar *number, int w) { zeroes++; } if (v >= 0) { - rustsecp256k1_v0_10_0_scalar_set_int(&t, v); + rustsecp256k1_v0_11_scalar_set_int(&t, v); } else { - rustsecp256k1_v0_10_0_scalar_set_int(&t, -v); - rustsecp256k1_v0_10_0_scalar_negate(&t, &t); + rustsecp256k1_v0_11_scalar_set_int(&t, -v); + rustsecp256k1_v0_11_scalar_negate(&t, &t); } - rustsecp256k1_v0_10_0_scalar_add(&x, &x, &t); + rustsecp256k1_v0_11_scalar_add(&x, &x, &t); } - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&x, number)); /* check that wnaf represents number */ + CHECK(rustsecp256k1_v0_11_scalar_eq(&x, number)); /* check that wnaf represents number */ } -static void test_fixed_wnaf(const rustsecp256k1_v0_10_0_scalar *number, int w) { - rustsecp256k1_v0_10_0_scalar x, shift; +static void test_fixed_wnaf(const rustsecp256k1_v0_11_scalar *number, int w) { + rustsecp256k1_v0_11_scalar x, shift; int wnaf[256] = {0}; int i; int skew; - rustsecp256k1_v0_10_0_scalar num, unused; + rustsecp256k1_v0_11_scalar num, unused; - rustsecp256k1_v0_10_0_scalar_set_int(&x, 0); - rustsecp256k1_v0_10_0_scalar_set_int(&shift, 1 << w); + rustsecp256k1_v0_11_scalar_set_int(&x, 0); + rustsecp256k1_v0_11_scalar_set_int(&shift, 1 << w); /* Make num a 128-bit scalar. */ - rustsecp256k1_v0_10_0_scalar_split_128(&num, &unused, number); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_split_128(&num, &unused, number); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); for (i = WNAF_SIZE(w)-1; i >= 0; --i) { - rustsecp256k1_v0_10_0_scalar t; + rustsecp256k1_v0_11_scalar t; int v = wnaf[i]; CHECK(v == 0 || v & 1); /* check parity */ CHECK(v > -(1 << w)); /* check range above */ CHECK(v < (1 << w)); /* check range below */ - rustsecp256k1_v0_10_0_scalar_mul(&x, &x, &shift); + rustsecp256k1_v0_11_scalar_mul(&x, &x, &shift); if (v >= 0) { - rustsecp256k1_v0_10_0_scalar_set_int(&t, v); + rustsecp256k1_v0_11_scalar_set_int(&t, v); } else { - rustsecp256k1_v0_10_0_scalar_set_int(&t, -v); - rustsecp256k1_v0_10_0_scalar_negate(&t, &t); + rustsecp256k1_v0_11_scalar_set_int(&t, -v); + rustsecp256k1_v0_11_scalar_negate(&t, &t); } - rustsecp256k1_v0_10_0_scalar_add(&x, &x, &t); + rustsecp256k1_v0_11_scalar_add(&x, &x, &t); } /* If skew is 1 then add 1 to num */ - rustsecp256k1_v0_10_0_scalar_cadd_bit(&num, 0, skew == 1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&x, &num)); + rustsecp256k1_v0_11_scalar_cadd_bit(&num, 0, skew == 1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&x, &num)); } /* Checks that the first 8 elements of wnaf are equal to wnaf_expected and the @@ -5323,18 +5319,18 @@ static void test_fixed_wnaf_small(void) { int wnaf[256] = {0}; int i; int skew; - rustsecp256k1_v0_10_0_scalar num; + rustsecp256k1_v0_11_scalar num; - rustsecp256k1_v0_10_0_scalar_set_int(&num, 0); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_set_int(&num, 0); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); for (i = WNAF_SIZE(w)-1; i >= 0; --i) { int v = wnaf[i]; CHECK(v == 0); } CHECK(skew == 0); - rustsecp256k1_v0_10_0_scalar_set_int(&num, 1); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_set_int(&num, 1); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); for (i = WNAF_SIZE(w)-1; i >= 1; --i) { int v = wnaf[i]; CHECK(v == 0); @@ -5344,29 +5340,29 @@ static void test_fixed_wnaf_small(void) { { int wnaf_expected[8] = { 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf }; - rustsecp256k1_v0_10_0_scalar_set_int(&num, 0xffffffff); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_set_int(&num, 0xffffffff); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 0); } { int wnaf_expected[8] = { -1, -1, -1, -1, -1, -1, -1, 0xf }; - rustsecp256k1_v0_10_0_scalar_set_int(&num, 0xeeeeeeee); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_set_int(&num, 0xeeeeeeee); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 1); } { int wnaf_expected[8] = { 1, 0, 1, 0, 1, 0, 1, 0 }; - rustsecp256k1_v0_10_0_scalar_set_int(&num, 0x01010101); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_set_int(&num, 0x01010101); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 0); } { int wnaf_expected[8] = { -0xf, 0, 0xf, -0xf, 0, 0xf, 1, 0 }; - rustsecp256k1_v0_10_0_scalar_set_int(&num, 0x01ef1ef1); - skew = rustsecp256k1_v0_10_0_wnaf_fixed(wnaf, &num, w); + rustsecp256k1_v0_11_scalar_set_int(&num, 0x01ef1ef1); + skew = rustsecp256k1_v0_11_wnaf_fixed(wnaf, &num, w); test_fixed_wnaf_small_helper(wnaf, wnaf_expected, w); CHECK(skew == 0); } @@ -5374,60 +5370,60 @@ static void test_fixed_wnaf_small(void) { static void run_wnaf(void) { int i; - rustsecp256k1_v0_10_0_scalar n; + rustsecp256k1_v0_11_scalar n; /* Test 0 for fixed wnaf */ 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)); } - rustsecp256k1_v0_10_0_scalar_set_int(&n, 0); - CHECK(rustsecp256k1_v0_10_0_scalar_cond_negate(&n, 1) == -1); - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&n)); - CHECK(rustsecp256k1_v0_10_0_scalar_cond_negate(&n, 0) == 1); - CHECK(rustsecp256k1_v0_10_0_scalar_is_zero(&n)); + rustsecp256k1_v0_11_scalar_set_int(&n, 0); + CHECK(rustsecp256k1_v0_11_scalar_cond_negate(&n, 1) == -1); + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&n)); + CHECK(rustsecp256k1_v0_11_scalar_cond_negate(&n, 0) == 1); + CHECK(rustsecp256k1_v0_11_scalar_is_zero(&n)); } -static int test_ecmult_accumulate_cb(rustsecp256k1_v0_10_0_scalar* sc, rustsecp256k1_v0_10_0_ge* pt, size_t idx, void* data) { - const rustsecp256k1_v0_10_0_scalar* indata = (const rustsecp256k1_v0_10_0_scalar*)data; +static int test_ecmult_accumulate_cb(rustsecp256k1_v0_11_scalar* sc, rustsecp256k1_v0_11_ge* pt, size_t idx, void* data) { + const rustsecp256k1_v0_11_scalar* indata = (const rustsecp256k1_v0_11_scalar*)data; *sc = *indata; - *pt = rustsecp256k1_v0_10_0_ge_const_g; + *pt = rustsecp256k1_v0_11_ge_const_g; CHECK(idx == 0); return 1; } -static void test_ecmult_accumulate(rustsecp256k1_v0_10_0_sha256* acc, const rustsecp256k1_v0_10_0_scalar* x, rustsecp256k1_v0_10_0_scratch* scratch) { +static void test_ecmult_accumulate(rustsecp256k1_v0_11_sha256* acc, const rustsecp256k1_v0_11_scalar* x, rustsecp256k1_v0_11_scratch* scratch) { /* Compute x*G in 6 different ways, serialize it uncompressed, and feed it into acc. */ - rustsecp256k1_v0_10_0_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj; - rustsecp256k1_v0_10_0_ge r; + rustsecp256k1_v0_11_gej rj1, rj2, rj3, rj4, rj5, rj6, gj, infj; + rustsecp256k1_v0_11_ge r; unsigned char bytes[65]; size_t size = 65; - rustsecp256k1_v0_10_0_gej_set_ge(&gj, &rustsecp256k1_v0_10_0_ge_const_g); - rustsecp256k1_v0_10_0_gej_set_infinity(&infj); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); - rustsecp256k1_v0_10_0_ecmult(&rj2, &gj, x, &rustsecp256k1_v0_10_0_scalar_zero); - rustsecp256k1_v0_10_0_ecmult(&rj3, &infj, &rustsecp256k1_v0_10_0_scalar_zero, x); - rustsecp256k1_v0_10_0_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0); - rustsecp256k1_v0_10_0_ecmult_multi_var(NULL, scratch, &rj5, &rustsecp256k1_v0_10_0_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1); - rustsecp256k1_v0_10_0_ecmult_const(&rj6, &rustsecp256k1_v0_10_0_ge_const_g, x); - rustsecp256k1_v0_10_0_ge_set_gej_var(&r, &rj1); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&rj2, &r)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&rj3, &r)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&rj4, &r)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&rj5, &r)); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&rj6, &r)); - if (rustsecp256k1_v0_10_0_ge_is_infinity(&r)) { + rustsecp256k1_v0_11_gej_set_ge(&gj, &rustsecp256k1_v0_11_ge_const_g); + rustsecp256k1_v0_11_gej_set_infinity(&infj); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &rj1, x); + rustsecp256k1_v0_11_ecmult(&rj2, &gj, x, &rustsecp256k1_v0_11_scalar_zero); + rustsecp256k1_v0_11_ecmult(&rj3, &infj, &rustsecp256k1_v0_11_scalar_zero, x); + CHECK(rustsecp256k1_v0_11_ecmult_multi_var(&CTX->error_callback, scratch, &rj4, x, NULL, NULL, 0)); + CHECK(rustsecp256k1_v0_11_ecmult_multi_var(&CTX->error_callback, scratch, &rj5, &rustsecp256k1_v0_11_scalar_zero, test_ecmult_accumulate_cb, (void*)x, 1)); + rustsecp256k1_v0_11_ecmult_const(&rj6, &rustsecp256k1_v0_11_ge_const_g, x); + rustsecp256k1_v0_11_ge_set_gej_var(&r, &rj1); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&rj2, &r)); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&rj3, &r)); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&rj4, &r)); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&rj5, &r)); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&rj6, &r)); + if (rustsecp256k1_v0_11_ge_is_infinity(&r)) { /* Store infinity as 0x00 */ const unsigned char zerobyte[1] = {0}; - rustsecp256k1_v0_10_0_sha256_write(acc, zerobyte, 1); + rustsecp256k1_v0_11_sha256_write(acc, zerobyte, 1); } else { /* Store other points using their uncompressed serialization. */ - rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&r, bytes, &size, 0); + rustsecp256k1_v0_11_eckey_pubkey_serialize(&r, bytes, &size, 0); CHECK(size == 65); - rustsecp256k1_v0_10_0_sha256_write(acc, bytes, size); + rustsecp256k1_v0_11_sha256_write(acc, bytes, size); } } @@ -5440,11 +5436,11 @@ static void test_ecmult_constants_2bit(void) { * - For j in 1..255 (only odd values): * - Key (j*2^i) mod order */ - rustsecp256k1_v0_10_0_scalar x; - rustsecp256k1_v0_10_0_sha256 acc; + rustsecp256k1_v0_11_scalar x; + rustsecp256k1_v0_11_sha256 acc; unsigned char b32[32]; int i, j; - rustsecp256k1_v0_10_0_scratch_space *scratch = rustsecp256k1_v0_10_0_scratch_space_create(CTX, 65536); + rustsecp256k1_v0_11_scratch_space *scratch = rustsecp256k1_v0_11_scratch_space_create(CTX, 65536); /* Expected hash of all the computed points; created with an independent * implementation. */ @@ -5454,25 +5450,25 @@ static void test_ecmult_constants_2bit(void) { 0x3a, 0x75, 0x87, 0x60, 0x1a, 0xf9, 0x63, 0x60, 0xd0, 0xcb, 0x1f, 0xaa, 0x85, 0x9a, 0xb7, 0xb4 }; - rustsecp256k1_v0_10_0_sha256_initialize(&acc); + rustsecp256k1_v0_11_sha256_initialize(&acc); for (i = 0; i <= 36; ++i) { - rustsecp256k1_v0_10_0_scalar_set_int(&x, i); + rustsecp256k1_v0_11_scalar_set_int(&x, i); test_ecmult_accumulate(&acc, &x, scratch); - rustsecp256k1_v0_10_0_scalar_negate(&x, &x); + rustsecp256k1_v0_11_scalar_negate(&x, &x); test_ecmult_accumulate(&acc, &x, scratch); }; for (i = 0; i < 256; ++i) { for (j = 1; j < 256; j += 2) { int k; - rustsecp256k1_v0_10_0_scalar_set_int(&x, j); - for (k = 0; k < i; ++k) rustsecp256k1_v0_10_0_scalar_add(&x, &x, &x); + rustsecp256k1_v0_11_scalar_set_int(&x, j); + for (k = 0; k < i; ++k) rustsecp256k1_v0_11_scalar_add(&x, &x, &x); test_ecmult_accumulate(&acc, &x, scratch); } } - rustsecp256k1_v0_10_0_sha256_finalize(&acc, b32); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(b32, expected32, 32) == 0); + rustsecp256k1_v0_11_sha256_finalize(&acc, b32); + CHECK(rustsecp256k1_v0_11_memcmp_var(b32, expected32, 32) == 0); - rustsecp256k1_v0_10_0_scratch_space_destroy(CTX, scratch); + rustsecp256k1_v0_11_scratch_space_destroy(CTX, scratch); } static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsigned char* expected32) { @@ -5483,39 +5479,39 @@ static void test_ecmult_constants_sha(uint32_t prefix, size_t iter, const unsign * - For i in range(iter): * - Key SHA256(LE32(prefix) || LE16(i)) */ - rustsecp256k1_v0_10_0_scalar x; - rustsecp256k1_v0_10_0_sha256 acc; + rustsecp256k1_v0_11_scalar x; + rustsecp256k1_v0_11_sha256 acc; unsigned char b32[32]; unsigned char inp[6]; size_t i; - rustsecp256k1_v0_10_0_scratch_space *scratch = rustsecp256k1_v0_10_0_scratch_space_create(CTX, 65536); + rustsecp256k1_v0_11_scratch_space *scratch = rustsecp256k1_v0_11_scratch_space_create(CTX, 65536); inp[0] = prefix & 0xFF; inp[1] = (prefix >> 8) & 0xFF; inp[2] = (prefix >> 16) & 0xFF; inp[3] = (prefix >> 24) & 0xFF; - rustsecp256k1_v0_10_0_sha256_initialize(&acc); - rustsecp256k1_v0_10_0_scalar_set_int(&x, 0); + rustsecp256k1_v0_11_sha256_initialize(&acc); + rustsecp256k1_v0_11_scalar_set_int(&x, 0); test_ecmult_accumulate(&acc, &x, scratch); - rustsecp256k1_v0_10_0_scalar_set_int(&x, 1); + rustsecp256k1_v0_11_scalar_set_int(&x, 1); test_ecmult_accumulate(&acc, &x, scratch); - rustsecp256k1_v0_10_0_scalar_negate(&x, &x); + rustsecp256k1_v0_11_scalar_negate(&x, &x); test_ecmult_accumulate(&acc, &x, scratch); for (i = 0; i < iter; ++i) { - rustsecp256k1_v0_10_0_sha256 gen; + rustsecp256k1_v0_11_sha256 gen; inp[4] = i & 0xff; inp[5] = (i >> 8) & 0xff; - rustsecp256k1_v0_10_0_sha256_initialize(&gen); - rustsecp256k1_v0_10_0_sha256_write(&gen, inp, sizeof(inp)); - rustsecp256k1_v0_10_0_sha256_finalize(&gen, b32); - rustsecp256k1_v0_10_0_scalar_set_b32(&x, b32, NULL); + rustsecp256k1_v0_11_sha256_initialize(&gen); + rustsecp256k1_v0_11_sha256_write(&gen, inp, sizeof(inp)); + rustsecp256k1_v0_11_sha256_finalize(&gen, b32); + rustsecp256k1_v0_11_scalar_set_b32(&x, b32, NULL); test_ecmult_accumulate(&acc, &x, scratch); } - rustsecp256k1_v0_10_0_sha256_finalize(&acc, b32); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(b32, expected32, 32) == 0); + rustsecp256k1_v0_11_sha256_finalize(&acc, b32); + CHECK(rustsecp256k1_v0_11_memcmp_var(b32, expected32, 32) == 0); - rustsecp256k1_v0_10_0_scratch_space_destroy(CTX, scratch); + rustsecp256k1_v0_11_scratch_space_destroy(CTX, scratch); } static void run_ecmult_constants(void) { @@ -5547,96 +5543,117 @@ 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(); } } 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. */ - rustsecp256k1_v0_10_0_scalar key; - rustsecp256k1_v0_10_0_scalar b; + rustsecp256k1_v0_11_scalar key; + rustsecp256k1_v0_11_scalar b; unsigned char seed32[32]; - rustsecp256k1_v0_10_0_gej pgej; - rustsecp256k1_v0_10_0_gej pgej2; - rustsecp256k1_v0_10_0_gej i; - rustsecp256k1_v0_10_0_ge pge; - random_scalar_order_test(&key); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); - rustsecp256k1_v0_10_0_testrand256(seed32); - b = CTX->ecmult_gen_ctx.blind; - i = CTX->ecmult_gen_ctx.initial; - rustsecp256k1_v0_10_0_ecmult_gen_blind(&CTX->ecmult_gen_ctx, seed32); - CHECK(!rustsecp256k1_v0_10_0_scalar_eq(&b, &CTX->ecmult_gen_ctx.blind)); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej2, &key); + rustsecp256k1_v0_11_gej pgej; + rustsecp256k1_v0_11_gej pgej2; + rustsecp256k1_v0_11_ge p; + rustsecp256k1_v0_11_ge pge; + testutil_random_scalar_order_test(&key); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &pgej, &key); + testrand256(seed32); + b = CTX->ecmult_gen_ctx.scalar_offset; + p = CTX->ecmult_gen_ctx.ge_offset; + rustsecp256k1_v0_11_ecmult_gen_blind(&CTX->ecmult_gen_ctx, seed32); + CHECK(!rustsecp256k1_v0_11_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); + rustsecp256k1_v0_11_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)); - rustsecp256k1_v0_10_0_ge_set_gej(&pge, &pgej); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&pgej2, &pge)); + CHECK(!rustsecp256k1_v0_11_ge_eq_var(&p, &CTX->ecmult_gen_ctx.ge_offset)); + rustsecp256k1_v0_11_ge_set_gej(&pge, &pgej); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&pgej2, &pge)); } static void test_ecmult_gen_blind_reset(void) { /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ - rustsecp256k1_v0_10_0_scalar b; - rustsecp256k1_v0_10_0_gej initial; - rustsecp256k1_v0_10_0_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); - b = CTX->ecmult_gen_ctx.blind; - initial = CTX->ecmult_gen_ctx.initial; - rustsecp256k1_v0_10_0_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&b, &CTX->ecmult_gen_ctx.blind)); - CHECK(gej_xyz_equals_gej(&initial, &CTX->ecmult_gen_ctx.initial)); + rustsecp256k1_v0_11_scalar b; + rustsecp256k1_v0_11_ge p1, p2; + rustsecp256k1_v0_11_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); + b = CTX->ecmult_gen_ctx.scalar_offset; + p1 = CTX->ecmult_gen_ctx.ge_offset; + rustsecp256k1_v0_11_ecmult_gen_blind(&CTX->ecmult_gen_ctx, 0); + CHECK(rustsecp256k1_v0_11_scalar_eq(&b, &CTX->ecmult_gen_ctx.scalar_offset)); + p2 = CTX->ecmult_gen_ctx.ge_offset; + CHECK(rustsecp256k1_v0_11_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; + rustsecp256k1_v0_11_gej res1, res2, res3; + rustsecp256k1_v0_11_scalar gn = rustsecp256k1_v0_11_scalar_one; /* gn = 1 */ + rustsecp256k1_v0_11_scalar_add(&gn, &gn, &CTX->ecmult_gen_ctx.scalar_offset); /* gn = 1 + scalar_offset */ + rustsecp256k1_v0_11_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). */ + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &res1, &gn); + rustsecp256k1_v0_11_ecmult(&res2, NULL, &rustsecp256k1_v0_11_scalar_zero, &gn); + rustsecp256k1_v0_11_ecmult_const(&res3, &rustsecp256k1_v0_11_ge_const_g, &gn); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&res1, &res2)); + CHECK(rustsecp256k1_v0_11_gej_eq_var(&res1, &res3)); + rustsecp256k1_v0_11_scalar_add(&gn, &gn, &rustsecp256k1_v0_11_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(); } } /***** ENDOMORPHISH TESTS *****/ -static void test_scalar_split(const rustsecp256k1_v0_10_0_scalar* full) { - rustsecp256k1_v0_10_0_scalar s, s1, slam; +static void test_scalar_split(const rustsecp256k1_v0_11_scalar* full) { + rustsecp256k1_v0_11_scalar s, s1, slam; const unsigned char zero[32] = {0}; unsigned char tmp[32]; - rustsecp256k1_v0_10_0_scalar_split_lambda(&s1, &slam, full); + rustsecp256k1_v0_11_scalar_split_lambda(&s1, &slam, full); /* check slam*lambda + s1 == full */ - rustsecp256k1_v0_10_0_scalar_mul(&s, &rustsecp256k1_v0_10_0_const_lambda, &slam); - rustsecp256k1_v0_10_0_scalar_add(&s, &s, &s1); - CHECK(rustsecp256k1_v0_10_0_scalar_eq(&s, full)); + rustsecp256k1_v0_11_scalar_mul(&s, &rustsecp256k1_v0_11_const_lambda, &slam); + rustsecp256k1_v0_11_scalar_add(&s, &s, &s1); + CHECK(rustsecp256k1_v0_11_scalar_eq(&s, full)); /* check that both are <= 128 bits in size */ - if (rustsecp256k1_v0_10_0_scalar_is_high(&s1)) { - rustsecp256k1_v0_10_0_scalar_negate(&s1, &s1); + if (rustsecp256k1_v0_11_scalar_is_high(&s1)) { + rustsecp256k1_v0_11_scalar_negate(&s1, &s1); } - if (rustsecp256k1_v0_10_0_scalar_is_high(&slam)) { - rustsecp256k1_v0_10_0_scalar_negate(&slam, &slam); + if (rustsecp256k1_v0_11_scalar_is_high(&slam)) { + rustsecp256k1_v0_11_scalar_negate(&slam, &slam); } - rustsecp256k1_v0_10_0_scalar_get_b32(tmp, &s1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zero, tmp, 16) == 0); - rustsecp256k1_v0_10_0_scalar_get_b32(tmp, &slam); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zero, tmp, 16) == 0); + rustsecp256k1_v0_11_scalar_get_b32(tmp, &s1); + CHECK(rustsecp256k1_v0_11_memcmp_var(zero, tmp, 16) == 0); + rustsecp256k1_v0_11_scalar_get_b32(tmp, &slam); + CHECK(rustsecp256k1_v0_11_memcmp_var(zero, tmp, 16) == 0); } static void run_endomorphism_tests(void) { unsigned i; - static rustsecp256k1_v0_10_0_scalar s; - test_scalar_split(&rustsecp256k1_v0_10_0_scalar_zero); - test_scalar_split(&rustsecp256k1_v0_10_0_scalar_one); - rustsecp256k1_v0_10_0_scalar_negate(&s,&rustsecp256k1_v0_10_0_scalar_one); + static rustsecp256k1_v0_11_scalar s; + test_scalar_split(&rustsecp256k1_v0_11_scalar_zero); + test_scalar_split(&rustsecp256k1_v0_11_scalar_one); + rustsecp256k1_v0_11_scalar_negate(&s,&rustsecp256k1_v0_11_scalar_one); test_scalar_split(&s); - test_scalar_split(&rustsecp256k1_v0_10_0_const_lambda); - rustsecp256k1_v0_10_0_scalar_add(&s, &rustsecp256k1_v0_10_0_const_lambda, &rustsecp256k1_v0_10_0_scalar_one); + test_scalar_split(&rustsecp256k1_v0_11_const_lambda); + rustsecp256k1_v0_11_scalar_add(&s, &rustsecp256k1_v0_11_const_lambda, &rustsecp256k1_v0_11_scalar_one); test_scalar_split(&s); for (i = 0; i < 100U * COUNT; ++i) { - rustsecp256k1_v0_10_0_scalar full; - random_scalar_order_test(&full); + rustsecp256k1_v0_11_scalar 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) { @@ -5646,8 +5663,8 @@ static void run_endomorphism_tests(void) { static void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { unsigned char pubkeyc[65]; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_ge ge; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_ge ge; size_t pubkeyclen; for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { @@ -5674,38 +5691,38 @@ static void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, in size_t outl; memset(&pubkey, 0, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); outl = 65; SECP256K1_CHECKMEM_UNDEFINE(pubkeyo, 65); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); SECP256K1_CHECKMEM_CHECK(pubkeyo, outl); CHECK(outl == 33); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkeyo[1], &pubkeyc[1], 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkeyo[1], &pubkeyc[1], 32) == 0); CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); if (ypass) { /* This test isn't always done because we decode with alternative signs, so the y won't match. */ CHECK(pubkeyo[0] == ysign); - CHECK(rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey) == 1); memset(&pubkey, 0, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - rustsecp256k1_v0_10_0_pubkey_save(&pubkey, &ge); + rustsecp256k1_v0_11_pubkey_save(&pubkey, &ge); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); outl = 65; SECP256K1_CHECKMEM_UNDEFINE(pubkeyo, 65); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); SECP256K1_CHECKMEM_CHECK(pubkeyo, outl); CHECK(outl == 65); CHECK(pubkeyo[0] == 4); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkeyo[1], input, 64) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkeyo[1], input, 64) == 0); } } else { /* These cases must fail to parse. */ memset(&pubkey, 0xfe, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); } } } @@ -5892,8 +5909,8 @@ static void run_ec_pubkey_parse_test(void) { }; unsigned char sout[65]; unsigned char shortkey[2] = { 0 }; - rustsecp256k1_v0_10_0_ge ge; - rustsecp256k1_v0_10_0_pubkey pubkey; + rustsecp256k1_v0_11_ge ge; + rustsecp256k1_v0_11_pubkey pubkey; size_t len; int32_t i; @@ -5903,18 +5920,18 @@ static void run_ec_pubkey_parse_test(void) { memset(&pubkey, 0xfe, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(shortkey, 2); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, shortkey, 0) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, shortkey, 0) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); /* Length one claimed, fail, zeroize, no illegal arg error. */ for (i = 0; i < 256 ; i++) { memset(&pubkey, 0xfe, sizeof(pubkey)); shortkey[0] = i; SECP256K1_CHECKMEM_UNDEFINE(&shortkey[1], 1); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, shortkey, 1) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, shortkey, 1) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); } /* Length two claimed, fail, zeroize, no illegal arg error. */ for (i = 0; i < 65536 ; i++) { @@ -5922,68 +5939,68 @@ static void run_ec_pubkey_parse_test(void) { shortkey[0] = i & 255; shortkey[1] = i >> 8; SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, shortkey, 2) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, shortkey, 2) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); } memset(&pubkey, 0xfe, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 33) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 33) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, NULL, pubkeyc, 65)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_parse(CTX, NULL, pubkeyc, 65)); /* NULL input string. Illegal arg and zeroize output. */ memset(&pubkey, 0xfe, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, NULL, 65)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, NULL, 65)); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ memset(&pubkey, 0xfe, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 64) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 64) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ memset(&pubkey, 0xfe, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 66) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 66) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey)); /* Valid parse. */ memset(&pubkey, 0, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 65) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(rustsecp256k1_v0_10_0_context_static, &pubkey, pubkeyc, 65) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, 65) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(rustsecp256k1_v0_11_context_static, &pubkey, pubkeyc, 65) == 1); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&ge, sizeof(ge)); - CHECK(rustsecp256k1_v0_10_0_pubkey_load(CTX, &ge, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_pubkey_load(CTX, &ge, &pubkey) == 1); SECP256K1_CHECKMEM_CHECK(&ge.x, sizeof(ge.x)); SECP256K1_CHECKMEM_CHECK(&ge.y, sizeof(ge.y)); SECP256K1_CHECKMEM_CHECK(&ge.infinity, sizeof(ge.infinity)); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&ge, &rustsecp256k1_v0_10_0_ge_const_g)); - /* rustsecp256k1_v0_10_0_ec_pubkey_serialize illegal args. */ + CHECK(rustsecp256k1_v0_11_ge_eq_var(&ge, &rustsecp256k1_v0_11_ge_const_g)); + /* rustsecp256k1_v0_11_ec_pubkey_serialize illegal args. */ len = 65; - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED)); CHECK(len == 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED)); len = 65; SECP256K1_CHECKMEM_UNDEFINE(sout, 65); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED)); SECP256K1_CHECKMEM_CHECK(sout, 65); CHECK(len == 0); len = 65; - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, sout, &len, &pubkey, ~0)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, sout, &len, &pubkey, ~0)); CHECK(len == 0); len = 65; SECP256K1_CHECKMEM_UNDEFINE(sout, 65); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); SECP256K1_CHECKMEM_CHECK(sout, 65); CHECK(len == 65); /* Multiple illegal args. Should still set arg error only once. */ - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, NULL, NULL, 65)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_parse(CTX, NULL, NULL, 65)); /* Try a bunch of prefabbed points with all possible encodings. */ for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { ec_pubkey_parse_pointtest(valid[i], 1, 1); @@ -6003,276 +6020,276 @@ static void run_eckey_edge_case_test(void) { 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 }; - const unsigned char zeros[sizeof(rustsecp256k1_v0_10_0_pubkey)] = {0x00}; + const unsigned char zeros[sizeof(rustsecp256k1_v0_11_pubkey)] = {0x00}; unsigned char ctmp[33]; unsigned char ctmp2[33]; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_pubkey pubkey2; - rustsecp256k1_v0_10_0_pubkey pubkey_one; - rustsecp256k1_v0_10_0_pubkey pubkey_negone; - const rustsecp256k1_v0_10_0_pubkey *pubkeys[3]; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_pubkey pubkey2; + rustsecp256k1_v0_11_pubkey pubkey_one; + rustsecp256k1_v0_11_pubkey pubkey_negone; + const rustsecp256k1_v0_11_pubkey *pubkeys[3]; size_t len; /* Group order is too large, reject. */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, orderc) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, orderc) == 0); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, orderc) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, orderc) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); /* Maximum value is too large, reject. */ memset(ctmp, 255, 32); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 0); memset(&pubkey, 1, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); /* Zero is too small, reject. */ memset(ctmp, 0, 32); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 0); memset(&pubkey, 1, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); /* One must be accepted. */ ctmp[31] = 0x01; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 1); memset(&pubkey, 0, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) > 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) > 0); pubkey_one = pubkey; /* Group order + 1 is too large, reject. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x42; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 0); memset(&pubkey, 1, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, ctmp) == 0); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); /* -1 must be accepted. */ ctmp[31] = 0x40; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 1); memset(&pubkey, 0, sizeof(pubkey)); SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, ctmp) == 1); SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) > 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) > 0); pubkey_negone = pubkey; /* Tweak of zero leaves the value unchanged. */ memset(ctmp2, 0, 32); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, ctmp, ctmp2) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, ctmp, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); memcpy(&pubkey2, &pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Multiply tweak of zero zeroizes the output. */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(CTX, ctmp, ctmp2) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros, ctmp, 32) == 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey, ctmp2) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_mul(CTX, ctmp, ctmp2) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros, ctmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey, ctmp2) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing seckey, the seckey is zeroized. */ memcpy(ctmp, orderc, 32); memset(ctmp2, 0, 32); ctmp2[31] = 0x01; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp2) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 0); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, ctmp, ctmp2) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros, ctmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, ctmp, ctmp2) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(CTX, ctmp, ctmp2) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros, ctmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_mul(CTX, ctmp, ctmp2) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros, ctmp, 32) == 0); /* If seckey_tweak_add or seckey_tweak_mul are called with an overflowing tweak, the seckey is zeroized. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, ctmp, orderc) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros, ctmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, ctmp, orderc) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(CTX, ctmp, orderc) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros, ctmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_mul(CTX, ctmp, orderc) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros, ctmp, 32) == 0); memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; /* If pubkey_tweak_add or pubkey_tweak_mul are called with an overflowing tweak, the pubkey is zeroized. */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, orderc) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, orderc) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey, orderc) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey, orderc) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); - /* If the resulting key in rustsecp256k1_v0_10_0_ec_seckey_tweak_add and - * rustsecp256k1_v0_10_0_ec_pubkey_tweak_add is 0 the functions fail and in the latter + /* If the resulting key in rustsecp256k1_v0_11_ec_seckey_tweak_add and + * rustsecp256k1_v0_11_ec_pubkey_tweak_add is 0 the functions fail and in the latter * case the pubkey is zeroized. */ memcpy(ctmp, orderc, 32); ctmp[31] = 0x40; memset(ctmp2, 0, 32); ctmp2[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, ctmp2, ctmp) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(zeros, ctmp2, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, ctmp2, ctmp) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(zeros, ctmp2, 32) == 0); ctmp2[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); /* Tweak computation wraps and results in a key of 1. */ ctmp2[31] = 2; - CHECK(rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, ctmp2, ctmp) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, ctmp2, ctmp) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); ctmp2[31] = 2; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); ctmp2[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey2, ctmp2) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey2, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Tweak mul * 2 = 1+1. */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2) == 1); ctmp2[31] = 2; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey2, ctmp2) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey2, ctmp2) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); /* Zeroize pubkey on parse error. */ memset(&pubkey, 0, 32); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, ctmp2)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(pubkey)) == 0); memcpy(&pubkey, &pubkey2, sizeof(pubkey)); memset(&pubkey2, 0, 32); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey2, ctmp2)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey2, zeros, sizeof(pubkey2)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey2, ctmp2)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey2, zeros, sizeof(pubkey2)) == 0); /* Plain argument errors. */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, ctmp) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, NULL)); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, ctmp) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_seckey_verify(CTX, NULL)); memset(ctmp2, 0, 32); ctmp2[31] = 4; - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, NULL, ctmp2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, NULL)); memset(ctmp2, 0, 32); ctmp2[31] = 4; - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, NULL, ctmp2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey, NULL)); memset(ctmp2, 0, 32); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, ctmp, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, NULL, ctmp2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, ctmp, NULL)); memset(ctmp2, 0, 32); ctmp2[31] = 1; - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(CTX, NULL, ctmp2)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(CTX, ctmp, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, NULL, ctmp)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_seckey_tweak_mul(CTX, NULL, ctmp2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_seckey_tweak_mul(CTX, ctmp, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_create(CTX, NULL, ctmp)); memset(&pubkey, 1, sizeof(pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, NULL)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); - /* rustsecp256k1_v0_10_0_ec_pubkey_combine tests. */ + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, NULL)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); + /* rustsecp256k1_v0_11_ec_pubkey_combine tests. */ pubkeys[0] = &pubkey_one; - SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[0], sizeof(rustsecp256k1_v0_10_0_pubkey *)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[1], sizeof(rustsecp256k1_v0_10_0_pubkey *)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[2], sizeof(rustsecp256k1_v0_10_0_pubkey *)); - memset(&pubkey, 255, sizeof(rustsecp256k1_v0_10_0_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &pubkey, pubkeys, 0)); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, NULL, pubkeys, 1)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); - memset(&pubkey, 255, sizeof(rustsecp256k1_v0_10_0_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &pubkey, NULL, 1)); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); + SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[0], sizeof(rustsecp256k1_v0_11_pubkey *)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[1], sizeof(rustsecp256k1_v0_11_pubkey *)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkeys[2], sizeof(rustsecp256k1_v0_11_pubkey *)); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_11_pubkey)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &pubkey, pubkeys, 0)); + SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_combine(CTX, NULL, pubkeys, 1)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_11_pubkey)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &pubkey, NULL, 1)); + SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); pubkeys[0] = &pubkey_negone; - memset(&pubkey, 255, sizeof(rustsecp256k1_v0_10_0_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &pubkey, pubkeys, 1) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) > 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_11_pubkey)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &pubkey, pubkeys, 1) == 1); + SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) > 0); len = 33; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(ctmp, ctmp2, 33) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(ctmp, ctmp2, 33) == 0); /* Result is infinity. */ pubkeys[0] = &pubkey_one; pubkeys[1] = &pubkey_negone; - memset(&pubkey, 255, sizeof(rustsecp256k1_v0_10_0_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 0); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) == 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_11_pubkey)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 0); + SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) == 0); /* Passes through infinity but comes out one. */ pubkeys[2] = &pubkey_one; - memset(&pubkey, 255, sizeof(rustsecp256k1_v0_10_0_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &pubkey, pubkeys, 3) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) > 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_11_pubkey)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &pubkey, pubkeys, 3) == 1); + SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) > 0); len = 33; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(ctmp, ctmp2, 33) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(ctmp, ctmp2, 33) == 0); /* Adds to two. */ pubkeys[1] = &pubkey_one; - memset(&pubkey, 255, sizeof(rustsecp256k1_v0_10_0_pubkey)); - SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 1); - SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_10_0_pubkey)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_10_0_pubkey)) > 0); + memset(&pubkey, 255, sizeof(rustsecp256k1_v0_11_pubkey)); + SECP256K1_CHECKMEM_UNDEFINE(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_combine(CTX, &pubkey, pubkeys, 2) == 1); + SECP256K1_CHECKMEM_CHECK(&pubkey, sizeof(rustsecp256k1_v0_11_pubkey)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, zeros, sizeof(rustsecp256k1_v0_11_pubkey)) > 0); } 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 */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_negate(CTX, seckey) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(seckey, seckey_tmp, 32) != 0); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_negate(CTX, seckey) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(seckey, seckey_tmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_negate(CTX, seckey) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(seckey, seckey_tmp, 32) != 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_negate(CTX, seckey) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(seckey, seckey_tmp, 32) == 0); /* Check that privkey alias gives same result */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_negate(CTX, seckey) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_privkey_negate(CTX, seckey_tmp) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(seckey, seckey_tmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_negate(CTX, seckey) == 1); + CHECK(rustsecp256k1_v0_11_ec_privkey_negate(CTX, seckey_tmp) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(seckey, seckey_tmp, 32) == 0); /* Negating all 0s fails */ memset(seckey, 0, 32); memset(seckey_tmp, 0, 32); - CHECK(rustsecp256k1_v0_10_0_ec_seckey_negate(CTX, seckey) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_negate(CTX, seckey) == 0); /* Check that seckey is not modified */ - CHECK(rustsecp256k1_v0_10_0_memcmp_var(seckey, seckey_tmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(seckey, seckey_tmp, 32) == 0); /* 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(rustsecp256k1_v0_10_0_ec_seckey_negate(CTX, seckey) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(seckey, seckey_tmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_seckey_negate(CTX, seckey) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(seckey, seckey_tmp, 32) == 0); } -static void random_sign(rustsecp256k1_v0_10_0_scalar *sigr, rustsecp256k1_v0_10_0_scalar *sigs, const rustsecp256k1_v0_10_0_scalar *key, const rustsecp256k1_v0_10_0_scalar *msg, int *recid) { - rustsecp256k1_v0_10_0_scalar nonce; +static void random_sign(rustsecp256k1_v0_11_scalar *sigr, rustsecp256k1_v0_11_scalar *sigs, const rustsecp256k1_v0_11_scalar *key, const rustsecp256k1_v0_11_scalar *msg, int *recid) { + rustsecp256k1_v0_11_scalar nonce; do { - random_scalar_order_test(&nonce); - } while(!rustsecp256k1_v0_10_0_ecdsa_sig_sign(&CTX->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); + testutil_random_scalar_order_test(&nonce); + } while(!rustsecp256k1_v0_11_ecdsa_sig_sign(&CTX->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); } static void test_ecdsa_sign_verify(void) { - rustsecp256k1_v0_10_0_gej pubj; - rustsecp256k1_v0_10_0_ge pub; - rustsecp256k1_v0_10_0_scalar one; - rustsecp256k1_v0_10_0_scalar msg, key; - rustsecp256k1_v0_10_0_scalar sigr, sigs; + rustsecp256k1_v0_11_gej pubj; + rustsecp256k1_v0_11_ge pub; + rustsecp256k1_v0_11_scalar one; + rustsecp256k1_v0_11_scalar msg, key; + rustsecp256k1_v0_11_scalar sigr, sigs; int getrec; int recid; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key); - rustsecp256k1_v0_10_0_ge_set_gej(&pub, &pubj); - getrec = rustsecp256k1_v0_10_0_testrand_bits(1); + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &pubj, &key); + rustsecp256k1_v0_11_ge_set_gej(&pub, &pubj); + 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) { @@ -6281,10 +6298,10 @@ static void test_ecdsa_sign_verify(void) { } else { random_sign(&sigr, &sigs, &key, &msg, NULL); } - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); - rustsecp256k1_v0_10_0_scalar_set_int(&one, 1); - rustsecp256k1_v0_10_0_scalar_add(&msg, &msg, &one); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); + rustsecp256k1_v0_11_scalar_set_int(&one, 1); + rustsecp256k1_v0_11_scalar_add(&msg, &msg, &one); + CHECK(!rustsecp256k1_v0_11_ecdsa_sig_verify(&sigr, &sigs, &pub, &msg)); } static void run_ecdsa_sign_verify(void) { @@ -6341,9 +6358,9 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); } -static int is_empty_signature(const rustsecp256k1_v0_10_0_ecdsa_signature *sig) { - static const unsigned char res[sizeof(rustsecp256k1_v0_10_0_ecdsa_signature)] = {0}; - return rustsecp256k1_v0_10_0_memcmp_var(sig, res, sizeof(rustsecp256k1_v0_10_0_ecdsa_signature)) == 0; +static int is_empty_signature(const rustsecp256k1_v0_11_ecdsa_signature *sig) { + static const unsigned char res[sizeof(rustsecp256k1_v0_11_ecdsa_signature)] = {0}; + return rustsecp256k1_v0_11_memcmp_var(sig, res, sizeof(rustsecp256k1_v0_11_ecdsa_signature)) == 0; } static void test_ecdsa_end_to_end(void) { @@ -6351,191 +6368,191 @@ static void test_ecdsa_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; unsigned char privkey2[32]; - rustsecp256k1_v0_10_0_ecdsa_signature signature[6]; - rustsecp256k1_v0_10_0_scalar r, s; + rustsecp256k1_v0_11_ecdsa_signature signature[6]; + rustsecp256k1_v0_11_scalar r, s; unsigned char sig[74]; size_t siglen = 74; unsigned char pubkeyc[65]; size_t pubkeyclen = 65; - rustsecp256k1_v0_10_0_pubkey pubkey; - rustsecp256k1_v0_10_0_pubkey pubkey_tmp; + rustsecp256k1_v0_11_pubkey pubkey; + rustsecp256k1_v0_11_pubkey pubkey_tmp; unsigned char seckey[300]; size_t seckeylen = 300; /* Generate a random key and message. */ { - rustsecp256k1_v0_10_0_scalar msg, key; - random_scalar_order_test(&msg); - random_scalar_order_test(&key); - rustsecp256k1_v0_10_0_scalar_get_b32(privkey, &key); - rustsecp256k1_v0_10_0_scalar_get_b32(message, &msg); + rustsecp256k1_v0_11_scalar msg, key; + testutil_random_scalar_order_test(&msg); + testutil_random_scalar_order_test(&key); + rustsecp256k1_v0_11_scalar_get_b32(privkey, &key); + rustsecp256k1_v0_11_scalar_get_b32(message, &msg); } /* Construct and verify corresponding public key. */ - CHECK(rustsecp256k1_v0_10_0_ec_seckey_verify(CTX, privkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, privkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_seckey_verify(CTX, privkey) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, privkey) == 1); /* Verify exporting and importing public key. */ - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_serialize(CTX, pubkeyc, &pubkeyclen, &pubkey, rustsecp256k1_v0_10_0_testrand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_serialize(CTX, pubkeyc, &pubkeyclen, &pubkey, testrand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); memset(&pubkey, 0, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pubkeyc, pubkeyclen) == 1); /* Verify negation changes the key and changes it back */ memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_negate(CTX, &pubkey_tmp) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_negate(CTX, &pubkey_tmp) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_negate(CTX, &pubkey_tmp) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_negate(CTX, &pubkey_tmp) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); /* Verify private key import and export. */ - CHECK(ec_privkey_export_der(CTX, seckey, &seckeylen, privkey, rustsecp256k1_v0_10_0_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(rustsecp256k1_v0_10_0_memcmp_var(privkey, privkey2, 32) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(privkey, privkey2, 32) == 0); /* Optionally tweak the keys using addition. */ - if (rustsecp256k1_v0_10_0_testrand_int(3) == 0) { + if (testrand_int(3) == 0) { int ret1; int ret2; int ret3; unsigned char rnd[32]; unsigned char privkey_tmp[32]; - rustsecp256k1_v0_10_0_pubkey pubkey2; - rustsecp256k1_v0_10_0_testrand256_test(rnd); + rustsecp256k1_v0_11_pubkey pubkey2; + testrand256_test(rnd); memcpy(privkey_tmp, privkey, 32); - ret1 = rustsecp256k1_v0_10_0_ec_seckey_tweak_add(CTX, privkey, rnd); - ret2 = rustsecp256k1_v0_10_0_ec_pubkey_tweak_add(CTX, &pubkey, rnd); + ret1 = rustsecp256k1_v0_11_ec_seckey_tweak_add(CTX, privkey, rnd); + ret2 = rustsecp256k1_v0_11_ec_pubkey_tweak_add(CTX, &pubkey, rnd); /* Check that privkey alias gives same result */ - ret3 = rustsecp256k1_v0_10_0_ec_privkey_tweak_add(CTX, privkey_tmp, rnd); + ret3 = rustsecp256k1_v0_11_ec_privkey_tweak_add(CTX, privkey_tmp, rnd); CHECK(ret1 == ret2); CHECK(ret2 == ret3); if (ret1 == 0) { return; } - CHECK(rustsecp256k1_v0_10_0_memcmp_var(privkey, privkey_tmp, 32) == 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(privkey, privkey_tmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Optionally tweak the keys using multiplication. */ - if (rustsecp256k1_v0_10_0_testrand_int(3) == 0) { + if (testrand_int(3) == 0) { int ret1; int ret2; int ret3; unsigned char rnd[32]; unsigned char privkey_tmp[32]; - rustsecp256k1_v0_10_0_pubkey pubkey2; - rustsecp256k1_v0_10_0_testrand256_test(rnd); + rustsecp256k1_v0_11_pubkey pubkey2; + testrand256_test(rnd); memcpy(privkey_tmp, privkey, 32); - ret1 = rustsecp256k1_v0_10_0_ec_seckey_tweak_mul(CTX, privkey, rnd); - ret2 = rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul(CTX, &pubkey, rnd); + ret1 = rustsecp256k1_v0_11_ec_seckey_tweak_mul(CTX, privkey, rnd); + ret2 = rustsecp256k1_v0_11_ec_pubkey_tweak_mul(CTX, &pubkey, rnd); /* Check that privkey alias gives same result */ - ret3 = rustsecp256k1_v0_10_0_ec_privkey_tweak_mul(CTX, privkey_tmp, rnd); + ret3 = rustsecp256k1_v0_11_ec_privkey_tweak_mul(CTX, privkey_tmp, rnd); CHECK(ret1 == ret2); CHECK(ret2 == ret3); if (ret1 == 0) { return; } - CHECK(rustsecp256k1_v0_10_0_memcmp_var(privkey, privkey_tmp, 32) == 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(privkey, privkey_tmp, 32) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey2, privkey) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Sign. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &signature[4], message, privkey, NULL, NULL) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &signature[1], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &signature[4], message, privkey, NULL, NULL) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &signature[1], message, privkey, NULL, extra) == 1); extra[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &signature[2], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &signature[2], message, privkey, NULL, extra) == 1); extra[31] = 0; extra[0] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &signature[3], message, privkey, NULL, extra) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[0], &signature[4], sizeof(signature[0])) == 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[0], &signature[1], sizeof(signature[0])) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[0], &signature[2], sizeof(signature[0])) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[0], &signature[3], sizeof(signature[0])) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[1], &signature[2], sizeof(signature[0])) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[1], &signature[3], sizeof(signature[0])) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[2], &signature[3], sizeof(signature[0])) != 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &signature[3], message, privkey, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[0], &signature[4], sizeof(signature[0])) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[0], &signature[1], sizeof(signature[0])) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[0], &signature[2], sizeof(signature[0])) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[0], &signature[3], sizeof(signature[0])) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[1], &signature[2], sizeof(signature[0])) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[1], &signature[3], sizeof(signature[0])) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[2], &signature[3], sizeof(signature[0])) != 0); /* Verify. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[1], message, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[2], message, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[3], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[1], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[2], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[3], message, &pubkey) == 1); /* Test lower-S form, malleate, verify and fail, test again, malleate again */ - CHECK(!rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, NULL, &signature[0])); - rustsecp256k1_v0_10_0_ecdsa_signature_load(CTX, &r, &s, &signature[0]); - rustsecp256k1_v0_10_0_scalar_negate(&s, &s); - rustsecp256k1_v0_10_0_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, NULL, &signature[5])); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, &signature[5], &signature[5])); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, NULL, &signature[5])); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, &signature[5], &signature[5])); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 1); - rustsecp256k1_v0_10_0_scalar_negate(&s, &s); - rustsecp256k1_v0_10_0_ecdsa_signature_save(&signature[5], &r, &s); - CHECK(!rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, NULL, &signature[5])); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&signature[5], &signature[0], 64) == 0); + CHECK(!rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, NULL, &signature[0])); + rustsecp256k1_v0_11_ecdsa_signature_load(CTX, &r, &s, &signature[0]); + rustsecp256k1_v0_11_scalar_negate(&s, &s); + rustsecp256k1_v0_11_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, NULL, &signature[5])); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, &signature[5], &signature[5])); + CHECK(!rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, NULL, &signature[5])); + CHECK(!rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, &signature[5], &signature[5])); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 1); + rustsecp256k1_v0_11_scalar_negate(&s, &s); + rustsecp256k1_v0_11_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(!rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, NULL, &signature[5])); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[5], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&signature[5], &signature[0], 64) == 0); /* Serialize/parse DER and verify again */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); memset(&signature[0], 0, sizeof(signature[0])); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 1); /* Serialize/destroy/parse DER and verify again. */ siglen = 74; - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); - sig[rustsecp256k1_v0_10_0_testrand_int(siglen)] += 1 + rustsecp256k1_v0_10_0_testrand_int(255); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 0 || - rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, sig, &siglen, &signature[0]) == 1); + sig[testrand_int(siglen)] += 1 + testrand_int(255); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &signature[0], sig, siglen) == 0 || + rustsecp256k1_v0_11_ecdsa_verify(CTX, &signature[0], message, &pubkey) == 0); } static void test_random_pubkeys(void) { - rustsecp256k1_v0_10_0_ge elem; - rustsecp256k1_v0_10_0_ge elem2; + rustsecp256k1_v0_11_ge elem; + rustsecp256k1_v0_11_ge elem2; unsigned char in[65]; /* Generate some randomly sized pubkeys. */ - size_t len = rustsecp256k1_v0_10_0_testrand_bits(2) == 0 ? 65 : 33; - if (rustsecp256k1_v0_10_0_testrand_bits(2) == 0) { - len = rustsecp256k1_v0_10_0_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] = rustsecp256k1_v0_10_0_testrand_bits(1) ? 4 : (rustsecp256k1_v0_10_0_testrand_bits(1) ? 6 : 7); + in[0] = testrand_bits(1) ? 4 : (testrand_bits(1) ? 6 : 7); } else { - in[0] = rustsecp256k1_v0_10_0_testrand_bits(1) ? 2 : 3; + in[0] = testrand_bits(1) ? 2 : 3; } - if (rustsecp256k1_v0_10_0_testrand_bits(3) == 0) { - in[0] = rustsecp256k1_v0_10_0_testrand_bits(8); + if (testrand_bits(3) == 0) { + in[0] = testrand_bits(8); } if (len > 1) { - rustsecp256k1_v0_10_0_testrand256(&in[1]); + testrand256(&in[1]); } if (len > 33) { - rustsecp256k1_v0_10_0_testrand256(&in[33]); + testrand256(&in[33]); } - if (rustsecp256k1_v0_10_0_eckey_pubkey_parse(&elem, in, len)) { + if (rustsecp256k1_v0_11_eckey_pubkey_parse(&elem, in, len)) { unsigned char out[65]; unsigned char firstb; int res; size_t size = len; firstb = in[0]; /* If the pubkey can be parsed, it should round-trip... */ - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&elem, out, &size, len == 33)); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_serialize(&elem, out, &size, len == 33)); CHECK(size == len); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&in[1], &out[1], len-1) == 0); + CHECK(rustsecp256k1_v0_11_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(rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&elem, in, &size, 0)); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_serialize(&elem, in, &size, 0)); CHECK(size == 65); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&elem2, in, size)); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&elem2, &elem)); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&elem2, in, size)); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&elem2, &elem)); /* Check that the X9.62 hybrid type is checked. */ - in[0] = rustsecp256k1_v0_10_0_testrand_bits(1) ? 6 : 7; - res = rustsecp256k1_v0_10_0_eckey_pubkey_parse(&elem2, in, size); + in[0] = testrand_bits(1) ? 6 : 7; + res = rustsecp256k1_v0_11_eckey_pubkey_parse(&elem2, in, size); if (firstb == 2 || firstb == 3) { if (in[0] == firstb + 4) { CHECK(res); @@ -6544,9 +6561,9 @@ static void test_random_pubkeys(void) { } } if (res) { - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&elem, &elem2)); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_serialize(&elem, out, &size, 0)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&in[1], &out[1], 64) == 0); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&elem, &elem2)); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_serialize(&elem, out, &size, 0)); + CHECK(rustsecp256k1_v0_11_memcmp_var(&in[1], &out[1], 64) == 0); } } } @@ -6562,40 +6579,187 @@ static void run_pubkey_comparison(void) { 0xde, 0x36, 0x0e, 0x87, 0x59, 0x8f, 0x3c, 0x01, 0x36, 0x2a, 0x2a, 0xb8, 0xc6, 0xf4, 0x5e, 0x4d, 0xb2, 0xc2, 0xd5, 0x03, 0xa7, 0xf9, 0xf1, 0x4f, 0xa8, 0xfa, 0x95, 0xa8, 0xe9, 0x69, 0x76, 0x1c }; - rustsecp256k1_v0_10_0_pubkey pk1; - rustsecp256k1_v0_10_0_pubkey pk2; - - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pk1, pk1_ser, sizeof(pk1_ser)) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pk2, pk2_ser, sizeof(pk2_ser)) == 1); - - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, NULL, &pk2) < 0)); - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk1, NULL) > 0)); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk1, &pk2) < 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk1, &pk1) == 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk2, &pk2) == 0); + rustsecp256k1_v0_11_pubkey pk1; + rustsecp256k1_v0_11_pubkey pk2; + + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pk1, pk1_ser, sizeof(pk1_ser)) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pk2, pk2_ser, sizeof(pk2_ser)) == 1); + + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, NULL, &pk2) < 0)); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk1, NULL) > 0)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk1, &pk2) < 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk1, &pk1) == 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk2, &pk2) == 0); { - rustsecp256k1_v0_10_0_pubkey pk_tmp; + rustsecp256k1_v0_11_pubkey pk_tmp; memset(&pk_tmp, 0, sizeof(pk_tmp)); /* illegal pubkey */ - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk_tmp, &pk2) < 0)); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk_tmp, &pk2) < 0)); { int32_t ecount = 0; - rustsecp256k1_v0_10_0_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk_tmp, &pk_tmp) == 0); + rustsecp256k1_v0_11_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk_tmp, &pk_tmp) == 0); CHECK(ecount == 2); - rustsecp256k1_v0_10_0_context_set_illegal_callback(CTX, NULL, NULL); + rustsecp256k1_v0_11_context_set_illegal_callback(CTX, NULL, NULL); } - CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk2, &pk_tmp) > 0)); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk2, &pk_tmp) > 0)); } /* Make pk2 the same as pk1 but with 3 rather than 2. Note that in * an uncompressed encoding, these would have the opposite ordering */ pk1_ser[0] = 3; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pk2, pk1_ser, sizeof(pk1_ser)) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk1, &pk2) < 0); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pk2, pk1_ser, sizeof(pk1_ser)) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk1, &pk2) < 0); + CHECK(rustsecp256k1_v0_11_ec_pubkey_cmp(CTX, &pk2, &pk1) > 0); +} + +static void test_sort_helper(rustsecp256k1_v0_11_pubkey *pk, size_t *pk_order, size_t n_pk) { + size_t i; + const rustsecp256k1_v0_11_pubkey *pk_test[5]; + + for (i = 0; i < n_pk; i++) { + pk_test[i] = &pk[pk_order[i]]; + } + rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pk_test, n_pk); + for (i = 0; i < n_pk; i++) { + CHECK(rustsecp256k1_v0_11_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 = testrand_int(i + 1); + tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } +} + +static void test_sort_api(void) { + rustsecp256k1_v0_11_pubkey pks[2]; + const rustsecp256k1_v0_11_pubkey *pks_ptr[2]; + + pks_ptr[0] = &pks[0]; + pks_ptr[1] = &pks[1]; + + testutil_random_pubkey_test(&pks[0]); + testutil_random_pubkey_test(&pks[1]); + + CHECK(rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_sort(CTX, NULL, 2)); + CHECK(rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pks_ptr, 0) == 1); + /* Test illegal public keys */ + memset(&pks[0], 0, sizeof(pks[0])); + CHECK_ILLEGAL_VOID(CTX, CHECK(rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pks_ptr, 2) == 1)); + memset(&pks[1], 0, sizeof(pks[1])); + { + int32_t ecount = 0; + rustsecp256k1_v0_11_context_set_illegal_callback(CTX, counting_callback_fn, &ecount); + CHECK(rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pks_ptr, 2) == 1); + CHECK(ecount == 2); + rustsecp256k1_v0_11_context_set_illegal_callback(CTX, NULL, NULL); + } +} + +static void test_sort(void) { + rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_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 rustsecp256k1_v0_11_pubkey *pk_ptr[5]; + for (j = 0; j < 5; j++) { + testutil_random_pubkey_test(&pk[j]); + pk_ptr[j] = &pk[j]; + } + rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pk_ptr, 5); + for (j = 1; j < 5; j++) { + CHECK(rustsecp256k1_v0_11_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 } + }; + rustsecp256k1_v0_11_pubkey pubkeys[N_PUBKEYS]; + rustsecp256k1_v0_11_pubkey *sorted[N_PUBKEYS]; + const rustsecp256k1_v0_11_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(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkeys[i], pk_ser[i], sizeof(pk_ser[i]))); + pks_ptr[i] = &pubkeys[i]; + } + CHECK(rustsecp256k1_v0_11_ec_pubkey_sort(CTX, pks_ptr, N_PUBKEYS) == 1); + for (i = 0; i < N_PUBKEYS; i++) { + CHECK(rustsecp256k1_v0_11_memcmp_var(pks_ptr[i], sorted[i], sizeof(rustsecp256k1_v0_11_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++) { @@ -6615,36 +6779,36 @@ static int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int cer int ret = 0; - rustsecp256k1_v0_10_0_ecdsa_signature sig_der; + rustsecp256k1_v0_11_ecdsa_signature sig_der; unsigned char roundtrip_der[2048]; unsigned char compact_der[64]; size_t len_der = 2048; int parsed_der = 0, valid_der = 0, roundtrips_der = 0; - rustsecp256k1_v0_10_0_ecdsa_signature sig_der_lax; + rustsecp256k1_v0_11_ecdsa_signature sig_der_lax; unsigned char roundtrip_der_lax[2048]; unsigned char compact_der_lax[64]; size_t len_der_lax = 2048; int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; - parsed_der = rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig_der, sig, siglen); + parsed_der = rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig_der, sig, siglen); if (parsed_der) { - ret |= (!rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(CTX, compact_der, &sig_der)) << 0; - valid_der = (rustsecp256k1_v0_10_0_memcmp_var(compact_der, zeroes, 32) != 0) && (rustsecp256k1_v0_10_0_memcmp_var(compact_der + 32, zeroes, 32) != 0); + ret |= (!rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(CTX, compact_der, &sig_der)) << 0; + valid_der = (rustsecp256k1_v0_11_memcmp_var(compact_der, zeroes, 32) != 0) && (rustsecp256k1_v0_11_memcmp_var(compact_der + 32, zeroes, 32) != 0); } if (valid_der) { - ret |= (!rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, roundtrip_der, &len_der, &sig_der)) << 1; - roundtrips_der = (len_der == siglen) && rustsecp256k1_v0_10_0_memcmp_var(roundtrip_der, sig, siglen) == 0; + ret |= (!rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, roundtrip_der, &len_der, &sig_der)) << 1; + roundtrips_der = (len_der == siglen) && rustsecp256k1_v0_11_memcmp_var(roundtrip_der, sig, siglen) == 0; } - parsed_der_lax = rustsecp256k1_v0_10_0_ecdsa_signature_parse_der_lax(CTX, &sig_der_lax, sig, siglen); + parsed_der_lax = rustsecp256k1_v0_11_ecdsa_signature_parse_der_lax(CTX, &sig_der_lax, sig, siglen); if (parsed_der_lax) { - ret |= (!rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(CTX, compact_der_lax, &sig_der_lax)) << 10; - valid_der_lax = (rustsecp256k1_v0_10_0_memcmp_var(compact_der_lax, zeroes, 32) != 0) && (rustsecp256k1_v0_10_0_memcmp_var(compact_der_lax + 32, zeroes, 32) != 0); + ret |= (!rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(CTX, compact_der_lax, &sig_der_lax)) << 10; + valid_der_lax = (rustsecp256k1_v0_11_memcmp_var(compact_der_lax, zeroes, 32) != 0) && (rustsecp256k1_v0_11_memcmp_var(compact_der_lax + 32, zeroes, 32) != 0); } if (valid_der_lax) { - ret |= (!rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; - roundtrips_der_lax = (len_der_lax == siglen) && rustsecp256k1_v0_10_0_memcmp_var(roundtrip_der_lax, sig, siglen) == 0; + ret |= (!rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; + roundtrips_der_lax = (len_der_lax == siglen) && rustsecp256k1_v0_11_memcmp_var(roundtrip_der_lax, sig, siglen) == 0; } if (certainly_der) { @@ -6660,7 +6824,7 @@ static int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int cer if (valid_der) { ret |= (!roundtrips_der_lax) << 12; ret |= (len_der != len_der_lax) << 13; - ret |= ((len_der != len_der_lax) || (rustsecp256k1_v0_10_0_memcmp_var(roundtrip_der_lax, roundtrip_der, len_der) != 0)) << 14; + ret |= ((len_der != len_der_lax) || (rustsecp256k1_v0_11_memcmp_var(roundtrip_der_lax, roundtrip_der, len_der) != 0)) << 14; } ret |= (roundtrips_der != roundtrips_der_lax) << 15; if (parsed_der) { @@ -6684,27 +6848,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 = rustsecp256k1_v0_10_0_testrand_bits(3); + int action = testrand_bits(3); if (action < 1 && *len > 3) { /* Delete a byte. */ - pos = rustsecp256k1_v0_10_0_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 = rustsecp256k1_v0_10_0_testrand_int(1 + *len); + pos = testrand_int(1 + *len); memmove(sig + pos + 1, sig + pos, *len - pos); - sig[pos] = rustsecp256k1_v0_10_0_testrand_bits(8); + sig[pos] = testrand_bits(8); (*len)++; return; } else if (action < 4) { /* Modify a byte. */ - sig[rustsecp256k1_v0_10_0_testrand_int(*len)] += 1 + rustsecp256k1_v0_10_0_testrand_int(255); + sig[testrand_int(*len)] += 1 + testrand_int(255); return; } else { /* action < 8 */ /* Modify a bit. */ - sig[rustsecp256k1_v0_10_0_testrand_int(*len)] ^= 1 << rustsecp256k1_v0_10_0_testrand_bits(3); + sig[testrand_int(*len)] ^= 1 << testrand_bits(3); return; } } @@ -6717,23 +6881,23 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly int n; *len = 0; - der = rustsecp256k1_v0_10_0_testrand_bits(2) == 0; + der = testrand_bits(2) == 0; *certainly_der = der; *certainly_not_der = 0; - indet = der ? 0 : rustsecp256k1_v0_10_0_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 : (rustsecp256k1_v0_10_0_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] ? rustsecp256k1_v0_10_0_testrand_int(33) : 32 + rustsecp256k1_v0_10_0_testrand_int(200) * rustsecp256k1_v0_10_0_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 : rustsecp256k1_v0_10_0_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 + rustsecp256k1_v0_10_0_testrand_bits(7) : 1 + rustsecp256k1_v0_10_0_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] ? rustsecp256k1_v0_10_0_testrand_int(3) : rustsecp256k1_v0_10_0_testrand_int(300 - nlen[n]) * rustsecp256k1_v0_10_0_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; } @@ -6742,7 +6906,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 = rustsecp256k1_v0_10_0_testrand_int(127 - nlenlen[n]) * rustsecp256k1_v0_10_0_testrand_bits(4) * rustsecp256k1_v0_10_0_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; @@ -6756,7 +6920,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 : rustsecp256k1_v0_10_0_testrand_int(980 - tlen) * rustsecp256k1_v0_10_0_testrand_bits(3) / 8; + elen = (der || indet) ? 0 : testrand_int(980 - tlen) * testrand_bits(3) / 8; if (elen != 0) { *certainly_not_der = 1; } @@ -6764,7 +6928,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 : rustsecp256k1_v0_10_0_testrand_int(990 - tlen) * rustsecp256k1_v0_10_0_testrand_bits(3) / 8; + glen = der ? 0 : testrand_int(990 - tlen) * testrand_bits(3) / 8; if (glen != 0) { *certainly_not_der = 1; } @@ -6779,7 +6943,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 = rustsecp256k1_v0_10_0_testrand_int(127 - tlenlen) * rustsecp256k1_v0_10_0_testrand_bits(4) * rustsecp256k1_v0_10_0_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; @@ -6830,13 +6994,13 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly nlen[n]--; } /* Generate remaining random bytes of number */ - rustsecp256k1_v0_10_0_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. */ - rustsecp256k1_v0_10_0_testrand_bytes_test(sig + *len, elen); + testrand_bytes_test(sig + *len, elen); *len += elen; /* Generate end-of-contents bytes. */ @@ -6848,7 +7012,7 @@ static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly CHECK(tlen + glen <= 1121); /* Generate random garbage outside tuple. */ - rustsecp256k1_v0_10_0_testrand_bytes_test(sig + *len, glen); + testrand_bytes_test(sig + *len, glen); *len += glen; tlen += glen; CHECK(tlen <= 1121); @@ -6889,22 +7053,22 @@ static void run_ecdsa_der_parse(void) { /* Tests several edge cases. */ static void test_ecdsa_edge_cases(void) { int t; - rustsecp256k1_v0_10_0_ecdsa_signature sig; + rustsecp256k1_v0_11_ecdsa_signature sig; /* Test the case where ECDSA recomputes a point that is infinity. */ { - rustsecp256k1_v0_10_0_gej keyj; - rustsecp256k1_v0_10_0_ge key; - rustsecp256k1_v0_10_0_scalar msg; - rustsecp256k1_v0_10_0_scalar sr, ss; - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 1); - rustsecp256k1_v0_10_0_scalar_negate(&ss, &ss); - rustsecp256k1_v0_10_0_scalar_inverse(&ss, &ss); - rustsecp256k1_v0_10_0_scalar_set_int(&sr, 1); - rustsecp256k1_v0_10_0_ecmult_gen(&CTX->ecmult_gen_ctx, &keyj, &sr); - rustsecp256k1_v0_10_0_ge_set_gej(&key, &keyj); + rustsecp256k1_v0_11_gej keyj; + rustsecp256k1_v0_11_ge key; + rustsecp256k1_v0_11_scalar msg; + rustsecp256k1_v0_11_scalar sr, ss; + rustsecp256k1_v0_11_scalar_set_int(&ss, 1); + rustsecp256k1_v0_11_scalar_negate(&ss, &ss); + rustsecp256k1_v0_11_scalar_inverse(&ss, &ss); + rustsecp256k1_v0_11_scalar_set_int(&sr, 1); + rustsecp256k1_v0_11_ecmult_gen(&CTX->ecmult_gen_ctx, &keyj, &sr); + rustsecp256k1_v0_11_ge_set_gej(&key, &keyj); msg = ss; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); } /* Verify signature with r of zero fails. */ @@ -6916,14 +7080,14 @@ static void test_ecdsa_edge_cases(void) { 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 }; - rustsecp256k1_v0_10_0_ge key; - rustsecp256k1_v0_10_0_scalar msg; - rustsecp256k1_v0_10_0_scalar sr, ss; - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 1); - rustsecp256k1_v0_10_0_scalar_set_int(&msg, 0); - rustsecp256k1_v0_10_0_scalar_set_int(&sr, 0); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0); + rustsecp256k1_v0_11_ge key; + rustsecp256k1_v0_11_scalar msg; + rustsecp256k1_v0_11_scalar sr, ss; + rustsecp256k1_v0_11_scalar_set_int(&ss, 1); + rustsecp256k1_v0_11_scalar_set_int(&msg, 0); + rustsecp256k1_v0_11_scalar_set_int(&sr, 0); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify( &sr, &ss, &key, &msg) == 0); } /* Verify signature with s of zero fails. */ @@ -6935,14 +7099,14 @@ static void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; - rustsecp256k1_v0_10_0_ge key; - rustsecp256k1_v0_10_0_scalar msg; - rustsecp256k1_v0_10_0_scalar sr, ss; - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 0); - rustsecp256k1_v0_10_0_scalar_set_int(&msg, 0); - rustsecp256k1_v0_10_0_scalar_set_int(&sr, 1); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); + rustsecp256k1_v0_11_ge key; + rustsecp256k1_v0_11_scalar msg; + rustsecp256k1_v0_11_scalar sr, ss; + rustsecp256k1_v0_11_scalar_set_int(&ss, 0); + rustsecp256k1_v0_11_scalar_set_int(&msg, 0); + rustsecp256k1_v0_11_scalar_set_int(&sr, 1); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); } /* Verify signature with message 0 passes. */ @@ -6961,23 +7125,23 @@ static void test_ecdsa_edge_cases(void) { 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x43 }; - rustsecp256k1_v0_10_0_ge key; - rustsecp256k1_v0_10_0_ge key2; - rustsecp256k1_v0_10_0_scalar msg; - rustsecp256k1_v0_10_0_scalar sr, ss; - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 2); - rustsecp256k1_v0_10_0_scalar_set_int(&msg, 0); - rustsecp256k1_v0_10_0_scalar_set_int(&sr, 2); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - rustsecp256k1_v0_10_0_scalar_negate(&ss, &ss); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0); + rustsecp256k1_v0_11_ge key; + rustsecp256k1_v0_11_ge key2; + rustsecp256k1_v0_11_scalar msg; + rustsecp256k1_v0_11_scalar sr, ss; + rustsecp256k1_v0_11_scalar_set_int(&ss, 2); + rustsecp256k1_v0_11_scalar_set_int(&msg, 0); + rustsecp256k1_v0_11_scalar_set_int(&sr, 2); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_11_scalar_negate(&ss, &ss); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_11_scalar_set_int(&ss, 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0); } /* Verify signature with message 1 passes. */ @@ -7002,24 +7166,24 @@ static void test_ecdsa_edge_cases(void) { 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb }; - rustsecp256k1_v0_10_0_ge key; - rustsecp256k1_v0_10_0_ge key2; - rustsecp256k1_v0_10_0_scalar msg; - rustsecp256k1_v0_10_0_scalar sr, ss; - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 1); - rustsecp256k1_v0_10_0_scalar_set_int(&msg, 1); - rustsecp256k1_v0_10_0_scalar_set_b32(&sr, csr, NULL); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key2, pubkey2, 33)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - rustsecp256k1_v0_10_0_scalar_negate(&ss, &ss); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 2); - rustsecp256k1_v0_10_0_scalar_inverse_var(&ss, &ss); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0); + rustsecp256k1_v0_11_ge key; + rustsecp256k1_v0_11_ge key2; + rustsecp256k1_v0_11_scalar msg; + rustsecp256k1_v0_11_scalar sr, ss; + rustsecp256k1_v0_11_scalar_set_int(&ss, 1); + rustsecp256k1_v0_11_scalar_set_int(&msg, 1); + rustsecp256k1_v0_11_scalar_set_b32(&sr, csr, NULL); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_11_scalar_negate(&ss, &ss); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 1); + rustsecp256k1_v0_11_scalar_set_int(&ss, 2); + rustsecp256k1_v0_11_scalar_inverse_var(&ss, &ss); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key2, &msg) == 0); } /* Verify signature with message -1 passes. */ @@ -7037,25 +7201,25 @@ static void test_ecdsa_edge_cases(void) { 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee }; - rustsecp256k1_v0_10_0_ge key; - rustsecp256k1_v0_10_0_scalar msg; - rustsecp256k1_v0_10_0_scalar sr, ss; - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 1); - rustsecp256k1_v0_10_0_scalar_set_int(&msg, 1); - rustsecp256k1_v0_10_0_scalar_negate(&msg, &msg); - rustsecp256k1_v0_10_0_scalar_set_b32(&sr, csr, NULL); - CHECK(rustsecp256k1_v0_10_0_eckey_pubkey_parse(&key, pubkey, 33)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - rustsecp256k1_v0_10_0_scalar_negate(&ss, &ss); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); - rustsecp256k1_v0_10_0_scalar_set_int(&ss, 3); - rustsecp256k1_v0_10_0_scalar_inverse_var(&ss, &ss); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); + rustsecp256k1_v0_11_ge key; + rustsecp256k1_v0_11_scalar msg; + rustsecp256k1_v0_11_scalar sr, ss; + rustsecp256k1_v0_11_scalar_set_int(&ss, 1); + rustsecp256k1_v0_11_scalar_set_int(&msg, 1); + rustsecp256k1_v0_11_scalar_negate(&msg, &msg); + rustsecp256k1_v0_11_scalar_set_b32(&sr, csr, NULL); + CHECK(rustsecp256k1_v0_11_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); + rustsecp256k1_v0_11_scalar_negate(&ss, &ss); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 1); + rustsecp256k1_v0_11_scalar_set_int(&ss, 3); + rustsecp256k1_v0_11_scalar_inverse_var(&ss, &ss); + CHECK(rustsecp256k1_v0_11_ecdsa_sig_verify(&sr, &ss, &key, &msg) == 0); } /* Signature where s would be zero. */ { - rustsecp256k1_v0_10_0_pubkey pubkey; + rustsecp256k1_v0_11_pubkey pubkey; size_t siglen; unsigned char signature[72]; static const unsigned char nonce[32] = { @@ -7082,42 +7246,42 @@ static void test_ecdsa_edge_cases(void) { 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, }; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce) == 0); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); msg[31] = 0xaa; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_sign(CTX, NULL, msg, key, precomputed_nonce_function, nonce2)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, NULL, key, precomputed_nonce_function, nonce2)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, NULL, precomputed_nonce_function, nonce2)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, key) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_verify(CTX, NULL, msg, &pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, NULL, &pubkey)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg, &pubkey) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ec_pubkey_create(CTX, &pubkey, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_sign(CTX, NULL, msg, key, precomputed_nonce_function, nonce2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, NULL, key, precomputed_nonce_function, nonce2)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, NULL, precomputed_nonce_function, nonce2)); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, key) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_verify(CTX, NULL, msg, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, NULL, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg, &pubkey) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ec_pubkey_create(CTX, &pubkey, NULL)); /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_verify(CTX, &sig, msg, &pubkey)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_verify(CTX, &sig, msg, &pubkey)); siglen = 72; - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, NULL, &siglen, &sig)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, signature, NULL, &sig)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, signature, &siglen, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, signature, &siglen, &sig) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, NULL, signature, siglen)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, NULL, siglen)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &sig, signature, siglen) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, NULL, &siglen, &sig)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, signature, NULL, &sig)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, signature, &siglen, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, signature, &siglen, &sig) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, NULL, signature, siglen)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, NULL, siglen)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &sig, signature, siglen) == 1); siglen = 10; /* Too little room for a signature does not fail via ARGCHECK. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der(CTX, signature, &siglen, &sig) == 0); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_normalize(CTX, NULL, NULL)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(CTX, NULL, &sig)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(CTX, signature, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact(CTX, signature, &sig) == 1); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(CTX, NULL, signature)); - CHECK_ILLEGAL(CTX, rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(CTX, &sig, NULL)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(CTX, &sig, signature) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_der(CTX, signature, &siglen, &sig) == 0); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_normalize(CTX, NULL, NULL)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(CTX, NULL, &sig)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(CTX, signature, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_serialize_compact(CTX, signature, &sig) == 1); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_parse_compact(CTX, NULL, signature)); + CHECK_ILLEGAL(CTX, rustsecp256k1_v0_11_ecdsa_signature_parse_compact(CTX, &sig, NULL)); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_compact(CTX, &sig, signature) == 1); memset(signature, 255, 64); - CHECK(rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact(CTX, &sig, signature) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_signature_parse_compact(CTX, &sig, signature) == 0); } /* Nonce function corner cases. */ @@ -7126,43 +7290,43 @@ static void test_ecdsa_edge_cases(void) { int i; unsigned char key[32]; unsigned char msg[32]; - rustsecp256k1_v0_10_0_ecdsa_signature sig2; - rustsecp256k1_v0_10_0_scalar sr[512], ss; + rustsecp256k1_v0_11_ecdsa_signature sig2; + rustsecp256k1_v0_11_scalar sr[512], ss; const unsigned char *extra; extra = t == 0 ? NULL : zero; memset(msg, 0, 32); msg[31] = 1; /* High key results in signature failure. */ memset(key, 0xFF, 32); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, NULL, extra) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, NULL, extra) == 0); CHECK(is_empty_signature(&sig)); /* Zero key results in signature failure. */ memset(key, 0, 32); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, NULL, extra) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, NULL, extra) == 0); CHECK(is_empty_signature(&sig)); /* Nonce function failure results in signature failure. */ key[31] = 1; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, nonce_function_test_fail, extra) == 0); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, nonce_function_test_fail, extra) == 0); CHECK(is_empty_signature(&sig)); /* The retry loop successfully makes its way to the first good value. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig, msg, key, nonce_function_test_retry, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig, msg, key, nonce_function_test_retry, extra) == 1); CHECK(!is_empty_signature(&sig)); - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); CHECK(!is_empty_signature(&sig2)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&sig, &sig2, sizeof(sig)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function is deterministic. */ - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&sig, &sig2, sizeof(sig)) == 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function changes output with different messages. */ for(i = 0; i < 256; i++) { int j; msg[0] = i; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - rustsecp256k1_v0_10_0_ecdsa_signature_load(CTX, &sr[i], &ss, &sig2); + rustsecp256k1_v0_11_ecdsa_signature_load(CTX, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { - CHECK(!rustsecp256k1_v0_10_0_scalar_eq(&sr[i], &sr[j])); + CHECK(!rustsecp256k1_v0_11_scalar_eq(&sr[i], &sr[j])); } } msg[0] = 0; @@ -7171,11 +7335,11 @@ static void test_ecdsa_edge_cases(void) { for(i = 256; i < 512; i++) { int j; key[0] = i - 256; - CHECK(rustsecp256k1_v0_10_0_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); + CHECK(rustsecp256k1_v0_11_ecdsa_sign(CTX, &sig2, msg, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - rustsecp256k1_v0_10_0_ecdsa_signature_load(CTX, &sr[i], &ss, &sig2); + rustsecp256k1_v0_11_ecdsa_signature_load(CTX, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { - CHECK(!rustsecp256k1_v0_10_0_scalar_eq(&sr[i], &sr[j])); + CHECK(!rustsecp256k1_v0_11_scalar_eq(&sr[i], &sr[j])); } } key[0] = 0; @@ -7200,12 +7364,12 @@ static void test_ecdsa_edge_cases(void) { SECP256K1_CHECKMEM_CHECK(nonce3,32); CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); SECP256K1_CHECKMEM_CHECK(nonce4,32); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce, nonce2, 32) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce, nonce3, 32) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce, nonce4, 32) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce2, nonce3, 32) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce2, nonce4, 32) != 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(nonce3, nonce4, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce, nonce2, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce, nonce3, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce, nonce4, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce2, nonce3, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce2, nonce4, 32) != 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(nonce3, nonce4, 32) != 0); } @@ -7234,29 +7398,29 @@ static void run_ecdsa_edge_cases(void) { The tests check for known attacks (range checks in (r,s), arithmetic errors, malleability). */ static void test_ecdsa_wycheproof(void) { - #include "wycheproof/ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.h" + #include "wycheproof/ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.h" int t; for (t = 0; t < SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS; t++) { - rustsecp256k1_v0_10_0_ecdsa_signature signature; - rustsecp256k1_v0_10_0_sha256 hasher; - rustsecp256k1_v0_10_0_pubkey pubkey; + rustsecp256k1_v0_11_ecdsa_signature signature; + rustsecp256k1_v0_11_sha256 hasher; + rustsecp256k1_v0_11_pubkey pubkey; const unsigned char *msg, *sig, *pk; unsigned char out[32] = {0}; int actual_verify = 0; memset(&pubkey, 0, sizeof(pubkey)); pk = &wycheproof_ecdsa_public_keys[testvectors[t].pk_offset]; - CHECK(rustsecp256k1_v0_10_0_ec_pubkey_parse(CTX, &pubkey, pk, 65) == 1); + CHECK(rustsecp256k1_v0_11_ec_pubkey_parse(CTX, &pubkey, pk, 65) == 1); - rustsecp256k1_v0_10_0_sha256_initialize(&hasher); + rustsecp256k1_v0_11_sha256_initialize(&hasher); msg = &wycheproof_ecdsa_messages[testvectors[t].msg_offset]; - rustsecp256k1_v0_10_0_sha256_write(&hasher, msg, testvectors[t].msg_len); - rustsecp256k1_v0_10_0_sha256_finalize(&hasher, out); + rustsecp256k1_v0_11_sha256_write(&hasher, msg, testvectors[t].msg_len); + rustsecp256k1_v0_11_sha256_finalize(&hasher, out); sig = &wycheproof_ecdsa_signatures[testvectors[t].sig_offset]; - if (rustsecp256k1_v0_10_0_ecdsa_signature_parse_der(CTX, &signature, sig, testvectors[t].sig_len) == 1) { - actual_verify = rustsecp256k1_v0_10_0_ecdsa_verify(CTX, (const rustsecp256k1_v0_10_0_ecdsa_signature *)&signature, out, &pubkey); + if (rustsecp256k1_v0_11_ecdsa_signature_parse_der(CTX, &signature, sig, testvectors[t].sig_len) == 1) { + actual_verify = rustsecp256k1_v0_11_ecdsa_verify(CTX, (const rustsecp256k1_v0_11_ecdsa_signature *)&signature, out, &pubkey); } CHECK(testvectors[t].expected_verify == actual_verify); } @@ -7283,36 +7447,52 @@ 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 -static void run_rustsecp256k1_v0_10_0_memczero_test(void) { +static void run_rustsecp256k1_v0_11_memczero_test(void) { unsigned char buf1[6] = {1, 2, 3, 4, 5, 6}; unsigned char buf2[sizeof(buf1)]; - /* rustsecp256k1_v0_10_0_memczero(..., ..., 0) is a noop. */ + /* rustsecp256k1_v0_11_memczero(..., ..., 0) is a noop. */ memcpy(buf2, buf1, sizeof(buf1)); - rustsecp256k1_v0_10_0_memczero(buf1, sizeof(buf1), 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); + rustsecp256k1_v0_11_memczero(buf1, sizeof(buf1), 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); - /* rustsecp256k1_v0_10_0_memczero(..., ..., 1) zeros the buffer. */ + /* rustsecp256k1_v0_11_memczero(..., ..., 1) zeros the buffer. */ memset(buf2, 0, sizeof(buf2)); - rustsecp256k1_v0_10_0_memczero(buf1, sizeof(buf1) , 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); + rustsecp256k1_v0_11_memczero(buf1, sizeof(buf1) , 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(buf1, buf2, sizeof(buf1)) == 0); +} + + +static void run_rustsecp256k1_v0_11_is_zero_array_test(void) { + unsigned char buf1[3] = {0, 1}; + unsigned char buf2[3] = {1, 0}; + + CHECK(rustsecp256k1_v0_11_is_zero_array(buf1, 0) == 1); + CHECK(rustsecp256k1_v0_11_is_zero_array(buf1, 1) == 1); + CHECK(rustsecp256k1_v0_11_is_zero_array(buf1, 2) == 0); + CHECK(rustsecp256k1_v0_11_is_zero_array(buf2, 1) == 0); + CHECK(rustsecp256k1_v0_11_is_zero_array(buf2, 2) == 0); } -static void run_rustsecp256k1_v0_10_0_byteorder_tests(void) { +static void run_rustsecp256k1_v0_11_byteorder_tests(void) { { const uint32_t x = 0xFF03AB45; const unsigned char x_be[4] = {0xFF, 0x03, 0xAB, 0x45}; unsigned char buf[4]; uint32_t x_; - rustsecp256k1_v0_10_0_write_be32(buf, x); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf, x_be, sizeof(buf)) == 0); + rustsecp256k1_v0_11_write_be32(buf, x); + CHECK(rustsecp256k1_v0_11_memcmp_var(buf, x_be, sizeof(buf)) == 0); - x_ = rustsecp256k1_v0_10_0_read_be32(buf); + x_ = rustsecp256k1_v0_11_read_be32(buf); CHECK(x == x_); } @@ -7322,10 +7502,10 @@ static void run_rustsecp256k1_v0_10_0_byteorder_tests(void) { unsigned char buf[8]; uint64_t x_; - rustsecp256k1_v0_10_0_write_be64(buf, x); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(buf, x_be, sizeof(buf)) == 0); + rustsecp256k1_v0_11_write_be64(buf, x); + CHECK(rustsecp256k1_v0_11_memcmp_var(buf, x_be, sizeof(buf)) == 0); - x_ = rustsecp256k1_v0_10_0_read_be64(buf); + x_ = rustsecp256k1_v0_11_read_be64(buf); CHECK(x == x_); } } @@ -7334,145 +7514,145 @@ static void int_cmov_test(void) { int r = INT_MAX; int a = 0; - rustsecp256k1_v0_10_0_int_cmov(&r, &a, 0); + rustsecp256k1_v0_11_int_cmov(&r, &a, 0); CHECK(r == INT_MAX); r = 0; a = INT_MAX; - rustsecp256k1_v0_10_0_int_cmov(&r, &a, 1); + rustsecp256k1_v0_11_int_cmov(&r, &a, 1); CHECK(r == INT_MAX); a = 0; - rustsecp256k1_v0_10_0_int_cmov(&r, &a, 1); + rustsecp256k1_v0_11_int_cmov(&r, &a, 1); CHECK(r == 0); a = 1; - rustsecp256k1_v0_10_0_int_cmov(&r, &a, 1); + rustsecp256k1_v0_11_int_cmov(&r, &a, 1); CHECK(r == 1); r = 1; a = 0; - rustsecp256k1_v0_10_0_int_cmov(&r, &a, 0); + rustsecp256k1_v0_11_int_cmov(&r, &a, 0); CHECK(r == 1); } static void fe_cmov_test(void) { - static const rustsecp256k1_v0_10_0_fe zero = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0); - static const rustsecp256k1_v0_10_0_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - static const rustsecp256k1_v0_10_0_fe max = SECP256K1_FE_CONST( + static const rustsecp256k1_v0_11_fe zero = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0); + static const rustsecp256k1_v0_11_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + static const rustsecp256k1_v0_11_fe max = SECP256K1_FE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); - rustsecp256k1_v0_10_0_fe r = max; - rustsecp256k1_v0_10_0_fe a = zero; + rustsecp256k1_v0_11_fe r = max; + rustsecp256k1_v0_11_fe a = zero; - rustsecp256k1_v0_10_0_fe_cmov(&r, &a, 0); + rustsecp256k1_v0_11_fe_cmov(&r, &a, 0); CHECK(fe_identical(&r, &max)); r = zero; a = max; - rustsecp256k1_v0_10_0_fe_cmov(&r, &a, 1); + rustsecp256k1_v0_11_fe_cmov(&r, &a, 1); CHECK(fe_identical(&r, &max)); a = zero; - rustsecp256k1_v0_10_0_fe_cmov(&r, &a, 1); + rustsecp256k1_v0_11_fe_cmov(&r, &a, 1); CHECK(fe_identical(&r, &zero)); a = one; - rustsecp256k1_v0_10_0_fe_cmov(&r, &a, 1); + rustsecp256k1_v0_11_fe_cmov(&r, &a, 1); CHECK(fe_identical(&r, &one)); r = one; a = zero; - rustsecp256k1_v0_10_0_fe_cmov(&r, &a, 0); + rustsecp256k1_v0_11_fe_cmov(&r, &a, 0); CHECK(fe_identical(&r, &one)); } static void fe_storage_cmov_test(void) { - static const rustsecp256k1_v0_10_0_fe_storage zero = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0); - static const rustsecp256k1_v0_10_0_fe_storage one = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1); - static const rustsecp256k1_v0_10_0_fe_storage max = SECP256K1_FE_STORAGE_CONST( + static const rustsecp256k1_v0_11_fe_storage zero = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0); + static const rustsecp256k1_v0_11_fe_storage one = SECP256K1_FE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + static const rustsecp256k1_v0_11_fe_storage max = SECP256K1_FE_STORAGE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); - rustsecp256k1_v0_10_0_fe_storage r = max; - rustsecp256k1_v0_10_0_fe_storage a = zero; + rustsecp256k1_v0_11_fe_storage r = max; + rustsecp256k1_v0_11_fe_storage a = zero; - rustsecp256k1_v0_10_0_fe_storage_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &max, sizeof(r)) == 0); + rustsecp256k1_v0_11_fe_storage_cmov(&r, &a, 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &max, sizeof(r)) == 0); r = zero; a = max; - rustsecp256k1_v0_10_0_fe_storage_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &max, sizeof(r)) == 0); + rustsecp256k1_v0_11_fe_storage_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &max, sizeof(r)) == 0); a = zero; - rustsecp256k1_v0_10_0_fe_storage_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &zero, sizeof(r)) == 0); + rustsecp256k1_v0_11_fe_storage_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &zero, sizeof(r)) == 0); a = one; - rustsecp256k1_v0_10_0_fe_storage_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &one, sizeof(r)) == 0); + rustsecp256k1_v0_11_fe_storage_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &one, sizeof(r)) == 0); r = one; a = zero; - rustsecp256k1_v0_10_0_fe_storage_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &one, sizeof(r)) == 0); + rustsecp256k1_v0_11_fe_storage_cmov(&r, &a, 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &one, sizeof(r)) == 0); } static void scalar_cmov_test(void) { - static const rustsecp256k1_v0_10_0_scalar max = SECP256K1_SCALAR_CONST( + static const rustsecp256k1_v0_11_scalar max = SECP256K1_SCALAR_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364140UL ); - rustsecp256k1_v0_10_0_scalar r = max; - rustsecp256k1_v0_10_0_scalar a = rustsecp256k1_v0_10_0_scalar_zero; + rustsecp256k1_v0_11_scalar r = max; + rustsecp256k1_v0_11_scalar a = rustsecp256k1_v0_11_scalar_zero; - rustsecp256k1_v0_10_0_scalar_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &max, sizeof(r)) == 0); + rustsecp256k1_v0_11_scalar_cmov(&r, &a, 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &max, sizeof(r)) == 0); - r = rustsecp256k1_v0_10_0_scalar_zero; a = max; - rustsecp256k1_v0_10_0_scalar_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &max, sizeof(r)) == 0); + r = rustsecp256k1_v0_11_scalar_zero; a = max; + rustsecp256k1_v0_11_scalar_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &max, sizeof(r)) == 0); - a = rustsecp256k1_v0_10_0_scalar_zero; - rustsecp256k1_v0_10_0_scalar_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &rustsecp256k1_v0_10_0_scalar_zero, sizeof(r)) == 0); + a = rustsecp256k1_v0_11_scalar_zero; + rustsecp256k1_v0_11_scalar_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &rustsecp256k1_v0_11_scalar_zero, sizeof(r)) == 0); - a = rustsecp256k1_v0_10_0_scalar_one; - rustsecp256k1_v0_10_0_scalar_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &rustsecp256k1_v0_10_0_scalar_one, sizeof(r)) == 0); + a = rustsecp256k1_v0_11_scalar_one; + rustsecp256k1_v0_11_scalar_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &rustsecp256k1_v0_11_scalar_one, sizeof(r)) == 0); - r = rustsecp256k1_v0_10_0_scalar_one; a = rustsecp256k1_v0_10_0_scalar_zero; - rustsecp256k1_v0_10_0_scalar_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &rustsecp256k1_v0_10_0_scalar_one, sizeof(r)) == 0); + r = rustsecp256k1_v0_11_scalar_one; a = rustsecp256k1_v0_11_scalar_zero; + rustsecp256k1_v0_11_scalar_cmov(&r, &a, 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &rustsecp256k1_v0_11_scalar_one, sizeof(r)) == 0); } static void ge_storage_cmov_test(void) { - static const rustsecp256k1_v0_10_0_ge_storage zero = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - static const rustsecp256k1_v0_10_0_ge_storage one = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); - static const rustsecp256k1_v0_10_0_ge_storage max = SECP256K1_GE_STORAGE_CONST( + static const rustsecp256k1_v0_11_ge_storage zero = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + static const rustsecp256k1_v0_11_ge_storage one = SECP256K1_GE_STORAGE_CONST(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1); + static const rustsecp256k1_v0_11_ge_storage max = SECP256K1_GE_STORAGE_CONST( 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL ); - rustsecp256k1_v0_10_0_ge_storage r = max; - rustsecp256k1_v0_10_0_ge_storage a = zero; + rustsecp256k1_v0_11_ge_storage r = max; + rustsecp256k1_v0_11_ge_storage a = zero; - rustsecp256k1_v0_10_0_ge_storage_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &max, sizeof(r)) == 0); + rustsecp256k1_v0_11_ge_storage_cmov(&r, &a, 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &max, sizeof(r)) == 0); r = zero; a = max; - rustsecp256k1_v0_10_0_ge_storage_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &max, sizeof(r)) == 0); + rustsecp256k1_v0_11_ge_storage_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &max, sizeof(r)) == 0); a = zero; - rustsecp256k1_v0_10_0_ge_storage_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &zero, sizeof(r)) == 0); + rustsecp256k1_v0_11_ge_storage_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &zero, sizeof(r)) == 0); a = one; - rustsecp256k1_v0_10_0_ge_storage_cmov(&r, &a, 1); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &one, sizeof(r)) == 0); + rustsecp256k1_v0_11_ge_storage_cmov(&r, &a, 1); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &one, sizeof(r)) == 0); r = one; a = zero; - rustsecp256k1_v0_10_0_ge_storage_cmov(&r, &a, 0); - CHECK(rustsecp256k1_v0_10_0_memcmp_var(&r, &one, sizeof(r)) == 0); + rustsecp256k1_v0_11_ge_storage_cmov(&r, &a, 0); + CHECK(rustsecp256k1_v0_11_memcmp_var(&r, &one, sizeof(r)) == 0); } static void run_cmov_tests(void) { @@ -7511,28 +7691,28 @@ int main(int argc, char **argv) { run_xoshiro256pp_tests(); /* find random seed */ - rustsecp256k1_v0_10_0_testrand_init(argc > 2 ? argv[2] : NULL); + testrand_init(argc > 2 ? argv[2] : NULL); /*** Setup test environment ***/ /* Create a global context available to all tests */ - CTX = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); + CTX = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); /* 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 (rustsecp256k1_v0_10_0_testrand_bits(4)) { + if (testrand_bits(4)) { unsigned char rand32[32]; - rustsecp256k1_v0_10_0_testrand256(rand32); - CHECK(rustsecp256k1_v0_10_0_context_randomize(CTX, rand32)); + testrand256(rand32); + CHECK(rustsecp256k1_v0_11_context_randomize(CTX, rand32)); } - /* Make a writable copy of rustsecp256k1_v0_10_0_context_static in order to test the effect of API functions + /* Make a writable copy of rustsecp256k1_v0_11_context_static in order to test the effect of API functions that write to the context. The API does not support cloning the static context, so we use memcpy instead. The user is not supposed to copy a context but we should still ensure that the API functions handle copies of the static context gracefully. */ - STATIC_CTX = malloc(sizeof(*rustsecp256k1_v0_10_0_context_static)); + STATIC_CTX = malloc(sizeof(*rustsecp256k1_v0_11_context_static)); CHECK(STATIC_CTX != NULL); - memcpy(STATIC_CTX, rustsecp256k1_v0_10_0_context_static, sizeof(rustsecp256k1_v0_10_0_context)); - CHECK(!rustsecp256k1_v0_10_0_context_is_proper(STATIC_CTX)); + memcpy(STATIC_CTX, rustsecp256k1_v0_11_context_static, sizeof(rustsecp256k1_v0_11_context)); + CHECK(!rustsecp256k1_v0_11_context_is_proper(STATIC_CTX)); /*** Run actual tests ***/ @@ -7555,6 +7735,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(); @@ -7611,6 +7794,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(); @@ -7631,21 +7815,26 @@ 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 /* util tests */ - run_rustsecp256k1_v0_10_0_memczero_test(); - run_rustsecp256k1_v0_10_0_byteorder_tests(); + run_rustsecp256k1_v0_11_memczero_test(); + run_rustsecp256k1_v0_11_is_zero_array_test(); + run_rustsecp256k1_v0_11_byteorder_tests(); run_cmov_tests(); /*** Tear down test environment ***/ free(STATIC_CTX); - rustsecp256k1_v0_10_0_context_destroy(CTX); + rustsecp256k1_v0_11_context_destroy(CTX); - rustsecp256k1_v0_10_0_testrand_finish(); + testrand_finish(); printf("no problems found\n"); return 0; diff --git a/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c b/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c index 9f4526499..722b03c5f 100644 --- a/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c +++ b/secp256k1-sys/depend/secp256k1/src/tests_exhaustive.c @@ -42,10 +42,10 @@ SECP256K1_INLINE static int skip_section(uint64_t* iter) { return ((((uint32_t)*iter ^ (*iter >> 32)) * num_cores) >> 32) != this_core; } -static int rustsecp256k1_v0_10_0_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, +static int rustsecp256k1_v0_11_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int attempt) { - rustsecp256k1_v0_10_0_scalar s; + rustsecp256k1_v0_11_scalar s; int *idata = data; (void)msg32; (void)key32; @@ -57,94 +57,94 @@ static int rustsecp256k1_v0_10_0_nonce_function_smallint(unsigned char *nonce32, if (attempt > 0) { *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; } - rustsecp256k1_v0_10_0_scalar_set_int(&s, *idata); - rustsecp256k1_v0_10_0_scalar_get_b32(nonce32, &s); + rustsecp256k1_v0_11_scalar_set_int(&s, *idata); + rustsecp256k1_v0_11_scalar_get_b32(nonce32, &s); return 1; } -static void test_exhaustive_endomorphism(const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_endomorphism(const rustsecp256k1_v0_11_ge *group) { int i; for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_ge res; - rustsecp256k1_v0_10_0_ge_mul_lambda(&res, &group[i]); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res)); + rustsecp256k1_v0_11_ge res; + rustsecp256k1_v0_11_ge_mul_lambda(&res, &group[i]); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res)); } } -static void test_exhaustive_addition(const rustsecp256k1_v0_10_0_ge *group, const rustsecp256k1_v0_10_0_gej *groupj) { +static void test_exhaustive_addition(const rustsecp256k1_v0_11_ge *group, const rustsecp256k1_v0_11_gej *groupj) { int i, j; uint64_t iter = 0; /* Sanity-check (and check infinity functions) */ - CHECK(rustsecp256k1_v0_10_0_ge_is_infinity(&group[0])); - CHECK(rustsecp256k1_v0_10_0_gej_is_infinity(&groupj[0])); + CHECK(rustsecp256k1_v0_11_ge_is_infinity(&group[0])); + CHECK(rustsecp256k1_v0_11_gej_is_infinity(&groupj[0])); for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - CHECK(!rustsecp256k1_v0_10_0_ge_is_infinity(&group[i])); - CHECK(!rustsecp256k1_v0_10_0_gej_is_infinity(&groupj[i])); + CHECK(!rustsecp256k1_v0_11_ge_is_infinity(&group[i])); + CHECK(!rustsecp256k1_v0_11_gej_is_infinity(&groupj[i])); } /* Check all addition formulae */ for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { - rustsecp256k1_v0_10_0_fe fe_inv; + rustsecp256k1_v0_11_fe fe_inv; if (skip_section(&iter)) continue; - rustsecp256k1_v0_10_0_fe_inv(&fe_inv, &groupj[j].z); + rustsecp256k1_v0_11_fe_inv(&fe_inv, &groupj[j].z); for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_ge zless_gej; - rustsecp256k1_v0_10_0_gej tmp; + rustsecp256k1_v0_11_ge zless_gej; + rustsecp256k1_v0_11_gej tmp; /* add_var */ - rustsecp256k1_v0_10_0_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); /* add_ge */ if (j > 0) { - rustsecp256k1_v0_10_0_gej_add_ge(&tmp, &groupj[i], &group[j]); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_gej_add_ge(&tmp, &groupj[i], &group[j]); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); } /* add_ge_var */ - rustsecp256k1_v0_10_0_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); + CHECK(rustsecp256k1_v0_11_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; - rustsecp256k1_v0_10_0_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(i + j) % EXHAUSTIVE_TEST_ORDER])); } } /* Check doubling */ for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_gej tmp; - rustsecp256k1_v0_10_0_gej_double(&tmp, &groupj[i]); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(2 * i) % EXHAUSTIVE_TEST_ORDER])); - rustsecp256k1_v0_10_0_gej_double_var(&tmp, &groupj[i], NULL); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(2 * i) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_gej_double(&tmp, &groupj[i]); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(2 * i) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_gej_double_var(&tmp, &groupj[i], NULL); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(2 * i) % EXHAUSTIVE_TEST_ORDER])); } /* Check negation */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_ge tmp; - rustsecp256k1_v0_10_0_gej tmpj; - rustsecp256k1_v0_10_0_ge_neg(&tmp, &group[i]); - CHECK(rustsecp256k1_v0_10_0_ge_eq_var(&tmp, &group[EXHAUSTIVE_TEST_ORDER - i])); - rustsecp256k1_v0_10_0_gej_neg(&tmpj, &groupj[i]); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmpj, &group[EXHAUSTIVE_TEST_ORDER - i])); + rustsecp256k1_v0_11_ge tmp; + rustsecp256k1_v0_11_gej tmpj; + rustsecp256k1_v0_11_ge_neg(&tmp, &group[i]); + CHECK(rustsecp256k1_v0_11_ge_eq_var(&tmp, &group[EXHAUSTIVE_TEST_ORDER - i])); + rustsecp256k1_v0_11_gej_neg(&tmpj, &groupj[i]); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmpj, &group[EXHAUSTIVE_TEST_ORDER - i])); } } -static void test_exhaustive_ecmult(const rustsecp256k1_v0_10_0_ge *group, const rustsecp256k1_v0_10_0_gej *groupj) { +static void test_exhaustive_ecmult(const rustsecp256k1_v0_11_ge *group, const rustsecp256k1_v0_11_gej *groupj) { int i, j, r_log; uint64_t iter = 0; for (r_log = 1; r_log < EXHAUSTIVE_TEST_ORDER; r_log++) { for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { if (skip_section(&iter)) continue; for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_gej tmp; - rustsecp256k1_v0_10_0_scalar na, ng; - rustsecp256k1_v0_10_0_scalar_set_int(&na, i); - rustsecp256k1_v0_10_0_scalar_set_int(&ng, j); + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_scalar na, ng; + rustsecp256k1_v0_11_scalar_set_int(&na, i); + rustsecp256k1_v0_11_scalar_set_int(&ng, j); - rustsecp256k1_v0_10_0_ecmult(&tmp, &groupj[r_log], &na, &ng); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_ecmult(&tmp, &groupj[r_log], &na, &ng); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(i * r_log + j) % EXHAUSTIVE_TEST_ORDER])); } } } @@ -152,141 +152,141 @@ static void test_exhaustive_ecmult(const rustsecp256k1_v0_10_0_ge *group, const for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { int ret; - rustsecp256k1_v0_10_0_gej tmp; - rustsecp256k1_v0_10_0_fe xn, xd, tmpf; - rustsecp256k1_v0_10_0_scalar ng; + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_fe xn, xd, tmpf; + rustsecp256k1_v0_11_scalar ng; if (skip_section(&iter)) continue; - rustsecp256k1_v0_10_0_scalar_set_int(&ng, j); + rustsecp256k1_v0_11_scalar_set_int(&ng, j); - /* Test rustsecp256k1_v0_10_0_ecmult_const. */ - rustsecp256k1_v0_10_0_ecmult_const(&tmp, &group[i], &ng); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i * j) % EXHAUSTIVE_TEST_ORDER])); + /* Test rustsecp256k1_v0_11_ecmult_const. */ + rustsecp256k1_v0_11_ecmult_const(&tmp, &group[i], &ng); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(i * j) % EXHAUSTIVE_TEST_ORDER])); if (i != 0 && j != 0) { - /* Test rustsecp256k1_v0_10_0_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */ - ret = rustsecp256k1_v0_10_0_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0); + /* Test rustsecp256k1_v0_11_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */ + ret = rustsecp256k1_v0_11_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); + CHECK(rustsecp256k1_v0_11_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); - /* Test rustsecp256k1_v0_10_0_ecmult_const_xonly with all curve X coordinates, with random xd. */ - random_fe_non_zero(&xd); - rustsecp256k1_v0_10_0_fe_mul(&xn, &xd, &group[i].x); - ret = rustsecp256k1_v0_10_0_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0); + /* Test rustsecp256k1_v0_11_ecmult_const_xonly with all curve X coordinates, with random xd. */ + testutil_random_fe_non_zero(&xd); + rustsecp256k1_v0_11_fe_mul(&xn, &xd, &group[i].x); + ret = rustsecp256k1_v0_11_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0); CHECK(ret); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); + CHECK(rustsecp256k1_v0_11_fe_equal(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x)); } } } } typedef struct { - rustsecp256k1_v0_10_0_scalar sc[2]; - rustsecp256k1_v0_10_0_ge pt[2]; + rustsecp256k1_v0_11_scalar sc[2]; + rustsecp256k1_v0_11_ge pt[2]; } ecmult_multi_data; -static int ecmult_multi_callback(rustsecp256k1_v0_10_0_scalar *sc, rustsecp256k1_v0_10_0_ge *pt, size_t idx, void *cbdata) { +static int ecmult_multi_callback(rustsecp256k1_v0_11_scalar *sc, rustsecp256k1_v0_11_ge *pt, size_t idx, void *cbdata) { ecmult_multi_data *data = (ecmult_multi_data*) cbdata; *sc = data->sc[idx]; *pt = data->pt[idx]; return 1; } -static void test_exhaustive_ecmult_multi(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_ecmult_multi(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { int i, j, k, x, y; uint64_t iter = 0; - rustsecp256k1_v0_10_0_scratch *scratch = rustsecp256k1_v0_10_0_scratch_create(&ctx->error_callback, 4096); + rustsecp256k1_v0_11_scratch *scratch = rustsecp256k1_v0_11_scratch_create(&ctx->error_callback, 4096); for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) { for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) { for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { for (x = 0; x < EXHAUSTIVE_TEST_ORDER; x++) { if (skip_section(&iter)) continue; for (y = 0; y < EXHAUSTIVE_TEST_ORDER; y++) { - rustsecp256k1_v0_10_0_gej tmp; - rustsecp256k1_v0_10_0_scalar g_sc; + rustsecp256k1_v0_11_gej tmp; + rustsecp256k1_v0_11_scalar g_sc; ecmult_multi_data data; - rustsecp256k1_v0_10_0_scalar_set_int(&data.sc[0], i); - rustsecp256k1_v0_10_0_scalar_set_int(&data.sc[1], j); - rustsecp256k1_v0_10_0_scalar_set_int(&g_sc, k); + rustsecp256k1_v0_11_scalar_set_int(&data.sc[0], i); + rustsecp256k1_v0_11_scalar_set_int(&data.sc[1], j); + rustsecp256k1_v0_11_scalar_set_int(&g_sc, k); data.pt[0] = group[x]; data.pt[1] = group[y]; - rustsecp256k1_v0_10_0_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); - CHECK(rustsecp256k1_v0_10_0_gej_eq_ge_var(&tmp, &group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER])); + rustsecp256k1_v0_11_ecmult_multi_var(&ctx->error_callback, scratch, &tmp, &g_sc, ecmult_multi_callback, &data, 2); + CHECK(rustsecp256k1_v0_11_gej_eq_ge_var(&tmp, &group[(i * x + j * y + k) % EXHAUSTIVE_TEST_ORDER])); } } } } } - rustsecp256k1_v0_10_0_scratch_destroy(&ctx->error_callback, scratch); + rustsecp256k1_v0_11_scratch_destroy(&ctx->error_callback, scratch); } -static void r_from_k(rustsecp256k1_v0_10_0_scalar *r, const rustsecp256k1_v0_10_0_ge *group, int k, int* overflow) { - rustsecp256k1_v0_10_0_fe x; +static void r_from_k(rustsecp256k1_v0_11_scalar *r, const rustsecp256k1_v0_11_ge *group, int k, int* overflow) { + rustsecp256k1_v0_11_fe x; unsigned char x_bin[32]; k %= EXHAUSTIVE_TEST_ORDER; x = group[k].x; - rustsecp256k1_v0_10_0_fe_normalize(&x); - rustsecp256k1_v0_10_0_fe_get_b32(x_bin, &x); - rustsecp256k1_v0_10_0_scalar_set_b32(r, x_bin, overflow); + rustsecp256k1_v0_11_fe_normalize(&x); + rustsecp256k1_v0_11_fe_get_b32(x_bin, &x); + rustsecp256k1_v0_11_scalar_set_b32(r, x_bin, overflow); } -static void test_exhaustive_verify(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_verify(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { int s, r, msg, key; uint64_t iter = 0; for (s = 1; s < EXHAUSTIVE_TEST_ORDER; s++) { for (r = 1; r < EXHAUSTIVE_TEST_ORDER; r++) { for (msg = 1; msg < EXHAUSTIVE_TEST_ORDER; msg++) { for (key = 1; key < EXHAUSTIVE_TEST_ORDER; key++) { - rustsecp256k1_v0_10_0_ge nonconst_ge; - rustsecp256k1_v0_10_0_ecdsa_signature sig; - rustsecp256k1_v0_10_0_pubkey pk; - rustsecp256k1_v0_10_0_scalar sk_s, msg_s, r_s, s_s; - rustsecp256k1_v0_10_0_scalar s_times_k_s, msg_plus_r_times_sk_s; + rustsecp256k1_v0_11_ge nonconst_ge; + rustsecp256k1_v0_11_ecdsa_signature sig; + rustsecp256k1_v0_11_pubkey pk; + rustsecp256k1_v0_11_scalar sk_s, msg_s, r_s, s_s; + rustsecp256k1_v0_11_scalar s_times_k_s, msg_plus_r_times_sk_s; int k, should_verify; unsigned char msg32[32]; if (skip_section(&iter)) continue; - rustsecp256k1_v0_10_0_scalar_set_int(&s_s, s); - rustsecp256k1_v0_10_0_scalar_set_int(&r_s, r); - rustsecp256k1_v0_10_0_scalar_set_int(&msg_s, msg); - rustsecp256k1_v0_10_0_scalar_set_int(&sk_s, key); + rustsecp256k1_v0_11_scalar_set_int(&s_s, s); + rustsecp256k1_v0_11_scalar_set_int(&r_s, r); + rustsecp256k1_v0_11_scalar_set_int(&msg_s, msg); + rustsecp256k1_v0_11_scalar_set_int(&sk_s, key); /* Verify by hand */ /* Run through every k value that gives us this r and check that *one* works. * Note there could be none, there could be multiple, ECDSA is weird. */ should_verify = 0; for (k = 0; k < EXHAUSTIVE_TEST_ORDER; k++) { - rustsecp256k1_v0_10_0_scalar check_x_s; + rustsecp256k1_v0_11_scalar check_x_s; r_from_k(&check_x_s, group, k, NULL); if (r_s == check_x_s) { - rustsecp256k1_v0_10_0_scalar_set_int(&s_times_k_s, k); - rustsecp256k1_v0_10_0_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); - rustsecp256k1_v0_10_0_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); - rustsecp256k1_v0_10_0_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); - should_verify |= rustsecp256k1_v0_10_0_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + rustsecp256k1_v0_11_scalar_set_int(&s_times_k_s, k); + rustsecp256k1_v0_11_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + rustsecp256k1_v0_11_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + rustsecp256k1_v0_11_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= rustsecp256k1_v0_11_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); } } /* nb we have a "high s" rule */ - should_verify &= !rustsecp256k1_v0_10_0_scalar_is_high(&s_s); + should_verify &= !rustsecp256k1_v0_11_scalar_is_high(&s_s); /* Verify by calling verify */ - rustsecp256k1_v0_10_0_ecdsa_signature_save(&sig, &r_s, &s_s); + rustsecp256k1_v0_11_ecdsa_signature_save(&sig, &r_s, &s_s); memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); - rustsecp256k1_v0_10_0_pubkey_save(&pk, &nonconst_ge); - rustsecp256k1_v0_10_0_scalar_get_b32(msg32, &msg_s); + rustsecp256k1_v0_11_pubkey_save(&pk, &nonconst_ge); + rustsecp256k1_v0_11_scalar_get_b32(msg32, &msg_s); CHECK(should_verify == - rustsecp256k1_v0_10_0_ecdsa_verify(ctx, &sig, msg32, &pk)); + rustsecp256k1_v0_11_ecdsa_verify(ctx, &sig, msg32, &pk)); } } } } } -static void test_exhaustive_sign(const rustsecp256k1_v0_10_0_context *ctx, const rustsecp256k1_v0_10_0_ge *group) { +static void test_exhaustive_sign(const rustsecp256k1_v0_11_context *ctx, const rustsecp256k1_v0_11_ge *group) { int i, j, k; uint64_t iter = 0; @@ -297,18 +297,18 @@ static void test_exhaustive_sign(const rustsecp256k1_v0_10_0_context *ctx, const for (k = 1; k < EXHAUSTIVE_TEST_ORDER; k++) { /* nonce */ const int starting_k = k; int ret; - rustsecp256k1_v0_10_0_ecdsa_signature sig; - rustsecp256k1_v0_10_0_scalar sk, msg, r, s, expected_r; + rustsecp256k1_v0_11_ecdsa_signature sig; + rustsecp256k1_v0_11_scalar sk, msg, r, s, expected_r; unsigned char sk32[32], msg32[32]; - rustsecp256k1_v0_10_0_scalar_set_int(&msg, i); - rustsecp256k1_v0_10_0_scalar_set_int(&sk, j); - rustsecp256k1_v0_10_0_scalar_get_b32(sk32, &sk); - rustsecp256k1_v0_10_0_scalar_get_b32(msg32, &msg); + rustsecp256k1_v0_11_scalar_set_int(&msg, i); + rustsecp256k1_v0_11_scalar_set_int(&sk, j); + rustsecp256k1_v0_11_scalar_get_b32(sk32, &sk); + rustsecp256k1_v0_11_scalar_get_b32(msg32, &msg); - ret = rustsecp256k1_v0_10_0_ecdsa_sign(ctx, &sig, msg32, sk32, rustsecp256k1_v0_10_0_nonce_function_smallint, &k); + ret = rustsecp256k1_v0_11_ecdsa_sign(ctx, &sig, msg32, sk32, rustsecp256k1_v0_11_nonce_function_smallint, &k); CHECK(ret == 1); - rustsecp256k1_v0_10_0_ecdsa_signature_load(ctx, &r, &s, &sig); + rustsecp256k1_v0_11_ecdsa_signature_load(ctx, &r, &s, &sig); /* Note that we compute expected_r *after* signing -- this is important * because our nonce-computing function function might change k during * signing. */ @@ -353,10 +353,10 @@ static void test_exhaustive_sign(const rustsecp256k1_v0_10_0_context *ctx, const int main(int argc, char** argv) { int i; - rustsecp256k1_v0_10_0_gej groupj[EXHAUSTIVE_TEST_ORDER]; - rustsecp256k1_v0_10_0_ge group[EXHAUSTIVE_TEST_ORDER]; + rustsecp256k1_v0_11_gej groupj[EXHAUSTIVE_TEST_ORDER]; + rustsecp256k1_v0_11_ge group[EXHAUSTIVE_TEST_ORDER]; unsigned char rand32[32]; - rustsecp256k1_v0_10_0_context *ctx; + rustsecp256k1_v0_11_context *ctx; /* Disable buffering for stdout to improve reliability of getting * diagnostic information. Happens right at the start of main because @@ -375,7 +375,7 @@ int main(int argc, char** argv) { printf("test count = %i\n", count); /* find random seed */ - rustsecp256k1_v0_10_0_testrand_init(argc > 2 ? argv[2] : NULL); + testrand_init(argc > 2 ? argv[2] : NULL); /* set up split processing */ if (argc > 4) { @@ -389,43 +389,43 @@ int main(int argc, char** argv) { } /* Recreate the ecmult{,_gen} tables using the right generator (as selected via EXHAUSTIVE_TEST_ORDER) */ - rustsecp256k1_v0_10_0_ecmult_gen_compute_table(&rustsecp256k1_v0_10_0_ecmult_gen_prec_table[0][0], &rustsecp256k1_v0_10_0_ge_const_g, ECMULT_GEN_PREC_BITS); - rustsecp256k1_v0_10_0_ecmult_compute_two_tables(rustsecp256k1_v0_10_0_pre_g, rustsecp256k1_v0_10_0_pre_g_128, WINDOW_G, &rustsecp256k1_v0_10_0_ge_const_g); + rustsecp256k1_v0_11_ecmult_gen_compute_table(&rustsecp256k1_v0_11_ecmult_gen_prec_table[0][0], &rustsecp256k1_v0_11_ge_const_g, COMB_BLOCKS, COMB_TEETH, COMB_SPACING); + rustsecp256k1_v0_11_ecmult_compute_two_tables(rustsecp256k1_v0_11_pre_g, rustsecp256k1_v0_11_pre_g_128, WINDOW_G, &rustsecp256k1_v0_11_ge_const_g); while (count--) { /* Build context */ - ctx = rustsecp256k1_v0_10_0_context_create(SECP256K1_CONTEXT_NONE); - rustsecp256k1_v0_10_0_testrand256(rand32); - CHECK(rustsecp256k1_v0_10_0_context_randomize(ctx, rand32)); + ctx = rustsecp256k1_v0_11_context_create(SECP256K1_CONTEXT_NONE); + testrand256(rand32); + CHECK(rustsecp256k1_v0_11_context_randomize(ctx, rand32)); /* Generate the entire group */ - rustsecp256k1_v0_10_0_gej_set_infinity(&groupj[0]); - rustsecp256k1_v0_10_0_ge_set_gej(&group[0], &groupj[0]); + rustsecp256k1_v0_11_gej_set_infinity(&groupj[0]); + rustsecp256k1_v0_11_ge_set_gej(&group[0], &groupj[0]); for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { - rustsecp256k1_v0_10_0_gej_add_ge(&groupj[i], &groupj[i - 1], &rustsecp256k1_v0_10_0_ge_const_g); - rustsecp256k1_v0_10_0_ge_set_gej(&group[i], &groupj[i]); + rustsecp256k1_v0_11_gej_add_ge(&groupj[i], &groupj[i - 1], &rustsecp256k1_v0_11_ge_const_g); + rustsecp256k1_v0_11_ge_set_gej(&group[i], &groupj[i]); if (count != 0) { /* Set a different random z-value for each Jacobian point, except z=1 is used in the last iteration. */ - rustsecp256k1_v0_10_0_fe z; - random_fe(&z); - rustsecp256k1_v0_10_0_gej_rescale(&groupj[i], &z); + rustsecp256k1_v0_11_fe z; + testutil_random_fe(&z); + rustsecp256k1_v0_11_gej_rescale(&groupj[i], &z); } /* Verify against ecmult_gen */ { - rustsecp256k1_v0_10_0_scalar scalar_i; - rustsecp256k1_v0_10_0_gej generatedj; - rustsecp256k1_v0_10_0_ge generated; + rustsecp256k1_v0_11_scalar scalar_i; + rustsecp256k1_v0_11_gej generatedj; + rustsecp256k1_v0_11_ge generated; - rustsecp256k1_v0_10_0_scalar_set_int(&scalar_i, i); - rustsecp256k1_v0_10_0_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); - rustsecp256k1_v0_10_0_ge_set_gej(&generated, &generatedj); + rustsecp256k1_v0_11_scalar_set_int(&scalar_i, i); + rustsecp256k1_v0_11_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); + rustsecp256k1_v0_11_ge_set_gej(&generated, &generatedj); CHECK(group[i].infinity == 0); CHECK(generated.infinity == 0); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&generated.x, &group[i].x)); - CHECK(rustsecp256k1_v0_10_0_fe_equal(&generated.y, &group[i].y)); + CHECK(rustsecp256k1_v0_11_fe_equal(&generated.x, &group[i].x)); + CHECK(rustsecp256k1_v0_11_fe_equal(&generated.y, &group[i].y)); } } @@ -456,10 +456,10 @@ int main(int argc, char** argv) { #endif #endif - rustsecp256k1_v0_10_0_context_destroy(ctx); + rustsecp256k1_v0_11_context_destroy(ctx); } - rustsecp256k1_v0_10_0_testrand_finish(); + testrand_finish(); printf("no problems found\n"); return 0; diff --git a/secp256k1-sys/depend/secp256k1/src/testutil.h b/secp256k1-sys/depend/secp256k1/src/testutil.h index 78262ac37..bd4ac6043 100644 --- a/secp256k1-sys/depend/secp256k1/src/testutil.h +++ b/secp256k1-sys/depend/secp256k1/src/testutil.h @@ -7,23 +7,142 @@ #define SECP256K1_TESTUTIL_H #include "field.h" +#include "group.h" #include "testrand.h" #include "util.h" -static void random_fe(rustsecp256k1_v0_10_0_fe *x) { +static void testutil_random_fe(rustsecp256k1_v0_11_fe *x) { unsigned char bin[32]; do { - rustsecp256k1_v0_10_0_testrand256(bin); - if (rustsecp256k1_v0_10_0_fe_set_b32_limit(x, bin)) { + testrand256(bin); + if (rustsecp256k1_v0_11_fe_set_b32_limit(x, bin)) { return; } } while(1); } -static void random_fe_non_zero(rustsecp256k1_v0_10_0_fe *nz) { +static void testutil_random_fe_non_zero(rustsecp256k1_v0_11_fe *nz) { do { - random_fe(nz); - } while (rustsecp256k1_v0_10_0_fe_is_zero(nz)); + testutil_random_fe(nz); + } while (rustsecp256k1_v0_11_fe_is_zero(nz)); +} + +static void testutil_random_fe_magnitude(rustsecp256k1_v0_11_fe *fe, int m) { + rustsecp256k1_v0_11_fe zero; + int n = testrand_int(m + 1); + rustsecp256k1_v0_11_fe_normalize(fe); + if (n == 0) { + return; + } + rustsecp256k1_v0_11_fe_set_int(&zero, 0); + rustsecp256k1_v0_11_fe_negate(&zero, &zero, 0); + rustsecp256k1_v0_11_fe_mul_int_unchecked(&zero, n - 1); + rustsecp256k1_v0_11_fe_add(fe, &zero); +#ifdef VERIFY + CHECK(fe->magnitude == n); +#endif +} + +static void testutil_random_fe_test(rustsecp256k1_v0_11_fe *x) { + unsigned char bin[32]; + do { + testrand256_test(bin); + if (rustsecp256k1_v0_11_fe_set_b32_limit(x, bin)) { + return; + } + } while(1); +} + +static void testutil_random_fe_non_zero_test(rustsecp256k1_v0_11_fe *fe) { + do { + testutil_random_fe_test(fe); + } while(rustsecp256k1_v0_11_fe_is_zero(fe)); +} + +static void testutil_random_ge_x_magnitude(rustsecp256k1_v0_11_ge *ge) { + testutil_random_fe_magnitude(&ge->x, SECP256K1_GE_X_MAGNITUDE_MAX); +} + +static void testutil_random_ge_y_magnitude(rustsecp256k1_v0_11_ge *ge) { + testutil_random_fe_magnitude(&ge->y, SECP256K1_GE_Y_MAGNITUDE_MAX); +} + +static void testutil_random_gej_x_magnitude(rustsecp256k1_v0_11_gej *gej) { + testutil_random_fe_magnitude(&gej->x, SECP256K1_GEJ_X_MAGNITUDE_MAX); +} + +static void testutil_random_gej_y_magnitude(rustsecp256k1_v0_11_gej *gej) { + testutil_random_fe_magnitude(&gej->y, SECP256K1_GEJ_Y_MAGNITUDE_MAX); +} + +static void testutil_random_gej_z_magnitude(rustsecp256k1_v0_11_gej *gej) { + testutil_random_fe_magnitude(&gej->z, SECP256K1_GEJ_Z_MAGNITUDE_MAX); +} + +static void testutil_random_ge_test(rustsecp256k1_v0_11_ge *ge) { + rustsecp256k1_v0_11_fe fe; + do { + testutil_random_fe_test(&fe); + if (rustsecp256k1_v0_11_ge_set_xo_var(ge, &fe, testrand_bits(1))) { + rustsecp256k1_v0_11_fe_normalize(&ge->y); + break; + } + } while(1); + ge->infinity = 0; +} + +static void testutil_random_ge_jacobian_test(rustsecp256k1_v0_11_gej *gej, const rustsecp256k1_v0_11_ge *ge) { + rustsecp256k1_v0_11_fe z2, z3; + testutil_random_fe_non_zero_test(&gej->z); + rustsecp256k1_v0_11_fe_sqr(&z2, &gej->z); + rustsecp256k1_v0_11_fe_mul(&z3, &z2, &gej->z); + rustsecp256k1_v0_11_fe_mul(&gej->x, &ge->x, &z2); + rustsecp256k1_v0_11_fe_mul(&gej->y, &ge->y, &z3); + gej->infinity = ge->infinity; +} + +static void testutil_random_gej_test(rustsecp256k1_v0_11_gej *gej) { + rustsecp256k1_v0_11_ge ge; + testutil_random_ge_test(&ge); + testutil_random_ge_jacobian_test(gej, &ge); +} + +static void testutil_random_pubkey_test(rustsecp256k1_v0_11_pubkey *pk) { + rustsecp256k1_v0_11_ge ge; + testutil_random_ge_test(&ge); + rustsecp256k1_v0_11_pubkey_save(pk, &ge); +} + +static void testutil_random_scalar_order_test(rustsecp256k1_v0_11_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + testrand256_test(b32); + rustsecp256k1_v0_11_scalar_set_b32(num, b32, &overflow); + if (overflow || rustsecp256k1_v0_11_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +static void testutil_random_scalar_order(rustsecp256k1_v0_11_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + testrand256(b32); + rustsecp256k1_v0_11_scalar_set_b32(num, b32, &overflow); + if (overflow || rustsecp256k1_v0_11_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +static void testutil_random_scalar_order_b32(unsigned char *b32) { + rustsecp256k1_v0_11_scalar num; + testutil_random_scalar_order(&num); + rustsecp256k1_v0_11_scalar_get_b32(b32, &num); } #endif /* SECP256K1_TESTUTIL_H */ diff --git a/secp256k1-sys/depend/secp256k1/src/util.h b/secp256k1-sys/depend/secp256k1/src/util.h index 3975b3eca..702ffe1a1 100644 --- a/secp256k1-sys/depend/secp256k1/src/util.h +++ b/secp256k1-sys/depend/secp256k1/src/util.h @@ -8,10 +8,16 @@ #define SECP256K1_UTIL_H #include "../include/secp256k1.h" +#include "checkmem.h" +#include #include #include #include +#if defined(_MSC_VER) +/* For SecureZeroMemory */ +#include +#endif #define STR_(x) #x #define STR(x) STR_(x) @@ -30,13 +36,27 @@ # define SECP256K1_INLINE inline # endif +/** Assert statically that expr is true. + * + * This is a statement-like macro and can only be used inside functions. + */ +#define STATIC_ASSERT(expr) do { \ + switch(0) { \ + case 0: \ + /* If expr evaluates to 0, we have two case labels "0", which is illegal. */ \ + case /* ERROR: static assertion failed */ (expr): \ + ; \ + } \ +} while(0) + /** Assert statically that expr is an integer constant expression, and run stmt. * * Useful for example to enforce that magnitude arguments are constant. */ #define ASSERT_INT_CONST_AND_DO(expr, stmt) do { \ switch(42) { \ - case /* ERROR: integer argument is not constant */ expr: \ + /* C allows only integer constant expressions as case labels. */ \ + case /* ERROR: integer argument is not constant */ (expr): \ break; \ default: ; \ } \ @@ -46,35 +66,35 @@ typedef struct { void (*fn)(const char *text, void* data); const void* data; -} rustsecp256k1_v0_10_0_callback; +} rustsecp256k1_v0_11_callback; -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_callback_call(const rustsecp256k1_v0_10_0_callback * const cb, const char * const text) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_callback_call(const rustsecp256k1_v0_11_callback * const cb, const char * const text) { cb->fn(text, (void*)cb->data); } #ifndef USE_EXTERNAL_DEFAULT_CALLBACKS -static void rustsecp256k1_v0_10_0_default_illegal_callback_fn(const char* str, void* data) { +static void rustsecp256k1_v0_11_default_illegal_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); abort(); } -static void rustsecp256k1_v0_10_0_default_error_callback_fn(const char* str, void* data) { +static void rustsecp256k1_v0_11_default_error_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); abort(); } #else -void rustsecp256k1_v0_10_0_default_illegal_callback_fn(const char* str, void* data); -void rustsecp256k1_v0_10_0_default_error_callback_fn(const char* str, void* data); +void rustsecp256k1_v0_11_default_illegal_callback_fn(const char* str, void* data); +void rustsecp256k1_v0_11_default_error_callback_fn(const char* str, void* data); #endif -static const rustsecp256k1_v0_10_0_callback default_illegal_callback = { - rustsecp256k1_v0_10_0_default_illegal_callback_fn, +static const rustsecp256k1_v0_11_callback default_illegal_callback = { + rustsecp256k1_v0_11_default_illegal_callback_fn, NULL }; -static const rustsecp256k1_v0_10_0_callback default_error_callback = { - rustsecp256k1_v0_10_0_default_error_callback_fn, +static const rustsecp256k1_v0_11_callback default_error_callback = { + rustsecp256k1_v0_11_default_error_callback_fn, NULL }; @@ -118,7 +138,7 @@ static const rustsecp256k1_v0_10_0_callback default_error_callback = { #define VERIFY_CHECK(cond) #endif -static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callback* cb, size_t size) { +static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_11_callback* cb, size_t size) { (void) cb; (void) size; return NULL; @@ -133,7 +153,10 @@ static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callbac #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) @@ -152,14 +175,6 @@ static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callbac # 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 @@ -167,7 +182,7 @@ static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callbac #endif /* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_memczero(void *s, size_t len, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_memczero(void *s, size_t len, int flag) { unsigned char *p = (unsigned char *)s; /* Access flag with a volatile-qualified lvalue. This prevents clang from figuring out (after inlining) that flag can @@ -181,12 +196,40 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_memczero(void *s, size_t len, } } +/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ +static SECP256K1_INLINE void rustsecp256k1_v0_11_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. * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189 */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_memcmp_var(const void *s1, const void *s2, size_t n) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_memcmp_var(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; size_t i; @@ -199,8 +242,24 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_memcmp_var(const void *s1, con return 0; } +/* Return 1 if all elements of array s are 0 and otherwise return 0. + * Constant-time. */ +static SECP256K1_INLINE int rustsecp256k1_v0_11_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. */ + rustsecp256k1_v0_11_memclear(&acc, sizeof(acc)); + 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 rustsecp256k1_v0_10_0_int_cmov(int *r, const int *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_int_cmov(int *r, const int *a, int flag) { unsigned int mask0, mask1, r_masked, a_masked; /* Access flag with a volatile-qualified lvalue. This prevents clang from figuring out (after inlining) that flag can @@ -255,8 +314,8 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_int_cmov(int *r, const int *a /* Determine the number of trailing zero bits in a (non-zero) 32-bit x. * This function is only intended to be used as fallback for - * rustsecp256k1_v0_10_0_ctz32_var, but permits it to be tested separately. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var_debruijn(uint32_t x) { + * rustsecp256k1_v0_11_ctz32_var, but permits it to be tested separately. */ +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz32_var_debruijn(uint32_t x) { static const uint8_t debruijn[32] = { 0x00, 0x01, 0x02, 0x18, 0x03, 0x13, 0x06, 0x19, 0x16, 0x04, 0x14, 0x0A, 0x10, 0x07, 0x0C, 0x1A, 0x1F, 0x17, 0x12, 0x05, 0x15, 0x09, 0x0F, 0x0B, @@ -267,8 +326,8 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var_debruijn(uint32_t x) /* Determine the number of trailing zero bits in a (non-zero) 64-bit x. * This function is only intended to be used as fallback for - * rustsecp256k1_v0_10_0_ctz64_var, but permits it to be tested separately. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var_debruijn(uint64_t x) { + * rustsecp256k1_v0_11_ctz64_var, but permits it to be tested separately. */ +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz64_var_debruijn(uint64_t x) { static const uint8_t debruijn[64] = { 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, @@ -279,7 +338,7 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var_debruijn(uint64_t x) } /* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var(uint32_t x) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz32_var(uint32_t x) { VERIFY_CHECK(x != 0); #if (__has_builtin(__builtin_ctz) || SECP256K1_GNUC_PREREQ(3,4)) /* If the unsigned type is sufficient to represent the largest uint32_t, consider __builtin_ctz. */ @@ -292,12 +351,12 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var(uint32_t x) { return __builtin_ctzl(x); #else /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */ - return rustsecp256k1_v0_10_0_ctz32_var_debruijn(x); + return rustsecp256k1_v0_11_ctz32_var_debruijn(x); #endif } /* Determine the number of trailing zero bits in a (non-zero) 64-bit x. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var(uint64_t x) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz64_var(uint64_t x) { VERIFY_CHECK(x != 0); #if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4)) /* If the unsigned long type is sufficient to represent the largest uint64_t, consider __builtin_ctzl. */ @@ -310,12 +369,12 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var(uint64_t x) { return __builtin_ctzll(x); #else /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */ - return rustsecp256k1_v0_10_0_ctz64_var_debruijn(x); + return rustsecp256k1_v0_11_ctz64_var_debruijn(x); #endif } /* Read a uint32_t in big endian */ -SECP256K1_INLINE static uint32_t rustsecp256k1_v0_10_0_read_be32(const unsigned char* p) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_read_be32(const unsigned char* p) { return (uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | @@ -323,7 +382,7 @@ SECP256K1_INLINE static uint32_t rustsecp256k1_v0_10_0_read_be32(const unsigned } /* Write a uint32_t in big endian */ -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be32(unsigned char* p, uint32_t x) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_write_be32(unsigned char* p, uint32_t x) { p[3] = x; p[2] = x >> 8; p[1] = x >> 16; @@ -331,7 +390,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be32(unsigned char* p, } /* Read a uint64_t in big endian */ -SECP256K1_INLINE static uint64_t rustsecp256k1_v0_10_0_read_be64(const unsigned char* p) { +SECP256K1_INLINE static uint64_t rustsecp256k1_v0_11_read_be64(const unsigned char* p) { return (uint64_t)p[0] << 56 | (uint64_t)p[1] << 48 | (uint64_t)p[2] << 40 | @@ -343,7 +402,7 @@ SECP256K1_INLINE static uint64_t rustsecp256k1_v0_10_0_read_be64(const unsigned } /* Write a uint64_t in big endian */ -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be64(unsigned char* p, uint64_t x) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_write_be64(unsigned char* p, uint64_t x) { p[7] = x; p[6] = x >> 8; p[5] = x >> 16; @@ -354,4 +413,16 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be64(unsigned char* p, p[0] = x >> 56; } +/* Rotate a uint32_t to the right. */ +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_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 */ diff --git a/secp256k1-sys/depend/secp256k1/src/util.h.orig b/secp256k1-sys/depend/secp256k1/src/util.h.orig index 7a9cf796b..446ed169c 100644 --- a/secp256k1-sys/depend/secp256k1/src/util.h.orig +++ b/secp256k1-sys/depend/secp256k1/src/util.h.orig @@ -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) @@ -51,13 +57,27 @@ static void print_buf_plain(const unsigned char *buf, size_t len) { # define SECP256K1_INLINE inline # endif +/** Assert statically that expr is true. + * + * This is a statement-like macro and can only be used inside functions. + */ +#define STATIC_ASSERT(expr) do { \ + switch(0) { \ + case 0: \ + /* If expr evaluates to 0, we have two case labels "0", which is illegal. */ \ + case /* ERROR: static assertion failed */ (expr): \ + ; \ + } \ +} while(0) + /** Assert statically that expr is an integer constant expression, and run stmt. * * Useful for example to enforce that magnitude arguments are constant. */ #define ASSERT_INT_CONST_AND_DO(expr, stmt) do { \ switch(42) { \ - case /* ERROR: integer argument is not constant */ expr: \ + /* C allows only integer constant expressions as case labels. */ \ + case /* ERROR: integer argument is not constant */ (expr): \ break; \ default: ; \ } \ @@ -67,35 +87,35 @@ static void print_buf_plain(const unsigned char *buf, size_t len) { typedef struct { void (*fn)(const char *text, void* data); const void* data; -} rustsecp256k1_v0_10_0_callback; +} rustsecp256k1_v0_11_callback; -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_callback_call(const rustsecp256k1_v0_10_0_callback * const cb, const char * const text) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_callback_call(const rustsecp256k1_v0_11_callback * const cb, const char * const text) { cb->fn(text, (void*)cb->data); } #ifndef USE_EXTERNAL_DEFAULT_CALLBACKS -static void rustsecp256k1_v0_10_0_default_illegal_callback_fn(const char* str, void* data) { +static void rustsecp256k1_v0_11_default_illegal_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); abort(); } -static void rustsecp256k1_v0_10_0_default_error_callback_fn(const char* str, void* data) { +static void rustsecp256k1_v0_11_default_error_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); abort(); } #else -void rustsecp256k1_v0_10_0_default_illegal_callback_fn(const char* str, void* data); -void rustsecp256k1_v0_10_0_default_error_callback_fn(const char* str, void* data); +void rustsecp256k1_v0_11_default_illegal_callback_fn(const char* str, void* data); +void rustsecp256k1_v0_11_default_error_callback_fn(const char* str, void* data); #endif -static const rustsecp256k1_v0_10_0_callback default_illegal_callback = { - rustsecp256k1_v0_10_0_default_illegal_callback_fn, +static const rustsecp256k1_v0_11_callback default_illegal_callback = { + rustsecp256k1_v0_11_default_illegal_callback_fn, NULL }; -static const rustsecp256k1_v0_10_0_callback default_error_callback = { - rustsecp256k1_v0_10_0_default_error_callback_fn, +static const rustsecp256k1_v0_11_callback default_error_callback = { + rustsecp256k1_v0_11_default_error_callback_fn, NULL }; @@ -139,10 +159,10 @@ static const rustsecp256k1_v0_10_0_callback default_error_callback = { #define VERIFY_CHECK(cond) #endif -static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callback* cb, size_t size) { +static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_11_callback* cb, size_t size) { void *ret = malloc(size); if (ret == NULL) { - rustsecp256k1_v0_10_0_callback_call(cb, "Out of memory"); + rustsecp256k1_v0_11_callback_call(cb, "Out of memory"); } return ret; } @@ -156,7 +176,10 @@ static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callbac #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) @@ -175,14 +198,6 @@ static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callbac # 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 @@ -190,7 +205,7 @@ static SECP256K1_INLINE void *checked_malloc(const rustsecp256k1_v0_10_0_callbac #endif /* Zero memory if flag == 1. Flag must be 0 or 1. Constant time. */ -static SECP256K1_INLINE void rustsecp256k1_v0_10_0_memczero(void *s, size_t len, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_memczero(void *s, size_t len, int flag) { unsigned char *p = (unsigned char *)s; /* Access flag with a volatile-qualified lvalue. This prevents clang from figuring out (after inlining) that flag can @@ -204,12 +219,40 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_memczero(void *s, size_t len, } } +/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */ +static SECP256K1_INLINE void rustsecp256k1_v0_11_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. * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95189 */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_memcmp_var(const void *s1, const void *s2, size_t n) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_memcmp_var(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; size_t i; @@ -222,8 +265,24 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_memcmp_var(const void *s1, con return 0; } +/* Return 1 if all elements of array s are 0 and otherwise return 0. + * Constant-time. */ +static SECP256K1_INLINE int rustsecp256k1_v0_11_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. */ + rustsecp256k1_v0_11_memclear(&acc, sizeof(acc)); + 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 rustsecp256k1_v0_10_0_int_cmov(int *r, const int *a, int flag) { +static SECP256K1_INLINE void rustsecp256k1_v0_11_int_cmov(int *r, const int *a, int flag) { unsigned int mask0, mask1, r_masked, a_masked; /* Access flag with a volatile-qualified lvalue. This prevents clang from figuring out (after inlining) that flag can @@ -278,8 +337,8 @@ static SECP256K1_INLINE void rustsecp256k1_v0_10_0_int_cmov(int *r, const int *a /* Determine the number of trailing zero bits in a (non-zero) 32-bit x. * This function is only intended to be used as fallback for - * rustsecp256k1_v0_10_0_ctz32_var, but permits it to be tested separately. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var_debruijn(uint32_t x) { + * rustsecp256k1_v0_11_ctz32_var, but permits it to be tested separately. */ +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz32_var_debruijn(uint32_t x) { static const uint8_t debruijn[32] = { 0x00, 0x01, 0x02, 0x18, 0x03, 0x13, 0x06, 0x19, 0x16, 0x04, 0x14, 0x0A, 0x10, 0x07, 0x0C, 0x1A, 0x1F, 0x17, 0x12, 0x05, 0x15, 0x09, 0x0F, 0x0B, @@ -290,8 +349,8 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var_debruijn(uint32_t x) /* Determine the number of trailing zero bits in a (non-zero) 64-bit x. * This function is only intended to be used as fallback for - * rustsecp256k1_v0_10_0_ctz64_var, but permits it to be tested separately. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var_debruijn(uint64_t x) { + * rustsecp256k1_v0_11_ctz64_var, but permits it to be tested separately. */ +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz64_var_debruijn(uint64_t x) { static const uint8_t debruijn[64] = { 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28, 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11, @@ -302,7 +361,7 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var_debruijn(uint64_t x) } /* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var(uint32_t x) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz32_var(uint32_t x) { VERIFY_CHECK(x != 0); #if (__has_builtin(__builtin_ctz) || SECP256K1_GNUC_PREREQ(3,4)) /* If the unsigned type is sufficient to represent the largest uint32_t, consider __builtin_ctz. */ @@ -315,12 +374,12 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz32_var(uint32_t x) { return __builtin_ctzl(x); #else /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */ - return rustsecp256k1_v0_10_0_ctz32_var_debruijn(x); + return rustsecp256k1_v0_11_ctz32_var_debruijn(x); #endif } /* Determine the number of trailing zero bits in a (non-zero) 64-bit x. */ -static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var(uint64_t x) { +static SECP256K1_INLINE int rustsecp256k1_v0_11_ctz64_var(uint64_t x) { VERIFY_CHECK(x != 0); #if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4)) /* If the unsigned long type is sufficient to represent the largest uint64_t, consider __builtin_ctzl. */ @@ -333,12 +392,12 @@ static SECP256K1_INLINE int rustsecp256k1_v0_10_0_ctz64_var(uint64_t x) { return __builtin_ctzll(x); #else /* If no suitable CTZ builtin is available, use a (variable time) software emulation. */ - return rustsecp256k1_v0_10_0_ctz64_var_debruijn(x); + return rustsecp256k1_v0_11_ctz64_var_debruijn(x); #endif } /* Read a uint32_t in big endian */ -SECP256K1_INLINE static uint32_t rustsecp256k1_v0_10_0_read_be32(const unsigned char* p) { +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_read_be32(const unsigned char* p) { return (uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | @@ -346,7 +405,7 @@ SECP256K1_INLINE static uint32_t rustsecp256k1_v0_10_0_read_be32(const unsigned } /* Write a uint32_t in big endian */ -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be32(unsigned char* p, uint32_t x) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_write_be32(unsigned char* p, uint32_t x) { p[3] = x; p[2] = x >> 8; p[1] = x >> 16; @@ -354,7 +413,7 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be32(unsigned char* p, } /* Read a uint64_t in big endian */ -SECP256K1_INLINE static uint64_t rustsecp256k1_v0_10_0_read_be64(const unsigned char* p) { +SECP256K1_INLINE static uint64_t rustsecp256k1_v0_11_read_be64(const unsigned char* p) { return (uint64_t)p[0] << 56 | (uint64_t)p[1] << 48 | (uint64_t)p[2] << 40 | @@ -366,7 +425,7 @@ SECP256K1_INLINE static uint64_t rustsecp256k1_v0_10_0_read_be64(const unsigned } /* Write a uint64_t in big endian */ -SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be64(unsigned char* p, uint64_t x) { +SECP256K1_INLINE static void rustsecp256k1_v0_11_write_be64(unsigned char* p, uint64_t x) { p[7] = x; p[6] = x >> 8; p[5] = x >> 16; @@ -377,4 +436,16 @@ SECP256K1_INLINE static void rustsecp256k1_v0_10_0_write_be64(unsigned char* p, p[0] = x >> 56; } +/* Rotate a uint32_t to the right. */ +SECP256K1_INLINE static uint32_t rustsecp256k1_v0_11_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 */ diff --git a/secp256k1-sys/depend/secp256k1/src/wycheproof/WYCHEPROOF_COPYING b/secp256k1-sys/depend/secp256k1/src/wycheproof/WYCHEPROOF_COPYING index 71db1983e..87835e2d1 100644 --- a/secp256k1-sys/depend/secp256k1/src/wycheproof/WYCHEPROOF_COPYING +++ b/secp256k1-sys/depend/secp256k1/src/wycheproof/WYCHEPROOF_COPYING @@ -1,10 +1,10 @@ -* The file `ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.json` in this directory +* The file `ecdsa_rustsecp256k1_v0_11_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_rustsecp256k1_v0_10_0_sha256_bitcoin_test.json + https://github.com/google/wycheproof/blob/b063b4aedae951c69df014cd25fa6d69ae9e8cb9/testvectors_v1/ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.json -* The file `ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.h` is generated from - `ecdsa_rustsecp256k1_v0_10_0_sha256_bitcoin_test.json` using the script +* The file `ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.h` is generated from + `ecdsa_rustsecp256k1_v0_11_sha256_bitcoin_test.json` using the script `tests_wycheproof_generate.py`. ------------------------------------------------------------------------------- diff --git a/secp256k1-sys/depend/secp256k1/tools/check-abi.sh b/secp256k1-sys/depend/secp256k1/tools/check-abi.sh index 8f6119cd8..601a64ba9 100755 --- a/secp256k1-sys/depend/secp256k1/tools/check-abi.sh +++ b/secp256k1-sys/depend/secp256k1/tools/check-abi.sh @@ -3,17 +3,19 @@ set -eu default_base_version="$(git describe --match "v*.*.*" --abbrev=0)" -default_new_version="master" +default_new_version="HEAD" display_help_and_exit() { - echo "Usage: $0 " + echo "Usage: $0 [ []]" echo "" echo "Description: This script uses the ABI Compliance Checker tool to determine if the ABI" echo " of a new version of libsecp256k1 has changed in a backward-incompatible way." echo "" echo "Options:" - echo " base_ver Specify the base version (default: $default_base_version)" - echo " new_ver Specify the new version (default: $default_new_version)" + echo " base_ver Specify the base version as a git commit-ish" + echo " (default: most recent reachable tag matching \"v.*.*\", currently \"$default_base_version\")" + echo " new_ver Specify the new version as a git commit-ish" + echo " (default: $default_new_version)" echo " -h, --help Display this help message" exit 0 } @@ -23,9 +25,11 @@ if [ "$#" -eq 0 ]; then new_version="$default_new_version" elif [ "$#" -eq 1 ] && { [ "$1" = "-h" ] || [ "$1" = "--help" ]; }; then display_help_and_exit -elif [ "$#" -eq 2 ]; then +elif [ "$#" -eq 1 ] || [ "$#" -eq 2 ]; then base_version="$1" - new_version="$2" + if [ "$#" -eq 2 ]; then + new_version="$2" + fi else echo "Invalid usage. See help:" echo "" @@ -33,7 +37,8 @@ else fi checkout_and_build() { - git worktree add -d "$1" "$2" + _orig_dir="$(pwd)" + git worktree add --detach "$1" "$2" cd "$1" mkdir build && cd build cmake -S .. --preset dev-mode \ @@ -44,21 +49,26 @@ 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" + # 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" } echo "Comparing $base_version (base version) to $new_version (new version)" echo -original_dir="$(pwd)" - -base_source_dir=$(mktemp -d) +base_source_dir="$(mktemp -d)" checkout_and_build "$base_source_dir" "$base_version" -new_source_dir=$(mktemp -d) +new_source_dir="$(mktemp -d)" checkout_and_build "$new_source_dir" "$new_version" -cd "$original_dir" abi-compliance-checker -lib libsecp256k1 -old "${base_source_dir}/build/ABI.dump" -new "${new_source_dir}/build/ABI.dump" git worktree remove "$base_source_dir" git worktree remove "$new_source_dir" diff --git a/secp256k1-sys/depend/secp256k1/tools/test_vectors_musig2_generate.py b/secp256k1-sys/depend/secp256k1/tools/test_vectors_musig2_generate.py new file mode 100755 index 000000000..97424419f --- /dev/null +++ b/secp256k1-sys/depend/secp256k1/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) diff --git a/secp256k1-sys/src/lib.rs b/secp256k1-sys/src/lib.rs index d0b720506..85daba309 100644 --- a/secp256k1-sys/src/lib.rs +++ b/secp256k1-sys/src/lib.rs @@ -559,110 +559,110 @@ impl_raw_debug!(ElligatorSwift); extern "C" { /// Default ECDH hash function - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdh_hash_function_default")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdh_hash_function_default")] pub static secp256k1_ecdh_hash_function_default: EcdhHashFn; /// Default ECDH hash function for BIP324 key establishment - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ellswift_xdh_hash_function_bip324")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ellswift_xdh_hash_function_bip324")] pub static secp256k1_ellswift_xdh_hash_function_bip324: EllswiftEcdhHashFn; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_nonce_function_rfc6979")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_nonce_function_rfc6979")] pub static secp256k1_nonce_function_rfc6979: NonceFn; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_nonce_function_default")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_nonce_function_default")] pub static secp256k1_nonce_function_default: NonceFn; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_nonce_function_bip340")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_nonce_function_bip340")] pub static secp256k1_nonce_function_bip340: SchnorrNonceFn; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_no_precomp")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_no_precomp")] pub static secp256k1_context_no_precomp: *const Context; // Contexts - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_preallocated_destroy")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_preallocated_destroy")] pub fn secp256k1_context_preallocated_destroy(cx: NonNull); // Signatures - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_signature_parse_der")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_signature_parse_der")] pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, sig: *mut Signature, input: *const c_uchar, in_len: size_t) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_signature_parse_compact")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_signature_parse_compact")] pub fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature, input64: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_signature_parse_der_lax")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_signature_parse_der_lax")] pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature, input: *const c_uchar, in_len: size_t) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_signature_serialize_der")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_signature_serialize_der")] pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar, out_len: *mut size_t, sig: *const Signature) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_signature_serialize_compact")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_signature_serialize_compact")] pub fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar, sig: *const Signature) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_signature_normalize")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_signature_normalize")] pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, out_sig: *mut Signature, in_sig: *const Signature) -> c_int; // Secret Keys - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_seckey_verify")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_seckey_verify")] pub fn secp256k1_ec_seckey_verify(cx: *const Context, sk: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_seckey_negate")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_seckey_negate")] pub fn secp256k1_ec_seckey_negate(cx: *const Context, sk: *mut c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_seckey_tweak_add")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_seckey_tweak_add")] pub fn secp256k1_ec_seckey_tweak_add(cx: *const Context, sk: *mut c_uchar, tweak: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_seckey_tweak_mul")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_seckey_tweak_mul")] pub fn secp256k1_ec_seckey_tweak_mul(cx: *const Context, sk: *mut c_uchar, tweak: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_keypair_sec")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_keypair_sec")] pub fn secp256k1_keypair_sec(cx: *const Context, output_seckey: *mut c_uchar, keypair: *const Keypair) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_keypair_pub")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_keypair_pub")] pub fn secp256k1_keypair_pub(cx: *const Context, output_pubkey: *mut PublicKey, keypair: *const Keypair) -> c_int; // Elligator Swift - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ellswift_encode")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ellswift_encode")] pub fn secp256k1_ellswift_encode(ctx: *const Context, ell64: *mut c_uchar, pubkey: *const PublicKey, rnd32: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ellswift_decode")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ellswift_decode")] pub fn secp256k1_ellswift_decode(ctx: *const Context, pubkey: *mut u8, ell64: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ellswift_create")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ellswift_create")] pub fn secp256k1_ellswift_create(ctx: *const Context, ell64: *mut c_uchar, seckey32: *const c_uchar, aux_rand32: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ellswift_xdh")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ellswift_xdh")] pub fn secp256k1_ellswift_xdh(ctx: *const Context, output: *mut c_uchar, ell_a64: *const c_uchar, @@ -677,71 +677,71 @@ extern "C" { #[cfg(not(secp256k1_fuzz))] extern "C" { // Contexts - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_preallocated_size")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_preallocated_size")] pub fn secp256k1_context_preallocated_size(flags: c_uint) -> size_t; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_preallocated_create")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_preallocated_create")] pub fn secp256k1_context_preallocated_create(prealloc: NonNull, flags: c_uint) -> NonNull; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_preallocated_clone_size")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_preallocated_clone_size")] pub fn secp256k1_context_preallocated_clone_size(cx: *const Context) -> size_t; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_preallocated_clone")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_preallocated_clone")] pub fn secp256k1_context_preallocated_clone(cx: *const Context, prealloc: NonNull) -> NonNull; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_context_randomize")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_context_randomize")] pub fn secp256k1_context_randomize(cx: NonNull, seed32: *const c_uchar) -> c_int; // Pubkeys - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_parse")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_parse")] pub fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey, input: *const c_uchar, in_len: size_t) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_serialize")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_serialize")] pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar, out_len: *mut size_t, pk: *const PublicKey, compressed: c_uint) -> c_int; // EC - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_create")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_create")] pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey, sk: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_negate")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_negate")] pub fn secp256k1_ec_pubkey_negate(cx: *const Context, pk: *mut PublicKey) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_cmp")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_cmp")] pub fn secp256k1_ec_pubkey_cmp(cx: *const Context, pubkey1: *const PublicKey, pubkey2: *const PublicKey) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_tweak_add")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_tweak_add")] pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, pk: *mut PublicKey, tweak: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_tweak_mul")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_tweak_mul")] pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, pk: *mut PublicKey, tweak: *const c_uchar) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ec_pubkey_combine")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ec_pubkey_combine")] pub fn secp256k1_ec_pubkey_combine(cx: *const Context, out: *mut PublicKey, ins: *const *const PublicKey, n: size_t) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdh")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdh")] pub fn secp256k1_ecdh( cx: *const Context, output: *mut c_uchar, @@ -752,14 +752,14 @@ extern "C" { ) -> c_int; // ECDSA - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_verify")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_verify")] pub fn secp256k1_ecdsa_verify(cx: *const Context, sig: *const Signature, msg32: *const c_uchar, pk: *const PublicKey) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_sign")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_sign")] pub fn secp256k1_ecdsa_sign(cx: *const Context, sig: *mut Signature, msg32: *const c_uchar, @@ -769,7 +769,7 @@ extern "C" { -> c_int; // Schnorr Signatures - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_schnorrsig_sign")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_schnorrsig_sign")] pub fn secp256k1_schnorrsig_sign( cx: *const Context, sig: *mut c_uchar, @@ -779,7 +779,7 @@ extern "C" { ) -> c_int; // Schnorr Signatures with extra parameters (see [`SchnorrSigExtraParams`]) - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_schnorrsig_sign_custom")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_schnorrsig_sign_custom")] pub fn secp256k1_schnorrsig_sign_custom( cx: *const Context, sig: *mut c_uchar, @@ -789,7 +789,7 @@ extern "C" { extra_params: *const SchnorrSigExtraParams, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_schnorrsig_verify")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_schnorrsig_verify")] pub fn secp256k1_schnorrsig_verify( cx: *const Context, sig64: *const c_uchar, @@ -799,28 +799,28 @@ extern "C" { ) -> c_int; // Extra keys - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_keypair_create")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_keypair_create")] pub fn secp256k1_keypair_create( cx: *const Context, keypair: *mut Keypair, seckey: *const c_uchar, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_xonly_pubkey_parse")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_xonly_pubkey_parse")] pub fn secp256k1_xonly_pubkey_parse( cx: *const Context, pubkey: *mut XOnlyPublicKey, input32: *const c_uchar, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_xonly_pubkey_serialize")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_xonly_pubkey_serialize")] pub fn secp256k1_xonly_pubkey_serialize( cx: *const Context, output32: *mut c_uchar, pubkey: *const XOnlyPublicKey, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_xonly_pubkey_from_pubkey")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_xonly_pubkey_from_pubkey")] pub fn secp256k1_xonly_pubkey_from_pubkey( cx: *const Context, xonly_pubkey: *mut XOnlyPublicKey, @@ -828,14 +828,14 @@ extern "C" { pubkey: *const PublicKey, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_xonly_pubkey_cmp")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_xonly_pubkey_cmp")] pub fn secp256k1_xonly_pubkey_cmp( cx: *const Context, pubkey1: *const XOnlyPublicKey, pubkey2: *const XOnlyPublicKey ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_xonly_pubkey_tweak_add")] pub fn secp256k1_xonly_pubkey_tweak_add( cx: *const Context, output_pubkey: *mut PublicKey, @@ -843,7 +843,7 @@ extern "C" { tweak32: *const c_uchar, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_keypair_xonly_pub")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_keypair_xonly_pub")] pub fn secp256k1_keypair_xonly_pub( cx: *const Context, pubkey: *mut XOnlyPublicKey, @@ -851,14 +851,14 @@ extern "C" { keypair: *const Keypair ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_keypair_xonly_tweak_add")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_keypair_xonly_tweak_add")] pub fn secp256k1_keypair_xonly_tweak_add( cx: *const Context, keypair: *mut Keypair, tweak32: *const c_uchar, ) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_xonly_pubkey_tweak_add_check")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_xonly_pubkey_tweak_add_check")] pub fn secp256k1_xonly_pubkey_tweak_add_check( cx: *const Context, tweaked_pubkey32: *const c_uchar, @@ -885,7 +885,7 @@ extern "C" { /// The newly created secp256k1 raw context. #[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))] pub unsafe fn secp256k1_context_create(flags: c_uint) -> NonNull { - rustsecp256k1_v0_10_0_context_create(flags) + rustsecp256k1_v0_11_context_create(flags) } /// A reimplementation of the C function `secp256k1_context_create` in rust. @@ -894,7 +894,7 @@ pub unsafe fn secp256k1_context_create(flags: c_uint) -> NonNull { #[no_mangle] #[allow(clippy::missing_safety_doc)] // Documented above. #[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))] -pub unsafe extern "C" fn rustsecp256k1_v0_10_0_context_create(flags: c_uint) -> NonNull { +pub unsafe extern "C" fn rustsecp256k1_v0_11_context_create(flags: c_uint) -> NonNull { use core::mem; use crate::alloc::alloc; assert!(ALIGN_TO >= mem::align_of::()); @@ -927,13 +927,13 @@ pub unsafe extern "C" fn rustsecp256k1_v0_10_0_context_create(flags: c_uint) -> /// `ctx` must be a valid pointer to a block of memory created using [`secp256k1_context_create`]. #[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))] pub unsafe fn secp256k1_context_destroy(ctx: NonNull) { - rustsecp256k1_v0_10_0_context_destroy(ctx) + rustsecp256k1_v0_11_context_destroy(ctx) } #[no_mangle] #[allow(clippy::missing_safety_doc)] // Documented above. #[cfg(all(feature = "alloc", not(rust_secp_no_symbol_renaming)))] -pub unsafe extern "C" fn rustsecp256k1_v0_10_0_context_destroy(mut ctx: NonNull) { +pub unsafe extern "C" fn rustsecp256k1_v0_11_context_destroy(mut ctx: NonNull) { use crate::alloc::alloc; secp256k1_context_preallocated_destroy(ctx); let ctx: *mut Context = ctx.as_mut(); @@ -969,7 +969,7 @@ pub unsafe extern "C" fn rustsecp256k1_v0_10_0_context_destroy(mut ctx: NonNull< /// For exact safety constraints see [`std::slice::from_raw_parts`] and [`std::str::from_utf8_unchecked`]. #[no_mangle] #[cfg(not(rust_secp_no_symbol_renaming))] -pub unsafe extern "C" fn rustsecp256k1_v0_10_0_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) { +pub unsafe extern "C" fn rustsecp256k1_v0_11_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) { use core::str; let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); let msg = str::from_utf8_unchecked(msg_slice); @@ -997,7 +997,7 @@ pub unsafe extern "C" fn rustsecp256k1_v0_10_0_default_illegal_callback_fn(messa /// For exact safety constraints see [`std::slice::from_raw_parts`] and [`std::str::from_utf8_unchecked`]. #[no_mangle] #[cfg(not(rust_secp_no_symbol_renaming))] -pub unsafe extern "C" fn rustsecp256k1_v0_10_0_default_error_callback_fn(message: *const c_char, _data: *mut c_void) { +pub unsafe extern "C" fn rustsecp256k1_v0_11_default_error_callback_fn(message: *const c_char, _data: *mut c_void) { use core::str; let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); let msg = str::from_utf8_unchecked(msg_slice); @@ -1106,9 +1106,9 @@ mod fuzz_dummy { #[cfg(rust_secp_no_symbol_renaming)] compile_error!("We do not support fuzzing with rust_secp_no_symbol_renaming"); extern "C" { - fn rustsecp256k1_v0_10_0_context_preallocated_size(flags: c_uint) -> size_t; - fn rustsecp256k1_v0_10_0_context_preallocated_create(prealloc: NonNull, flags: c_uint) -> NonNull; - fn rustsecp256k1_v0_10_0_context_preallocated_clone(cx: *const Context, prealloc: NonNull) -> NonNull; + fn rustsecp256k1_v0_11_context_preallocated_size(flags: c_uint) -> size_t; + fn rustsecp256k1_v0_11_context_preallocated_create(prealloc: NonNull, flags: c_uint) -> NonNull; + fn rustsecp256k1_v0_11_context_preallocated_clone(cx: *const Context, prealloc: NonNull) -> NonNull; } #[cfg(feature = "lowmemory")] @@ -1117,7 +1117,7 @@ mod fuzz_dummy { const CTX_SIZE: usize = 1024 * (1024 + 128); // Contexts pub unsafe fn secp256k1_context_preallocated_size(flags: c_uint) -> size_t { - assert!(rustsecp256k1_v0_10_0_context_preallocated_size(flags) + std::mem::size_of::() <= CTX_SIZE); + assert!(rustsecp256k1_v0_11_context_preallocated_size(flags) + std::mem::size_of::() <= CTX_SIZE); CTX_SIZE } @@ -1137,8 +1137,8 @@ mod fuzz_dummy { if have_ctx == HAVE_CONTEXT_NONE { have_ctx = HAVE_PREALLOCATED_CONTEXT.swap(HAVE_CONTEXT_WORKING, Ordering::AcqRel); if have_ctx == HAVE_CONTEXT_NONE { - assert!(rustsecp256k1_v0_10_0_context_preallocated_size(SECP256K1_START_SIGN | SECP256K1_START_VERIFY) + std::mem::size_of::() <= CTX_SIZE); - assert_eq!(rustsecp256k1_v0_10_0_context_preallocated_create( + assert!(rustsecp256k1_v0_11_context_preallocated_size(SECP256K1_START_SIGN | SECP256K1_START_VERIFY) + std::mem::size_of::() <= CTX_SIZE); + assert_eq!(rustsecp256k1_v0_11_context_preallocated_create( NonNull::new_unchecked(PREALLOCATED_CONTEXT[..].as_mut_ptr() as *mut c_void), SECP256K1_START_SIGN | SECP256K1_START_VERIFY), NonNull::new_unchecked(PREALLOCATED_CONTEXT[..].as_mut_ptr() as *mut Context)); @@ -1167,7 +1167,7 @@ mod fuzz_dummy { let new_ptr = (prealloc.as_ptr() as *mut u8).add(CTX_SIZE).sub(std::mem::size_of::()); let flags = (orig_ptr as *mut c_uint).read(); (new_ptr as *mut c_uint).write(flags); - rustsecp256k1_v0_10_0_context_preallocated_clone(cx, prealloc) + rustsecp256k1_v0_11_context_preallocated_clone(cx, prealloc) } pub unsafe fn secp256k1_context_randomize(cx: NonNull, diff --git a/secp256k1-sys/src/recovery.rs b/secp256k1-sys/src/recovery.rs index d17e5fbab..0a5c2aaea 100644 --- a/secp256k1-sys/src/recovery.rs +++ b/secp256k1-sys/src/recovery.rs @@ -100,17 +100,17 @@ impl core::hash::Hash for RecoverableSignature { } extern "C" { - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_parse_compact")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_recoverable_signature_parse_compact")] pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature, input64: *const c_uchar, recid: c_int) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_serialize_compact")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_recoverable_signature_serialize_compact")] pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar, recid: *mut c_int, sig: *const RecoverableSignature) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_recoverable_signature_convert")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_recoverable_signature_convert")] pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature, input: *const RecoverableSignature) -> c_int; @@ -118,7 +118,7 @@ extern "C" { #[cfg(not(secp256k1_fuzz))] extern "C" { - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_sign_recoverable")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_sign_recoverable")] pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, sig: *mut RecoverableSignature, msg32: *const c_uchar, @@ -127,7 +127,7 @@ extern "C" { noncedata: *const c_void) -> c_int; - #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_10_0_ecdsa_recover")] + #[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_11_ecdsa_recover")] pub fn secp256k1_ecdsa_recover(cx: *const Context, pk: *mut PublicKey, sig: *const RecoverableSignature, diff --git a/secp256k1-sys/vendor-libsecp.sh b/secp256k1-sys/vendor-libsecp.sh index 735bb0189..03c50bb5e 100755 --- a/secp256k1-sys/vendor-libsecp.sh +++ b/secp256k1-sys/vendor-libsecp.sh @@ -8,7 +8,7 @@ else SECP_VENDOR_GIT_ROOT="$(realpath "$SECP_VENDOR_GIT_ROOT")" fi SECP_SYS="$SECP_VENDOR_GIT_ROOT"/secp256k1-sys -DEFAULT_VERSION_CODE=$(grep "^version" "$SECP_SYS/Cargo.toml" | sed 's/\./_/g' | sed 's/.*"\(.*\)".*/\1/') +DEFAULT_VERSION_CODE=$(grep "^version" "$SECP_SYS/Cargo.toml" | sed 's/\./_/g' | sed 's/.*"\(.*\)".*/\1/' | cut -d_ -f1-2) DEFAULT_DEPEND_DIR="$SECP_SYS/depend" DEFAULT_SECP_REPO=https://github.com/bitcoin-core/secp256k1.git @@ -96,6 +96,7 @@ echo "$SOURCE_REV" >> ./secp256k1-HEAD-revision.txt # To compensate, the secp_context_create and _destroy methods are redefined in Rust. patch "$DIR/include/secp256k1.h" "./secp256k1.h.patch" patch "$DIR/src/secp256k1.c" "./secp256k1.c.patch" +patch "$DIR/src/scratch.h" "./scratch.h.patch" patch "$DIR/src/scratch_impl.h" "./scratch_impl.h.patch" patch "$DIR/src/util.h" "./util.h.patch"